From 893ee257c52e17b9511dece2038f32a5bbdcc761 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Thu, 26 Sep 2024 14:19:48 +0100 Subject: [PATCH 01/18] actions --- .../versions/intellij/VersionPropsAction.java | 32 +++++++++++++++ .../intellij/VersionPropsFileListener.java | 1 + .../intellij/VersionPropsToolbar.java | 40 +++++++++++++++++++ .../src/main/resources/META-INF/plugin.xml | 11 ++++- 4 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java new file mode 100644 index 0000000..21f82f5 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.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.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; + +public class VersionPropsAction extends AnAction { + + public VersionPropsAction() { + super("Click me"); + } + + @Override + public void actionPerformed(AnActionEvent e) { + System.out.println("hello"); + } +} 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 d9fc505..3e7c444 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 @@ -47,6 +47,7 @@ public final class VersionPropsFileListener implements AsyncFileListener { private static final Logger log = LoggerFactory.getLogger(VersionPropsFileListener.class); private static final String TASK_NAME = "writeVersionsLock"; + @Nullable @Override public ChangeApplier prepareChange(List events) { diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java new file mode 100644 index 0000000..4a817a9 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java @@ -0,0 +1,40 @@ +/* + * (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.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarProvider; + +public class VersionPropsToolbar implements FloatingToolbarProvider { + + @Override + public boolean isApplicable(DataContext dataContext) { + return true; + } + + @Override + public ActionGroup getActionGroup() { + return (ActionGroup) ActionManager.getInstance().getAction("MyFloatingToolbarActionGroup"); + } + + @Override + public boolean getAutoHideable() { + return false; + } +} \ No newline at end of file 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 cea3497..9c1d8da 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 @@ -10,6 +10,13 @@ com.intellij.modules.platform org.jetbrains.plugins.gradle + + + + + + + @@ -21,6 +28,8 @@ - + + + \ No newline at end of file From 63ef409f63ea66b4be65a28fb8f6bb94b907e1ec Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Tue, 1 Oct 2024 09:28:04 +0100 Subject: [PATCH 02/18] move to develop --- .../versions/intellij/VersionPropsAction.java | 3 +- .../intellij/VersionPropsFileListener.java | 1 - .../intellij/VersionPropsToolbar.java | 41 ++++++++++++++----- .../src/main/resources/META-INF/plugin.xml | 9 ++-- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java index 21f82f5..ca48ba2 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java @@ -18,6 +18,7 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.ui.Messages; public class VersionPropsAction extends AnAction { @@ -27,6 +28,6 @@ public VersionPropsAction() { @Override public void actionPerformed(AnActionEvent e) { - System.out.println("hello"); + Messages.showMessageDialog("Hello", "Information", Messages.getInformationIcon()); } } 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 3e7c444..d9fc505 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 @@ -47,7 +47,6 @@ public final class VersionPropsFileListener implements AsyncFileListener { private static final Logger log = LoggerFactory.getLogger(VersionPropsFileListener.class); private static final String TASK_NAME = "writeVersionsLock"; - @Nullable @Override public ChangeApplier prepareChange(List events) { diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java index 4a817a9..057d7ec 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java @@ -16,25 +16,46 @@ package com.palantir.gradle.versions.intellij; -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarProvider; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.toolbar.floating.AbstractFloatingToolbarProvider; +import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import java.util.Optional; -public class VersionPropsToolbar implements FloatingToolbarProvider { +public class VersionPropsToolbar extends AbstractFloatingToolbarProvider { + private static final String FILE_NAME = "versions.props"; + + public VersionPropsToolbar() { + super("VersionPropsActionGroup"); + } @Override - public boolean isApplicable(DataContext dataContext) { - return true; + public boolean getAutoHideable() { + return false; } @Override - public ActionGroup getActionGroup() { - return (ActionGroup) ActionManager.getInstance().getAction("MyFloatingToolbarActionGroup"); + public void register(DataContext dataContext, FloatingToolbarComponent component, Disposable parentDisposable) { + // look at + // https://github.com/yunyizhi/clion-platformio-plus/blob/18cab368c63f516a9b12af00450d4f28cbd07b13/src/main/java/org/btik/platformioplus/ini/reload/PlatformioIniFloatingToolbarProvider.java + super.register(dataContext, component, parentDisposable); + + Project project = dataContext.getData(CommonDataKeys.PROJECT); + if (project == null) { + return; + } } @Override - public boolean getAutoHideable() { - return false; + public boolean isApplicable(DataContext dataContext) { + return Optional.ofNullable(dataContext.getData(CommonDataKeys.EDITOR)) + .map(Editor::getVirtualFile) + .map(VirtualFile::getName) + .map(FILE_NAME::equals) + .orElse(false); } } \ No newline at end of file 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 9c1d8da..127dfc8 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 @@ -11,9 +11,8 @@ org.jetbrains.plugins.gradle - - - + + @@ -28,8 +27,8 @@ - - + + \ No newline at end of file From 570c0c63252092038b859e12f7a4d999a30f466e Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Tue, 1 Oct 2024 11:08:07 +0100 Subject: [PATCH 03/18] tracks changes but ugly --- .../versions/intellij/VersionPropsAction.java | 13 ++ .../intellij/VersionPropsToolbar.java | 115 +++++++++++++++--- 2 files changed, 109 insertions(+), 19 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java index ca48ba2..62c1701 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java @@ -18,7 +18,11 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vfs.VirtualFile; public class VersionPropsAction extends AnAction { @@ -29,5 +33,14 @@ public VersionPropsAction() { @Override public void actionPerformed(AnActionEvent e) { Messages.showMessageDialog("Hello", "Information", Messages.getInformationIcon()); + + DataContext dataContext = e.getDataContext(); + Editor editor = dataContext.getData(CommonDataKeys.EDITOR); + if (editor != null) { + VirtualFile file = editor.getVirtualFile(); + if (file != null) { + VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath()); + } + } } } diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java index 057d7ec..181a8ca 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java @@ -1,36 +1,44 @@ -/* - * (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.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.editor.toolbar.floating.AbstractFloatingToolbarProvider; import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent; +import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.messages.MessageBusConnection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Optional; +import java.util.Set; +import org.jetbrains.annotations.NotNull; public class VersionPropsToolbar extends AbstractFloatingToolbarProvider { + private static VersionPropsToolbar instance; + private MessageBusConnection projectBusConnection; + private final Map filesToolbarComponents; + private final Set changedFiles; + private final Map originalContent; + private static final String FILE_NAME = "versions.props"; public VersionPropsToolbar() { super("VersionPropsActionGroup"); + filesToolbarComponents = new HashMap<>(); + changedFiles = new HashSet<>(); + originalContent = new HashMap<>(); + instance = this; + } + + public static VersionPropsToolbar getInstance() { + return instance; } @Override @@ -40,14 +48,76 @@ public boolean getAutoHideable() { @Override public void register(DataContext dataContext, FloatingToolbarComponent component, Disposable parentDisposable) { - // look at - // https://github.com/yunyizhi/clion-platformio-plus/blob/18cab368c63f516a9b12af00450d4f28cbd07b13/src/main/java/org/btik/platformioplus/ini/reload/PlatformioIniFloatingToolbarProvider.java super.register(dataContext, component, parentDisposable); - Project project = dataContext.getData(CommonDataKeys.PROJECT); + FileEditor fileEditor = dataContext.getData(PlatformDataKeys.FILE_EDITOR); + if (fileEditor == null || fileEditor.getFile() == null) { + return; + } + + Project project = dataContext.getData(PlatformDataKeys.PROJECT); if (project == null) { return; } + + if (projectBusConnection == null) { + projectBusConnection = project.getMessageBus().connect(); + registerOnChangeHandlers(dataContext, fileEditor, parentDisposable); + } + + filesToolbarComponents.put(fileEditor.getFile().getPath(), component); + if (changedFiles.contains(fileEditor.getFile().getPath())) { + component.scheduleShow(); + } + } + + private void registerOnChangeHandlers(DataContext dataContext, FileEditor fileEditor, Disposable parentDisposable) { + Editor editor = dataContext.getData(CommonDataKeys.EDITOR); + if (editor != null) { + VirtualFile file = fileEditor.getFile(); + if (file != null) { + originalContent.put(file.getPath(), editor.getDocument().getText()); + } + editor.getDocument() + .addDocumentListener( + new DocumentListener() { + @Override + public void beforeDocumentChange(@NotNull DocumentEvent event) { + // No action needed before the document change + } + + @Override + public void documentChanged(@NotNull DocumentEvent event) { + VirtualFile file = fileEditor.getFile(); + if (file != null && FILE_NAME.equals(file.getName())) { + String currentContent = + editor.getDocument().getText(); + if (!originalContent.get(file.getPath()).equals(currentContent)) { + updateFileChanged(file.getPath()); + } else { + updateFileUnchanged(file.getPath()); + } + } + } + }, + parentDisposable); + } + } + + private void updateFileChanged(String filePath) { + changedFiles.add(filePath); + FloatingToolbarComponent jfrogToolBar = filesToolbarComponents.get(filePath); + if (jfrogToolBar != null) { + jfrogToolBar.scheduleShow(); + } + } + + private void updateFileUnchanged(String filePath) { + changedFiles.remove(filePath); + FloatingToolbarComponent jfrogToolBar = filesToolbarComponents.get(filePath); + if (jfrogToolBar != null) { + jfrogToolBar.scheduleHide(); + } } @Override @@ -58,4 +128,11 @@ public boolean isApplicable(DataContext dataContext) { .map(FILE_NAME::equals) .orElse(false); } + + public void hideToolbarForFile(String filePath) { + FloatingToolbarComponent toolbarComponent = filesToolbarComponents.get(filePath); + if (toolbarComponent != null) { + toolbarComponent.scheduleHide(); + } + } } \ No newline at end of file From b9d413a6719db18aed348a6a94403c8350a6ca01 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Tue, 1 Oct 2024 12:26:25 +0100 Subject: [PATCH 04/18] working cleaner --- .../versions/intellij/VersionPropsAction.java | 9 +- .../VersionPropsDocumentListener.java | 67 +++++++++++ .../intellij/VersionPropsToolbar.java | 108 +++++------------- versions.props | 2 +- 4 files changed, 104 insertions(+), 82 deletions(-) create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java index 62c1701..8f32a7b 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; @@ -36,11 +37,13 @@ public void actionPerformed(AnActionEvent e) { DataContext dataContext = e.getDataContext(); Editor editor = dataContext.getData(CommonDataKeys.EDITOR); - if (editor != null) { + Project project = e.getProject(); + + if (editor != null && project != null) { VirtualFile file = editor.getVirtualFile(); if (file != null) { - VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath()); + VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath(), project, dataContext); } } } -} +} \ No newline at end of file diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java new file mode 100644 index 0000000..2c4bc25 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java @@ -0,0 +1,67 @@ +package com.palantir.gradle.versions.intellij; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.event.DocumentListener; +import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.vfs.VirtualFile; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.jetbrains.annotations.NotNull; + +public class VersionPropsDocumentListener implements DocumentListener { + private final FileEditor fileEditor; + private final Editor editor; + private final Map originalContent; + private final Set changedFiles = new HashSet<>(); + private final Map filesToolbarComponents; + private static final String FILE_NAME = "versions.props"; + + public VersionPropsDocumentListener( + FileEditor fileEditor, + Editor editor, + Map originalContent, + Map filesToolbarComponents) { + this.fileEditor = fileEditor; + this.editor = editor; + this.originalContent = originalContent; + this.filesToolbarComponents = filesToolbarComponents; + } + + @Override + public void beforeDocumentChange(@NotNull DocumentEvent event) { + // No action needed before the document change + } + + @Override + public void documentChanged(@NotNull DocumentEvent event) { + VirtualFile file = fileEditor.getFile(); + if (file != null && FILE_NAME.equals(file.getName())) { + String currentContent = editor.getDocument().getText(); + + if (!originalContent.get(file.getPath()).equals(currentContent)) { + updateFileChanged(file.getPath()); + } else { + updateFileUnchanged(file.getPath()); + } + } + } + + private void updateFileChanged(String filePath) { + changedFiles.add(filePath); + FloatingToolbarComponent toolbarComponent = filesToolbarComponents.get(filePath); + if (toolbarComponent != null) { + toolbarComponent.scheduleShow(); + } + } + + private void updateFileUnchanged(String filePath) { + changedFiles.remove(filePath); + FloatingToolbarComponent toolbarComponent = filesToolbarComponents.get(filePath); + if (toolbarComponent != null) { + toolbarComponent.scheduleHide(); + } + } +} \ No newline at end of file diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java index 181a8ca..e3da427 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java @@ -5,35 +5,21 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.editor.toolbar.floating.AbstractFloatingToolbarProvider; import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.messages.MessageBusConnection; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Optional; -import java.util.Set; -import org.jetbrains.annotations.NotNull; public class VersionPropsToolbar extends AbstractFloatingToolbarProvider { private static VersionPropsToolbar instance; - private MessageBusConnection projectBusConnection; - private final Map filesToolbarComponents; - private final Set changedFiles; - private final Map originalContent; - - private static final String FILE_NAME = "versions.props"; + private final Map> projectFilesToolbarComponents = new HashMap<>(); + private final Map> projectOriginalContent = new HashMap<>(); public VersionPropsToolbar() { super("VersionPropsActionGroup"); - filesToolbarComponents = new HashMap<>(); - changedFiles = new HashSet<>(); - originalContent = new HashMap<>(); instance = this; } @@ -51,88 +37,54 @@ public void register(DataContext dataContext, FloatingToolbarComponent component super.register(dataContext, component, parentDisposable); FileEditor fileEditor = dataContext.getData(PlatformDataKeys.FILE_EDITOR); - if (fileEditor == null || fileEditor.getFile() == null) { - return; - } - Project project = dataContext.getData(PlatformDataKeys.PROJECT); - if (project == null) { + + if (fileEditor == null || fileEditor.getFile() == null || project == null) { return; } - if (projectBusConnection == null) { - projectBusConnection = project.getMessageBus().connect(); - registerOnChangeHandlers(dataContext, fileEditor, parentDisposable); - } + projectFilesToolbarComponents.computeIfAbsent(project, k -> new HashMap<>()); + projectOriginalContent.computeIfAbsent(project, k -> new HashMap<>()); - filesToolbarComponents.put(fileEditor.getFile().getPath(), component); - if (changedFiles.contains(fileEditor.getFile().getPath())) { - component.scheduleShow(); - } + registerOnChangeHandlers(dataContext, fileEditor, parentDisposable, project); + + projectFilesToolbarComponents.get(project).put(fileEditor.getFile().getPath(), component); } - private void registerOnChangeHandlers(DataContext dataContext, FileEditor fileEditor, Disposable parentDisposable) { + private void registerOnChangeHandlers( + DataContext dataContext, FileEditor fileEditor, Disposable parentDisposable, Project project) { Editor editor = dataContext.getData(CommonDataKeys.EDITOR); if (editor != null) { VirtualFile file = fileEditor.getFile(); if (file != null) { - originalContent.put(file.getPath(), editor.getDocument().getText()); + projectOriginalContent + .get(project) + .put(file.getPath(), editor.getDocument().getText()); } editor.getDocument() .addDocumentListener( - new DocumentListener() { - @Override - public void beforeDocumentChange(@NotNull DocumentEvent event) { - // No action needed before the document change - } - - @Override - public void documentChanged(@NotNull DocumentEvent event) { - VirtualFile file = fileEditor.getFile(); - if (file != null && FILE_NAME.equals(file.getName())) { - String currentContent = - editor.getDocument().getText(); - if (!originalContent.get(file.getPath()).equals(currentContent)) { - updateFileChanged(file.getPath()); - } else { - updateFileUnchanged(file.getPath()); - } - } - } - }, + new VersionPropsDocumentListener( + fileEditor, + editor, + projectOriginalContent.get(project), + projectFilesToolbarComponents.get(project)), parentDisposable); } } - private void updateFileChanged(String filePath) { - changedFiles.add(filePath); - FloatingToolbarComponent jfrogToolBar = filesToolbarComponents.get(filePath); - if (jfrogToolBar != null) { - jfrogToolBar.scheduleShow(); - } - } - - private void updateFileUnchanged(String filePath) { - changedFiles.remove(filePath); - FloatingToolbarComponent jfrogToolBar = filesToolbarComponents.get(filePath); - if (jfrogToolBar != null) { - jfrogToolBar.scheduleHide(); - } - } - - @Override - public boolean isApplicable(DataContext dataContext) { - return Optional.ofNullable(dataContext.getData(CommonDataKeys.EDITOR)) - .map(Editor::getVirtualFile) - .map(VirtualFile::getName) - .map(FILE_NAME::equals) - .orElse(false); - } - - public void hideToolbarForFile(String filePath) { - FloatingToolbarComponent toolbarComponent = filesToolbarComponents.get(filePath); + public final void hideToolbarForFile(String filePath, Project project, DataContext dataContext) { + FloatingToolbarComponent toolbarComponent = projectFilesToolbarComponents + .getOrDefault(project, new HashMap<>()) + .get(filePath); if (toolbarComponent != null) { toolbarComponent.scheduleHide(); } + + Editor editor = dataContext.getData(CommonDataKeys.EDITOR); + if (editor != null) { + projectOriginalContent + .get(project) + .put(filePath, editor.getDocument().getText()); + } } } \ No newline at end of file diff --git a/versions.props b/versions.props index d20ebb9..5c47aa4 100644 --- a/versions.props +++ b/versions.props @@ -9,4 +9,4 @@ com.github.ben-manes.caffeine:caffeine = 3.1.8 # Unnecessary once we have lock files com.google.code.findbugs:jsr305 = 3.0.2 -com.google.errorprone:error_prone_annotations = 2.11.0 +com.google.errorprone:error_prone_annotations = 2.11.0 \ No newline at end of file From ebb70702006b947a8b93f7f068c29b572c45ccaf Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Tue, 1 Oct 2024 14:02:43 +0100 Subject: [PATCH 05/18] tests --- .../build.gradle | 1 + ...tion.java => VersionPropsCloseAction.java} | 11 +- .../VersionPropsDocumentListener.java | 10 +- .../intellij/VersionPropsToolbar.java | 16 ++- ...ener.java => VersionPropsWriteAction.java} | 83 +++++---------- .../src/main/resources/META-INF/plugin.xml | 9 +- .../intellij/VersionPropsToolbarTest.java | 100 ++++++++++++++++++ versions.props | 1 + 8 files changed, 151 insertions(+), 80 deletions(-) rename gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/{VersionPropsAction.java => VersionPropsCloseAction.java} (83%) rename gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/{VersionPropsFileListener.java => VersionPropsWriteAction.java} (60%) create mode 100644 gradle-consistent-versions-idea-plugin/src/test/java/com/palantir/gradle/versions/intellij/VersionPropsToolbarTest.java diff --git a/gradle-consistent-versions-idea-plugin/build.gradle b/gradle-consistent-versions-idea-plugin/build.gradle index 916cd87..b08105e 100644 --- a/gradle-consistent-versions-idea-plugin/build.gradle +++ b/gradle-consistent-versions-idea-plugin/build.gradle @@ -30,6 +30,7 @@ dependencies { compileOnly 'org.immutables:value::annotations' testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.assertj:assertj-core' + testImplementation 'org.mockito:mockito-core' } grammarKit { diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java similarity index 83% rename from gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java rename to gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java index 8f32a7b..76d2116 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAction.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java @@ -22,19 +22,16 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; -public class VersionPropsAction extends AnAction { +public class VersionPropsCloseAction extends AnAction { - public VersionPropsAction() { - super("Click me"); + public VersionPropsCloseAction() { + super("Close"); } @Override public void actionPerformed(AnActionEvent e) { - Messages.showMessageDialog("Hello", "Information", Messages.getInformationIcon()); - DataContext dataContext = e.getDataContext(); Editor editor = dataContext.getData(CommonDataKeys.EDITOR); Project project = e.getProject(); @@ -42,7 +39,7 @@ public void actionPerformed(AnActionEvent e) { if (editor != null && project != null) { VirtualFile file = editor.getVirtualFile(); if (file != null) { - VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath(), project, dataContext); + VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath(), project, editor); } } } diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java index 2c4bc25..3c2f155 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java @@ -6,16 +6,12 @@ import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.vfs.VirtualFile; -import java.util.HashSet; import java.util.Map; -import java.util.Set; -import org.jetbrains.annotations.NotNull; public class VersionPropsDocumentListener implements DocumentListener { private final FileEditor fileEditor; private final Editor editor; private final Map originalContent; - private final Set changedFiles = new HashSet<>(); private final Map filesToolbarComponents; private static final String FILE_NAME = "versions.props"; @@ -31,12 +27,12 @@ public VersionPropsDocumentListener( } @Override - public void beforeDocumentChange(@NotNull DocumentEvent event) { + public void beforeDocumentChange(DocumentEvent event) { // No action needed before the document change } @Override - public void documentChanged(@NotNull DocumentEvent event) { + public void documentChanged(DocumentEvent event) { VirtualFile file = fileEditor.getFile(); if (file != null && FILE_NAME.equals(file.getName())) { String currentContent = editor.getDocument().getText(); @@ -50,7 +46,6 @@ public void documentChanged(@NotNull DocumentEvent event) { } private void updateFileChanged(String filePath) { - changedFiles.add(filePath); FloatingToolbarComponent toolbarComponent = filesToolbarComponents.get(filePath); if (toolbarComponent != null) { toolbarComponent.scheduleShow(); @@ -58,7 +53,6 @@ private void updateFileChanged(String filePath) { } private void updateFileUnchanged(String filePath) { - changedFiles.remove(filePath); FloatingToolbarComponent toolbarComponent = filesToolbarComponents.get(filePath); if (toolbarComponent != null) { toolbarComponent.scheduleHide(); diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java index e3da427..067c7b6 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java @@ -46,12 +46,12 @@ public void register(DataContext dataContext, FloatingToolbarComponent component projectFilesToolbarComponents.computeIfAbsent(project, k -> new HashMap<>()); projectOriginalContent.computeIfAbsent(project, k -> new HashMap<>()); - registerOnChangeHandlers(dataContext, fileEditor, parentDisposable, project); + registerDocumentListener(dataContext, fileEditor, parentDisposable, project); projectFilesToolbarComponents.get(project).put(fileEditor.getFile().getPath(), component); } - private void registerOnChangeHandlers( + private void registerDocumentListener( DataContext dataContext, FileEditor fileEditor, Disposable parentDisposable, Project project) { Editor editor = dataContext.getData(CommonDataKeys.EDITOR); if (editor != null) { @@ -72,7 +72,7 @@ private void registerOnChangeHandlers( } } - public final void hideToolbarForFile(String filePath, Project project, DataContext dataContext) { + public final void hideToolbarForFile(String filePath, Project project, Editor editor) { FloatingToolbarComponent toolbarComponent = projectFilesToolbarComponents .getOrDefault(project, new HashMap<>()) .get(filePath); @@ -80,11 +80,19 @@ public final void hideToolbarForFile(String filePath, Project project, DataConte toolbarComponent.scheduleHide(); } - Editor editor = dataContext.getData(CommonDataKeys.EDITOR); if (editor != null) { projectOriginalContent .get(project) .put(filePath, editor.getDocument().getText()); } } + + // getter methods used for tests + public final Map> getProjectFilesToolbarComponents() { + return projectFilesToolbarComponents; + } + + public final Map> getProjectOriginalContent() { + return projectOriginalContent; + } } \ No newline at end of file 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/VersionPropsWriteAction.java similarity index 60% rename from gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java rename to gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsWriteAction.java index d9fc505..53d0471 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/VersionPropsWriteAction.java @@ -17,70 +17,51 @@ package com.palantir.gradle.versions.intellij; import com.intellij.execution.executors.DefaultRunExecutor; -import com.intellij.openapi.components.ComponentManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder; import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings; import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; import com.intellij.openapi.externalSystem.task.TaskCallback; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.vfs.AsyncFileListener; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent; -import com.intellij.openapi.vfs.newvfs.events.VFileEvent; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; -import com.intellij.psi.util.PsiTreeUtil; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.Arrays; import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.util.GradleConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public final class VersionPropsFileListener implements AsyncFileListener { - private static final Logger log = LoggerFactory.getLogger(VersionPropsFileListener.class); +public class VersionPropsWriteAction extends AnAction { + private static final Logger log = LoggerFactory.getLogger(VersionPropsWriteAction.class); private static final String TASK_NAME = "writeVersionsLock"; - @Nullable - @Override - public ChangeApplier prepareChange(List events) { - List versionPropsEvents = events.stream() - .filter(event -> event instanceof VFileContentChangeEvent) - .map(event -> (VFileContentChangeEvent) event) - .filter(event -> "versions.props".equals(event.getFile().getName())) - .toList(); - - if (versionPropsEvents.isEmpty()) { - return null; - } + public VersionPropsWriteAction() { + super("Write Versions Lock"); + } - List projectsAffected = 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(); + @Override + public void actionPerformed(AnActionEvent e) { + DataContext dataContext = e.getDataContext(); + Editor editor = dataContext.getData(CommonDataKeys.EDITOR); + Project project = e.getProject(); + + if (editor != null && project != null) { + if (hasBuildSrc(project)) { + runTaskThenRefresh(project); + } else { + refreshProjectWithTask(project); + } - return new ChangeApplier() { - @Override - public void afterVfsChange() { - projectsAffected.forEach(project -> { - if (hasBuildSrc(project)) { - runTaskThenRefresh(project); - } else { - refreshProjectWithTask(project); - } - }); + VirtualFile file = editor.getVirtualFile(); + if (file != null) { + VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath(), project, editor); } - }; + } } private boolean hasBuildSrc(Project project) { @@ -131,14 +112,4 @@ private void refreshProject(Project project) { private void refreshProject(Project project, ImportSpecBuilder importSpec) { ExternalSystemUtil.refreshProject(project.getBasePath(), 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 PsiTreeUtil.hasErrorElements(psiFile); - } -} +} \ No newline at end of file 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 127dfc8..f0c0111 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 @@ -12,7 +12,8 @@ - + + @@ -23,12 +24,10 @@ + implementationClass="com.palantir.gradle.versions.intellij.VersionCompletionContributor"/> - - - + \ No newline at end of file diff --git a/gradle-consistent-versions-idea-plugin/src/test/java/com/palantir/gradle/versions/intellij/VersionPropsToolbarTest.java b/gradle-consistent-versions-idea-plugin/src/test/java/com/palantir/gradle/versions/intellij/VersionPropsToolbarTest.java new file mode 100644 index 0000000..8b61ee7 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/test/java/com/palantir/gradle/versions/intellij/VersionPropsToolbarTest.java @@ -0,0 +1,100 @@ +/* + * (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 static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class VersionPropsToolbarTest { + + @Test + public void testGetInstance() { + VersionPropsToolbar toolbar1 = new VersionPropsToolbar(); + VersionPropsToolbar toolbar2 = VersionPropsToolbar.getInstance(); + assertThat(toolbar1).isEqualTo(toolbar2); + } + + @Test + public void testGetAutoHideable() { + VersionPropsToolbar toolbar = new VersionPropsToolbar(); + assertThat(toolbar.getAutoHideable()).isFalse(); + } + + @Test + public void testRegister() { + VersionPropsToolbar toolbar = new VersionPropsToolbar(); + DataContext dataContext = mock(DataContext.class); + FloatingToolbarComponent component = mock(FloatingToolbarComponent.class); + Disposable parentDisposable = mock(Disposable.class); + FileEditor fileEditor = mock(FileEditor.class); + Project project = mock(Project.class); + VirtualFile virtualFile = mock(VirtualFile.class); + + when(dataContext.getData(PlatformDataKeys.FILE_EDITOR)).thenReturn(fileEditor); + when(dataContext.getData(PlatformDataKeys.PROJECT)).thenReturn(project); + when(fileEditor.getFile()).thenReturn(virtualFile); + when(virtualFile.getPath()).thenReturn("test-path"); + + toolbar.register(dataContext, component, parentDisposable); + + Map> projectFilesToolbarComponents = + toolbar.getProjectFilesToolbarComponents(); + assertThat(projectFilesToolbarComponents).containsKey(project); + assertThat(projectFilesToolbarComponents.get(project)).containsKey("test-path"); + } + + @Test + public void testHideToolbarForFile() { + VersionPropsToolbar toolbar = new VersionPropsToolbar(); + Project project = mock(Project.class); + Editor editor = mock(Editor.class); + Document document = mock(Document.class); + FloatingToolbarComponent component = mock(FloatingToolbarComponent.class); + + when(editor.getDocument()).thenReturn(document); + when(document.getText()).thenReturn("new"); + + Map fileToolbarMap = new HashMap<>(); + fileToolbarMap.put("test-path", component); + toolbar.getProjectFilesToolbarComponents().put(project, fileToolbarMap); + + Map fileContentMap = new HashMap<>(); + fileContentMap.put("test-path", "original"); + toolbar.getProjectOriginalContent().put(project, fileContentMap); + + toolbar.hideToolbarForFile("test-path", project, editor); + + Mockito.verify(component).scheduleHide(); + assertThat(toolbar.getProjectOriginalContent().get(project).get("test-path")) + .isEqualTo("new"); + } +} diff --git a/versions.props b/versions.props index 5c47aa4..1de03cf 100644 --- a/versions.props +++ b/versions.props @@ -6,6 +6,7 @@ org.immutables:value = 2.10.1 org.junit.jupiter:junit-jupiter = 5.11.1 org.jetbrains:annotations = 25.0.0 com.github.ben-manes.caffeine:caffeine = 3.1.8 +org.mockito:mockito-core = 5.14.1 # Unnecessary once we have lock files com.google.code.findbugs:jsr305 = 3.0.2 From f937288ff76e3244ab96fd7db8bfab278a1f0b60 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Wed, 2 Oct 2024 09:47:52 +0100 Subject: [PATCH 06/18] state management --- .../versions/intellij/VersionPropsCloseAction.java | 3 ++- .../gradle/versions/intellij/VersionPropsToolbar.java | 11 +++++------ .../versions/intellij/VersionPropsWriteAction.java | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java index 76d2116..359095f 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java @@ -23,6 +23,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import java.util.Optional; public class VersionPropsCloseAction extends AnAction { @@ -39,7 +40,7 @@ public void actionPerformed(AnActionEvent e) { if (editor != null && project != null) { VirtualFile file = editor.getVirtualFile(); if (file != null) { - VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath(), project, editor); + VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath(), project, Optional.empty()); } } } diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java index 067c7b6..3fb52a7 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java @@ -12,6 +12,7 @@ import com.intellij.openapi.vfs.VirtualFile; import java.util.HashMap; import java.util.Map; +import java.util.Optional; public class VersionPropsToolbar extends AbstractFloatingToolbarProvider { private static VersionPropsToolbar instance; @@ -72,7 +73,7 @@ private void registerDocumentListener( } } - public final void hideToolbarForFile(String filePath, Project project, Editor editor) { + public final void hideToolbarForFile(String filePath, Project project, Optional editor) { FloatingToolbarComponent toolbarComponent = projectFilesToolbarComponents .getOrDefault(project, new HashMap<>()) .get(filePath); @@ -80,11 +81,9 @@ public final void hideToolbarForFile(String filePath, Project project, Editor ed toolbarComponent.scheduleHide(); } - if (editor != null) { - projectOriginalContent - .get(project) - .put(filePath, editor.getDocument().getText()); - } + editor.ifPresent(value -> projectOriginalContent + .get(project) + .put(filePath, value.getDocument().getText())); } // getter methods used for tests diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsWriteAction.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsWriteAction.java index 53d0471..70d08a3 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsWriteAction.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsWriteAction.java @@ -32,6 +32,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Collections; +import java.util.Optional; import org.jetbrains.plugins.gradle.util.GradleConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,7 +60,7 @@ public void actionPerformed(AnActionEvent e) { VirtualFile file = editor.getVirtualFile(); if (file != null) { - VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath(), project, editor); + VersionPropsToolbar.getInstance().hideToolbarForFile(file.getPath(), project, Optional.of(editor)); } } } From 979b81b57ab695fb6ee5a0b13492e833c28af24a Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Wed, 2 Oct 2024 13:15:10 +0100 Subject: [PATCH 07/18] settings page --- .../VersionPropsSettingsConfigurable.java | 68 +++++++++++++++++++ .../intellij/VersionPropsSettingsState.java | 51 ++++++++++++++ .../src/main/resources/META-INF/plugin.xml | 2 + 3 files changed, 121 insertions(+) create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsConfigurable.java create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsState.java diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsConfigurable.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsConfigurable.java new file mode 100644 index 0000000..8f89f55 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsConfigurable.java @@ -0,0 +1,68 @@ +/* + * (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.options.Configurable; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JPanel; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.Nullable; + +public class VersionPropsSettingsConfigurable implements Configurable { + private JPanel panel; + private JCheckBox featureCheckbox; + + @Nls + @Override + public String getDisplayName() { + return "My Plugin Settings"; + } + + @Nullable + @Override + public JComponent createComponent() { + if (panel == null) { + panel = new JPanel(); + featureCheckbox = new JCheckBox("Enable My Feature"); + panel.add(featureCheckbox); + } + return panel; + } + + @Override + public boolean isModified() { + return featureCheckbox.isSelected() + != VersionPropsSettingsState.getInstance().isFeatureEnabled(); + } + + @Override + public void apply() { + VersionPropsSettingsState.getInstance().setFeatureEnabled(featureCheckbox.isSelected()); + } + + @Override + public void reset() { + featureCheckbox.setSelected(VersionPropsSettingsState.getInstance().isFeatureEnabled()); + } + + @Override + public void disposeUIResources() { + panel = null; + featureCheckbox = null; + } +} \ No newline at end of file diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsState.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsState.java new file mode 100644 index 0000000..27ab711 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsState.java @@ -0,0 +1,51 @@ +/* + * (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.application.ApplicationManager; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import org.jetbrains.annotations.Nullable; + +@State(name = "VersionPropsPluginSettings", storages = @Storage("VersionPropsSettings.xml")) +public class VersionPropsSettingsState implements PersistentStateComponent { + private boolean featureEnabled = false; + + public static VersionPropsSettingsState getInstance() { + return ApplicationManager.getApplication().getService(VersionPropsSettingsState.class); + } + + @Nullable + @Override + public VersionPropsSettingsState getState() { + return this; + } + + @Override + public void loadState(VersionPropsSettingsState state) { + this.featureEnabled = state.featureEnabled; + } + + public final boolean isFeatureEnabled() { + return featureEnabled; + } + + public final void setFeatureEnabled(boolean featureEnabled) { + this.featureEnabled = featureEnabled; + } +} \ No newline at end of file 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 f0c0111..21977c2 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 @@ -29,5 +29,7 @@ implementationClass="com.palantir.gradle.versions.intellij.FolderCompletionContributor"/> + + \ No newline at end of file From 35013d41c3d496a2f3d0e24c684ef63e7e200584 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Thu, 3 Oct 2024 10:12:34 +0100 Subject: [PATCH 08/18] simple settings page --- .../intellij/VersionPropsSettings.java | 111 ++++++++++++++++++ .../intellij/VersionPropsSettingsPage.java | 71 +++++++++++ .../src/main/resources/META-INF/plugin.xml | 2 + 3 files changed, 184 insertions(+) create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettings.java create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettings.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettings.java new file mode 100644 index 0000000..3286b53 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettings.java @@ -0,0 +1,111 @@ +/* + * (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.components.PersistentStateComponent; +import com.intellij.openapi.components.Service; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.project.Project; +import java.util.ArrayList; +import java.util.List; +import org.jetbrains.annotations.Nullable; + +@com.intellij.openapi.components.State( + name = "GradleConsistentVersionsSettings", + storages = {@Storage("gradle-consistent-versions-plugin-settings.xml")}) +@Service(Service.Level.PROJECT) +public final class VersionPropsSettings implements PersistentStateComponent { + + public enum EnabledState { + UNKNOWN, + ENABLED, + DISABLED + } + + public static final class State { + private EnabledState enabled = EnabledState.UNKNOWN; + private List mavenRepositories = new ArrayList<>(); + + public void setEnabled(@Nullable String enabledStr) { + if (enabledStr == null) { + enabled = EnabledState.UNKNOWN; + } else if (Boolean.valueOf(enabledStr)) { + enabled = EnabledState.ENABLED; + } else { + enabled = EnabledState.DISABLED; + } + } + + public String getEnabled() { + return switch (enabled) { + case ENABLED -> "true"; + case DISABLED -> "false"; + default -> null; + }; + } + + @Override + public String toString() { + return "State{" + "enabled=" + enabled + ", mavenRepositories=" + mavenRepositories + '}'; + } + + public List getMavenRepositories() { + return mavenRepositories; + } + + public void setMavenRepositories(List mavenRepositories) { + this.mavenRepositories = mavenRepositories; + } + } + + private State state = new State(); + + @Nullable + @Override + public State getState() { + return state; + } + + @Override + public void loadState(State status) { + this.state = status; + } + + public boolean isEnabled() { + return state.enabled.equals(EnabledState.ENABLED); + } + + public void setEnabled(boolean enabled) { + setEnabled(enabled ? EnabledState.ENABLED : EnabledState.DISABLED); + } + + public void setEnabled(EnabledState enabled) { + state.enabled = enabled; + } + + public List getMavenRepositories() { + return state.getMavenRepositories(); + } + + public void setMavenRepositories(List mavenRepositories) { + state.setMavenRepositories(mavenRepositories); + } + + public static VersionPropsSettings getInstance(Project project) { + return project.getService(VersionPropsSettings.class); + } +} diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java new file mode 100644 index 0000000..f580779 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java @@ -0,0 +1,71 @@ +/* + * (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.options.Configurable; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.project.Project; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JPanel; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.Nullable; + +public final class VersionPropsSettingsPage implements Configurable { + private JCheckBox enabledCheckbox; + + private final VersionPropsSettings settings; + + public VersionPropsSettingsPage(Project project) { + settings = VersionPropsSettings.getInstance(project); + } + + @Nls + @Override + public String getDisplayName() { + return "Gradle Consistent Versions"; + } + + @Nullable + @Override + public JComponent createComponent() { + JPanel rootPanel = new JPanel(); + enabledCheckbox = new JCheckBox("Enable gradle-consistent-versions plugin"); + rootPanel.add(enabledCheckbox); + return rootPanel; + } + + @Override + public boolean isModified() { + return enabledCheckbox.isSelected() != settings.isEnabled(); + } + + @Override + public void apply() throws ConfigurationException { + settings.setEnabled(enabledCheckbox.isSelected()); + } + + @Override + public void reset() { + enabledCheckbox.setSelected(settings.isEnabled()); + } + + @Override + public void disposeUIResources() { + // No resources to dispose + } +} 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 cea3497..3c98261 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 @@ -11,6 +11,8 @@ org.jetbrains.plugins.gradle + + From 6f8e5cb6e9722f1e555123570f4b0627c2798c1f Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Thu, 3 Oct 2024 10:18:05 +0100 Subject: [PATCH 09/18] dont run if not enabled --- .../gradle/versions/intellij/VersionPropsFileListener.java | 5 +++++ 1 file changed, 5 insertions(+) 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 d9fc505..125ddc0 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 @@ -73,6 +73,11 @@ public ChangeApplier prepareChange(List events) { @Override public void afterVfsChange() { projectsAffected.forEach(project -> { + VersionPropsSettings settings = VersionPropsSettings.getInstance(project); + if (!settings.isEnabled()) { + return; + } + if (hasBuildSrc(project)) { runTaskThenRefresh(project); } else { From 8e62b8cf61119adcd723fef8a9f108164595c493 Mon Sep 17 00:00:00 2001 From: svc-changelog Date: Thu, 3 Oct 2024 09:24:11 +0000 Subject: [PATCH 10/18] Add generated changelog entries --- changelog/@unreleased/pr-27.v2.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/@unreleased/pr-27.v2.yml diff --git a/changelog/@unreleased/pr-27.v2.yml b/changelog/@unreleased/pr-27.v2.yml new file mode 100644 index 0000000..46b3f08 --- /dev/null +++ b/changelog/@unreleased/pr-27.v2.yml @@ -0,0 +1,5 @@ +type: improvement +improvement: + description: Settings Page + links: + - https://github.com/palantir/gradle-consistent-versions-idea-plugin/pull/27 From b27403c08e0beb14cf2538f0a4ca6c069c00cd2a Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Thu, 3 Oct 2024 12:28:42 +0100 Subject: [PATCH 11/18] fix xml --- .../src/main/resources/META-INF/plugin.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 3c98261..b70dec5 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 @@ -11,8 +11,7 @@ org.jetbrains.plugins.gradle - - + From 362ac97f7e416c72789b49af0138592b1913fa24 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Thu, 3 Oct 2024 16:43:44 +0100 Subject: [PATCH 12/18] update setting --- .../intellij/VersionPropsFileListener.java | 2 +- ....java => VersionPropsProjectSettings.java} | 36 ++++--------------- .../intellij/VersionPropsSettingsPage.java | 4 +-- 3 files changed, 10 insertions(+), 32 deletions(-) rename gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/{VersionPropsSettings.java => VersionPropsProjectSettings.java} (67%) 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 125ddc0..c8bdc13 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 @@ -73,7 +73,7 @@ public ChangeApplier prepareChange(List events) { @Override public void afterVfsChange() { projectsAffected.forEach(project -> { - VersionPropsSettings settings = VersionPropsSettings.getInstance(project); + VersionPropsProjectSettings settings = VersionPropsProjectSettings.getInstance(project); if (!settings.isEnabled()) { return; } diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettings.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettings.java similarity index 67% rename from gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettings.java rename to gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettings.java index 3286b53..d1769aa 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettings.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettings.java @@ -20,15 +20,13 @@ import com.intellij.openapi.components.Service; import com.intellij.openapi.components.Storage; import com.intellij.openapi.project.Project; -import java.util.ArrayList; -import java.util.List; import org.jetbrains.annotations.Nullable; @com.intellij.openapi.components.State( - name = "GradleConsistentVersionsSettings", - storages = {@Storage("gradle-consistent-versions-plugin-settings.xml")}) + name = "ProjectSettings", + storages = {@Storage("gcv-plugin-settings.xml")}) @Service(Service.Level.PROJECT) -public final class VersionPropsSettings implements PersistentStateComponent { +public final class VersionPropsProjectSettings implements PersistentStateComponent { public enum EnabledState { UNKNOWN, @@ -37,8 +35,9 @@ public enum EnabledState { } public static final class State { + // Using an enum like this ensure that the file is created in .idea allowing for end users to configure it for + // all users private EnabledState enabled = EnabledState.UNKNOWN; - private List mavenRepositories = new ArrayList<>(); public void setEnabled(@Nullable String enabledStr) { if (enabledStr == null) { @@ -57,19 +56,6 @@ public String getEnabled() { default -> null; }; } - - @Override - public String toString() { - return "State{" + "enabled=" + enabled + ", mavenRepositories=" + mavenRepositories + '}'; - } - - public List getMavenRepositories() { - return mavenRepositories; - } - - public void setMavenRepositories(List mavenRepositories) { - this.mavenRepositories = mavenRepositories; - } } private State state = new State(); @@ -97,15 +83,7 @@ public void setEnabled(EnabledState enabled) { state.enabled = enabled; } - public List getMavenRepositories() { - return state.getMavenRepositories(); - } - - public void setMavenRepositories(List mavenRepositories) { - state.setMavenRepositories(mavenRepositories); - } - - public static VersionPropsSettings getInstance(Project project) { - return project.getService(VersionPropsSettings.class); + public static VersionPropsProjectSettings getInstance(Project project) { + return project.getService(VersionPropsProjectSettings.class); } } diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java index f580779..4accaf9 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java @@ -28,10 +28,10 @@ public final class VersionPropsSettingsPage implements Configurable { private JCheckBox enabledCheckbox; - private final VersionPropsSettings settings; + private final VersionPropsProjectSettings settings; public VersionPropsSettingsPage(Project project) { - settings = VersionPropsSettings.getInstance(project); + settings = VersionPropsProjectSettings.getInstance(project); } @Nls From 5258a5986baf2511c715abdeaac6ef53eac0a3c0 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Fri, 4 Oct 2024 10:28:25 +0100 Subject: [PATCH 13/18] better setting state management --- .../intellij/VersionPropsProjectSettings.java | 37 ++++--------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettings.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettings.java index d1769aa..113fc91 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettings.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettings.java @@ -18,43 +18,26 @@ import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.Service; +import com.intellij.openapi.components.Service.Level; import com.intellij.openapi.components.Storage; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.Nullable; +@Service(Level.PROJECT) @com.intellij.openapi.components.State( name = "ProjectSettings", storages = {@Storage("gcv-plugin-settings.xml")}) -@Service(Service.Level.PROJECT) public final class VersionPropsProjectSettings implements PersistentStateComponent { - public enum EnabledState { - UNKNOWN, - ENABLED, - DISABLED - } - public static final class State { - // Using an enum like this ensure that the file is created in .idea allowing for end users to configure it for - // all users - private EnabledState enabled = EnabledState.UNKNOWN; + private boolean enabled = true; - public void setEnabled(@Nullable String enabledStr) { - if (enabledStr == null) { - enabled = EnabledState.UNKNOWN; - } else if (Boolean.valueOf(enabledStr)) { - enabled = EnabledState.ENABLED; - } else { - enabled = EnabledState.DISABLED; - } + public void setEnabled(boolean enabled) { + this.enabled = enabled; } - public String getEnabled() { - return switch (enabled) { - case ENABLED -> "true"; - case DISABLED -> "false"; - default -> null; - }; + public boolean getEnabled() { + return this.enabled; } } @@ -72,14 +55,10 @@ public void loadState(State status) { } public boolean isEnabled() { - return state.enabled.equals(EnabledState.ENABLED); + return state.enabled; } public void setEnabled(boolean enabled) { - setEnabled(enabled ? EnabledState.ENABLED : EnabledState.DISABLED); - } - - public void setEnabled(EnabledState enabled) { state.enabled = enabled; } From 40919771da9472a43f49a1683f6e65572f17deb0 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Fri, 4 Oct 2024 10:56:05 +0100 Subject: [PATCH 14/18] add listener back in --- .../intellij/ProjectRefreshUtils.java | 97 +++++++++++++++++++ .../intellij/VersionPropsCloseAction.java | 8 +- .../VersionPropsDocumentListener.java | 19 +++- .../intellij/VersionPropsFileListener.java | 75 ++++++++++++++ .../VersionPropsSettingsConfigurable.java | 68 ------------- .../intellij/VersionPropsSettingsState.java | 51 ---------- .../intellij/VersionPropsToolbar.java | 22 ++++- .../intellij/VersionPropsWriteAction.java | 74 +------------- .../src/main/resources/META-INF/plugin.xml | 3 +- .../intellij/VersionPropsToolbarTest.java | 3 +- 10 files changed, 220 insertions(+), 200 deletions(-) create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/ProjectRefreshUtils.java create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java delete mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsConfigurable.java delete mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsState.java diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/ProjectRefreshUtils.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/ProjectRefreshUtils.java new file mode 100644 index 0000000..d5b5ada --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/ProjectRefreshUtils.java @@ -0,0 +1,97 @@ +/* + * (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.execution.executors.DefaultRunExecutor; +import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder; +import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings; +import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; +import com.intellij.openapi.externalSystem.task.TaskCallback; +import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; +import com.intellij.openapi.project.Project; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; +import org.jetbrains.plugins.gradle.util.GradleConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ProjectRefreshUtils { + private static final Logger log = LoggerFactory.getLogger(ProjectRefreshUtils.class); + + private ProjectRefreshUtils() { + // Utility class + } + + public static void runWriteVersionsLock(Project project) { + String taskName = "writeVersionsLock"; + if (hasBuildSrc(project)) { + runTaskThenRefresh(project, taskName); + } else { + refreshProjectWithTask(project, taskName); + } + } + + private static void runTaskThenRefresh(Project project, String taskName) { + log.debug("Running task {} on project {}", taskName, project.getName()); + TaskCallback callback = new TaskCallback() { + @Override + public void onSuccess() { + log.debug("Task {} successfully executed", taskName); + refreshProject(project); + } + + @Override + public void onFailure() { + log.error("Task {} failed", taskName); + } + }; + ExternalSystemTaskExecutionSettings settings = createExecutionSettings(project, taskName); + ExternalSystemUtil.runTask( + settings, + DefaultRunExecutor.EXECUTOR_ID, + project, + GradleConstants.SYSTEM_ID, + callback, + ProgressExecutionMode.IN_BACKGROUND_ASYNC); + } + + private static ExternalSystemTaskExecutionSettings createExecutionSettings(Project project, String taskName) { + ExternalSystemTaskExecutionSettings settings = new ExternalSystemTaskExecutionSettings(); + settings.setExternalProjectPath(project.getBasePath()); + settings.setTaskNames(Collections.singletonList(taskName)); + settings.setExternalSystemIdString(GradleConstants.SYSTEM_ID.toString()); + return settings; + } + + private static void refreshProjectWithTask(Project project, String taskName) { + log.debug("Refreshing project {} with task {}", project.getName(), taskName); + refreshProject(project, new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID).withArguments(taskName)); + } + + private static void refreshProject(Project project) { + refreshProject(project, new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)); + } + + private static void refreshProject(Project project, ImportSpecBuilder importSpec) { + ExternalSystemUtil.refreshProject(project.getBasePath(), importSpec); + } + + private static boolean hasBuildSrc(Project project) { + return Files.exists(Paths.get(project.getBasePath(), "buildSrc")); + } +} diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java index 359095f..7e5bb2d 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsCloseAction.java @@ -32,10 +32,10 @@ public VersionPropsCloseAction() { } @Override - public void actionPerformed(AnActionEvent e) { - DataContext dataContext = e.getDataContext(); + public final void actionPerformed(AnActionEvent event) { + DataContext dataContext = event.getDataContext(); Editor editor = dataContext.getData(CommonDataKeys.EDITOR); - Project project = e.getProject(); + Project project = event.getProject(); if (editor != null && project != null) { VirtualFile file = editor.getVirtualFile(); @@ -44,4 +44,4 @@ public void actionPerformed(AnActionEvent e) { } } } -} \ No newline at end of file +} diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java index 3c2f155..d6887f2 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java @@ -1,3 +1,18 @@ +/* + * (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.editor.Editor; @@ -32,7 +47,7 @@ public void beforeDocumentChange(DocumentEvent event) { } @Override - public void documentChanged(DocumentEvent event) { + public final void documentChanged(DocumentEvent event) { VirtualFile file = fileEditor.getFile(); if (file != null && FILE_NAME.equals(file.getName())) { String currentContent = editor.getDocument().getText(); @@ -58,4 +73,4 @@ private void updateFileUnchanged(String filePath) { toolbarComponent.scheduleHide(); } } -} \ No newline at end of file +} 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 new file mode 100644 index 0000000..02c55ac --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsFileListener.java @@ -0,0 +1,75 @@ +/* + * (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.components.ComponentManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.vfs.AsyncFileListener; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.util.PsiTreeUtil; +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; +import org.jetbrains.annotations.Nullable; + +public final class VersionPropsFileListener implements AsyncFileListener { + + @Nullable + @Override + public ChangeApplier prepareChange(List events) { + List versionPropsEvents = events.stream() + .filter(event -> event instanceof VFileContentChangeEvent) + .map(event -> (VFileContentChangeEvent) event) + .filter(event -> "versions.props".equals(event.getFile().getName())) + .toList(); + + if (versionPropsEvents.isEmpty()) { + return null; + } + + List projectsAffected = 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(); + + return new ChangeApplier() { + @Override + public void afterVfsChange() { + projectsAffected.forEach(ProjectRefreshUtils::runWriteVersionsLock); + } + }; + } + + 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 PsiTreeUtil.hasErrorElements(psiFile); + } +} diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsConfigurable.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsConfigurable.java deleted file mode 100644 index 8f89f55..0000000 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsConfigurable.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * (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.options.Configurable; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JPanel; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.Nullable; - -public class VersionPropsSettingsConfigurable implements Configurable { - private JPanel panel; - private JCheckBox featureCheckbox; - - @Nls - @Override - public String getDisplayName() { - return "My Plugin Settings"; - } - - @Nullable - @Override - public JComponent createComponent() { - if (panel == null) { - panel = new JPanel(); - featureCheckbox = new JCheckBox("Enable My Feature"); - panel.add(featureCheckbox); - } - return panel; - } - - @Override - public boolean isModified() { - return featureCheckbox.isSelected() - != VersionPropsSettingsState.getInstance().isFeatureEnabled(); - } - - @Override - public void apply() { - VersionPropsSettingsState.getInstance().setFeatureEnabled(featureCheckbox.isSelected()); - } - - @Override - public void reset() { - featureCheckbox.setSelected(VersionPropsSettingsState.getInstance().isFeatureEnabled()); - } - - @Override - public void disposeUIResources() { - panel = null; - featureCheckbox = null; - } -} \ No newline at end of file diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsState.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsState.java deleted file mode 100644 index 27ab711..0000000 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsState.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * (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.application.ApplicationManager; -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import org.jetbrains.annotations.Nullable; - -@State(name = "VersionPropsPluginSettings", storages = @Storage("VersionPropsSettings.xml")) -public class VersionPropsSettingsState implements PersistentStateComponent { - private boolean featureEnabled = false; - - public static VersionPropsSettingsState getInstance() { - return ApplicationManager.getApplication().getService(VersionPropsSettingsState.class); - } - - @Nullable - @Override - public VersionPropsSettingsState getState() { - return this; - } - - @Override - public void loadState(VersionPropsSettingsState state) { - this.featureEnabled = state.featureEnabled; - } - - public final boolean isFeatureEnabled() { - return featureEnabled; - } - - public final void setFeatureEnabled(boolean featureEnabled) { - this.featureEnabled = featureEnabled; - } -} \ No newline at end of file diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java index 3fb52a7..044ac6e 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsToolbar.java @@ -1,3 +1,18 @@ +/* + * (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; @@ -29,12 +44,13 @@ public static VersionPropsToolbar getInstance() { } @Override - public boolean getAutoHideable() { + public final boolean getAutoHideable() { return false; } @Override - public void register(DataContext dataContext, FloatingToolbarComponent component, Disposable parentDisposable) { + public final void register( + DataContext dataContext, FloatingToolbarComponent component, Disposable parentDisposable) { super.register(dataContext, component, parentDisposable); FileEditor fileEditor = dataContext.getData(PlatformDataKeys.FILE_EDITOR); @@ -94,4 +110,4 @@ public final Map> getProjectFiles public final Map> getProjectOriginalContent() { return projectOriginalContent; } -} \ No newline at end of file +} diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsWriteAction.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsWriteAction.java index 70d08a3..7cc17d9 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsWriteAction.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsWriteAction.java @@ -16,47 +16,32 @@ package com.palantir.gradle.versions.intellij; -import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder; -import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings; -import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; -import com.intellij.openapi.externalSystem.task.TaskCallback; -import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Collections; import java.util.Optional; -import org.jetbrains.plugins.gradle.util.GradleConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class VersionPropsWriteAction extends AnAction { private static final Logger log = LoggerFactory.getLogger(VersionPropsWriteAction.class); - private static final String TASK_NAME = "writeVersionsLock"; public VersionPropsWriteAction() { super("Write Versions Lock"); } @Override - public void actionPerformed(AnActionEvent e) { - DataContext dataContext = e.getDataContext(); + public final void actionPerformed(AnActionEvent event) { + DataContext dataContext = event.getDataContext(); Editor editor = dataContext.getData(CommonDataKeys.EDITOR); - Project project = e.getProject(); + Project project = event.getProject(); if (editor != null && project != null) { - if (hasBuildSrc(project)) { - runTaskThenRefresh(project); - } else { - refreshProjectWithTask(project); - } + ProjectRefreshUtils.runWriteVersionsLock(project); VirtualFile file = editor.getVirtualFile(); if (file != null) { @@ -64,53 +49,4 @@ public void actionPerformed(AnActionEvent e) { } } } - - private boolean hasBuildSrc(Project project) { - return Files.exists(Paths.get(project.getBasePath(), "buildSrc")); - } - - private void runTaskThenRefresh(Project project) { - log.debug("Running task {} on project {}", TASK_NAME, project.getName()); - TaskCallback callback = new TaskCallback() { - @Override - public void onSuccess() { - log.debug("Task {} successfully executed", TASK_NAME); - refreshProject(project); - } - - @Override - public void onFailure() { - log.error("Task {} failed", TASK_NAME); - } - }; - ExternalSystemTaskExecutionSettings settings = createExecutionSettings(project); - ExternalSystemUtil.runTask( - settings, - DefaultRunExecutor.EXECUTOR_ID, - project, - GradleConstants.SYSTEM_ID, - callback, - ProgressExecutionMode.IN_BACKGROUND_ASYNC); - } - - private ExternalSystemTaskExecutionSettings createExecutionSettings(Project project) { - ExternalSystemTaskExecutionSettings settings = new ExternalSystemTaskExecutionSettings(); - settings.setExternalProjectPath(project.getBasePath()); - settings.setTaskNames(Collections.singletonList(TASK_NAME)); - settings.setExternalSystemIdString(GradleConstants.SYSTEM_ID.toString()); - return settings; - } - - private void refreshProjectWithTask(Project project) { - log.debug("Refreshing project {} with task {}", project.getName(), TASK_NAME); - refreshProject(project, new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID).withArguments(TASK_NAME)); - } - - private void refreshProject(Project project) { - refreshProject(project, new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)); - } - - private void refreshProject(Project project, ImportSpecBuilder importSpec) { - ExternalSystemUtil.refreshProject(project.getBasePath(), importSpec); - } -} \ No newline at end of file +} 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 21977c2..3d93b7c 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 @@ -29,7 +29,6 @@ implementationClass="com.palantir.gradle.versions.intellij.FolderCompletionContributor"/> - - + \ No newline at end of file diff --git a/gradle-consistent-versions-idea-plugin/src/test/java/com/palantir/gradle/versions/intellij/VersionPropsToolbarTest.java b/gradle-consistent-versions-idea-plugin/src/test/java/com/palantir/gradle/versions/intellij/VersionPropsToolbarTest.java index 8b61ee7..c496f36 100644 --- a/gradle-consistent-versions-idea-plugin/src/test/java/com/palantir/gradle/versions/intellij/VersionPropsToolbarTest.java +++ b/gradle-consistent-versions-idea-plugin/src/test/java/com/palantir/gradle/versions/intellij/VersionPropsToolbarTest.java @@ -31,6 +31,7 @@ import com.intellij.openapi.vfs.VirtualFile; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -91,7 +92,7 @@ public void testHideToolbarForFile() { fileContentMap.put("test-path", "original"); toolbar.getProjectOriginalContent().put(project, fileContentMap); - toolbar.hideToolbarForFile("test-path", project, editor); + toolbar.hideToolbarForFile("test-path", project, Optional.of(editor)); Mockito.verify(component).scheduleHide(); assertThat(toolbar.getProjectOriginalContent().get(project).get("test-path")) From f581aa7012fbe7c15010aea7ffb322d265f6653e Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Fri, 4 Oct 2024 12:51:05 +0100 Subject: [PATCH 15/18] working with settings --- .../intellij/VersionPropsAppSettings.java | 68 ++++++++++++++++++ .../intellij/VersionPropsAppSettingsPage.java | 70 +++++++++++++++++++ .../VersionPropsDocumentListener.java | 27 +++++-- .../intellij/VersionPropsFileListener.java | 31 +------- ...a => VersionPropsProjectSettingsPage.java} | 4 +- .../src/main/resources/META-INF/plugin.xml | 7 +- 6 files changed, 170 insertions(+), 37 deletions(-) create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettings.java create mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettingsPage.java rename gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/{VersionPropsSettingsPage.java => VersionPropsProjectSettingsPage.java} (93%) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettings.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettings.java new file mode 100644 index 0000000..b970951 --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettings.java @@ -0,0 +1,68 @@ +/* + * (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.application.ApplicationManager; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.Service; +import com.intellij.openapi.components.Service.Level; +import com.intellij.openapi.components.Storage; +import org.jetbrains.annotations.Nullable; + +@Service(Level.APP) +@com.intellij.openapi.components.State( + name = "AppSettings", + storages = {@Storage("gcv-plugin-application-settings.xml")}) +public final class VersionPropsAppSettings implements PersistentStateComponent { + + public static final class State { + private boolean enabled = true; + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean getEnabled() { + return this.enabled; + } + } + + private State state = new State(); + + @Nullable + @Override + public State getState() { + return state; + } + + @Override + public void loadState(State status) { + this.state = status; + } + + public boolean isEnabled() { + return state.enabled; + } + + public void setEnabled(boolean enabled) { + state.enabled = enabled; + } + + public static VersionPropsAppSettings getInstance() { + return ApplicationManager.getApplication().getService(VersionPropsAppSettings.class); + } +} diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettingsPage.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettingsPage.java new file mode 100644 index 0000000..f46fafd --- /dev/null +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettingsPage.java @@ -0,0 +1,70 @@ +/* + * (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.options.Configurable; +import com.intellij.openapi.options.ConfigurationException; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JPanel; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.Nullable; + +public final class VersionPropsAppSettingsPage implements Configurable { + private JCheckBox enabledCheckbox; + + private final VersionPropsAppSettings settings; + + public VersionPropsAppSettingsPage() { + settings = VersionPropsAppSettings.getInstance(); + } + + @Nls + @Override + public String getDisplayName() { + return "Gradle Consistent Versions"; + } + + @Nullable + @Override + public JComponent createComponent() { + JPanel rootPanel = new JPanel(); + enabledCheckbox = new JCheckBox("Enable writeVersionsLock on save"); + rootPanel.add(enabledCheckbox); + return rootPanel; + } + + @Override + public boolean isModified() { + return enabledCheckbox.isSelected() != settings.isEnabled(); + } + + @Override + public void apply() throws ConfigurationException { + settings.setEnabled(enabledCheckbox.isSelected()); + } + + @Override + public void reset() { + enabledCheckbox.setSelected(settings.isEnabled()); + } + + @Override + public void disposeUIResources() { + // No resources to dispose + } +} \ No newline at end of file diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java index d6887f2..8d256f6 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsDocumentListener.java @@ -22,6 +22,11 @@ import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.vfs.VirtualFile; import java.util.Map; +import java.util.Objects; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.swing.SwingUtilities; public class VersionPropsDocumentListener implements DocumentListener { private final FileEditor fileEditor; @@ -29,6 +34,7 @@ public class VersionPropsDocumentListener implements DocumentListener { private final Map originalContent; private final Map filesToolbarComponents; private static final String FILE_NAME = "versions.props"; + private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); public VersionPropsDocumentListener( FileEditor fileEditor, @@ -42,24 +48,35 @@ public VersionPropsDocumentListener( } @Override - public void beforeDocumentChange(DocumentEvent event) { - // No action needed before the document change - } + public void beforeDocumentChange(DocumentEvent event) {} @Override public final void documentChanged(DocumentEvent event) { VirtualFile file = fileEditor.getFile(); if (file != null && FILE_NAME.equals(file.getName())) { + VersionPropsProjectSettings projectSettings = + VersionPropsProjectSettings.getInstance(Objects.requireNonNull(editor.getProject())); + VersionPropsAppSettings appSettings = VersionPropsAppSettings.getInstance(); + if (!projectSettings.isEnabled() || appSettings.isEnabled()) { + scheduleUpdate(() -> updateFileUnchanged(file.getPath())); + return; + } + String currentContent = editor.getDocument().getText(); + // This requires debouncing to so that the toolbar actually shows up if (!originalContent.get(file.getPath()).equals(currentContent)) { - updateFileChanged(file.getPath()); + scheduleUpdate(() -> updateFileChanged(file.getPath())); } else { - updateFileUnchanged(file.getPath()); + scheduleUpdate(() -> updateFileUnchanged(file.getPath())); } } } + private void scheduleUpdate(Runnable updateTask) { + scheduler.schedule(() -> SwingUtilities.invokeLater(updateTask), 300, TimeUnit.MILLISECONDS); + } + private void updateFileChanged(String filePath) { FloatingToolbarComponent toolbarComponent = filesToolbarComponents.get(filePath); if (toolbarComponent != null) { 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 59e2e33..f55a1c1 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 @@ -60,41 +60,16 @@ public ChangeApplier prepareChange(List events) { public void afterVfsChange() { projectsAffected.forEach(project -> { VersionPropsProjectSettings settings = VersionPropsProjectSettings.getInstance(project); - if (!settings.isEnabled()) { + VersionPropsAppSettings appSettings = VersionPropsAppSettings.getInstance(); + if (!settings.isEnabled() || !appSettings.isEnabled()) { return; } - - if (hasBuildSrc(project)) { - runTaskThenRefresh(project); - } else { - refreshProjectWithTask(project); - } + ProjectRefreshUtils.runWriteVersionsLock(project); }); } }; } - private boolean hasBuildSrc(Project project) { - return Files.exists(Paths.get(project.getBasePath(), "buildSrc")); - } - - private void runTaskThenRefresh(Project project) { - log.debug("Running task {} on project {}", TASK_NAME, project.getName()); - TaskCallback callback = new TaskCallback() { - @Override - public void onSuccess() { - log.debug("Task {} successfully executed", TASK_NAME); - refreshProject(project); - } - - @Override - public void onFailure() { - log.error("Task {} failed", TASK_NAME); - projectsAffected.forEach(ProjectRefreshUtils::runWriteVersionsLock); - } - }; - } - private static boolean isFileMalformed(Project project, VirtualFile file) { PsiFile psiFile = PsiManager.getInstance(project).findFile(file); diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettingsPage.java similarity index 93% rename from gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java rename to gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettingsPage.java index 4accaf9..bac0afa 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsProjectSettingsPage.java @@ -25,12 +25,12 @@ import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.Nullable; -public final class VersionPropsSettingsPage implements Configurable { +public final class VersionPropsProjectSettingsPage implements Configurable { private JCheckBox enabledCheckbox; private final VersionPropsProjectSettings settings; - public VersionPropsSettingsPage(Project project) { + public VersionPropsProjectSettingsPage(Project project) { settings = VersionPropsProjectSettings.getInstance(project); } 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 ab1dba9..df819fb 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 @@ -18,7 +18,10 @@ - + + + + @@ -29,7 +32,7 @@ - + \ No newline at end of file From f7e3bfd994855a6a1e6f998c2d19a52d8a335e46 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 7 Oct 2024 15:35:11 +0100 Subject: [PATCH 16/18] rename file --- .../intellij/VersionPropsSettingsPage.java | 71 ------------------- 1 file changed, 71 deletions(-) delete mode 100644 gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java deleted file mode 100644 index 4accaf9..0000000 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsSettingsPage.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * (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.options.Configurable; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.project.Project; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JPanel; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.Nullable; - -public final class VersionPropsSettingsPage implements Configurable { - private JCheckBox enabledCheckbox; - - private final VersionPropsProjectSettings settings; - - public VersionPropsSettingsPage(Project project) { - settings = VersionPropsProjectSettings.getInstance(project); - } - - @Nls - @Override - public String getDisplayName() { - return "Gradle Consistent Versions"; - } - - @Nullable - @Override - public JComponent createComponent() { - JPanel rootPanel = new JPanel(); - enabledCheckbox = new JCheckBox("Enable gradle-consistent-versions plugin"); - rootPanel.add(enabledCheckbox); - return rootPanel; - } - - @Override - public boolean isModified() { - return enabledCheckbox.isSelected() != settings.isEnabled(); - } - - @Override - public void apply() throws ConfigurationException { - settings.setEnabled(enabledCheckbox.isSelected()); - } - - @Override - public void reset() { - enabledCheckbox.setSelected(settings.isEnabled()); - } - - @Override - public void disposeUIResources() { - // No resources to dispose - } -} From 5f44409838221dbb1c2a2ded86d7f19a974e4dcc Mon Sep 17 00:00:00 2001 From: svc-changelog Date: Mon, 7 Oct 2024 14:36:58 +0000 Subject: [PATCH 17/18] Add generated changelog entries --- changelog/@unreleased/pr-33.v2.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/@unreleased/pr-33.v2.yml diff --git a/changelog/@unreleased/pr-33.v2.yml b/changelog/@unreleased/pr-33.v2.yml new file mode 100644 index 0000000..e1f55e2 --- /dev/null +++ b/changelog/@unreleased/pr-33.v2.yml @@ -0,0 +1,5 @@ +type: improvement +improvement: + description: button to trigger writeVersionsLock + links: + - https://github.com/palantir/gradle-consistent-versions-idea-plugin/pull/33 From b0944cb2f3efc6b7f3f0fbdaf46adbc0127a0809 Mon Sep 17 00:00:00 2001 From: Finlay Williams Date: Mon, 7 Oct 2024 15:43:23 +0100 Subject: [PATCH 18/18] spotless --- .../versions/intellij/VersionPropsAppSettingsPage.java | 2 +- .../versions/intellij/VersionPropsFileListener.java | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettingsPage.java b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettingsPage.java index f46fafd..60aa4ad 100644 --- a/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettingsPage.java +++ b/gradle-consistent-versions-idea-plugin/src/main/java/com/palantir/gradle/versions/intellij/VersionPropsAppSettingsPage.java @@ -67,4 +67,4 @@ public void reset() { public void disposeUIResources() { // No resources to dispose } -} \ No newline at end of file +} 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 b7f87e5..eb9bd43 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,13 +16,7 @@ package com.palantir.gradle.versions.intellij; -import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.openapi.components.ComponentManager; -import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder; -import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings; -import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; -import com.intellij.openapi.externalSystem.task.TaskCallback; -import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.vfs.AsyncFileListener; @@ -32,14 +26,10 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.util.PsiTreeUtil; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.gradle.util.GradleConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory;