diff --git a/CHANGELOG.md b/CHANGELOG.md index 742072c0..600a233d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,14 @@ ### Fixed +## 4.3.1 - Jun 26, 2026 + +### Fixed + +- Fixed `java.lang.IllegalStateException: This method is forbidden on EDT because it does not pump the event queue` when opening the table editor #1050 +- Fixed `RuntimeExceptionWithAttachments: Access is allowed from Event Dispatch Thread (EDT) only` in `CsvPlugin.openLink` #1008 +- Optimized `CsvFileEditorProvider.accept` to avoid `TimeoutCancellationException` by removing redundant service access. #1033 + ## 4.3.0 - Jun 21, 2026 ### Changed diff --git a/gradle.properties b/gradle.properties index 90bb7540..a1e86754 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ pluginName=CSV Editor pluginId=net.seesharpsoft.intellij.plugins.csv -pluginVersion=4.3.0 +pluginVersion=4.3.1 pluginSinceBuild=242 diff --git a/src/main/java/net/seesharpsoft/intellij/plugins/csv/CsvPlugin.java b/src/main/java/net/seesharpsoft/intellij/plugins/csv/CsvPlugin.java index cfeca095..5d2314ca 100644 --- a/src/main/java/net/seesharpsoft/intellij/plugins/csv/CsvPlugin.java +++ b/src/main/java/net/seesharpsoft/intellij/plugins/csv/CsvPlugin.java @@ -21,10 +21,10 @@ public class CsvPlugin implements ProjectActivity, DumbAware { private static void openLink(Project project, String link) { - if (project.isDisposed()) return; + if (project == null || project.isDisposed()) return; if (link.startsWith("#")) { - ApplicationManager.getApplication().executeOnPooledThread(() -> + ApplicationManager.getApplication().invokeLater(() -> ShowSettingsUtil.getInstance().showSettingsDialog(project, link.substring(1)) ); } else { @@ -62,40 +62,42 @@ public void run(@NotNull ProgressIndicator progressIndicator) { @Override public @Nullable Object execute(@NotNull Project project, @NotNull Continuation super Unit> continuation) { doAsyncProjectMaintenance(project); - - NotificationGroup notificationGroup = NotificationGroupManager.getInstance().getNotificationGroup("net.seesharpsoft.intellij.plugins.csv"); - String version = CsvPluginManager.getVersion(); - if (version.isEmpty() || notificationGroup == null || CsvEditorSettings.getInstance().checkCurrentPluginVersion(version)) { - return continuation; - } - Notification notification = notificationGroup.createNotification( - "CSV Editor " + version + " - Change Notes", - CsvPluginManager.getChangeNotes() + - "
You can always customize plugin settings to your likings (shortcuts below)!
" + - "Visit the CSV Editor homepage to read more about the available features & settings, " + - "submit issues & feature request, " + - "or show your support by rating this plugin. Thanks!
" - , - NotificationType.INFORMATION - ); + ApplicationManager.getApplication().invokeLater(() -> { + NotificationGroup notificationGroup = NotificationGroupManager.getInstance().getNotificationGroup("net.seesharpsoft.intellij.plugins.csv"); + String version = CsvPluginManager.getVersion(); + if (version.isEmpty() || notificationGroup == null || CsvEditorSettings.getInstance().checkCurrentPluginVersion(version)) { + return; + } - notification.addAction(NotificationAction.create("General settings", (anActionEvent, notification1) -> { - openLink(project, "#" + CsvEditorSettingsProvider.CSV_EDITOR_SETTINGS_ID); - })); - notification.addAction(NotificationAction.create("Color scheme", (anActionEvent, notification1) -> { - openLink(project, "#reference.settingsdialog.IDE.editor.colors.CSV/TSV/PSV"); - })); - notification.addAction(NotificationAction.create("Formatting", (anActionEvent, notification1) -> { - openLink(project, "#preferences.sourceCode.CSV/TSV/PSV"); - })); - notification.addAction(NotificationAction.create("Open CSV Editor homepage", (anActionEvent, notification1) -> { - openLink(project, "https://github.com/SeeSharpSoft/intellij-csv-validator"); - })); + Notification notification = notificationGroup.createNotification( + "CSV Editor " + version + " - Change Notes", + CsvPluginManager.getChangeNotes() + + "You can always customize plugin settings to your likings (shortcuts below)!
" + + "Visit the CSV Editor homepage to read more about the available features & settings, " + + "submit issues & feature request, " + + "or show your support by rating this plugin. Thanks!
" + , + NotificationType.INFORMATION + ); + + notification.addAction(NotificationAction.create("General settings", (anActionEvent, notification1) -> { + openLink(project, "#" + CsvEditorSettingsProvider.CSV_EDITOR_SETTINGS_ID); + })); + notification.addAction(NotificationAction.create("Color scheme", (anActionEvent, notification1) -> { + openLink(project, "#reference.settingsdialog.IDE.editor.colors.CSV/TSV/PSV"); + })); + notification.addAction(NotificationAction.create("Formatting", (anActionEvent, notification1) -> { + openLink(project, "#preferences.sourceCode.CSV/TSV/PSV"); + })); + notification.addAction(NotificationAction.create("Open CSV Editor homepage", (anActionEvent, notification1) -> { + openLink(project, "https://github.com/SeeSharpSoft/intellij-csv-validator"); + })); + + Notifications.Bus.notify(notification); + }); - Notifications.Bus.notify(notification); - return continuation; } } \ No newline at end of file diff --git a/src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/CsvFileEditorProvider.java b/src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/CsvFileEditorProvider.java index c9f1cc2f..a296c0ea 100644 --- a/src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/CsvFileEditorProvider.java +++ b/src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/CsvFileEditorProvider.java @@ -49,18 +49,8 @@ public static boolean acceptCsvFile(@NotNull Project project, @NotNull VirtualFi @Override public boolean accept(@NotNull Project project, @NotNull VirtualFile file) { // Guard against cases where the platform TextEditor can't be created for the given file - // (e.g., special virtual files used by Structure View or diff). In such cases, delegating - // to TextEditorProvider would lead to NPEs inside platform code. - if (!CsvFileEditorProvider.acceptCsvFile(project, file)) { - return false; - } - try { - TextEditorProvider textEditorProvider = TextEditorProvider.getInstance(); - return textEditorProvider != null && textEditorProvider.accept(project, file); - } catch (Throwable t) { - // Be conservative on any unexpected error and do not accept the file to avoid IDE crashes. - return false; - } + // (e.g., special virtual files used by Structure View or diff). + return CsvFileEditorProvider.acceptCsvFile(project, file); } protected void applySettings(EditorSettings editorSettings, CsvEditorSettings csvEditorSettings) { diff --git a/src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/table/CsvTableEditor.java b/src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/table/CsvTableEditor.java index b0700386..2fa65310 100644 --- a/src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/table/CsvTableEditor.java +++ b/src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/table/CsvTableEditor.java @@ -238,8 +238,24 @@ public final CsvFile getCsvFile() { } if (this.psiFile != null) { - this.currentSeparator = CsvHelper.getValueSeparator(this.psiFile); - this.currentEscapeCharacter = CsvHelper.getEscapeCharacter(this.psiFile); + if (ApplicationManager.getApplication().isDispatchThread()) { + // On EDT, we try to avoid initializing services that might block (see #940) + ReadAction.nonBlocking(() -> { + this.currentSeparator = CsvHelper.getValueSeparator(this.psiFile); + this.currentEscapeCharacter = CsvHelper.getEscapeCharacter(this.psiFile); + return null; + }) + .finishOnUiThread(com.intellij.openapi.application.ModalityState.any(), unused -> { + CsvTableModel tableModel = getTableModel(); + if (tableModel != null) { + tableModel.notifyUpdate(); + } + }) + .submit(com.intellij.util.concurrency.AppExecutorUtil.getAppExecutorService()); + } else { + this.currentSeparator = CsvHelper.getValueSeparator(this.psiFile); + this.currentEscapeCharacter = CsvHelper.getEscapeCharacter(this.psiFile); + } } } return this.psiFile instanceof CsvFile ? (CsvFile) psiFile : null; diff --git a/src/test/java/net/seesharpsoft/intellij/plugins/csv/editor/CsvFileEditorTest.java b/src/test/java/net/seesharpsoft/intellij/plugins/csv/editor/CsvFileEditorTest.java index 7a078242..b19140a1 100644 --- a/src/test/java/net/seesharpsoft/intellij/plugins/csv/editor/CsvFileEditorTest.java +++ b/src/test/java/net/seesharpsoft/intellij/plugins/csv/editor/CsvFileEditorTest.java @@ -7,6 +7,7 @@ import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager; import com.intellij.openapi.fileEditor.impl.text.TextEditorState; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.LightVirtualFile; import net.seesharpsoft.intellij.plugins.csv.CsvBasePlatformTestCase; import net.seesharpsoft.intellij.plugins.csv.settings.CsvEditorSettings; @@ -111,6 +112,18 @@ public DiffRequestProcessor createProcessor(@NotNull Project project) { } } + public void testAccept() { + CsvFileEditorProvider fileEditorProvider = new CsvFileEditorProvider(); + CsvEditorSettings csvEditorSettings = CsvEditorSettings.getInstance(); + VirtualFile csvFile = myFixture.getFile().getVirtualFile(); + + csvEditorSettings.setEditorPrio(CsvEditorSettings.EditorPrio.TEXT_FIRST); + assertTrue(fileEditorProvider.accept(myFixture.getProject(), csvFile)); + + csvEditorSettings.setEditorPrio(CsvEditorSettings.EditorPrio.TEXT_ONLY); + assertTrue(fileEditorProvider.accept(myFixture.getProject(), csvFile)); + } + public void testAcceptCsvFile() { assertTrue(CsvFileEditorProvider.acceptCsvFile(myFixture.getProject(), new LightVirtualFile(myFixture.getFile().getName()))); assertFalse(CsvFileEditorProvider.acceptCsvFile(myFixture.getProject(), new DiffVirtualFileDummy(myFixture.getFile().getName())));