From 6164a81e19e872542510a4817ec8403f201c3aaf Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Fri, 1 Nov 2024 14:26:55 +0000 Subject: [PATCH 01/16] working with debounce --- .../intellij/VersionPropsFileListener.java | 97 +++++++++++++++---- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java index c8bdc13d..47af36ce 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java @@ -37,6 +37,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.util.GradleConstants; @@ -47,6 +52,13 @@ public final class VersionPropsFileListener implements AsyncFileListener { private static final Logger log = LoggerFactory.getLogger(VersionPropsFileListener.class); private static final String TASK_NAME = "writeVersionsLock"; + // Shared state to track changes per project + private final ConcurrentMap projectChangeMap = new ConcurrentHashMap<>(); + + // Executor for debouncing + private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); + private static final long DEBOUNCE_DELAY_MS = 250; + @Nullable @Override public ChangeApplier prepareChange(List events) { @@ -56,38 +68,83 @@ public ChangeApplier prepareChange(List events) { .filter(event -> "versions.props".equals(event.getFile().getName())) .toList(); - if (versionPropsEvents.isEmpty()) { + List versionLockEvents = events.stream() + .filter(event -> event instanceof VFileContentChangeEvent) + .map(event -> (VFileContentChangeEvent) event) + .filter(event -> "versions.lock".equals(event.getFile().getName())) + .toList(); + + if (versionPropsEvents.isEmpty() && versionLockEvents.isEmpty()) { return null; } - List projectsAffected = Arrays.stream( + List allOpenProjects = Arrays.stream( ProjectManager.getInstance().getOpenProjects()) .filter(Project::isInitialized) .filter(Predicate.not(ComponentManager::isDisposed)) - .filter(project -> versionPropsEvents.stream() - .anyMatch(event -> event.getPath().startsWith(project.getBasePath()) - && !isFileMalformed(project, event.getFile()))) .toList(); + // Update the shared state based on current events + allOpenProjects.forEach(project -> { + String basePath = project.getBasePath(); + boolean hasPropsChange = versionPropsEvents.stream() + .anyMatch(event -> + event.getPath().startsWith(basePath) && !isFileMalformed(project, event.getFile())); + boolean hasLockChange = + versionLockEvents.stream().anyMatch(event -> event.getPath().startsWith(basePath)); + + if (hasPropsChange || hasLockChange) { + projectChangeMap.compute(project, (proj, flags) -> { + if (flags == null) { + return ChangeFlags.of(hasPropsChange, hasLockChange); + } else { + return ChangeFlags.of( + flags.hasPropsChange() || hasPropsChange, flags.hasLockChange() || hasLockChange); + } + }); + } + }); + return new ChangeApplier() { @Override public void afterVfsChange() { - projectsAffected.forEach(project -> { - VersionPropsProjectSettings settings = VersionPropsProjectSettings.getInstance(project); - if (!settings.isEnabled()) { - return; - } - - if (hasBuildSrc(project)) { - runTaskThenRefresh(project); - } else { - refreshProjectWithTask(project); - } + // Schedule processing after VFS changes have been applied + projectChangeMap.keySet().forEach(project -> { + scheduler.schedule(() -> processChanges(project), DEBOUNCE_DELAY_MS, TimeUnit.MILLISECONDS); }); } }; } + private void processChanges(Project project) { + ChangeFlags flags = projectChangeMap.remove(project); + if (flags == null) { + return; + } + + if (flags.hasPropsChange && flags.hasLockChange) { + // Both changes detected; do not process + log.debug( + "Project {} has both versions.props and versions.lock changes. Skipping processing.", + project.getName()); + return; + } + + if (flags.hasPropsChange) { + // Only props changed; process the project + VersionPropsProjectSettings settings = VersionPropsProjectSettings.getInstance(project); + if (!settings.isEnabled()) { + return; + } + + if (hasBuildSrc(project)) { + runTaskThenRefresh(project); + } else { + refreshProjectWithTask(project); + } + } + } + private boolean hasBuildSrc(Project project) { return Files.exists(Paths.get(project.getBasePath(), "buildSrc")); } @@ -146,4 +203,10 @@ private static boolean isFileMalformed(Project project, VirtualFile file) { return PsiTreeUtil.hasErrorElements(psiFile); } -} + + private record ChangeFlags(boolean hasPropsChange, boolean hasLockChange) { + public static ChangeFlags of(boolean hasPropsChange, boolean hasLockChange) { + return new ChangeFlags(hasPropsChange, hasLockChange); + } + } +} \ No newline at end of file From 1c91f031fce69914e0f177fb1958e717a3d463ed Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Fri, 1 Nov 2024 14:41:59 +0000 Subject: [PATCH 02/16] longer timeout --- .../gradle/versions/intellij/VersionPropsFileListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java index 47af36ce..e362131f 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java @@ -57,7 +57,7 @@ public final class VersionPropsFileListener implements AsyncFileListener { // Executor for debouncing private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); - private static final long DEBOUNCE_DELAY_MS = 250; + private static final long DEBOUNCE_DELAY_MS = 350; @Nullable @Override From 51d6048ba41d6cae89967a39e4d32914a62a960a Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Fri, 1 Nov 2024 15:09:06 +0000 Subject: [PATCH 03/16] weak link --- .../gradle/versions/intellij/VersionPropsFileListener.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java index e362131f..8590be48 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java @@ -16,6 +16,7 @@ package com.palantir.gradle.versions.intellij; +import com.google.common.collect.MapMaker; import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.openapi.components.ComponentManager; import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder; @@ -37,7 +38,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -53,7 +53,8 @@ public final class VersionPropsFileListener implements AsyncFileListener { private static final String TASK_NAME = "writeVersionsLock"; // Shared state to track changes per project - private final ConcurrentMap projectChangeMap = new ConcurrentHashMap<>(); + private final ConcurrentMap projectChangeMap = + new MapMaker().weakKeys().makeMap(); // Executor for debouncing private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); From 68e363274a3820543da2adbc2a7f84afd566aa67 Mon Sep 17 00:00:00 2001 From: svc-changelog Date: Fri, 1 Nov 2024 15:10:05 +0000 Subject: [PATCH 04/16] Add generated changelog entries --- changelog/@unreleased/pr-67.v2.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/@unreleased/pr-67.v2.yml diff --git a/changelog/@unreleased/pr-67.v2.yml b/changelog/@unreleased/pr-67.v2.yml new file mode 100644 index 00000000..263ab06a --- /dev/null +++ b/changelog/@unreleased/pr-67.v2.yml @@ -0,0 +1,5 @@ +type: fix +fix: + description: Don't write locks if both the locks and props change + links: + - https://github.com/palantir/gradle-consistent-versions-idea-plugin/pull/67 From 3d53607987d9186257d4edc3f430604f23c9d86e Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Fri, 1 Nov 2024 15:10:40 +0000 Subject: [PATCH 05/16] newline --- .../gradle/versions/intellij/VersionPropsFileListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java index 8590be48..02dac869 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java @@ -210,4 +210,4 @@ public static ChangeFlags of(boolean hasPropsChange, boolean hasLockChange) { return new ChangeFlags(hasPropsChange, hasLockChange); } } -} \ No newline at end of file +} From 7d5f7072718095f1357d8bd35ebe92f1b6ced097 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Tue, 5 Nov 2024 11:19:47 +0000 Subject: [PATCH 06/16] debounce and register --- .../intellij/DebouncingAsyncFileListener.java | 92 +++++++++++++++ .../intellij/VersionPropsFileListener.java | 107 +++++------------- .../VersionPropsListenerRegistrar.java | 32 ++++++ .../src/main/resources/META-INF/plugin.xml | 8 +- 4 files changed, 159 insertions(+), 80 deletions(-) create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java new file mode 100644 index 00000000..e4b2cb79 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java @@ -0,0 +1,92 @@ +/* + * (c) Copyright 2024 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.gradle.versions.intellij; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.vfs.AsyncFileListener; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.util.Alarm; +import java.util.ArrayList; +import java.util.List; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class DebouncingAsyncFileListener implements AsyncFileListener, Disposable { + private static final Logger log = LoggerFactory.getLogger(DebouncingAsyncFileListener.class); + + private final AsyncFileListener delegate; + private final long debounceDelayMillis; + private final Alarm alarm; + private final Object lock = new Object(); + + private final List bufferedEvents = new ArrayList<>(); + private boolean isDisposed = false; + + public DebouncingAsyncFileListener(AsyncFileListener delegate, long debounceDelayMillis) { + this.delegate = delegate; + this.debounceDelayMillis = debounceDelayMillis; + this.alarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, this); + } + + @Nullable + @Override + public ChangeApplier prepareChange(List events) { + synchronized (lock) { + if (isDisposed) { + return null; + } + log.debug("Received events: {}", events); + bufferedEvents.addAll(events); + scheduleDelegateInvocation(); + } + return null; + } + + private void scheduleDelegateInvocation() { + alarm.cancelAllRequests(); + alarm.addRequest( + () -> { + List eventsToProcess; + synchronized (lock) { + if (isDisposed) { + return; + } + eventsToProcess = new ArrayList<>(bufferedEvents); + bufferedEvents.clear(); + } + log.debug("Processing debounced events: {}", eventsToProcess); + AsyncFileListener.ChangeApplier applier = delegate.prepareChange(eventsToProcess); + if (applier != null) { + applier.afterVfsChange(); + } + }, + debounceDelayMillis); + } + + @Override + public void dispose() { + synchronized (lock) { + if (isDisposed) { + return; + } + isDisposed = true; + } + alarm.cancelAllRequests(); + alarm.dispose(); + } +} diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java index 02dac869..60072bc6 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java @@ -16,8 +16,8 @@ package com.palantir.gradle.versions.intellij; -import com.google.common.collect.MapMaker; import com.intellij.execution.executors.DefaultRunExecutor; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ComponentManager; import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder; import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings; @@ -26,6 +26,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.AsyncFileListener; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent; @@ -38,10 +39,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.util.GradleConstants; @@ -52,14 +49,6 @@ public final class VersionPropsFileListener implements AsyncFileListener { private static final Logger log = LoggerFactory.getLogger(VersionPropsFileListener.class); private static final String TASK_NAME = "writeVersionsLock"; - // Shared state to track changes per project - private final ConcurrentMap projectChangeMap = - new MapMaker().weakKeys().makeMap(); - - // Executor for debouncing - private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); - private static final long DEBOUNCE_DELAY_MS = 350; - @Nullable @Override public ChangeApplier prepareChange(List events) { @@ -75,77 +64,41 @@ public ChangeApplier prepareChange(List events) { .filter(event -> "versions.lock".equals(event.getFile().getName())) .toList(); - if (versionPropsEvents.isEmpty() && versionLockEvents.isEmpty()) { + if (versionPropsEvents.isEmpty()) { return null; } - List allOpenProjects = Arrays.stream( + List projectsAffected = Arrays.stream( ProjectManager.getInstance().getOpenProjects()) .filter(Project::isInitialized) .filter(Predicate.not(ComponentManager::isDisposed)) + .filter(project -> project.getBasePath() != null) + .filter(project -> versionPropsEvents.stream() + .anyMatch(event -> event.getPath().startsWith(project.getBasePath()) + && !isFileMalformed(project, event.getFile()))) + .filter(project -> versionLockEvents.stream() + .noneMatch(event -> event.getPath().startsWith(project.getBasePath()))) .toList(); - // Update the shared state based on current events - allOpenProjects.forEach(project -> { - String basePath = project.getBasePath(); - boolean hasPropsChange = versionPropsEvents.stream() - .anyMatch(event -> - event.getPath().startsWith(basePath) && !isFileMalformed(project, event.getFile())); - boolean hasLockChange = - versionLockEvents.stream().anyMatch(event -> event.getPath().startsWith(basePath)); - - if (hasPropsChange || hasLockChange) { - projectChangeMap.compute(project, (proj, flags) -> { - if (flags == null) { - return ChangeFlags.of(hasPropsChange, hasLockChange); - } else { - return ChangeFlags.of( - flags.hasPropsChange() || hasPropsChange, flags.hasLockChange() || hasLockChange); - } - }); - } - }); - return new ChangeApplier() { @Override public void afterVfsChange() { - // Schedule processing after VFS changes have been applied - projectChangeMap.keySet().forEach(project -> { - scheduler.schedule(() -> processChanges(project), DEBOUNCE_DELAY_MS, TimeUnit.MILLISECONDS); + projectsAffected.forEach(project -> { + VersionPropsProjectSettings settings = VersionPropsProjectSettings.getInstance(project); + if (!settings.isEnabled()) { + return; + } + + if (hasBuildSrc(project)) { + runTaskThenRefresh(project); + } else { + refreshProjectWithTask(project); + } }); } }; } - private void processChanges(Project project) { - ChangeFlags flags = projectChangeMap.remove(project); - if (flags == null) { - return; - } - - if (flags.hasPropsChange && flags.hasLockChange) { - // Both changes detected; do not process - log.debug( - "Project {} has both versions.props and versions.lock changes. Skipping processing.", - project.getName()); - return; - } - - if (flags.hasPropsChange) { - // Only props changed; process the project - VersionPropsProjectSettings settings = VersionPropsProjectSettings.getInstance(project); - if (!settings.isEnabled()) { - return; - } - - if (hasBuildSrc(project)) { - runTaskThenRefresh(project); - } else { - refreshProjectWithTask(project); - } - } - } - private boolean hasBuildSrc(Project project) { return Files.exists(Paths.get(project.getBasePath(), "buildSrc")); } @@ -196,18 +149,14 @@ private void refreshProject(Project project, ImportSpecBuilder importSpec) { } private static boolean isFileMalformed(Project project, VirtualFile file) { - PsiFile psiFile = PsiManager.getInstance(project).findFile(file); - - if (psiFile == null || !(psiFile.getFileType() instanceof VersionPropsFileType)) { - return true; - } + return ApplicationManager.getApplication().runReadAction((Computable) () -> { + PsiFile psiFile = PsiManager.getInstance(project).findFile(file); - return PsiTreeUtil.hasErrorElements(psiFile); - } + if (psiFile == null || !(psiFile.getFileType() instanceof VersionPropsFileType)) { + return true; + } - private record ChangeFlags(boolean hasPropsChange, boolean hasLockChange) { - public static ChangeFlags of(boolean hasPropsChange, boolean hasLockChange) { - return new ChangeFlags(hasPropsChange, hasLockChange); - } + return PsiTreeUtil.hasErrorElements(psiFile); + }); } } diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java new file mode 100644 index 00000000..69550658 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java @@ -0,0 +1,32 @@ +/* + * (c) Copyright 2024 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.gradle.versions.intellij; + +import com.intellij.ide.AppLifecycleListener; +import com.intellij.openapi.vfs.AsyncFileListener; +import com.intellij.openapi.vfs.VirtualFileManager; +import java.util.List; + +public final class VersionPropsListenerRegistrar implements AppLifecycleListener { + + @Override + public void appFrameCreated(List commandLineArgs) { + AsyncFileListener versionPropsListener = new VersionPropsFileListener(); + DebouncingAsyncFileListener debouncedListener = new DebouncingAsyncFileListener(versionPropsListener, 500); + VirtualFileManager.getInstance().addAsyncFileListener(debouncedListener, debouncedListener); + } +} diff --git a/gradle-consistent-versions-idea-plugin/src/main/resources/META-INF/plugin.xml b/gradle-consistent-versions-idea-plugin/src/main/resources/META-INF/plugin.xml index 2e0331fe..5f712220 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/resources/META-INF/plugin.xml +++ b/gradle-consistent-versions-idea-plugin/src/main/resources/META-INF/plugin.xml @@ -50,9 +50,15 @@ - + + + + From 82069e240d2978361f750b0ec1c13f70dd35fc68 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Tue, 5 Nov 2024 13:20:53 +0000 Subject: [PATCH 07/16] use file listener to register --- .../intellij/DebouncingAsyncFileListener.java | 2 +- .../VersionPropsListenerRegistrar.java | 20 ++++++++++++------- .../src/main/resources/META-INF/plugin.xml | 8 +------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java index e4b2cb79..4f215cfb 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java @@ -37,7 +37,7 @@ public final class DebouncingAsyncFileListener implements AsyncFileListener, Dis private final List bufferedEvents = new ArrayList<>(); private boolean isDisposed = false; - public DebouncingAsyncFileListener(AsyncFileListener delegate, long debounceDelayMillis) { + DebouncingAsyncFileListener(AsyncFileListener delegate, long debounceDelayMillis) { this.delegate = delegate; this.debounceDelayMillis = debounceDelayMillis; this.alarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, this); diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java index 69550658..129f240a 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java @@ -16,17 +16,23 @@ package com.palantir.gradle.versions.intellij; -import com.intellij.ide.AppLifecycleListener; import com.intellij.openapi.vfs.AsyncFileListener; -import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import java.util.List; +import org.jetbrains.annotations.Nullable; -public final class VersionPropsListenerRegistrar implements AppLifecycleListener { +public final class VersionPropsListenerRegistrar implements AsyncFileListener { - @Override - public void appFrameCreated(List commandLineArgs) { + private final DebouncingAsyncFileListener debouncedListener; + + VersionPropsListenerRegistrar() { AsyncFileListener versionPropsListener = new VersionPropsFileListener(); - DebouncingAsyncFileListener debouncedListener = new DebouncingAsyncFileListener(versionPropsListener, 500); - VirtualFileManager.getInstance().addAsyncFileListener(debouncedListener, debouncedListener); + debouncedListener = new DebouncingAsyncFileListener(versionPropsListener, 100); + } + + @Nullable + @Override + public ChangeApplier prepareChange(List events) { + return debouncedListener.prepareChange(events); } } diff --git a/gradle-consistent-versions-idea-plugin/src/main/resources/META-INF/plugin.xml b/gradle-consistent-versions-idea-plugin/src/main/resources/META-INF/plugin.xml index 5f712220..96cf6628 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/resources/META-INF/plugin.xml +++ b/gradle-consistent-versions-idea-plugin/src/main/resources/META-INF/plugin.xml @@ -50,15 +50,9 @@ + - - - - From 702343aee58eaf94db379a60f52494ca1c9c5407 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 11 Nov 2024 11:04:59 +0000 Subject: [PATCH 08/16] use single alarm --- .../intellij/DebouncingAsyncFileListener.java | 50 ++++++++----------- .../VersionPropsListenerRegistrar.java | 2 +- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java index 4f215cfb..096ccf1c 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java @@ -20,6 +20,7 @@ import com.intellij.openapi.vfs.AsyncFileListener; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.Alarm; +import com.intellij.util.SingleAlarm; import java.util.ArrayList; import java.util.List; import org.jetbrains.annotations.Nullable; @@ -30,17 +31,16 @@ public final class DebouncingAsyncFileListener implements AsyncFileListener, Dis private static final Logger log = LoggerFactory.getLogger(DebouncingAsyncFileListener.class); private final AsyncFileListener delegate; - private final long debounceDelayMillis; - private final Alarm alarm; + private final SingleAlarm alarm; private final Object lock = new Object(); private final List bufferedEvents = new ArrayList<>(); private boolean isDisposed = false; - DebouncingAsyncFileListener(AsyncFileListener delegate, long debounceDelayMillis) { + DebouncingAsyncFileListener(AsyncFileListener delegate, int debounceDelayMillis) { this.delegate = delegate; - this.debounceDelayMillis = debounceDelayMillis; - this.alarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, this); + this.alarm = + new SingleAlarm(this::processEvents, debounceDelayMillis, this, Alarm.ThreadToUse.POOLED_THREAD); } @Nullable @@ -52,30 +52,25 @@ public ChangeApplier prepareChange(List events) { } log.debug("Received events: {}", events); bufferedEvents.addAll(events); - scheduleDelegateInvocation(); + alarm.request(); } return null; } - private void scheduleDelegateInvocation() { - alarm.cancelAllRequests(); - alarm.addRequest( - () -> { - List eventsToProcess; - synchronized (lock) { - if (isDisposed) { - return; - } - eventsToProcess = new ArrayList<>(bufferedEvents); - bufferedEvents.clear(); - } - log.debug("Processing debounced events: {}", eventsToProcess); - AsyncFileListener.ChangeApplier applier = delegate.prepareChange(eventsToProcess); - if (applier != null) { - applier.afterVfsChange(); - } - }, - debounceDelayMillis); + private void processEvents() { + List eventsToProcess; + synchronized (lock) { + if (isDisposed) { + return; + } + eventsToProcess = new ArrayList<>(bufferedEvents); + bufferedEvents.clear(); + } + log.debug("Processing debounced events: {}", eventsToProcess); + AsyncFileListener.ChangeApplier applier = delegate.prepareChange(eventsToProcess); + if (applier != null) { + applier.afterVfsChange(); + } } @Override @@ -85,8 +80,7 @@ public void dispose() { return; } isDisposed = true; + alarm.cancelAllRequests(); } - alarm.cancelAllRequests(); - alarm.dispose(); } -} +} \ No newline at end of file diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java index 129f240a..79394b57 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java @@ -27,7 +27,7 @@ public final class VersionPropsListenerRegistrar implements AsyncFileListener { VersionPropsListenerRegistrar() { AsyncFileListener versionPropsListener = new VersionPropsFileListener(); - debouncedListener = new DebouncingAsyncFileListener(versionPropsListener, 100); + debouncedListener = new DebouncingAsyncFileListener(versionPropsListener, 250); } @Nullable From ea0c0907cade22bc9f8302cf4747357d017294e4 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 11 Nov 2024 11:10:14 +0000 Subject: [PATCH 09/16] end with new line --- .../gradle/versions/intellij/DebouncingAsyncFileListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java index 096ccf1c..262e3b3d 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java @@ -83,4 +83,4 @@ public void dispose() { alarm.cancelAllRequests(); } } -} \ No newline at end of file +} From ad5464d752bf313d62bb3755019ea8b7ed3d0322 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 11 Nov 2024 11:11:49 +0000 Subject: [PATCH 10/16] spotless --- .../gradle/versions/intellij/DebouncingAsyncFileListener.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java index 262e3b3d..4d648cb8 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java @@ -39,8 +39,7 @@ public final class DebouncingAsyncFileListener implements AsyncFileListener, Dis DebouncingAsyncFileListener(AsyncFileListener delegate, int debounceDelayMillis) { this.delegate = delegate; - this.alarm = - new SingleAlarm(this::processEvents, debounceDelayMillis, this, Alarm.ThreadToUse.POOLED_THREAD); + this.alarm = new SingleAlarm(this::processEvents, debounceDelayMillis, this, Alarm.ThreadToUse.POOLED_THREAD); } @Nullable From b480ec68e365c21d4469b65f42e0aca1a7dbf978 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 11 Nov 2024 13:31:59 +0000 Subject: [PATCH 11/16] one line use this --- .../versions/intellij/VersionPropsListenerRegistrar.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java index 79394b57..600e0f07 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java @@ -26,8 +26,7 @@ public final class VersionPropsListenerRegistrar implements AsyncFileListener { private final DebouncingAsyncFileListener debouncedListener; VersionPropsListenerRegistrar() { - AsyncFileListener versionPropsListener = new VersionPropsFileListener(); - debouncedListener = new DebouncingAsyncFileListener(versionPropsListener, 250); + this.debouncedListener = new DebouncingAsyncFileListener(new VersionPropsFileListener(), 250); } @Nullable From d72c3ce3b653040d4f89e204136ec10c00abeb24 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 11 Nov 2024 14:10:59 +0000 Subject: [PATCH 12/16] disposal --- .../intellij/DebouncingAsyncFileListener.java | 25 +++---------------- .../VersionPropsListenerRegistrar.java | 8 ++++-- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java index 4d648cb8..44b8e0cb 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java @@ -27,7 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public final class DebouncingAsyncFileListener implements AsyncFileListener, Disposable { +public final class DebouncingAsyncFileListener implements AsyncFileListener { private static final Logger log = LoggerFactory.getLogger(DebouncingAsyncFileListener.class); private final AsyncFileListener delegate; @@ -35,20 +35,17 @@ public final class DebouncingAsyncFileListener implements AsyncFileListener, Dis private final Object lock = new Object(); private final List bufferedEvents = new ArrayList<>(); - private boolean isDisposed = false; - DebouncingAsyncFileListener(AsyncFileListener delegate, int debounceDelayMillis) { + DebouncingAsyncFileListener(AsyncFileListener delegate, int debounceDelayMillis, Disposable parentDisposable) { this.delegate = delegate; - this.alarm = new SingleAlarm(this::processEvents, debounceDelayMillis, this, Alarm.ThreadToUse.POOLED_THREAD); + this.alarm = new SingleAlarm( + this::processEvents, debounceDelayMillis, parentDisposable, Alarm.ThreadToUse.POOLED_THREAD); } @Nullable @Override public ChangeApplier prepareChange(List events) { synchronized (lock) { - if (isDisposed) { - return null; - } log.debug("Received events: {}", events); bufferedEvents.addAll(events); alarm.request(); @@ -59,9 +56,6 @@ public ChangeApplier prepareChange(List events) { private void processEvents() { List eventsToProcess; synchronized (lock) { - if (isDisposed) { - return; - } eventsToProcess = new ArrayList<>(bufferedEvents); bufferedEvents.clear(); } @@ -71,15 +65,4 @@ private void processEvents() { applier.afterVfsChange(); } } - - @Override - public void dispose() { - synchronized (lock) { - if (isDisposed) { - return; - } - isDisposed = true; - alarm.cancelAllRequests(); - } - } } diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java index 600e0f07..6ea53a7f 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java @@ -16,17 +16,18 @@ package com.palantir.gradle.versions.intellij; +import com.intellij.openapi.Disposable; import com.intellij.openapi.vfs.AsyncFileListener; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import java.util.List; import org.jetbrains.annotations.Nullable; -public final class VersionPropsListenerRegistrar implements AsyncFileListener { +public final class VersionPropsListenerRegistrar implements AsyncFileListener, Disposable { private final DebouncingAsyncFileListener debouncedListener; VersionPropsListenerRegistrar() { - this.debouncedListener = new DebouncingAsyncFileListener(new VersionPropsFileListener(), 250); + this.debouncedListener = new DebouncingAsyncFileListener(new VersionPropsFileListener(), 250, this); } @Nullable @@ -34,4 +35,7 @@ public final class VersionPropsListenerRegistrar implements AsyncFileListener { public ChangeApplier prepareChange(List events) { return debouncedListener.prepareChange(events); } + + @Override + public void dispose() {} } From 7164347d95ed5c1cf77cbde3f4fab31fa3e23563 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 11 Nov 2024 14:22:00 +0000 Subject: [PATCH 13/16] use LinkedBlockingQueue --- .../intellij/DebouncingAsyncFileListener.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java index 44b8e0cb..1d489423 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java @@ -23,6 +23,7 @@ import com.intellij.util.SingleAlarm; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,9 +33,7 @@ public final class DebouncingAsyncFileListener implements AsyncFileListener { private final AsyncFileListener delegate; private final SingleAlarm alarm; - private final Object lock = new Object(); - - private final List bufferedEvents = new ArrayList<>(); + private final LinkedBlockingQueue bufferedEvents = new LinkedBlockingQueue<>(); DebouncingAsyncFileListener(AsyncFileListener delegate, int debounceDelayMillis, Disposable parentDisposable) { this.delegate = delegate; @@ -45,20 +44,19 @@ public final class DebouncingAsyncFileListener implements AsyncFileListener { @Nullable @Override public ChangeApplier prepareChange(List events) { - synchronized (lock) { - log.debug("Received events: {}", events); - bufferedEvents.addAll(events); - alarm.request(); - } + log.debug("Received events: {}", events); + bufferedEvents.addAll(events); + alarm.request(); return null; } private void processEvents() { - List eventsToProcess; - synchronized (lock) { - eventsToProcess = new ArrayList<>(bufferedEvents); - bufferedEvents.clear(); + List eventsToProcess = new ArrayList<>(); + int drained = bufferedEvents.drainTo(eventsToProcess); + if (drained == 0) { + return; } + log.debug("Processing debounced events: {}", eventsToProcess); AsyncFileListener.ChangeApplier applier = delegate.prepareChange(eventsToProcess); if (applier != null) { From c6c340f0a81ab8e34db92185370672b3e5ab4454 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 11 Nov 2024 14:41:49 +0000 Subject: [PATCH 14/16] filtering listener --- .../intellij/FilteringAsyncFileListener.java | 55 +++++++++++++++++++ .../VersionPropsListenerRegistrar.java | 15 ++++- 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/FilteringAsyncFileListener.java diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/FilteringAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/FilteringAsyncFileListener.java new file mode 100644 index 00000000..55589a71 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/FilteringAsyncFileListener.java @@ -0,0 +1,55 @@ +/* + * (c) Copyright 2024 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.gradle.versions.intellij; + +import com.intellij.openapi.vfs.AsyncFileListener; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import java.util.List; +import java.util.function.Predicate; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FilteringAsyncFileListener implements AsyncFileListener { + private static final Logger log = LoggerFactory.getLogger(FilteringAsyncFileListener.class); + + private final AsyncFileListener delegate; + private final Predicate filter; + + FilteringAsyncFileListener(AsyncFileListener delegate, Predicate filter) { + this.delegate = delegate; + this.filter = filter; + } + + @Nullable + @Override + public final ChangeApplier prepareChange(List events) { + List filteredEvents = events.stream() + .filter(event -> { + VirtualFile file = event.getFile(); + return file != null && filter.test(file); + }) + .toList(); + + if (filteredEvents.isEmpty()) { + return null; + } + + return delegate.prepareChange(filteredEvents); + } +} diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java index 6ea53a7f..19404525 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java @@ -18,22 +18,31 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.vfs.AsyncFileListener; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import java.util.List; +import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; public final class VersionPropsListenerRegistrar implements AsyncFileListener, Disposable { - private final DebouncingAsyncFileListener debouncedListener; + private final FilteringAsyncFileListener changeListener; VersionPropsListenerRegistrar() { - this.debouncedListener = new DebouncingAsyncFileListener(new VersionPropsFileListener(), 250, this); + + Predicate filter = virtualFile -> { + String fileName = virtualFile.getName(); + return "versions.props".equals(fileName) || "versions.lock".equals(fileName); + }; + + this.changeListener = new FilteringAsyncFileListener( + new DebouncingAsyncFileListener(new VersionPropsFileListener(), 250, this), filter); } @Nullable @Override public ChangeApplier prepareChange(List events) { - return debouncedListener.prepareChange(events); + return changeListener.prepareChange(events); } @Override From b45c1b996794a1779cf0b89d372fc48986bd066a Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 11 Nov 2024 14:48:50 +0000 Subject: [PATCH 15/16] log message --- .../gradle/versions/intellij/FilteringAsyncFileListener.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/FilteringAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/FilteringAsyncFileListener.java index 55589a71..fb7425f7 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/FilteringAsyncFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/FilteringAsyncFileListener.java @@ -46,6 +46,8 @@ public final ChangeApplier prepareChange(List events) { }) .toList(); + log.debug("Events after filtering {}", filteredEvents); + if (filteredEvents.isEmpty()) { return null; } From bd81414d2bc4b410b6473a8782559f1013fcc67c Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Tue, 12 Nov 2024 14:34:19 +0000 Subject: [PATCH 16/16] markups --- .../intellij/DebouncingAsyncFileListener.java | 3 ++- .../intellij/VersionPropsListenerRegistrar.java | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java index 1d489423..192dcdf5 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/DebouncingAsyncFileListener.java @@ -23,6 +23,7 @@ import com.intellij.util.SingleAlarm; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -33,7 +34,7 @@ public final class DebouncingAsyncFileListener implements AsyncFileListener { private final AsyncFileListener delegate; private final SingleAlarm alarm; - private final LinkedBlockingQueue bufferedEvents = new LinkedBlockingQueue<>(); + private final BlockingQueue bufferedEvents = new LinkedBlockingQueue<>(); DebouncingAsyncFileListener(AsyncFileListener delegate, int debounceDelayMillis, Disposable parentDisposable) { this.delegate = delegate; diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java index 19404525..d94f0b34 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsListenerRegistrar.java @@ -21,7 +21,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import java.util.List; -import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; public final class VersionPropsListenerRegistrar implements AsyncFileListener, Disposable { @@ -29,14 +28,13 @@ public final class VersionPropsListenerRegistrar implements AsyncFileListener, D private final FilteringAsyncFileListener changeListener; VersionPropsListenerRegistrar() { - - Predicate filter = virtualFile -> { - String fileName = virtualFile.getName(); - return "versions.props".equals(fileName) || "versions.lock".equals(fileName); - }; - this.changeListener = new FilteringAsyncFileListener( - new DebouncingAsyncFileListener(new VersionPropsFileListener(), 250, this), filter); + new DebouncingAsyncFileListener(new VersionPropsFileListener(), 250, this), this::isRelevantFile); + } + + private boolean isRelevantFile(VirtualFile virtualFile) { + String fileName = virtualFile.getName(); + return "versions.props".equals(fileName) || "versions.lock".equals(fileName); } @Nullable