From b4dc341e9bb4cbf89e942e28fd503170b203eef5 Mon Sep 17 00:00:00 2001 From: Clay Livince Date: Fri, 6 May 2022 15:47:22 +0800 Subject: [PATCH 1/8] fix: for 2022.1 version code has been changed to 1.9.6 --- .idea/compiler.xml | 2 +- .idea/libraries-with-intellij-classes.xml | 65 +++++++++++++++++++++++ .idea/misc.xml | 3 ++ build.gradle | 7 +-- gradle.properties | 15 ++++-- pluginVersion.txt | 2 +- 6 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 .idea/libraries-with-intellij-classes.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 9fde4533..e757a31a 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -2,6 +2,6 @@ \ No newline at end of file diff --git a/.idea/libraries-with-intellij-classes.xml b/.idea/libraries-with-intellij-classes.xml new file mode 100644 index 00000000..9fa31567 --- /dev/null +++ b/.idea/libraries-with-intellij-classes.xml @@ -0,0 +1,65 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 8c035d6a..1e0fef27 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,9 @@ + + + diff --git a/build.gradle b/build.gradle index d5584d2e..89af155e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { plugins { id "org.jetbrains.changelog" version '0.6.2' - id "org.jetbrains.intellij" version "1.2.1" + id 'org.jetbrains.intellij' version '1.5.2' } apply plugin: 'org.jetbrains.changelog' @@ -36,8 +36,8 @@ ext { allprojects { apply plugin: 'java' - sourceCompatibility = '1.8' - targetCompatibility = '1.8' + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 compileJava.options.encoding = "UTF-8" compileTestJava.options.encoding = "UTF-8" @@ -130,6 +130,7 @@ allprojects { } intellij { + version = '2022.1' plugins = myPlugins pluginName = 'kite-pycharm' updateSinceUntilBuild = false diff --git a/gradle.properties b/gradle.properties index 4b0a939e..37b13767 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -sinceBuild = 213.0 -untilBuild = 213.* +sinceBuild = 221.0 +untilBuild = 221.* #2021.1 #ideaVersion = IC-2021.1 @@ -12,6 +12,11 @@ untilBuild = 213.* #goPlugin = org.jetbrains.plugins.go:212.4746.92 # 2021.3 -ideaVersion = IC-213.5605.12-EAP-SNAPSHOT -pycharmPlugin = PythonCore:213.5605.80 -goPlugin = org.jetbrains.plugins.go:213.5605.12 \ No newline at end of file +#ideaVersion = IC-213.5605.12-EAP-SNAPSHOT +#pycharmPlugin = PythonCore:213.5605.80 +#goPlugin = org.jetbrains.plugins.go:213.5605.12 + +#2022.1 +ideaVersion = IC-221.5080.210 +pycharmPlugin = PythonCore:221.5080.210 +goPlugin = org.jetbrains.plugins.go:221.5080.210 \ No newline at end of file diff --git a/pluginVersion.txt b/pluginVersion.txt index 6ecac681..b4cac6fa 100644 --- a/pluginVersion.txt +++ b/pluginVersion.txt @@ -1 +1 @@ -1.9.5 \ No newline at end of file +1.9.6 \ No newline at end of file From 60b03e286662e8616558b8b8c5cda8e2a84da69f Mon Sep 17 00:00:00 2001 From: PavelA Date: Tue, 2 Aug 2022 11:57:34 +0300 Subject: [PATCH 2/8] fix 2022.2 --- build.gradle | 2 +- gradle.properties | 10 +++++----- pluginVersion.txt | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 89af155e..ce7a4b5d 100644 --- a/build.gradle +++ b/build.gradle @@ -130,7 +130,7 @@ allprojects { } intellij { - version = '2022.1' + version = '2022.2' plugins = myPlugins pluginName = 'kite-pycharm' updateSinceUntilBuild = false diff --git a/gradle.properties b/gradle.properties index 37b13767..81e24bbf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -sinceBuild = 221.0 -untilBuild = 221.* +sinceBuild = 222.0 +untilBuild = 222.* #2021.1 #ideaVersion = IC-2021.1 @@ -17,6 +17,6 @@ untilBuild = 221.* #goPlugin = org.jetbrains.plugins.go:213.5605.12 #2022.1 -ideaVersion = IC-221.5080.210 -pycharmPlugin = PythonCore:221.5080.210 -goPlugin = org.jetbrains.plugins.go:221.5080.210 \ No newline at end of file +ideaVersion = IU-222.3345.118 +pycharmPlugin = PythonCore:222.3345.131 +goPlugin = org.jetbrains.plugins.go:222.3345.118 \ No newline at end of file diff --git a/pluginVersion.txt b/pluginVersion.txt index b4cac6fa..0b9006ea 100644 --- a/pluginVersion.txt +++ b/pluginVersion.txt @@ -1 +1 @@ -1.9.6 \ No newline at end of file +1.9.7 \ No newline at end of file From 0bbbc93b2b15b285afe1662d2f8e62e3f6c06235 Mon Sep 17 00:00:00 2001 From: Wh1isper <9573586@qq.com> Date: Sun, 2 Apr 2023 16:19:10 +0800 Subject: [PATCH 3/8] try fix 2023.1 --- .gitignore | 2 +- .idea/$PRODUCT_WORKSPACE_FILE$ | 19 -- .idea/.gitignore | 4 - .idea/.name | 1 - .idea/codeStyleSettings.xml | 328 ---------------------- .idea/compiler.xml | 7 - .idea/encodings.xml | 6 - .idea/gradle.xml | 21 -- .idea/jarRepositories.xml | 35 --- .idea/libraries-with-intellij-classes.xml | 65 ----- .idea/misc.xml | 90 ------ .idea/runConfigurations/All_Tests.xml | 21 -- .idea/runConfigurations/Plugin.xml | 21 -- .idea/templateLanguages.xml | 6 - .idea/uiDesigner.xml | 141 ---------- .idea/vcs.xml | 7 - build.gradle | 2 +- gradle.properties | 15 +- pluginVersion.txt | 2 +- 19 files changed, 13 insertions(+), 780 deletions(-) delete mode 100644 .idea/$PRODUCT_WORKSPACE_FILE$ delete mode 100644 .idea/.gitignore delete mode 100644 .idea/.name delete mode 100644 .idea/codeStyleSettings.xml delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/jarRepositories.xml delete mode 100644 .idea/libraries-with-intellij-classes.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/runConfigurations/All_Tests.xml delete mode 100644 .idea/runConfigurations/Plugin.xml delete mode 100644 .idea/templateLanguages.xml delete mode 100644 .idea/uiDesigner.xml delete mode 100644 .idea/vcs.xml diff --git a/.gitignore b/.gitignore index cbdebfa3..e72eee13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .DS_Store .gradle -.idea/workspace.xml +.idea/* build/ out/ cache/ diff --git a/.idea/$PRODUCT_WORKSPACE_FILE$ b/.idea/$PRODUCT_WORKSPACE_FILE$ deleted file mode 100644 index 3733e0d3..00000000 --- a/.idea/$PRODUCT_WORKSPACE_FILE$ +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - 1.8 - - - - - - - - \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 62601d88..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Editor-based HTTP Client requests -/httpRequests/ -# Default ignored files -/shelf/ \ No newline at end of file diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 8602c800..00000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -kite-intellij-plugin \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml deleted file mode 100644 index 4ae8d3ab..00000000 --- a/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index e757a31a..00000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 4987ecab..00000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 3935e371..00000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index 26101af5..00000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries-with-intellij-classes.xml b/.idea/libraries-with-intellij-classes.xml deleted file mode 100644 index 9fa31567..00000000 --- a/.idea/libraries-with-intellij-classes.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 1e0fef27..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations/All_Tests.xml b/.idea/runConfigurations/All_Tests.xml deleted file mode 100644 index af0c38b9..00000000 --- a/.idea/runConfigurations/All_Tests.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - true - - - \ No newline at end of file diff --git a/.idea/runConfigurations/Plugin.xml b/.idea/runConfigurations/Plugin.xml deleted file mode 100644 index 4a0b6b7d..00000000 --- a/.idea/runConfigurations/Plugin.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - true - - - \ No newline at end of file diff --git a/.idea/templateLanguages.xml b/.idea/templateLanguages.xml deleted file mode 100644 index 046e9a38..00000000 --- a/.idea/templateLanguages.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml deleted file mode 100644 index bf322892..00000000 --- a/.idea/uiDesigner.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 5d7764b8..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/build.gradle b/build.gradle index ce7a4b5d..890c7ea8 100644 --- a/build.gradle +++ b/build.gradle @@ -130,7 +130,7 @@ allprojects { } intellij { - version = '2022.2' + version = '2023.1' plugins = myPlugins pluginName = 'kite-pycharm' updateSinceUntilBuild = false diff --git a/gradle.properties b/gradle.properties index 81e24bbf..f48265d1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -sinceBuild = 222.0 -untilBuild = 222.* +sinceBuild = 223.0 +untilBuild = 223.* #2021.1 #ideaVersion = IC-2021.1 @@ -17,6 +17,11 @@ untilBuild = 222.* #goPlugin = org.jetbrains.plugins.go:213.5605.12 #2022.1 -ideaVersion = IU-222.3345.118 -pycharmPlugin = PythonCore:222.3345.131 -goPlugin = org.jetbrains.plugins.go:222.3345.118 \ No newline at end of file +#ideaVersion = IU-222.3345.118 +#pycharmPlugin = PythonCore:222.3345.131 +#goPlugin = org.jetbrains.plugins.go:222.3345.118 + +#2023.1 +ideaVersion = IU-231.8109.175 +pycharmPlugin = PythonCore:231.8109.144 +goPlugin = org.jetbrains.plugins.go:231.8109.175 \ No newline at end of file diff --git a/pluginVersion.txt b/pluginVersion.txt index 0b9006ea..f5f0aa63 100644 --- a/pluginVersion.txt +++ b/pluginVersion.txt @@ -1 +1 @@ -1.9.7 \ No newline at end of file +1.9.8 \ No newline at end of file From 7582446f820c64b37f13fb925149a1c80d09e474 Mon Sep 17 00:00:00 2001 From: Wh1isper <9573586@qq.com> Date: Sun, 2 Apr 2023 16:48:17 +0800 Subject: [PATCH 4/8] drop SystemInfo.isWin7OrNewer --- src/main/java/com/kite/intellij/platform/KitePlatform.java | 3 +-- .../com/kite/intellij/startup/KiteProjectManagerListener.java | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/kite/intellij/platform/KitePlatform.java b/src/main/java/com/kite/intellij/platform/KitePlatform.java index 6de67dd5..c5cd20f6 100644 --- a/src/main/java/com/kite/intellij/platform/KitePlatform.java +++ b/src/main/java/com/kite/intellij/platform/KitePlatform.java @@ -23,8 +23,7 @@ public static boolean isOsVersionSupported() { } if (SystemInfo.isWindows) { - LOG.debug("OS: Windows " + SystemInfo.isWin7OrNewer + ", 64 bit: " + SystemInfo.is64Bit); - return SystemInfo.isWin7OrNewer /*&& SystemInfo.is64Bit*/; //the arch seems to equal the Java VM arch, but we need the installed OS architecture, disabled for now + return true; } if (SystemInfo.isLinux) { diff --git a/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java b/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java index 2ed674eb..61b85503 100644 --- a/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java +++ b/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java @@ -135,8 +135,6 @@ private boolean downloadAndInstallKite() { * @return {@code true} if the current IDE is incompatible with the autostart feature. */ private static boolean disallowKitedAutostart() { - return SystemInfo.isWin7OrNewer - && !SystemInfo.isWin8OrNewer - && ApplicationInfo.getInstance().getBuild().getBaselineVersion() == 193; + return false; } } From a1779e3b7d45b728406f69717ac28401dc027363 Mon Sep 17 00:00:00 2001 From: Wh1isper <9573586@qq.com> Date: Sun, 2 Apr 2023 17:25:18 +0800 Subject: [PATCH 5/8] Not upgrade UI version --- gradle.properties | 15 +++++---------- .../com/kite/intellij/platform/KitePlatform.java | 4 ++-- .../startup/KiteProjectManagerListener.java | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/gradle.properties b/gradle.properties index f48265d1..d09a1915 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -sinceBuild = 223.0 -untilBuild = 223.* +sinceBuild = 222.0 +untilBuild = 231.* #2021.1 #ideaVersion = IC-2021.1 @@ -17,11 +17,6 @@ untilBuild = 223.* #goPlugin = org.jetbrains.plugins.go:213.5605.12 #2022.1 -#ideaVersion = IU-222.3345.118 -#pycharmPlugin = PythonCore:222.3345.131 -#goPlugin = org.jetbrains.plugins.go:222.3345.118 - -#2023.1 -ideaVersion = IU-231.8109.175 -pycharmPlugin = PythonCore:231.8109.144 -goPlugin = org.jetbrains.plugins.go:231.8109.175 \ No newline at end of file +ideaVersion = IU-222.3345.118 +pycharmPlugin = PythonCore:222.3345.131 +goPlugin = org.jetbrains.plugins.go:222.3345.118 diff --git a/src/main/java/com/kite/intellij/platform/KitePlatform.java b/src/main/java/com/kite/intellij/platform/KitePlatform.java index c5cd20f6..6750bbf0 100644 --- a/src/main/java/com/kite/intellij/platform/KitePlatform.java +++ b/src/main/java/com/kite/intellij/platform/KitePlatform.java @@ -23,7 +23,7 @@ public static boolean isOsVersionSupported() { } if (SystemInfo.isWindows) { - return true; + return true; } if (SystemInfo.isLinux) { @@ -46,4 +46,4 @@ public static boolean isOsVersionNotSupported() { return !isOsVersionSupported(); } } - \ No newline at end of file + diff --git a/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java b/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java index 61b85503..596cd3f2 100644 --- a/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java +++ b/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java @@ -135,6 +135,6 @@ private boolean downloadAndInstallKite() { * @return {@code true} if the current IDE is incompatible with the autostart feature. */ private static boolean disallowKitedAutostart() { - return false; + return false; } } From c45e0e343d8556a9558a70bcef12a3093ec09e37 Mon Sep 17 00:00:00 2001 From: Clay Livince Date: Tue, 1 Aug 2023 21:00:54 +0800 Subject: [PATCH 6/8] fix: for 2023.2 and fixed most of the @deprecated things back on track --- build.gradle | 5 +- gradle.properties | 13 +++-- pluginVersion.txt | 2 +- .../intellij/action/KiteDelegatingAction.java | 11 ++-- .../action/KiteDelegatingEditorAction.java | 2 +- .../KiteSignaturePopupManager.java | 3 +- .../SignaturePopupController.java | 10 ++-- .../backend/http/KiteHttpConnection.java | 4 +- .../backend/json/KiteJsonParsing.java | 1 + .../KiteCodeFinderNotification.java | 3 +- .../editor/completion/KiteLookupElement.java | 1 + .../editor/events/AsyncKiteEventQueue.java | 8 +++ .../events/DefaultEditorEventListener.java | 54 ++++++++++--------- .../editor/events/KiteEventQueue.java | 6 +++ .../events/TestcaseEditorEventListener.java | 7 +-- .../documentation/DocumentationCleanup.java | 5 +- .../KiteDocumentationRendererService.java | 3 +- .../KiteDocumentFileLinkHandler.java | 5 +- .../KiteServiceNotificationsListener.java | 12 +++-- .../kite/intellij/platform/KiteDetector.java | 4 +- .../kite/intellij/platform/KitePlatform.java | 5 +- .../platform/KitePlatformComponent.java | 38 +++++-------- .../platform/fs/CanonicalFilePathFactory.java | 3 +- .../settings/KiteSettingsService.java | 4 +- .../KiteAutomaticInstallNotification.java | 7 ++- .../KiteDownloadPausedNotification.java | 7 ++- .../KiteDownloadUnpausedNotification.java | 6 +-- .../startup/KiteProjectManagerListener.java | 14 +++-- .../startup/NotificationRegistration.java | 10 ++-- .../intellij/status/KiteStatusBarWidget.java | 13 +++-- .../status/KiteStatusBarWidgetFactory.java | 25 +++++++++ .../status/KiteStatusBarWidgetProvider.java | 21 -------- .../com/kite/intellij/ui/KiteThemeUtil.java | 3 +- .../kite/intellij/ui/html/KiteXHTMLPanel.java | 14 ++--- .../ui/notifications/KiteNotifications.java | 5 +- .../welcome/KiteOnboardingManager.java | 2 +- .../welcome/KiteWelcomeNotification.java | 5 +- .../welcome/KiteWelcomeProjectListener.java | 23 +++++--- src/main/resources/META-INF/plugin.xml | 24 ++++----- .../DefaultEditorEventListenerTest.java | 6 +-- 40 files changed, 214 insertions(+), 180 deletions(-) create mode 100644 src/main/java/com/kite/intellij/status/KiteStatusBarWidgetFactory.java delete mode 100644 src/main/java/com/kite/intellij/status/KiteStatusBarWidgetProvider.java diff --git a/build.gradle b/build.gradle index 890c7ea8..06c2a44c 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,9 @@ buildscript { dependencies { classpath 'com.vladsch.flexmark:flexmark-all:0.62.2' } + repositories { + mavenCentral() + } } plugins { @@ -130,7 +133,7 @@ allprojects { } intellij { - version = '2023.1' + version = '2023.2' plugins = myPlugins pluginName = 'kite-pycharm' updateSinceUntilBuild = false diff --git a/gradle.properties b/gradle.properties index d09a1915..a7e74dbc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ sinceBuild = 222.0 -untilBuild = 231.* +untilBuild = 232.* #2021.1 #ideaVersion = IC-2021.1 @@ -17,6 +17,11 @@ untilBuild = 231.* #goPlugin = org.jetbrains.plugins.go:213.5605.12 #2022.1 -ideaVersion = IU-222.3345.118 -pycharmPlugin = PythonCore:222.3345.131 -goPlugin = org.jetbrains.plugins.go:222.3345.118 +#ideaVersion = IU-222.3345.118 +#pycharmPlugin = PythonCore:222.3345.131 +#goPlugin = org.jetbrains.plugins.go:222.3345.118 + +# 2023.2 +ideaVersion = IU-2023.2 +pycharmPlugin = PythonCore:232.8660.185 +goPlugin = org.jetbrains.plugins.go:232.8660.185 diff --git a/pluginVersion.txt b/pluginVersion.txt index f5f0aa63..c70654dd 100644 --- a/pluginVersion.txt +++ b/pluginVersion.txt @@ -1 +1 @@ -1.9.8 \ No newline at end of file +1.9.9 \ No newline at end of file diff --git a/src/main/java/com/kite/intellij/action/KiteDelegatingAction.java b/src/main/java/com/kite/intellij/action/KiteDelegatingAction.java index 1c552ec1..1d715495 100644 --- a/src/main/java/com/kite/intellij/action/KiteDelegatingAction.java +++ b/src/main/java/com/kite/intellij/action/KiteDelegatingAction.java @@ -92,7 +92,7 @@ public void actionPerformed(AnActionEvent e) { } @Override - protected void setShortcutSet(@NotNull ShortcutSet shortcutSet) { + public void setShortcutSet(@NotNull ShortcutSet shortcutSet) { //the shortcut must not be delegated because this breaks shortcuts in 163.x (no invocation of the action if the shortcut is pressed) //in that branch the registered action must have the shortcut itself, it seems super.setShortcutSet(shortcutSet); @@ -132,10 +132,11 @@ public boolean isInInjectedContext() { return fallbackAction.isInInjectedContext(); } - @Override - public boolean isTransparentUpdate() { - return fallbackAction.isTransparentUpdate(); - } + //@Override + //@Deprecated + //public boolean isTransparentUpdate() { + // return fallbackAction.isTransparentUpdate(); + //} @Override public boolean isDumbAware() { diff --git a/src/main/java/com/kite/intellij/action/KiteDelegatingEditorAction.java b/src/main/java/com/kite/intellij/action/KiteDelegatingEditorAction.java index 43e931b3..623f43ab 100644 --- a/src/main/java/com/kite/intellij/action/KiteDelegatingEditorAction.java +++ b/src/main/java/com/kite/intellij/action/KiteDelegatingEditorAction.java @@ -82,7 +82,7 @@ public void beforeActionPerformedUpdate(@Nonnull AnActionEvent e) { } @Override - protected void setShortcutSet(@NotNull ShortcutSet shortcutSet) { + public void setShortcutSet(@NotNull ShortcutSet shortcutSet) { //the shortcut must not be delegated because this breaks shortcuts in 163.x (no invocation of the action if the shortcut is pressed) //in that branch the registered action must have the shortcut itself, it seems super.setShortcutSet(shortcutSet); diff --git a/src/main/java/com/kite/intellij/action/signatureInfo/KiteSignaturePopupManager.java b/src/main/java/com/kite/intellij/action/signatureInfo/KiteSignaturePopupManager.java index 14a86ffa..f9944b24 100644 --- a/src/main/java/com/kite/intellij/action/signatureInfo/KiteSignaturePopupManager.java +++ b/src/main/java/com/kite/intellij/action/signatureInfo/KiteSignaturePopupManager.java @@ -1,7 +1,6 @@ package com.kite.intellij.action.signatureInfo; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -52,7 +51,7 @@ public static DocumentBuilderFactory createDocumentBuilderFactory() { @Nonnull public static KiteSignaturePopupManager getInstance(Project project) { - return ServiceManager.getService(project, KiteSignaturePopupManager.class); + return project.getService(KiteSignaturePopupManager.class); } @TestOnly diff --git a/src/main/java/com/kite/intellij/action/signatureInfo/SignaturePopupController.java b/src/main/java/com/kite/intellij/action/signatureInfo/SignaturePopupController.java index 85148f10..d1c8c53b 100644 --- a/src/main/java/com/kite/intellij/action/signatureInfo/SignaturePopupController.java +++ b/src/main/java/com/kite/intellij/action/signatureInfo/SignaturePopupController.java @@ -3,6 +3,7 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.codeInsight.lookup.LookupManagerListener; import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; @@ -66,6 +67,7 @@ import javax.xml.parsers.ParserConfigurationException; import java.awt.*; import java.beans.PropertyChangeListener; +import java.util.Objects; import java.util.Optional; import java.util.OptionalInt; @@ -177,19 +179,19 @@ public void caretPositionChanged(CaretEvent e) { this.htmlTextPopup.registerContentUpdateListener(htmlContentUpdateListener); - PropertyChangeListener lookupListener = evt -> { + LookupManagerListener lookupListener = (oldLookup, newLookup) -> { if (isDisposed()) { return; } - if (LookupManager.PROP_ACTIVE_LOOKUP.equals(evt.getPropertyName())) { - LookupImpl lookup = (LookupImpl) evt.getNewValue(); + if (Objects.equals(LookupManager.getActiveLookup(getEditor()), oldLookup)) { + LookupImpl lookup = (LookupImpl) newLookup; if (lookup != null) { adjustPositionForLookup(); } } }; - LookupManager.getInstance(file.getProject()).addPropertyChangeListener(lookupListener, this); + file.getProject().getMessageBus().connect().subscribe(LookupManagerListener.TOPIC, lookupListener); } public void show(LinkRenderContext linkRenderContext, SignatureLinkData linkData, Calls signatureInfo) { diff --git a/src/main/java/com/kite/intellij/backend/http/KiteHttpConnection.java b/src/main/java/com/kite/intellij/backend/http/KiteHttpConnection.java index acd73f0b..1bdea405 100644 --- a/src/main/java/com/kite/intellij/backend/http/KiteHttpConnection.java +++ b/src/main/java/com/kite/intellij/backend/http/KiteHttpConnection.java @@ -1,6 +1,6 @@ package com.kite.intellij.backend.http; -import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.application.ApplicationManager; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -15,7 +15,7 @@ public interface KiteHttpConnection { @Nonnull static KiteHttpConnection instance() { - return ServiceManager.getService(KiteHttpConnection.class); + return ApplicationManager.getApplication().getService(KiteHttpConnection.class); } /** diff --git a/src/main/java/com/kite/intellij/backend/json/KiteJsonParsing.java b/src/main/java/com/kite/intellij/backend/json/KiteJsonParsing.java index 3a575b37..239b249f 100644 --- a/src/main/java/com/kite/intellij/backend/json/KiteJsonParsing.java +++ b/src/main/java/com/kite/intellij/backend/json/KiteJsonParsing.java @@ -31,6 +31,7 @@ * Parsing of the model's JSON data structures. This implementation is thread-safe. * */ +@SuppressWarnings("deprecation") @Immutable @ThreadSafe public class KiteJsonParsing { diff --git a/src/main/java/com/kite/intellij/codeFinder/KiteCodeFinderNotification.java b/src/main/java/com/kite/intellij/codeFinder/KiteCodeFinderNotification.java index 2461a3fc..1e61cb13 100644 --- a/src/main/java/com/kite/intellij/codeFinder/KiteCodeFinderNotification.java +++ b/src/main/java/com/kite/intellij/codeFinder/KiteCodeFinderNotification.java @@ -17,6 +17,7 @@ */ class KiteCodeFinderNotification extends Notification implements KiteNotification, NotificationFullContent { public KiteCodeFinderNotification(@Nullable String title, @Nullable String content, @Nonnull NotificationType type) { - super(KiteNotifications.KITE_GROUP.getDisplayId(), Icons.KiteSmall, title, null, content, type, null); + super(KiteNotifications.KITE_GROUP.getDisplayId(), title == null ? "Kite" : title, content == null ? "" : content, type); + this.setIcon(Icons.KiteSmall); } } diff --git a/src/main/java/com/kite/intellij/editor/completion/KiteLookupElement.java b/src/main/java/com/kite/intellij/editor/completion/KiteLookupElement.java index 76757105..cbf9aff3 100644 --- a/src/main/java/com/kite/intellij/editor/completion/KiteLookupElement.java +++ b/src/main/java/com/kite/intellij/editor/completion/KiteLookupElement.java @@ -41,6 +41,7 @@ * It defines how a code completion item will appear in the user interface. * */ +@SuppressWarnings("deprecation") public class KiteLookupElement extends LookupElement { private static final Logger LOG = Logger.getInstance("#kite.completion"); private final KiteCompletion kiteData; diff --git a/src/main/java/com/kite/intellij/editor/events/AsyncKiteEventQueue.java b/src/main/java/com/kite/intellij/editor/events/AsyncKiteEventQueue.java index 5570b90b..5dba68d5 100644 --- a/src/main/java/com/kite/intellij/editor/events/AsyncKiteEventQueue.java +++ b/src/main/java/com/kite/intellij/editor/events/AsyncKiteEventQueue.java @@ -22,6 +22,7 @@ */ public class AsyncKiteEventQueue implements KiteEventQueue { private static final Logger LOG = Logger.getInstance("#kite.eventQueue"); + private boolean running = false; private final TransferQueue eventQueue = new LinkedTransferQueue<>(); @@ -36,6 +37,7 @@ public synchronized void start() { thread = new WorkerThread(eventQueue); thread.start(); + this.running = true; } @Override @@ -44,6 +46,12 @@ public synchronized void stop() { thread.interrupt(); thread = null; } + this.running = false; + } + + @Override + public boolean isRunning() { + return running; } @Override diff --git a/src/main/java/com/kite/intellij/editor/events/DefaultEditorEventListener.java b/src/main/java/com/kite/intellij/editor/events/DefaultEditorEventListener.java index 0464f2e8..b6eec58d 100644 --- a/src/main/java/com/kite/intellij/editor/events/DefaultEditorEventListener.java +++ b/src/main/java/com/kite/intellij/editor/events/DefaultEditorEventListener.java @@ -7,7 +7,6 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Document; @@ -20,11 +19,15 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.startup.ProjectActivity; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFrame; import com.intellij.psi.PsiDocumentManager; import com.intellij.util.Alarm; import com.kite.intellij.KiteConstants; +import com.kite.intellij.KiteProjectLifecycleService; import com.kite.intellij.backend.KiteServerSettingsService; import com.kite.intellij.backend.model.EventType; import com.kite.intellij.backend.model.TextSelection; @@ -33,7 +36,10 @@ import com.kite.intellij.platform.KitePlatform; import com.kite.intellij.platform.fs.CanonicalFilePath; import com.kite.intellij.platform.fs.CanonicalFilePathFactory; +import kotlin.Unit; +import kotlin.coroutines.Continuation; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.annotation.Nonnull; import java.awt.*; @@ -45,8 +51,9 @@ *

* It will only react to events if the current platform is supported by Kite. * - */ -public class DefaultEditorEventListener extends AbstractProjectComponent implements EditorEventListener, FrameStateListener, Disposable { + */ +public class DefaultEditorEventListener implements EditorEventListener, ProjectActivity, FrameStateListener, Disposable { + private Project myProject; private static final Logger LOG = Logger.getInstance("#kite.editorEvent"); private static final Key KEY_FLUSH_ON_DOC_COMMIT = Key.create("kite.docFlush"); @@ -56,26 +63,15 @@ public class DefaultEditorEventListener extends AbstractProjectComponent impleme private final int alarmDelayMillis; private final Set currentlyModifiedDocuments = Sets.newConcurrentHashSet(); private final CanonicalFilePathFactory filePathFactory; - private final FileEditorManager fileEditorManager; + private FileEditorManager fileEditorManager; //lock to synchronize on when accessing the request event maps private final Object requestLock = new Object(); - @SuppressWarnings("unused") - public DefaultEditorEventListener(Project project) { - this(project, - KiteConstants.DEFAULT_QUEUE_TIMEOUT_MILLIS, - CanonicalFilePathFactory.getInstance(), - KiteConstants.ALARM_DELAY_MILLIS); - } - - protected DefaultEditorEventListener(Project project, int queueIntervalMillis, CanonicalFilePathFactory filePathFactory, int alarmDelayMillis) { - super(project); - + protected DefaultEditorEventListener() { this.eventQueue = new AsyncKiteEventQueue(); - this.alarmDelayMillis = alarmDelayMillis; - this.fileEditorManager = FileEditorManager.getInstance(myProject); - this.filePathFactory = filePathFactory; + this.alarmDelayMillis = KiteConstants.ALARM_DELAY_MILLIS; + this.filePathFactory = CanonicalFilePathFactory.getInstance(); this.editAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, this); } @@ -113,13 +109,22 @@ public void dispose() { eventQueue.stop(); } + + @Nullable @Override - public void projectOpened() { + public Object execute(@NotNull Project project, @NotNull Continuation continuation) { + this.myProject = project; + this.fileEditorManager = FileEditorManager.getInstance(myProject); + if (!KitePlatform.isOsVersionSupported()) { - return; + return null; } - eventQueue.start(); + Disposer.register(project.getService(KiteProjectLifecycleService.class), this); + + // This is strange. why could it be started twice? + if (!eventQueue.isRunning()) + eventQueue.start(); EditorFactory editorFactory = EditorFactory.getInstance(); @@ -230,11 +235,8 @@ public void focusLost(@NotNull Editor editor) { }, this); ApplicationManager.getApplication().getMessageBus().connect(this).subscribe(FrameStateListener.TOPIC, this); - } - @Override - public void projectClosed() { - eventQueue.stop(); + return null; } /** @@ -242,7 +244,7 @@ public void projectClosed() { * If there is a current editor open and if it has the focus then a focus event is send to kite. */ @Override - public void onFrameActivated() { + public void onFrameActivated(@NotNull IdeFrame frame) { Editor editor = fileEditorManager.getSelectedTextEditor(); if (editor == null) { return; diff --git a/src/main/java/com/kite/intellij/editor/events/KiteEventQueue.java b/src/main/java/com/kite/intellij/editor/events/KiteEventQueue.java index b1ad9a60..04b5d007 100644 --- a/src/main/java/com/kite/intellij/editor/events/KiteEventQueue.java +++ b/src/main/java/com/kite/intellij/editor/events/KiteEventQueue.java @@ -70,6 +70,12 @@ static KiteEventQueue getInstance(Project project) { */ void addEvent(KiteEvent newEvent); + /** + * Indicates the queue is running or not. + * @return weather the queue is running or not. + */ + boolean isRunning(); + @FunctionalInterface interface KiteQueueComputable { T compute() throws KiteHttpException; diff --git a/src/main/java/com/kite/intellij/editor/events/TestcaseEditorEventListener.java b/src/main/java/com/kite/intellij/editor/events/TestcaseEditorEventListener.java index f4398105..e57672b4 100644 --- a/src/main/java/com/kite/intellij/editor/events/TestcaseEditorEventListener.java +++ b/src/main/java/com/kite/intellij/editor/events/TestcaseEditorEventListener.java @@ -23,11 +23,8 @@ @SuppressWarnings("ComponentNotRegistered") @TestOnly public class TestcaseEditorEventListener extends DefaultEditorEventListener { - public TestcaseEditorEventListener(Project project) { - super(project, - KiteConstants.DEFAULT_QUEUE_TIMEOUT_MILLIS, - CanonicalFilePathFactory.getInstance(), - KiteConstants.ALARM_DELAY_MILLIS); + public TestcaseEditorEventListener() { + super(); } public static void sleepForQueueWork(Project project) throws InterruptedException { diff --git a/src/main/java/com/kite/intellij/lang/documentation/DocumentationCleanup.java b/src/main/java/com/kite/intellij/lang/documentation/DocumentationCleanup.java index c491cfe0..ddc191a5 100644 --- a/src/main/java/com/kite/intellij/lang/documentation/DocumentationCleanup.java +++ b/src/main/java/com/kite/intellij/lang/documentation/DocumentationCleanup.java @@ -5,6 +5,7 @@ import com.kite.intellij.backend.response.SymbolReportResponse; import com.kite.intellij.backend.response.ValueReportResponse; import org.jsoup.Jsoup; +import org.jsoup.safety.Safelist; import org.jsoup.safety.Whitelist; /** @@ -12,12 +13,12 @@ * */ class DocumentationCleanup { - private static final Whitelist WHITELIST = Whitelist.relaxed() + private static final Safelist SAFELIST = Safelist.relaxed() .addAttributes(":all", "class", "style", "title") .addProtocols("a", "href", "kite", "#"); private static String cleanup(String html) { - return Jsoup.clean(html, WHITELIST); + return Jsoup.clean(html, SAFELIST); } static HoverResponse cleanup(HoverResponse hover) { diff --git a/src/main/java/com/kite/intellij/lang/documentation/KiteDocumentationRendererService.java b/src/main/java/com/kite/intellij/lang/documentation/KiteDocumentationRendererService.java index b64c31c4..be2571cf 100644 --- a/src/main/java/com/kite/intellij/lang/documentation/KiteDocumentationRendererService.java +++ b/src/main/java/com/kite/intellij/lang/documentation/KiteDocumentationRendererService.java @@ -1,7 +1,6 @@ package com.kite.intellij.lang.documentation; import com.intellij.openapi.Disposable; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; @@ -22,7 +21,7 @@ public KiteDocumentationRendererService() { @Nonnull public static KiteDocumentationRendererService getInstance(Project project) { - return ServiceManager.getService(project, KiteDocumentationRendererService.class); + return project.getService(KiteDocumentationRendererService.class); } public KiteDocumentationRenderer getDetailedRenderer() { diff --git a/src/main/java/com/kite/intellij/lang/documentation/linkHandler/KiteDocumentFileLinkHandler.java b/src/main/java/com/kite/intellij/lang/documentation/linkHandler/KiteDocumentFileLinkHandler.java index cd55dca2..e6df704a 100644 --- a/src/main/java/com/kite/intellij/lang/documentation/linkHandler/KiteDocumentFileLinkHandler.java +++ b/src/main/java/com/kite/intellij/lang/documentation/linkHandler/KiteDocumentFileLinkHandler.java @@ -15,6 +15,7 @@ import javax.annotation.Nonnull; import java.net.URI; +import java.util.List; import java.util.Optional; /** @@ -79,8 +80,8 @@ public void postRender(String link, LinkRenderContext renderContext) { VirtualFile file = fileOpt.get(); - FileEditorProvider[] providers = FileEditorProviderManager.getInstance().getProviders(renderContext.getProject(), file); - if (providers.length > 0) { + List providers = FileEditorProviderManager.getInstance().getProviderList(renderContext.getProject(), file); + if (!providers.isEmpty()) { //configured line at column 0, the logical line passed to the descriptor seems to start at 0 OpenFileDescriptor descriptor = new OpenFileDescriptor(renderContext.getProject(), file, linkData.getLine().orElse(1) - 1, 0); FileEditorManager.getInstance(renderContext.getProject()).openTextEditor(descriptor, true); diff --git a/src/main/java/com/kite/intellij/notifications/KiteServiceNotificationsListener.java b/src/main/java/com/kite/intellij/notifications/KiteServiceNotificationsListener.java index ea4b5a4b..3777170c 100644 --- a/src/main/java/com/kite/intellij/notifications/KiteServiceNotificationsListener.java +++ b/src/main/java/com/kite/intellij/notifications/KiteServiceNotificationsListener.java @@ -2,13 +2,15 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManagerListener; +import com.intellij.openapi.startup.ProjectActivity; import com.intellij.openapi.startup.StartupManager; import com.kite.intellij.KiteProjectLifecycleService; import com.kite.intellij.backend.KiteApiService; import com.kite.intellij.backend.json.KiteJsonParsing; import com.kite.intellij.backend.model.KiteServiceNotification; import com.kite.intellij.ui.notifications.KiteNotifications; +import kotlin.Unit; +import kotlin.coroutines.Continuation; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; @@ -17,13 +19,14 @@ * Listens for HTTP responses with status 503 (service unavailable) and displays * a notification if the HTTP response's body contained one. */ -public class KiteServiceNotificationsListener implements ProjectManagerListener { +public class KiteServiceNotificationsListener implements ProjectActivity { private static final Logger LOG = Logger.getInstance("#kite.notifications"); + @org.jetbrains.annotations.Nullable @Override - public void projectOpened(@NotNull Project project) { + public Object execute(@NotNull Project project, @NotNull Continuation continuation) { if (project.isDefault()) { - return; + return null; } StartupManager.getInstance(project).runAfterOpened(() -> { @@ -45,6 +48,7 @@ public void projectOpened(@NotNull Project project) { return false; }, KiteProjectLifecycleService.getInstance(project)); }); + return null; } private void handleKiteNotification(@NotNull Project project, @Nullable String body) { diff --git a/src/main/java/com/kite/intellij/platform/KiteDetector.java b/src/main/java/com/kite/intellij/platform/KiteDetector.java index 95e114e6..63964842 100644 --- a/src/main/java/com/kite/intellij/platform/KiteDetector.java +++ b/src/main/java/com/kite/intellij/platform/KiteDetector.java @@ -1,6 +1,6 @@ package com.kite.intellij.platform; -import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.SystemInfo; import com.kite.intellij.platform.exec.ExecutableDetector; import com.kite.intellij.platform.exec.GenericProcessLauncher; @@ -51,7 +51,7 @@ public KiteDetector() { @Nonnull public static KiteDetector getInstance() { - return ServiceManager.getService(KiteDetector.class); + return ApplicationManager.getApplication().getService(KiteDetector.class); } @Override diff --git a/src/main/java/com/kite/intellij/platform/KitePlatform.java b/src/main/java/com/kite/intellij/platform/KitePlatform.java index 6750bbf0..d67ea2a8 100644 --- a/src/main/java/com/kite/intellij/platform/KitePlatform.java +++ b/src/main/java/com/kite/intellij/platform/KitePlatform.java @@ -19,7 +19,10 @@ public class KitePlatform { public static boolean isOsVersionSupported() { if (SystemInfo.isMac) { LOG.debug("OS: Mac" + SystemInfo.getMacOSVersionCode()); - return SystemInfo.isMacOSYosemite; + + // Under JAVA 17, MAC already have enough version for this. + return true; + //return SystemInfo.isMacOSYosemite; } if (SystemInfo.isWindows) { diff --git a/src/main/java/com/kite/intellij/platform/KitePlatformComponent.java b/src/main/java/com/kite/intellij/platform/KitePlatformComponent.java index ee28d104..6beca60a 100644 --- a/src/main/java/com/kite/intellij/platform/KitePlatformComponent.java +++ b/src/main/java/com/kite/intellij/platform/KitePlatformComponent.java @@ -1,49 +1,35 @@ package com.kite.intellij.platform; import com.intellij.notification.Notification; -import com.intellij.notification.NotificationListener; import com.intellij.notification.NotificationType; import com.intellij.openapi.project.Project; +import com.intellij.openapi.startup.ProjectActivity; import com.kite.intellij.Icons; import com.kite.intellij.ui.notifications.KiteNotifications; +import kotlin.Unit; +import kotlin.coroutines.Continuation; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.annotation.Nonnull; /** * Project component which displays a warning if the current OS or OS version is not supported by Kite. */ -public class KitePlatformComponent implements com.intellij.openapi.components.ProjectComponent { - private final Project project; - - public KitePlatformComponent(Project project) { - this.project = project; - } - - @Nonnull - public static KitePlatformComponent getInstance(Project project) { - return project.getComponent(KitePlatformComponent.class); - } - - @Nonnull - @Override - public String getComponentName() { - return "kite.PlatformComponent"; - } - +public class KitePlatformComponent implements ProjectActivity { + @Nullable @Override - public void projectOpened() { + public Object execute(@NotNull Project project, @NotNull Continuation continuation) { if (KitePlatform.isOsVersionNotSupported()) { String title = "Kite"; String subtitle = "Unsupported platform"; String content = "Kite is currently not yet available for your system. Please check kite.com for the currently supported platforms."; - Notification notification = new Notification(KiteNotifications.KITE_GROUP.getDisplayId(), Icons.KiteSmall, title, subtitle, content, NotificationType.ERROR, new NotificationListener.UrlOpeningListener(false)); + Notification notification = new Notification(KiteNotifications.KITE_GROUP.getDisplayId(), title, content, NotificationType.ERROR); + notification.setSubtitle(subtitle); + notification.setIcon(Icons.KiteSmall); notification.notify(project); } - } - - @Override - public void projectClosed() { - + return null; } } diff --git a/src/main/java/com/kite/intellij/platform/fs/CanonicalFilePathFactory.java b/src/main/java/com/kite/intellij/platform/fs/CanonicalFilePathFactory.java index e7f3c93d..d839bd4d 100644 --- a/src/main/java/com/kite/intellij/platform/fs/CanonicalFilePathFactory.java +++ b/src/main/java/com/kite/intellij/platform/fs/CanonicalFilePathFactory.java @@ -1,5 +1,6 @@ package com.kite.intellij.platform.fs; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -17,7 +18,7 @@ public interface CanonicalFilePathFactory { @Nonnull static CanonicalFilePathFactory getInstance() { - return ServiceManager.getService(CanonicalFilePathFactory.class); + return ApplicationManager.getApplication().getService(CanonicalFilePathFactory.class); } @Nullable diff --git a/src/main/java/com/kite/intellij/settings/KiteSettingsService.java b/src/main/java/com/kite/intellij/settings/KiteSettingsService.java index 262c767f..a2b6d1c4 100644 --- a/src/main/java/com/kite/intellij/settings/KiteSettingsService.java +++ b/src/main/java/com/kite/intellij/settings/KiteSettingsService.java @@ -2,8 +2,8 @@ import com.google.common.collect.Lists; import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.util.Disposer; @@ -27,7 +27,7 @@ public KiteSettingsService() { } public static KiteSettingsService getInstance() { - return ServiceManager.getService(KiteSettingsService.class); + return ApplicationManager.getApplication().getService(KiteSettingsService.class); } @Nonnull diff --git a/src/main/java/com/kite/intellij/startup/KiteAutomaticInstallNotification.java b/src/main/java/com/kite/intellij/startup/KiteAutomaticInstallNotification.java index dc950f1c..5e1fb898 100644 --- a/src/main/java/com/kite/intellij/startup/KiteAutomaticInstallNotification.java +++ b/src/main/java/com/kite/intellij/startup/KiteAutomaticInstallNotification.java @@ -33,11 +33,10 @@ public static void showNotification(@Nullable Project project, @NotNull Runnable private static class InstallNotification extends Notification implements NotificationFullContent { private InstallNotification(@NotNull Runnable onInstallCallback) { super(KiteNotifications.KITE_GROUP.getDisplayId(), - Icons.KiteSmall, - "Kite", "", + "Kite", "Kite requires the Kite Copilot desktop application to provide completions and documentation. Please install it to use Kite.", - NotificationType.INFORMATION, null); - + NotificationType.INFORMATION); + this.setIcon(Icons.KiteSmall); addAction(new NotificationAction("Install") { @Override public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) { diff --git a/src/main/java/com/kite/intellij/startup/KiteDownloadPausedNotification.java b/src/main/java/com/kite/intellij/startup/KiteDownloadPausedNotification.java index a8c1c8d8..18293807 100644 --- a/src/main/java/com/kite/intellij/startup/KiteDownloadPausedNotification.java +++ b/src/main/java/com/kite/intellij/startup/KiteDownloadPausedNotification.java @@ -31,11 +31,10 @@ public static void showNotification(@Nullable Project project) { private static class PausedNotification extends Notification implements NotificationFullContent { private PausedNotification() { super(KiteNotifications.KITE_GROUP.getDisplayId(), - Icons.KiteSmall, - "Temporarily unable to install", "", + "Temporarily unable to install", "Kite requires the Kite Copilot to function. However, it cannot be downloaded for the next few weeks. This plugin will notify you when it's available again.", - NotificationType.INFORMATION, null); - + NotificationType.INFORMATION); + this.setIcon(Icons.KiteSmall); addAction(new NotificationAction("Close") { @Override public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) { diff --git a/src/main/java/com/kite/intellij/startup/KiteDownloadUnpausedNotification.java b/src/main/java/com/kite/intellij/startup/KiteDownloadUnpausedNotification.java index a10b7f88..037d2593 100644 --- a/src/main/java/com/kite/intellij/startup/KiteDownloadUnpausedNotification.java +++ b/src/main/java/com/kite/intellij/startup/KiteDownloadUnpausedNotification.java @@ -33,12 +33,12 @@ public static void showNotification(@Nullable Project project, @NotNull Runnable private static class UnpausedNotification extends Notification implements NotificationFullContent { private UnpausedNotification(@NotNull Runnable onInstallCallback) { super(KiteNotifications.KITE_GROUP.getDisplayId(), - Icons.KiteSmall, - "Kite", "", + "Kite", "The Kite Engine application is installable again. " + "Kite requires the Kite Engine desktop application to provide completions and documentation. " + "Please install it to use Kite.", - NotificationType.INFORMATION, null); + NotificationType.INFORMATION); + this.setIcon(Icons.KiteSmall); addAction(new NotificationAction("Install") { @Override diff --git a/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java b/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java index 596cd3f2..b7738c9d 100644 --- a/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java +++ b/src/main/java/com/kite/intellij/startup/KiteProjectManagerListener.java @@ -5,14 +5,17 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManagerListener; +import com.intellij.openapi.startup.ProjectActivity; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtilRt; import com.kite.intellij.platform.KiteDetector; import com.kite.intellij.platform.KiteInstallService; import com.kite.intellij.settings.KiteSettingsService; +import kotlin.Unit; +import kotlin.coroutines.Continuation; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -25,14 +28,15 @@ * notifications have to be displayed. The application listener has no project and may be executed before a project * window is shown. */ -public class KiteProjectManagerListener implements ProjectManagerListener { +public class KiteProjectManagerListener implements ProjectActivity { private static final Logger LOG = Logger.getInstance("#kite.startup"); private static volatile boolean firstProjectOpened; + @Nullable @Override - public void projectOpened(@NotNull Project project) { + public Object execute(@NotNull Project project, @NotNull Continuation continuation) { if (project.isDefault() || firstProjectOpened) { - return; + return null; } StartupManager.getInstance(project).runAfterOpened(() -> { @@ -45,8 +49,8 @@ public void projectOpened(@NotNull Project project) { ApplicationManager.getApplication().executeOnPooledThread(() -> onAppStarting(project)); } }); + return null; } - private void onAppStarting(@NotNull Project project) { if (KiteDetector.getInstance().isRunning()) { return; diff --git a/src/main/java/com/kite/intellij/startup/NotificationRegistration.java b/src/main/java/com/kite/intellij/startup/NotificationRegistration.java index 48ef3273..fdb36cf9 100644 --- a/src/main/java/com/kite/intellij/startup/NotificationRegistration.java +++ b/src/main/java/com/kite/intellij/startup/NotificationRegistration.java @@ -1,8 +1,8 @@ package com.kite.intellij.startup; -import com.intellij.openapi.application.PreloadingActivity; -import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.ide.ApplicationInitializedListener; import com.kite.intellij.ui.notifications.KiteNotifications; +import kotlinx.coroutines.CoroutineScope; import javax.annotation.Nonnull; @@ -10,12 +10,12 @@ * This preloading activity takes care of the Kite notification group. * */ -public class NotificationRegistration extends PreloadingActivity { +public class NotificationRegistration implements ApplicationInitializedListener { public NotificationRegistration() { } - @Override - public void preload(@Nonnull ProgressIndicator indicator) { + + public void execute(CoroutineScope asyncScope) { // access the Kite notification group to force it to initialize KiteNotifications.KITE_GROUP.getDisplayId(); } diff --git a/src/main/java/com/kite/intellij/status/KiteStatusBarWidget.java b/src/main/java/com/kite/intellij/status/KiteStatusBarWidget.java index 7f530069..b7fdc2e9 100644 --- a/src/main/java/com/kite/intellij/status/KiteStatusBarWidget.java +++ b/src/main/java/com/kite/intellij/status/KiteStatusBarWidget.java @@ -66,7 +66,7 @@ public KiteStatusBarWidget(@NotNull Project project) { iconLabel = new JBLabel(); iconLabel.putClientProperty(UIUtil.CENTER_TOOLTIP_DEFAULT, Boolean.TRUE); iconLabel.setOpaque(true); - iconLabel.setBorder(WidgetBorder.ICON); + //iconLabel.setBorder(WidgetBorder.ICON); connectionStatusListener = (connectionAvailable, error) -> { if (!connectionAvailable) { @@ -126,7 +126,7 @@ public String ID() { public void install(@Nonnull StatusBar statusBar) { super.install(statusBar); - Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor(); + Editor editor = FileEditorManager.getInstance(getProject()).getSelectedTextEditor(); CanonicalFilePath currentEditorFile = editor == null ? null : CanonicalFilePathFactory.getInstance().createFor(editor, CanonicalFilePathFactory.Context.Event); Pair status = computeIconStatus(currentEditorFile, null, KiteApiService.getInstance()); updateStatusbarIcon(status); @@ -157,7 +157,6 @@ public void dispose() { * * @param event The event */ - @Override public void selectionChanged(@NotNull FileEditorManagerEvent event) { refreshStatusIconAsync(); } @@ -237,7 +236,7 @@ public boolean openStatusPanel() { kiteStatusResponse != null ? kiteStatusResponse.getButton() : null); //the swing component must be made visible in the AWT EDT - UIUtil.invokeLaterIfNeeded(() -> popupController.show(KiteStatusBarWidget.this, myProject, model)); + UIUtil.invokeLaterIfNeeded(() -> popupController.show(KiteStatusBarWidget.this, getProject(), model)); } catch (Exception e) { LOG.error("Error while retrieving kite status", e); } @@ -308,7 +307,7 @@ static Pair computeIconStatus(@Nullable CanonicalFilePath cu } private void closePopup() { - JBPopup currentPopup = popupController.getCurrentPopup(myProject); + JBPopup currentPopup = popupController.getCurrentPopup(getProject()); if (currentPopup != null) { currentPopup.closeOk(null); } @@ -316,7 +315,7 @@ private void closePopup() { private void updateStatusbarIcon(@Nullable Pair iconAndText) { // myProject may be null if this widget is already disposed - if (isDisposed() || myProject.isDisposed()) { + if (isDisposed() || getProject().isDisposed()) { return; } @@ -332,7 +331,7 @@ private void updateStatusbarIcon(@Nullable Pair iconAndText) // disabled for now, as Kite's message is too long //iconLabel.setText(iconAndText.second); } else { - iconLabel.setBorder(WidgetBorder.ICON); + //iconLabel.setBorder(WidgetBorder.ICON); } }); } diff --git a/src/main/java/com/kite/intellij/status/KiteStatusBarWidgetFactory.java b/src/main/java/com/kite/intellij/status/KiteStatusBarWidgetFactory.java new file mode 100644 index 00000000..db98a98a --- /dev/null +++ b/src/main/java/com/kite/intellij/status/KiteStatusBarWidgetFactory.java @@ -0,0 +1,25 @@ +package com.kite.intellij.status; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.NlsContexts; +import com.intellij.openapi.wm.StatusBarWidget; +import com.intellij.openapi.wm.StatusBarWidgetFactory; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class KiteStatusBarWidgetFactory implements StatusBarWidgetFactory { + @Override + public @NotNull @NonNls String getId() { + return "kite.statusbar.widgetfactory"; + } + + @Override + public @NotNull @NlsContexts.ConfigurableName String getDisplayName() { + return "Kite"; + } + + @Override + public @NotNull StatusBarWidget createWidget(@NotNull Project project) { + return new KiteStatusBarWidget(project); + } +} diff --git a/src/main/java/com/kite/intellij/status/KiteStatusBarWidgetProvider.java b/src/main/java/com/kite/intellij/status/KiteStatusBarWidgetProvider.java deleted file mode 100644 index 42011eaf..00000000 --- a/src/main/java/com/kite/intellij/status/KiteStatusBarWidgetProvider.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.kite.intellij.status; - -import com.intellij.diagnostic.IdeMessagePanel; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.wm.StatusBar; -import com.intellij.openapi.wm.StatusBarWidget; -import com.intellij.openapi.wm.StatusBarWidgetProvider; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class KiteStatusBarWidgetProvider implements StatusBarWidgetProvider { - @Override - public @Nullable StatusBarWidget getWidget(@NotNull Project project) { - return new KiteStatusBarWidget(project); - } - - @Override - public @NotNull String getAnchor() { - return StatusBar.Anchors.before(IdeMessagePanel.FATAL_ERROR); - } -} diff --git a/src/main/java/com/kite/intellij/ui/KiteThemeUtil.java b/src/main/java/com/kite/intellij/ui/KiteThemeUtil.java index 09f07aef..7c358af5 100644 --- a/src/main/java/com/kite/intellij/ui/KiteThemeUtil.java +++ b/src/main/java/com/kite/intellij/ui/KiteThemeUtil.java @@ -19,7 +19,6 @@ * look&feel. * */ -@SuppressWarnings("UseJBColor") public class KiteThemeUtil { private KiteThemeUtil() { } @@ -47,7 +46,7 @@ public static boolean isConsistentToLookAndFeel(EditorColorsScheme scheme) { public static Color getPanelBackground(EditorColorsScheme colorScheme) { if (isConsistentToLookAndFeel(colorScheme)) { //the default light look&feel has a yellow bg color in 161.x, at least - return new JBColor(() -> UIManager.getColor("Panel.background")); + return JBColor.lazy(() -> UIManager.getColor("Panel.background")); } //the theme doesn't fit to the look&feel, i.e. probably a light theme for a dark look&feel (or a dark theme for a light look&feel) diff --git a/src/main/java/com/kite/intellij/ui/html/KiteXHTMLPanel.java b/src/main/java/com/kite/intellij/ui/html/KiteXHTMLPanel.java index 417a0d4d..7cae3ad6 100644 --- a/src/main/java/com/kite/intellij/ui/html/KiteXHTMLPanel.java +++ b/src/main/java/com/kite/intellij/ui/html/KiteXHTMLPanel.java @@ -140,19 +140,19 @@ public void log(String where, Level level, String msg, Throwable throwable) { public void setLevel(String logger, Level level) { Logger log = LOGGERS.get(logger); if (log != null) { - org.apache.log4j.Level targetLevel; + com.intellij.openapi.diagnostic.LogLevel targetLevel; if (level == Level.ALL) { - targetLevel = org.apache.log4j.Level.ERROR; + targetLevel = com.intellij.openapi.diagnostic.LogLevel.ERROR; } else if (level == Level.SEVERE) { - targetLevel = org.apache.log4j.Level.ERROR; + targetLevel = com.intellij.openapi.diagnostic.LogLevel.ERROR; } else if (level == Level.WARNING) { - targetLevel = org.apache.log4j.Level.WARN; + targetLevel = com.intellij.openapi.diagnostic.LogLevel.WARNING; } else if (level == Level.INFO) { - targetLevel = org.apache.log4j.Level.INFO; + targetLevel = com.intellij.openapi.diagnostic.LogLevel.INFO; } else if (level == Level.FINE) { - targetLevel = org.apache.log4j.Level.DEBUG; + targetLevel = com.intellij.openapi.diagnostic.LogLevel.DEBUG; } else { - targetLevel = org.apache.log4j.Level.TRACE; + targetLevel = com.intellij.openapi.diagnostic.LogLevel.TRACE; } log.setLevel(targetLevel); diff --git a/src/main/java/com/kite/intellij/ui/notifications/KiteNotifications.java b/src/main/java/com/kite/intellij/ui/notifications/KiteNotifications.java index df2d66b2..49dd259d 100644 --- a/src/main/java/com/kite/intellij/ui/notifications/KiteNotifications.java +++ b/src/main/java/com/kite/intellij/ui/notifications/KiteNotifications.java @@ -15,7 +15,7 @@ import javax.annotation.Nullable; public class KiteNotifications { - public static final NotificationGroup KITE_GROUP = new NotificationGroup("Kite", NotificationDisplayType.STICKY_BALLOON, true); + public static final NotificationGroup KITE_GROUP = NotificationGroupManager.getInstance().getNotificationGroup("Kite"); public static void showServiceNotification(@Nullable Project project, @Nonnull KiteServiceNotification kiteNotification) { // don't show more than one notification at a time @@ -65,7 +65,8 @@ public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification noti private static class KiteServiceUINotification extends Notification implements NotificationFullContent, KiteNotification { public KiteServiceUINotification(@NotNull NotificationType type) { - super(KiteNotifications.KITE_GROUP.getDisplayId(), Icons.KiteSmall, type); + super(KiteNotifications.KITE_GROUP.getDisplayId(), "", type); + this.setIcon(Icons.KiteSmall); } } } diff --git a/src/main/java/com/kite/intellij/welcome/KiteOnboardingManager.java b/src/main/java/com/kite/intellij/welcome/KiteOnboardingManager.java index 7f4d547f..c3d133ae 100644 --- a/src/main/java/com/kite/intellij/welcome/KiteOnboardingManager.java +++ b/src/main/java/com/kite/intellij/welcome/KiteOnboardingManager.java @@ -157,7 +157,7 @@ public static void showErrorNotification(@Nullable Project project, @Nullable St new KiteWelcomeNotification( "We were unable to open the tutorial", message.toString(), - NotificationType.ERROR, null + NotificationType.ERROR ).notify(project); } } diff --git a/src/main/java/com/kite/intellij/welcome/KiteWelcomeNotification.java b/src/main/java/com/kite/intellij/welcome/KiteWelcomeNotification.java index bbd15ce1..edfda08a 100644 --- a/src/main/java/com/kite/intellij/welcome/KiteWelcomeNotification.java +++ b/src/main/java/com/kite/intellij/welcome/KiteWelcomeNotification.java @@ -16,7 +16,8 @@ * */ class KiteWelcomeNotification extends Notification implements KiteNotification, NotificationFullContent { - public KiteWelcomeNotification(@Nullable String title, @Nullable String content, @Nonnull NotificationType type, @Nullable NotificationListener listener) { - super(KiteNotifications.KITE_GROUP.getDisplayId(), Icons.KiteSmall, title, null, content, type, listener); + public KiteWelcomeNotification(@Nullable String title, @Nullable String content, @Nonnull NotificationType type) { + super(KiteNotifications.KITE_GROUP.getDisplayId(), title == null ? "Kite" : title, content == null ? "" : content, type); + this.setIcon(Icons.KiteSmall); } } diff --git a/src/main/java/com/kite/intellij/welcome/KiteWelcomeProjectListener.java b/src/main/java/com/kite/intellij/welcome/KiteWelcomeProjectListener.java index 11309fc2..a7d4036a 100644 --- a/src/main/java/com/kite/intellij/welcome/KiteWelcomeProjectListener.java +++ b/src/main/java/com/kite/intellij/welcome/KiteWelcomeProjectListener.java @@ -9,11 +9,12 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManagerListener; +import com.intellij.openapi.startup.ProjectActivity; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.wm.WindowManager; import com.intellij.util.messages.MessageBusConnection; import com.kite.intellij.KiteConstants; +import com.kite.intellij.KiteProjectLifecycleService; import com.kite.intellij.backend.KiteApiService; import com.kite.intellij.backend.KiteServerSettings; import com.kite.intellij.backend.http.KiteHttpException; @@ -21,7 +22,10 @@ import com.kite.intellij.settings.KiteSettingsService; import com.kite.intellij.startup.KiteAutostartListener; import com.kite.intellij.util.KiteBrowserUtil; +import kotlin.Unit; +import kotlin.coroutines.Continuation; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.annotation.Nonnull; import javax.swing.*; @@ -33,17 +37,18 @@ * The notification contains a link to the public http url and an ignore action to suppress the message on next startup. * */ -public class KiteWelcomeProjectListener implements ProjectManagerListener, DumbAware { +public class KiteWelcomeProjectListener implements ProjectActivity, DumbAware { private static final Logger LOG = Logger.getInstance("#kite.welcome"); + @Nullable @Override - public void projectOpened(@NotNull Project project) { - StartupManager.getInstance(project).runWhenProjectIsInitialized(() -> { + public Object execute(@NotNull Project project, @NotNull Continuation continuation) { + StartupManager.getInstance(project).runAfterOpened(() -> { Application app = ApplicationManager.getApplication(); - MessageBusConnection connection = app.getMessageBus().connect(project); + MessageBusConnection connection = app.getMessageBus().connect(project.getService(KiteProjectLifecycleService.class)); // if this plugin starts kited, then do onboarding as soon as it's available - connection.subscribe(KiteAutostartListener.TOPIC, () -> { + connection.subscribe(KiteAutostartListener.TOPIC, (KiteAutostartListener) () -> { JFrame frame = WindowManager.getInstance().getFrame(project); if (frame != null && frame.isActive()) { app.executeOnPooledThread(() -> doOnboarding(project)); @@ -59,8 +64,10 @@ public void projectOpened(@NotNull Project project) { } } }); + return null; } + private void doOnboarding(@NotNull Project project) { assert ApplicationManager.getApplication().isUnitTestMode() || !ApplicationManager.getApplication().isDispatchThread(); @@ -96,7 +103,7 @@ private void doOnboarding(@NotNull Project project) { Notification notification = new KiteWelcomeNotification( "Welcome to the future of programming.", "Kite is now integrated with your IDE.", - NotificationType.INFORMATION, null); + NotificationType.INFORMATION); notification.addAction(new ShowKiteDocsAction(notification, "Learn how to use Kite")); notification.addAction(new DisableWelcomeInfoAction(notification)); notification.notify(project); @@ -114,7 +121,7 @@ private void doOnboardingAction(@Nonnull KiteLanguage language, Project project) Notification notification = new KiteWelcomeNotification("Welcome to Kite!", "We've setup an interactive tutorial for you, but we have docs to get you started too!
", - NotificationType.INFORMATION, null); + NotificationType.INFORMATION); notification.addAction(new ShowKiteDocsAction(notification, "Learn more about Kite")); notification.addAction(new DisableWelcomeInfoAction(notification)); notification.notify(project); diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 9e33db4c..9f942b05 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -23,15 +23,8 @@ - - - - + @@ -83,9 +76,7 @@ - - - + Kite kiteCodeNavIntention + + + + + + + diff --git a/src/test/java/com/kite/intellij/editor/events/DefaultEditorEventListenerTest.java b/src/test/java/com/kite/intellij/editor/events/DefaultEditorEventListenerTest.java index d6e7f711..c9af2a21 100644 --- a/src/test/java/com/kite/intellij/editor/events/DefaultEditorEventListenerTest.java +++ b/src/test/java/com/kite/intellij/editor/events/DefaultEditorEventListenerTest.java @@ -252,15 +252,15 @@ protected void addOverridingRequest(Map requestMap, T key, Alar } }; - listener.addOverridingRequest(listener.pendingEditorChangeRequests, new MockDocument(), listener.editAlarm, () -> { + listener.addOverridingRequest(listener.getPendingEditorChangeRequests(), new MockDocument(), listener.getEditAlarm(), () -> { performedRequests.add("a"); }); - listener.addOverridingRequest(listener.pendingEditorChangeRequests, new MockDocument(), listener.editAlarm, () -> { + listener.addOverridingRequest(listener.getPendingEditorChangeRequests(), new MockDocument(), listener.getEditAlarm(), () -> { performedRequests.add("b"); }); - listener.addOverridingRequest(listener.pendingEditorChangeRequests, new MockDocument(), listener.editAlarm, () -> { + listener.addOverridingRequest(listener.getPendingEditorChangeRequests(), new MockDocument(), listener.getEditAlarm(), () -> { performedRequests.add("c"); }); From cee987ed8ed1407c0fdf1b4b9c0e86a9d5d0492d Mon Sep 17 00:00:00 2001 From: Clay Livince Date: Wed, 2 Aug 2023 10:02:18 +0800 Subject: [PATCH 7/8] fix: cross-project listener management to avoid bugs --- pluginVersion.txt | 2 +- .../events/DefaultEditorEventListener.java | 390 +---------------- .../events/ProjectEditorEventListener.java | 409 ++++++++++++++++++ .../DefaultEditorEventListenerTest.java | 10 +- .../com/kite/intellij/test/KiteTestUtils.java | 6 +- 5 files changed, 426 insertions(+), 391 deletions(-) create mode 100644 src/main/java/com/kite/intellij/editor/events/ProjectEditorEventListener.java diff --git a/pluginVersion.txt b/pluginVersion.txt index c70654dd..b3fc49da 100644 --- a/pluginVersion.txt +++ b/pluginVersion.txt @@ -1 +1 @@ -1.9.9 \ No newline at end of file +1.9.9b \ No newline at end of file diff --git a/src/main/java/com/kite/intellij/editor/events/DefaultEditorEventListener.java b/src/main/java/com/kite/intellij/editor/events/DefaultEditorEventListener.java index b6eec58d..070261fe 100644 --- a/src/main/java/com/kite/intellij/editor/events/DefaultEditorEventListener.java +++ b/src/main/java/com/kite/intellij/editor/events/DefaultEditorEventListener.java @@ -1,50 +1,17 @@ package com.kite.intellij.editor.events; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.intellij.ide.FrameStateListener; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Caret; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.editor.event.*; -import com.intellij.openapi.editor.ex.DocumentEx; -import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.ex.FocusChangeListener; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.ProjectActivity; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.util.Alarm; -import com.kite.intellij.KiteConstants; import com.kite.intellij.KiteProjectLifecycleService; -import com.kite.intellij.backend.KiteServerSettingsService; -import com.kite.intellij.backend.model.EventType; -import com.kite.intellij.backend.model.TextSelection; -import com.kite.intellij.editor.util.FileEditorUtil; -import com.kite.intellij.lang.KiteLanguageSupport; import com.kite.intellij.platform.KitePlatform; -import com.kite.intellij.platform.fs.CanonicalFilePath; -import com.kite.intellij.platform.fs.CanonicalFilePathFactory; import kotlin.Unit; import kotlin.coroutines.Continuation; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.annotation.Nonnull; -import java.awt.*; import java.util.Map; -import java.util.Set; /** * Listens to IntelliJ's events and executes the coresponding Kite events whenever necessary. @@ -52,366 +19,25 @@ * It will only react to events if the current platform is supported by Kite. * */ -public class DefaultEditorEventListener implements EditorEventListener, ProjectActivity, FrameStateListener, Disposable { - private Project myProject; - private static final Logger LOG = Logger.getInstance("#kite.editorEvent"); - private static final Key KEY_FLUSH_ON_DOC_COMMIT = Key.create("kite.docFlush"); - - protected final Alarm editAlarm; - protected final Map pendingEditorChangeRequests = Maps.newHashMap(); - private final KiteEventQueue eventQueue; - private final int alarmDelayMillis; - private final Set currentlyModifiedDocuments = Sets.newConcurrentHashSet(); - private final CanonicalFilePathFactory filePathFactory; - private FileEditorManager fileEditorManager; - - //lock to synchronize on when accessing the request event maps - private final Object requestLock = new Object(); - - protected DefaultEditorEventListener() { - this.eventQueue = new AsyncKiteEventQueue(); - this.alarmDelayMillis = KiteConstants.ALARM_DELAY_MILLIS; - this.filePathFactory = CanonicalFilePathFactory.getInstance(); - - this.editAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, this); - } - - @Override - public KiteEventQueue getEventQueue() { - return eventQueue; - } - - public void awaitEvents() { - if (LOG.isTraceEnabled()) { - LOG.trace("awaitEvents"); - } - - if (isEventDispatchThread()) { - synchronized (requestLock) { - //editAlarm.flush() can not be used because it doesn't wrap with an outer write session - //and calls invokeLater for the runnables - editAlarm.cancelAllRequests(); - - //we need to iterate on a copy because the runnables remove the map entry on their own - if (!pendingEditorChangeRequests.isEmpty()) { - for (Runnable runnable : Lists.newArrayList(pendingEditorChangeRequests.values())) { - runnable.run(); - } - - pendingEditorChangeRequests.clear(); - } - } - } - } - - @Override - public void dispose() { - eventQueue.stop(); - } - +public class DefaultEditorEventListener implements ProjectActivity { + private final Map listenerByProject = Maps.newHashMap(); @Nullable @Override public Object execute(@NotNull Project project, @NotNull Continuation continuation) { - this.myProject = project; - this.fileEditorManager = FileEditorManager.getInstance(myProject); - if (!KitePlatform.isOsVersionSupported()) { return null; } - Disposer.register(project.getService(KiteProjectLifecycleService.class), this); - - // This is strange. why could it be started twice? - if (!eventQueue.isRunning()) - eventQueue.start(); - - EditorFactory editorFactory = EditorFactory.getInstance(); - - EditorEventMulticaster eventMulticaster = editorFactory.getEventMulticaster(); - - eventMulticaster.addDocumentListener(new DocumentListener() { - @Override - public void beforeDocumentChange(@NotNull DocumentEvent e) { - Document document = e.getDocument(); - - VirtualFile file = FileDocumentManager.getInstance().getFile(document); - if (file == null || !file.isInLocalFileSystem()) { - return; - } - - if (!Boolean.TRUE.equals(KEY_FLUSH_ON_DOC_COMMIT.get(document))) { - KEY_FLUSH_ON_DOC_COMMIT.set(document, Boolean.TRUE); - - //we need to flush pending events (for the current file) on document flush - //the code completion commits and then calls the completion provider - //we can't flush pending edit events in our completion provider because this will lead to a dead lock - // - EDT calls completion in a pooled thread - // - pooled thread calls completion -> completion calls flush -> flushed actions must be run on EDT - // - waiting on the EDT here will dead-lock our application - // we're not invoking PsiDocumentManagerBase.addRunOnCommit directly, - // because it changed to a non-static method in 2020.2 - PsiDocumentManager.getInstance(myProject).performForCommittedDocument(document, () -> { - //the commit action is only run once, we need to re-register before the next change event - if (LOG.isTraceEnabled()) { - LOG.trace("awaitEvents on commit"); - } - - try { - awaitEvents(); - } finally { - KEY_FLUSH_ON_DOC_COMMIT.set(document, null); - } - }); - } - - //this call must not be added to the alarm ticker because Alarm on 171.x doesn't seem to guarantee - //execution order and thus the beforeDocumentChange event might be called after the documentChange - //which is added later to the alarm and this breaks our logic - //beforeDocumentChange is rather cheap, so we call it directly - DefaultEditorEventListener.this.beforeDocumentChange(e); - } - - @Override - public void documentChanged(@NotNull DocumentEvent e) { - Document document = e.getDocument(); - VirtualFile file = FileDocumentManager.getInstance().getFile(document); - if (file == null || !file.isInLocalFileSystem()) { - return; - } - - if (LOG.isTraceEnabled()) { - LOG.trace("Edit event \"" + e.getNewFragment() + "\""); - } - - addOverridingRequest(pendingEditorChangeRequests, document, editAlarm, () -> DefaultEditorEventListener.this.documentChanged(e)); - } - }, this); - - eventMulticaster.addCaretListener(new CaretListener() { - @Override - public void caretPositionChanged(@NotNull CaretEvent e) { - Document document = e.getEditor().getDocument(); - - VirtualFile file = FileDocumentManager.getInstance().getFile(document); - if (file == null || !file.isInLocalFileSystem()) { - return; - } - - addOverridingRequest(pendingEditorChangeRequests, document, editAlarm, () -> DefaultEditorEventListener.this.caretPositionChanged(e)); - - } - }, this); - - // We don't subscribe with myProject.getMessageBus().connect(myProject).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER - // because the the FILE_EDITOR_MANAGER event is only triggered when a new editor is created, - // we listen for focus changes (e.g. by tab activation) below but attach to each new editor - // we must handle editors restored at startup, though. Extra careful testing in the new IJ branches must be - // done to make sure that restored files generate focus events - editorFactory.addEditorFactoryListener(new EditorFactoryListener() { - @Override - public void editorCreated(@NotNull EditorFactoryEvent event) { - Editor editor = event.getEditor(); - if (!(editor instanceof EditorEx)) { - return; - } - - ((EditorEx) editor).addFocusListener(new FocusChangeListener() { - @Override - public void focusGained(@NotNull Editor editor) { - if (editor instanceof EditorEx) { - VirtualFile virtualFile = ((EditorEx) editor).getVirtualFile(); - if (virtualFile != null) { - DefaultEditorEventListener.this.fileFocused(editor, virtualFile); - } - } - } - - @Override - public void focusLost(@NotNull Editor editor) { - } - }, DefaultEditorEventListener.this); - } - }, this); - - ApplicationManager.getApplication().getMessageBus().connect(this).subscribe(FrameStateListener.TOPIC, this); - - return null; - } - - /** - * Called when the IntelliJ window's frame is activated. - * If there is a current editor open and if it has the focus then a focus event is send to kite. - */ - @Override - public void onFrameActivated(@NotNull IdeFrame frame) { - Editor editor = fileEditorManager.getSelectedTextEditor(); - if (editor == null) { - return; - } - - CanonicalFilePath path = filePathFactory.createFor(editor, CanonicalFilePathFactory.Context.Event); - if (path != null) { - eventQueue.addEvent(KiteEventFactory.create(EventType.FOCUS, path, editor)); - if (LOG.isDebugEnabled()) { - LOG.debug("Focus event after frame activation"); - } + if (!listenerByProject.containsKey(project)){ + listenerByProject.put(project, new ProjectEditorEventListener(project)); } - } - - public void fileFocused(@Nonnull Editor editor, @Nonnull VirtualFile file) { - if (editor.isDisposed() || editor.isOneLineMode() || editor.isViewer()) { - return; - } - - CanonicalFilePath filePath = filePathFactory.createFor(editor, CanonicalFilePathFactory.Context.Event); - if (filePath == null) { - return; - } - - if (file.getLength() > KiteServerSettingsService.getInstance().getMaxFileSizeBytes()) { - eventQueue.addEvent(KiteEventFactory.createSkipEvent(filePath)); - } else { - eventQueue.addEvent(KiteEventFactory.create(EventType.FOCUS, filePath, editor)); - } - } - - /** - * Registers a new request which handles an editor event. - * - * @param requestMap The map where the new request is inserted and any previous event of the same kind is removed from - * @param key - * @param alarm - * @param newRequest - * @param - */ - protected void addOverridingRequest(Map requestMap, T key, Alarm alarm, Runnable newRequest) { - synchronized (requestLock) { - Runnable oldRequest = requestMap.get(key); - if (oldRequest != null) { - requestMap.remove(key); - alarm.cancelRequest(oldRequest); - - if (LOG.isTraceEnabled()) { - LOG.trace("Dropping request due to new editor action"); - } - } - } - - Runnable runnable = () -> { - //this is not totally safe because (in theory) it might happen that there was another key added for key in the meantime - synchronized (requestLock) { - requestMap.remove(key); - } - newRequest.run(); - }; + ProjectEditorEventListener projectEditorEventListener = listenerByProject.get(project); + Disposer.register(project.getService(KiteProjectLifecycleService.class), projectEditorEventListener); - synchronized (requestLock) { - requestMap.put(key, runnable); - } - - alarm.addRequest(runnable, alarmDelayMillis); - } - - private void caretPositionChanged(CaretEvent e) { - if (LOG.isTraceEnabled()) { - LOG.trace("caretPositionChanged"); - } - - Caret caret = e.getCaret(); - if (caret == null) { - return; - } - - Editor editor = e.getEditor(); - if (editor.isDisposed()) { - return; - } + projectEditorEventListener.execute(); - CanonicalFilePath filePath = filePathFactory.createFor(e.getEditor(), CanonicalFilePathFactory.Context.Event); - if (filePath == null) { - return; - } - - if (e.getEditor().getDocument().getTextLength() > KiteServerSettingsService.getInstance().getMaxFileSizeBytes()) { - //text length is != byte length but decoding is expensive - if (LOG.isTraceEnabled()) { - LOG.trace("Sending skip event instead of caret change for " + filePath); - } - eventQueue.addEvent(KiteEventFactory.createSkipEvent(filePath)); - return; - } - - TextSelection selection; - if (caret.hasSelection()) { - selection = TextSelection.create(caret.getSelectionStart(), caret.getSelectionEnd()); - } else { - selection = TextSelection.create(caret.getOffset()); - } - - // http status listener updates only if the current file is supported by Kite, - boolean supported = KiteLanguageSupport.isSupported(editor, KiteLanguageSupport.Feature.BasicSupport); - eventQueue.addEvent(KiteEventFactory.create(EventType.SELECTION, filePath, FileEditorUtil.contentOf(editor), selection, editor.getDocument(), supported)); - } - - private void beforeDocumentChange(DocumentEvent event) { - if (LOG.isTraceEnabled()) { - LOG.trace("beforeDocumentChanged"); - } - - Document document = event.getDocument(); - if (document instanceof DocumentEx && document.isInBulkUpdate()) { - return; - } - - CanonicalFilePath filePath = filePathFactory.createFor(document, CanonicalFilePathFactory.Context.Event); - if (filePath != null && document.getTextLength() <= KiteServerSettingsService.getInstance().getMaxFileSizeBytes()) { - //text length is != file size with non-ascii content. decoding into bytes is expensive, though. - currentlyModifiedDocuments.add(filePath); - } - } - - private void documentChanged(DocumentEvent event) { - if (LOG.isTraceEnabled()) { - LOG.trace("documentChanged"); - } - - Document document = event.getDocument(); - if (document instanceof DocumentEx && document.isInBulkUpdate()) { - return; - } - - CanonicalFilePath filePath = filePathFactory.createFor(document, CanonicalFilePathFactory.Context.Event); - if (filePath == null) { - //may happen in test cases or for documents which do not represent a file system element, e.g. a LightVirtualFile used to do code completions etc. - return; - } - - try { - final Editor textEditor = fileEditorManager.getSelectedTextEditor(); - if (textEditor == null || !textEditor.getDocument().equals(document)) { - //a document modification without an editor could be a refactoring - //IntelliJ does not automatically save changes after a refactoring, so have to send events for these files, too - if (LOG.isTraceEnabled()) { - LOG.trace("Ignoring change outside of the current editor: " + filePath.asOSDelimitedPath()); - } - return; - } - - //null file paths might happen in test cases, for example, when the document is not yet attached to an actual VirtualFile/PsiFile. - if (currentlyModifiedDocuments.contains(filePath)) { - int editorOffset = textEditor.getCaretModel().getOffset(); - eventQueue.addEvent(KiteEventFactory.create(EventType.EDIT, filePath, FileEditorUtil.contentOf(document), TextSelection.create(editorOffset), document, true)); - } - } finally { - currentlyModifiedDocuments.remove(filePath); - } - } - - // taken from JetBrain's Alarm as it was removed from 183.x - private static boolean isEventDispatchThread() { - Application app = ApplicationManager.getApplication(); - return app != null && app.isDispatchThread() || EventQueue.isDispatchThread(); + return null; } } diff --git a/src/main/java/com/kite/intellij/editor/events/ProjectEditorEventListener.java b/src/main/java/com/kite/intellij/editor/events/ProjectEditorEventListener.java new file mode 100644 index 00000000..11baefa5 --- /dev/null +++ b/src/main/java/com/kite/intellij/editor/events/ProjectEditorEventListener.java @@ -0,0 +1,409 @@ +package com.kite.intellij.editor.events; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.intellij.ide.FrameStateListener; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Caret; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.event.*; +import com.intellij.openapi.editor.ex.DocumentEx; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.ex.FocusChangeListener; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFrame; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.util.Alarm; +import com.kite.intellij.KiteConstants; +import com.kite.intellij.backend.KiteServerSettingsService; +import com.kite.intellij.backend.model.EventType; +import com.kite.intellij.backend.model.TextSelection; +import com.kite.intellij.editor.util.FileEditorUtil; +import com.kite.intellij.lang.KiteLanguageSupport; +import com.kite.intellij.platform.fs.CanonicalFilePath; +import com.kite.intellij.platform.fs.CanonicalFilePathFactory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nonnull; +import java.awt.*; +import java.util.Map; +import java.util.Set; + +/** + * Listens to IntelliJ's events and executes the coresponding Kite events whenever necessary. + *

+ * It will only react to events if the current platform is supported by Kite. + * + */ +public class ProjectEditorEventListener implements EditorEventListener, FrameStateListener, Disposable { + private static final Logger LOG = Logger.getInstance("#kite.editorEvent"); + private static final Key KEY_FLUSH_ON_DOC_COMMIT = Key.create("kite.docFlush"); + + protected final Alarm editAlarm; + protected final Map pendingEditorChangeRequests = Maps.newHashMap(); + private final int alarmDelayMillis; + private final Set currentlyModifiedDocuments = Sets.newConcurrentHashSet(); + private final CanonicalFilePathFactory filePathFactory; + + //lock to synchronize on when accessing the request event maps + private final Object requestLock = new Object(); + + private final Project myProject; + + private final KiteEventQueue eventQueue; + private final FileEditorManager fileEditorManager; + + protected ProjectEditorEventListener(Project project) { + this.myProject = project; + this.eventQueue = new AsyncKiteEventQueue(); + this.fileEditorManager = FileEditorManager.getInstance(project); + + this.alarmDelayMillis = KiteConstants.ALARM_DELAY_MILLIS; + this.filePathFactory = CanonicalFilePathFactory.getInstance(); + + this.editAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, this); + } + + @Override + public KiteEventQueue getEventQueue() { + return eventQueue; + } + + public void awaitEvents() { + if (LOG.isTraceEnabled()) { + LOG.trace("awaitEvents"); + } + + if (isEventDispatchThread()) { + synchronized (requestLock) { + //editAlarm.flush() can not be used because it doesn't wrap with an outer write session + //and calls invokeLater for the runnables + editAlarm.cancelAllRequests(); + + //we need to iterate on a copy because the runnables remove the map entry on their own + if (!pendingEditorChangeRequests.isEmpty()) { + for (Runnable runnable : Lists.newArrayList(pendingEditorChangeRequests.values())) { + runnable.run(); + } + + pendingEditorChangeRequests.clear(); + } + } + } + } + + @Override + public void dispose() { + eventQueue.stop(); + } + + + @Nullable + public Object execute() { + // This is strange. why could it be started twice? + if (!eventQueue.isRunning()) + eventQueue.start(); + + EditorFactory editorFactory = EditorFactory.getInstance(); + + EditorEventMulticaster eventMulticaster = editorFactory.getEventMulticaster(); + + eventMulticaster.addDocumentListener(new DocumentListener() { + @Override + public void beforeDocumentChange(@NotNull DocumentEvent e) { + Document document = e.getDocument(); + + VirtualFile file = FileDocumentManager.getInstance().getFile(document); + if (file == null || !file.isInLocalFileSystem()) { + return; + } + + if (!Boolean.TRUE.equals(KEY_FLUSH_ON_DOC_COMMIT.get(document))) { + KEY_FLUSH_ON_DOC_COMMIT.set(document, Boolean.TRUE); + + //we need to flush pending events (for the current file) on document flush + //the code completion commits and then calls the completion provider + //we can't flush pending edit events in our completion provider because this will lead to a dead lock + // - EDT calls completion in a pooled thread + // - pooled thread calls completion -> completion calls flush -> flushed actions must be run on EDT + // - waiting on the EDT here will dead-lock our application + // we're not invoking PsiDocumentManagerBase.addRunOnCommit directly, + // because it changed to a non-static method in 2020.2 + PsiDocumentManager.getInstance(myProject).performForCommittedDocument(document, () -> { + //the commit action is only run once, we need to re-register before the next change event + if (LOG.isTraceEnabled()) { + LOG.trace("awaitEvents on commit"); + } + + try { + awaitEvents(); + } finally { + KEY_FLUSH_ON_DOC_COMMIT.set(document, null); + } + }); + } + + //this call must not be added to the alarm ticker because Alarm on 171.x doesn't seem to guarantee + //execution order and thus the beforeDocumentChange event might be called after the documentChange + //which is added later to the alarm and this breaks our logic + //beforeDocumentChange is rather cheap, so we call it directly + ProjectEditorEventListener.this.beforeDocumentChange(e); + } + + @Override + public void documentChanged(@NotNull DocumentEvent e) { + Document document = e.getDocument(); + VirtualFile file = FileDocumentManager.getInstance().getFile(document); + if (file == null || !file.isInLocalFileSystem()) { + return; + } + + if (LOG.isTraceEnabled()) { + LOG.trace("Edit event \"" + e.getNewFragment() + "\""); + } + + addOverridingRequest(pendingEditorChangeRequests, document, editAlarm, () -> ProjectEditorEventListener.this.documentChanged(e)); + } + }, this); + + eventMulticaster.addCaretListener(new CaretListener() { + @Override + public void caretPositionChanged(@NotNull CaretEvent e) { + Document document = e.getEditor().getDocument(); + + VirtualFile file = FileDocumentManager.getInstance().getFile(document); + if (file == null || !file.isInLocalFileSystem()) { + return; + } + + addOverridingRequest(pendingEditorChangeRequests, document, editAlarm, () -> ProjectEditorEventListener.this.caretPositionChanged(e)); + + } + }, this); + + // We don't subscribe with myProject.getMessageBus().connect(myProject).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER + // because the the FILE_EDITOR_MANAGER event is only triggered when a new editor is created, + // we listen for focus changes (e.g. by tab activation) below but attach to each new editor + // we must handle editors restored at startup, though. Extra careful testing in the new IJ branches must be + // done to make sure that restored files generate focus events + editorFactory.addEditorFactoryListener(new EditorFactoryListener() { + @Override + public void editorCreated(@NotNull EditorFactoryEvent event) { + Editor editor = event.getEditor(); + if (!(editor instanceof EditorEx)) { + return; + } + + ((EditorEx) editor).addFocusListener(new FocusChangeListener() { + @Override + public void focusGained(@NotNull Editor editor) { + if (editor instanceof EditorEx) { + VirtualFile virtualFile = ((EditorEx) editor).getVirtualFile(); + if (virtualFile != null) { + ProjectEditorEventListener.this.fileFocused(editor, virtualFile); + } + } + } + + }, ProjectEditorEventListener.this); + } + }, this); + + ApplicationManager.getApplication().getMessageBus().connect(this).subscribe(FrameStateListener.TOPIC, this); + + return null; + } + + /** + * Called when the IntelliJ window's frame is activated. + * If there is a current editor open and if it has the focus then a focus event is send to kite. + */ + @Override + public void onFrameActivated(@NotNull IdeFrame frame) { + Project project = frame.getProject(); + if (project == null || project.isDisposed()){ + return; + } + + Editor editor = fileEditorManager.getSelectedTextEditor(); + if (editor == null) { + return; + } + + CanonicalFilePath path = filePathFactory.createFor(editor, CanonicalFilePathFactory.Context.Event); + if (path != null) { + eventQueue.addEvent(KiteEventFactory.create(EventType.FOCUS, path, editor)); + if (LOG.isDebugEnabled()) { + LOG.debug("Focus event after frame activation"); + } + } + } + + public void fileFocused(@Nonnull Editor editor, @Nonnull VirtualFile file) { + if (editor.isDisposed() || editor.isOneLineMode() || editor.isViewer()) { + return; + } + + CanonicalFilePath filePath = filePathFactory.createFor(editor, CanonicalFilePathFactory.Context.Event); + if (filePath == null) { + return; + } + + if (file.getLength() > KiteServerSettingsService.getInstance().getMaxFileSizeBytes()) { + eventQueue.addEvent(KiteEventFactory.createSkipEvent(filePath)); + } else { + eventQueue.addEvent(KiteEventFactory.create(EventType.FOCUS, filePath, editor)); + } + } + + /** + * Registers a new request which handles an editor event. + * + * @param requestMap The map where the new request is inserted and any previous event of the same kind is removed from + * @param key + * @param alarm + * @param newRequest + * @param + */ + protected void addOverridingRequest(Map requestMap, T key, Alarm alarm, Runnable newRequest) { + synchronized (requestLock) { + Runnable oldRequest = requestMap.get(key); + if (oldRequest != null) { + requestMap.remove(key); + alarm.cancelRequest(oldRequest); + + if (LOG.isTraceEnabled()) { + LOG.trace("Dropping request due to new editor action"); + } + } + } + + Runnable runnable = () -> { + //this is not totally safe because (in theory) it might happen that there was another key added for key in the meantime + synchronized (requestLock) { + requestMap.remove(key); + } + + newRequest.run(); + }; + + synchronized (requestLock) { + requestMap.put(key, runnable); + } + + alarm.addRequest(runnable, alarmDelayMillis); + } + + private void caretPositionChanged(CaretEvent e) { + if (LOG.isTraceEnabled()) { + LOG.trace("caretPositionChanged"); + } + + Caret caret = e.getCaret(); + if (caret == null) { + return; + } + + Editor editor = e.getEditor(); + if (editor.isDisposed()) { + return; + } + + CanonicalFilePath filePath = filePathFactory.createFor(e.getEditor(), CanonicalFilePathFactory.Context.Event); + if (filePath == null) { + return; + } + + if (e.getEditor().getDocument().getTextLength() > KiteServerSettingsService.getInstance().getMaxFileSizeBytes()) { + //text length is != byte length but decoding is expensive + if (LOG.isTraceEnabled()) { + LOG.trace("Sending skip event instead of caret change for " + filePath); + } + eventQueue.addEvent(KiteEventFactory.createSkipEvent(filePath)); + return; + } + + TextSelection selection; + if (caret.hasSelection()) { + selection = TextSelection.create(caret.getSelectionStart(), caret.getSelectionEnd()); + } else { + selection = TextSelection.create(caret.getOffset()); + } + + // http status listener updates only if the current file is supported by Kite, + boolean supported = KiteLanguageSupport.isSupported(editor, KiteLanguageSupport.Feature.BasicSupport); + eventQueue.addEvent(KiteEventFactory.create(EventType.SELECTION, filePath, FileEditorUtil.contentOf(editor), selection, editor.getDocument(), supported)); + } + + private void beforeDocumentChange(DocumentEvent event) { + if (LOG.isTraceEnabled()) { + LOG.trace("beforeDocumentChanged"); + } + + Document document = event.getDocument(); + if (document instanceof DocumentEx && document.isInBulkUpdate()) { + return; + } + + CanonicalFilePath filePath = filePathFactory.createFor(document, CanonicalFilePathFactory.Context.Event); + if (filePath != null && document.getTextLength() <= KiteServerSettingsService.getInstance().getMaxFileSizeBytes()) { + //text length is != file size with non-ascii content. decoding into bytes is expensive, though. + currentlyModifiedDocuments.add(filePath); + } + } + + private void documentChanged(DocumentEvent event) { + + if (LOG.isTraceEnabled()) { + LOG.trace("documentChanged"); + } + + Document document = event.getDocument(); + if (document instanceof DocumentEx && document.isInBulkUpdate()) { + return; + } + + CanonicalFilePath filePath = filePathFactory.createFor(document, CanonicalFilePathFactory.Context.Event); + if (filePath == null) { + //may happen in test cases or for documents which do not represent a file system element, e.g. a LightVirtualFile used to do code completions etc. + return; + } + + try { + final Editor textEditor = fileEditorManager.getSelectedTextEditor(); + if (textEditor == null || !textEditor.getDocument().equals(document)) { + //a document modification without an editor could be a refactoring + //IntelliJ does not automatically save changes after a refactoring, so have to send events for these files, too + if (LOG.isTraceEnabled()) { + LOG.trace("Ignoring change outside of the current editor: " + filePath.asOSDelimitedPath()); + } + return; + } + + //null file paths might happen in test cases, for example, when the document is not yet attached to an actual VirtualFile/PsiFile. + if (currentlyModifiedDocuments.contains(filePath)) { + int editorOffset = textEditor.getCaretModel().getOffset(); + eventQueue.addEvent(KiteEventFactory.create(EventType.EDIT, filePath, FileEditorUtil.contentOf(document), TextSelection.create(editorOffset), document, true)); + } + } finally { + currentlyModifiedDocuments.remove(filePath); + } + } + + // taken from JetBrain's Alarm as it was removed from 183.x + private static boolean isEventDispatchThread() { + Application app = ApplicationManager.getApplication(); + return app != null && app.isDispatchThread() || EventQueue.isDispatchThread(); + } +} diff --git a/src/test/java/com/kite/intellij/editor/events/DefaultEditorEventListenerTest.java b/src/test/java/com/kite/intellij/editor/events/DefaultEditorEventListenerTest.java index c9af2a21..f63b8ef9 100644 --- a/src/test/java/com/kite/intellij/editor/events/DefaultEditorEventListenerTest.java +++ b/src/test/java/com/kite/intellij/editor/events/DefaultEditorEventListenerTest.java @@ -173,7 +173,7 @@ public void testUnsupportedFilesWhitelisting() throws Exception { @Test public void testOnFrameActivation() throws Exception { - DefaultEditorEventListener eventListener = (DefaultEditorEventListener) EditorEventListener.getInstance(getProject()); + ProjectEditorEventListener eventListener = (ProjectEditorEventListener) EditorEventListener.getInstance(getProject()); MockKiteApiService api = MockKiteApiService.getInstance(); Assert.assertTrue("No api calls expected before the edit events", api.getCallHistory().isEmpty()); @@ -224,7 +224,7 @@ public void testAwaitEventsInSwingThread() throws Exception { AtomicBoolean inAwaitCall = new AtomicBoolean(false); List performedRequests = new CopyOnWriteArrayList<>(); - DefaultEditorEventListener listener = new DefaultEditorEventListener(getProject(), 500, CanonicalFilePathFactory.getInstance(), 500) { + ProjectEditorEventListener listener = new ProjectEditorEventListener(getProject()) { @Override public void awaitEvents() { awaitWasCalled.set(true); @@ -252,15 +252,15 @@ protected void addOverridingRequest(Map requestMap, T key, Alar } }; - listener.addOverridingRequest(listener.getPendingEditorChangeRequests(), new MockDocument(), listener.getEditAlarm(), () -> { + listener.addOverridingRequest(listener.pendingEditorChangeRequests, new MockDocument(), listener.editAlarm, () -> { performedRequests.add("a"); }); - listener.addOverridingRequest(listener.getPendingEditorChangeRequests(), new MockDocument(), listener.getEditAlarm(), () -> { + listener.addOverridingRequest(listener.pendingEditorChangeRequests, new MockDocument(), listener.editAlarm, () -> { performedRequests.add("b"); }); - listener.addOverridingRequest(listener.getPendingEditorChangeRequests(), new MockDocument(), listener.getEditAlarm(), () -> { + listener.addOverridingRequest(listener.pendingEditorChangeRequests, new MockDocument(), listener.editAlarm, () -> { performedRequests.add("c"); }); diff --git a/src/test/java/com/kite/intellij/test/KiteTestUtils.java b/src/test/java/com/kite/intellij/test/KiteTestUtils.java index 54bd8b14..88f5de22 100644 --- a/src/test/java/com/kite/intellij/test/KiteTestUtils.java +++ b/src/test/java/com/kite/intellij/test/KiteTestUtils.java @@ -7,7 +7,7 @@ import com.intellij.openapi.util.io.StreamUtil; import com.intellij.psi.PsiFile; import com.intellij.testFramework.fixtures.CodeInsightTestFixture; -import com.kite.intellij.editor.events.DefaultEditorEventListener; +import com.kite.intellij.editor.events.ProjectEditorEventListener; import com.kite.intellij.editor.events.EditorEventListener; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -133,11 +133,11 @@ public static void configureByFileAndFocus(String filePath, CodeInsightTestFixtu public static void emulateFocusEvent(PsiFile psiFile) { Project project = psiFile.getProject(); Editor selectedTextEditor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - ((DefaultEditorEventListener) EditorEventListener.getInstance(project)).fileFocused(selectedTextEditor, psiFile.getVirtualFile()); + ((ProjectEditorEventListener) EditorEventListener.getInstance(project)).fileFocused(selectedTextEditor, psiFile.getVirtualFile()); } public static void emulatedFrameActivation(Project project) { - ((DefaultEditorEventListener) EditorEventListener.getInstance(project)).onFrameActivated(); + ((ProjectEditorEventListener) EditorEventListener.getInstance(project)).onFrameActivated(); } private static String trimHtmlWhitespace(String prettyHtml) { From 2770c78eed52a00e3efc09a7b5883cd7baf549de Mon Sep 17 00:00:00 2001 From: Clay Livince Date: Tue, 12 Dec 2023 18:51:01 +0800 Subject: [PATCH 8/8] fix: for 2023.3 --- build.gradle | 2 +- gradle.properties | 13 +++++++++---- pluginVersion.txt | 2 +- .../completion/KiteDocumentationProvider.java | 2 +- .../intellij/backend/http/HttpStatusException.java | 2 +- .../backend/http/JettyAsyncHttpConnection.java | 2 +- .../com/kite/intellij/backend/json/JsonUtils.java | 2 +- .../editor/completion/KiteLookupElement.java | 2 +- .../platform/exec/GenericProcessWatcher.java | 2 +- .../com/kite/intellij/status/KiteStatusModel.java | 2 +- .../kite/intellij/ui/html/InvalidHTMLException.java | 2 +- .../java/com/kite/intellij/util/SwingDebugUtil.java | 2 +- .../completion/KiteCompletionAutoinsertTest.java | 2 +- .../editor/events/EditorEventLatencyTest.java | 2 +- .../java/com/kite/testrunner/TestRunnerUtil.java | 2 +- .../java/com/kite/testrunner/TestStepHelper.java | 2 +- .../kite/testrunner/actions/RemoveTextAction.java | 2 +- .../testrunner/expectations/RequestExpectation.java | 2 +- 18 files changed, 26 insertions(+), 21 deletions(-) diff --git a/build.gradle b/build.gradle index 06c2a44c..99ea28d2 100644 --- a/build.gradle +++ b/build.gradle @@ -133,7 +133,7 @@ allprojects { } intellij { - version = '2023.2' + version = '2023.3' plugins = myPlugins pluginName = 'kite-pycharm' updateSinceUntilBuild = false diff --git a/gradle.properties b/gradle.properties index a7e74dbc..181756c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ sinceBuild = 222.0 -untilBuild = 232.* +untilBuild = 233.* #2021.1 #ideaVersion = IC-2021.1 @@ -22,6 +22,11 @@ untilBuild = 232.* #goPlugin = org.jetbrains.plugins.go:222.3345.118 # 2023.2 -ideaVersion = IU-2023.2 -pycharmPlugin = PythonCore:232.8660.185 -goPlugin = org.jetbrains.plugins.go:232.8660.185 +# ideaVersion = IU-2023.2 +# pycharmPlugin = PythonCore:232.8660.185 +# goPlugin = org.jetbrains.plugins.go:232.8660.185 + +# 2023.3 +ideaVersion = IC-2023.3 +pycharmPlugin = PythonCore:233.11799.241 +goPlugin = org.jetbrains.plugins.go:233.11799.228 \ No newline at end of file diff --git a/pluginVersion.txt b/pluginVersion.txt index b3fc49da..95c1eb68 100644 --- a/pluginVersion.txt +++ b/pluginVersion.txt @@ -1 +1 @@ -1.9.9b \ No newline at end of file +1.9.10 \ No newline at end of file diff --git a/src/main/java-python/com/kite/intellij/editor/completion/KiteDocumentationProvider.java b/src/main/java-python/com/kite/intellij/editor/completion/KiteDocumentationProvider.java index 6c32cdcd..d2097d33 100644 --- a/src/main/java-python/com/kite/intellij/editor/completion/KiteDocumentationProvider.java +++ b/src/main/java-python/com/kite/intellij/editor/completion/KiteDocumentationProvider.java @@ -3,7 +3,7 @@ import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.Nullable; import java.util.List; diff --git a/src/main/java/com/kite/intellij/backend/http/HttpStatusException.java b/src/main/java/com/kite/intellij/backend/http/HttpStatusException.java index 70fd7b11..2d141b9f 100644 --- a/src/main/java/com/kite/intellij/backend/http/HttpStatusException.java +++ b/src/main/java/com/kite/intellij/backend/http/HttpStatusException.java @@ -1,6 +1,6 @@ package com.kite.intellij.backend.http; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NonNls; import javax.annotation.Nonnull; diff --git a/src/main/java/com/kite/intellij/backend/http/JettyAsyncHttpConnection.java b/src/main/java/com/kite/intellij/backend/http/JettyAsyncHttpConnection.java index 6e529501..8295983f 100644 --- a/src/main/java/com/kite/intellij/backend/http/JettyAsyncHttpConnection.java +++ b/src/main/java/com/kite/intellij/backend/http/JettyAsyncHttpConnection.java @@ -6,7 +6,7 @@ import com.kite.intellij.KiteConstants; import com.kite.monitoring.TimeTracker; import com.kite.monitoring.TimerTrackers; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpResponseException; import org.eclipse.jetty.client.api.ContentResponse; diff --git a/src/main/java/com/kite/intellij/backend/json/JsonUtils.java b/src/main/java/com/kite/intellij/backend/json/JsonUtils.java index 6fc6f855..d4130f59 100644 --- a/src/main/java/com/kite/intellij/backend/json/JsonUtils.java +++ b/src/main/java/com/kite/intellij/backend/json/JsonUtils.java @@ -1,7 +1,7 @@ package com.kite.intellij.backend.json; import com.google.gson.JsonPrimitive; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; diff --git a/src/main/java/com/kite/intellij/editor/completion/KiteLookupElement.java b/src/main/java/com/kite/intellij/editor/completion/KiteLookupElement.java index cbf9aff3..42a7c225 100644 --- a/src/main/java/com/kite/intellij/editor/completion/KiteLookupElement.java +++ b/src/main/java/com/kite/intellij/editor/completion/KiteLookupElement.java @@ -24,7 +24,7 @@ import com.kite.intellij.platform.fs.CanonicalFilePathFactory; import com.kite.intellij.util.PyCharmUtil; import gnu.trove.THashSet; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; diff --git a/src/main/java/com/kite/intellij/platform/exec/GenericProcessWatcher.java b/src/main/java/com/kite/intellij/platform/exec/GenericProcessWatcher.java index c1813502..10062f52 100644 --- a/src/main/java/com/kite/intellij/platform/exec/GenericProcessWatcher.java +++ b/src/main/java/com/kite/intellij/platform/exec/GenericProcessWatcher.java @@ -5,7 +5,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import com.intellij.util.SystemProperties; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import javax.annotation.Nonnull; import java.nio.file.Files; diff --git a/src/main/java/com/kite/intellij/status/KiteStatusModel.java b/src/main/java/com/kite/intellij/status/KiteStatusModel.java index 9f02bc79..d6c417d9 100644 --- a/src/main/java/com/kite/intellij/status/KiteStatusModel.java +++ b/src/main/java/com/kite/intellij/status/KiteStatusModel.java @@ -21,7 +21,7 @@ import com.kite.intellij.platform.KiteDetector; import com.kite.intellij.platform.fs.CanonicalFilePath; import com.kite.intellij.util.KiteBrowserUtil; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; diff --git a/src/main/java/com/kite/intellij/ui/html/InvalidHTMLException.java b/src/main/java/com/kite/intellij/ui/html/InvalidHTMLException.java index f84c4338..b4fb74e8 100644 --- a/src/main/java/com/kite/intellij/ui/html/InvalidHTMLException.java +++ b/src/main/java/com/kite/intellij/ui/html/InvalidHTMLException.java @@ -1,6 +1,6 @@ package com.kite.intellij.ui.html; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.Nullable; public class InvalidHTMLException extends RuntimeException { diff --git a/src/main/java/com/kite/intellij/util/SwingDebugUtil.java b/src/main/java/com/kite/intellij/util/SwingDebugUtil.java index 041d60c2..1e0cee8f 100644 --- a/src/main/java/com/kite/intellij/util/SwingDebugUtil.java +++ b/src/main/java/com/kite/intellij/util/SwingDebugUtil.java @@ -1,6 +1,6 @@ package com.kite.intellij.util; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import javax.swing.*; import java.awt.*; diff --git a/src/test/java/com/kite/intellij/editor/completion/KiteCompletionAutoinsertTest.java b/src/test/java/com/kite/intellij/editor/completion/KiteCompletionAutoinsertTest.java index 3df29867..910879b3 100644 --- a/src/test/java/com/kite/intellij/editor/completion/KiteCompletionAutoinsertTest.java +++ b/src/test/java/com/kite/intellij/editor/completion/KiteCompletionAutoinsertTest.java @@ -10,7 +10,7 @@ import com.kite.intellij.editor.events.TestcaseEditorEventListener; import com.kite.intellij.settings.KiteSettingsService; import com.kite.intellij.test.KiteLightFixtureTest; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.junit.Assert; import org.junit.Test; diff --git a/src/test/java/com/kite/intellij/editor/events/EditorEventLatencyTest.java b/src/test/java/com/kite/intellij/editor/events/EditorEventLatencyTest.java index a408c8fc..70af9de9 100644 --- a/src/test/java/com/kite/intellij/editor/events/EditorEventLatencyTest.java +++ b/src/test/java/com/kite/intellij/editor/events/EditorEventLatencyTest.java @@ -6,7 +6,7 @@ import com.kite.intellij.backend.MockKiteApiService; import com.kite.intellij.backend.http.test.MockKiteHttpConnection; import com.kite.intellij.test.KiteLightFixtureTest; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; diff --git a/src/test/java/com/kite/testrunner/TestRunnerUtil.java b/src/test/java/com/kite/testrunner/TestRunnerUtil.java index 36f3fd4d..6e22a9b1 100644 --- a/src/test/java/com/kite/testrunner/TestRunnerUtil.java +++ b/src/test/java/com/kite/testrunner/TestRunnerUtil.java @@ -13,7 +13,7 @@ import com.intellij.util.ThrowableRunnable; import com.kite.intellij.action.signatureInfo.KiteSignaturePopupManager; import com.kite.intellij.editor.events.TestcaseEditorEventListener; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.ide.PooledThreadExecutor; import javax.annotation.Nonnull; diff --git a/src/test/java/com/kite/testrunner/TestStepHelper.java b/src/test/java/com/kite/testrunner/TestStepHelper.java index c08f1a76..29ca7d8c 100644 --- a/src/test/java/com/kite/testrunner/TestStepHelper.java +++ b/src/test/java/com/kite/testrunner/TestStepHelper.java @@ -6,7 +6,7 @@ import com.intellij.psi.PsiDocumentManager; import com.kite.intellij.editor.events.TestcaseEditorEventListener; import com.kite.testrunner.model.TestStep; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.ide.PooledThreadExecutor; import javax.annotation.Nonnull; diff --git a/src/test/java/com/kite/testrunner/actions/RemoveTextAction.java b/src/test/java/com/kite/testrunner/actions/RemoveTextAction.java index 108e27ee..3b8411cf 100644 --- a/src/test/java/com/kite/testrunner/actions/RemoveTextAction.java +++ b/src/test/java/com/kite/testrunner/actions/RemoveTextAction.java @@ -11,7 +11,7 @@ import com.kite.testrunner.TestRunnerUtil; import com.kite.testrunner.model.TestStep; import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import java.nio.charset.StandardCharsets; diff --git a/src/test/java/com/kite/testrunner/expectations/RequestExpectation.java b/src/test/java/com/kite/testrunner/expectations/RequestExpectation.java index 3cc89588..88f62670 100644 --- a/src/test/java/com/kite/testrunner/expectations/RequestExpectation.java +++ b/src/test/java/com/kite/testrunner/expectations/RequestExpectation.java @@ -10,7 +10,7 @@ import com.kite.testrunner.TestFailedException; import com.kite.testrunner.TestRunnerUtil; import com.kite.testrunner.model.TestStep; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import java.util.Collections; import java.util.LinkedList;