diff --git a/src/main/java/org/sonarlint/intellij/actions/MarkAsResolvedAction.kt b/src/main/java/org/sonarlint/intellij/actions/MarkAsResolvedAction.kt index af4ce89246..0752dcd7b3 100644 --- a/src/main/java/org/sonarlint/intellij/actions/MarkAsResolvedAction.kt +++ b/src/main/java/org/sonarlint/intellij/actions/MarkAsResolvedAction.kt @@ -47,6 +47,7 @@ import org.sonarlint.intellij.ui.resolve.MarkAsResolvedDialog import org.sonarlint.intellij.util.DataKeys.Companion.ISSUE_DATA_KEY import org.sonarlint.intellij.util.DataKeys.Companion.TAINT_VULNERABILITY_DATA_KEY import org.sonarlint.intellij.util.SonarLintAppUtils.findModuleForFile +import org.sonarlint.intellij.util.computeOnPooledThread import org.sonarlint.intellij.util.runOnPooledThread import org.sonarsource.sonarlint.core.client.utils.IssueResolutionStatus import org.sonarsource.sonarlint.core.rpc.protocol.backend.issue.CheckStatusChangePermittedResponse @@ -87,7 +88,9 @@ class MarkAsResolvedAction( project, "No module could be found for this file" ) val serverKey = issue.getServerKey() ?: issue.getId().toString() - val response = checkPermission(project, connection, serverKey) ?: return + val response = computeOnPooledThread(project, "Checking permission to mark issue as resolved") { + checkPermission(project, connection, serverKey) + } ?: return if (response.isPermitted) { runOnUiThread(project) { @@ -97,7 +100,9 @@ class MarkAsResolvedAction( response, ).chooseResolution() ?: return@runOnUiThread if (confirm(project, connection.productName, resolution.newStatus)) { - markAsResolved(project, module, issue, resolution, serverKey) + runOnPooledThread(project) { + markAsResolved(project, module, issue, resolution, serverKey) + } } } } else { diff --git a/src/main/java/org/sonarlint/intellij/actions/OpenSecurityHotspotInBrowserAction.kt b/src/main/java/org/sonarlint/intellij/actions/OpenSecurityHotspotInBrowserAction.kt index 97548a783c..1d9edfbb00 100644 --- a/src/main/java/org/sonarlint/intellij/actions/OpenSecurityHotspotInBrowserAction.kt +++ b/src/main/java/org/sonarlint/intellij/actions/OpenSecurityHotspotInBrowserAction.kt @@ -29,6 +29,7 @@ import org.sonarlint.intellij.core.BackendService import org.sonarlint.intellij.core.ProjectBindingManager import org.sonarlint.intellij.finding.hotspot.LiveSecurityHotspot import org.sonarlint.intellij.util.SonarLintAppUtils.findModuleForFile +import org.sonarlint.intellij.util.runOnPooledThread class OpenSecurityHotspotInBrowserAction : AbstractSonarAction( "Open In Browser", @@ -57,7 +58,9 @@ class OpenSecurityHotspotInBrowserAction : AbstractSonarAction( val key = securityHotspot?.getServerKey() ?: return val localFile = securityHotspot.file() val localFileModule = findModuleForFile(localFile, project) ?: return - getService(BackendService::class.java).openHotspotInBrowser(localFileModule, key) + runOnPooledThread(project) { + getService(BackendService::class.java).openHotspotInBrowser(localFileModule, key) + } } private fun serverConnection(project: Project): ServerConnection? = getService(project, ProjectBindingManager::class.java).tryGetServerConnection().orElse(null) diff --git a/src/main/java/org/sonarlint/intellij/actions/ReopenIssueAction.kt b/src/main/java/org/sonarlint/intellij/actions/ReopenIssueAction.kt index 523d45d7ac..3125310276 100644 --- a/src/main/java/org/sonarlint/intellij/actions/ReopenIssueAction.kt +++ b/src/main/java/org/sonarlint/intellij/actions/ReopenIssueAction.kt @@ -45,6 +45,7 @@ import org.sonarlint.intellij.notifications.SonarLintProjectNotifications import org.sonarlint.intellij.ui.UiUtils import org.sonarlint.intellij.util.DataKeys import org.sonarlint.intellij.util.SonarLintAppUtils.findModuleForFile +import org.sonarlint.intellij.util.runOnPooledThread private const val SKIP_CONFIRM_REOPEN_DIALOG_PROPERTY = "SonarLint.reopenIssue.hideConfirmation" @@ -75,7 +76,7 @@ class ReopenIssueAction(private var issue: LiveIssue? = null) : AbstractSonarAct serverKey ?: return displayNotificationError(project, "The issue key could not be found") if (confirm(project, connection.productName)) { - reopenFinding(project, module, issue, serverKey) + runOnPooledThread(project) {reopenFinding(project, module, issue, serverKey)} } } diff --git a/src/main/java/org/sonarlint/intellij/actions/RestartBackendAction.kt b/src/main/java/org/sonarlint/intellij/actions/RestartBackendAction.kt index 577fc7f902..a24c3ecfc9 100644 --- a/src/main/java/org/sonarlint/intellij/actions/RestartBackendAction.kt +++ b/src/main/java/org/sonarlint/intellij/actions/RestartBackendAction.kt @@ -22,6 +22,7 @@ package org.sonarlint.intellij.actions import com.intellij.openapi.actionSystem.AnActionEvent import org.sonarlint.intellij.common.util.SonarLintUtils import org.sonarlint.intellij.core.BackendService +import org.sonarlint.intellij.util.runOnPooledThread class RestartBackendAction : AbstractSonarAction("Restart SonarLint Service") { @@ -30,7 +31,9 @@ class RestartBackendAction : AbstractSonarAction("Restart SonarLint Service") { } override fun actionPerformed(e: AnActionEvent) { - SonarLintUtils.getService(BackendService::class.java).restartBackendService() + runOnPooledThread() { + SonarLintUtils.getService(BackendService::class.java).restartBackendService() + } } } diff --git a/src/main/java/org/sonarlint/intellij/actions/ReviewSecurityHotspotAction.kt b/src/main/java/org/sonarlint/intellij/actions/ReviewSecurityHotspotAction.kt index dcfc93fead..a0bb616549 100644 --- a/src/main/java/org/sonarlint/intellij/actions/ReviewSecurityHotspotAction.kt +++ b/src/main/java/org/sonarlint/intellij/actions/ReviewSecurityHotspotAction.kt @@ -42,6 +42,7 @@ import org.sonarlint.intellij.tasks.FutureAwaitingTask import org.sonarlint.intellij.ui.UiUtils.Companion.runOnUiThread import org.sonarlint.intellij.ui.review.ReviewSecurityHotspotDialog import org.sonarlint.intellij.util.SonarLintAppUtils.findModuleForFile +import org.sonarlint.intellij.util.computeOnPooledThread import org.sonarlint.intellij.util.runOnPooledThread import org.sonarsource.sonarlint.core.commons.HotspotReviewStatus import org.sonarsource.sonarlint.core.rpc.protocol.backend.hotspot.CheckStatusChangePermittedResponse @@ -103,7 +104,10 @@ class ReviewSecurityHotspotAction(private var serverFindingKey: String? = null, "No module could be found for this file" ) - val response = checkPermission(project, connection, hotspotKey) ?: return + val response = computeOnPooledThread(project, "Checking permission to mark issue as resolved") { + checkPermission(project, connection, hotspotKey) + } ?: return + val newStatus = HotspotStatus.valueOf(currentStatus.name) runOnUiThread(project) { if (ReviewSecurityHotspotDialog(project, connection.productName, module, hotspotKey, response, newStatus).showAndGet()) { diff --git a/src/main/java/org/sonarlint/intellij/cayc/NewCodePeriodCache.kt b/src/main/java/org/sonarlint/intellij/cayc/NewCodePeriodCache.kt index 1936276aaf..546b46ce67 100644 --- a/src/main/java/org/sonarlint/intellij/cayc/NewCodePeriodCache.kt +++ b/src/main/java/org/sonarlint/intellij/cayc/NewCodePeriodCache.kt @@ -24,19 +24,22 @@ import com.intellij.openapi.project.Project import java.util.Locale import org.sonarlint.intellij.common.util.SonarLintUtils.getService import org.sonarlint.intellij.core.BackendService +import org.sonarlint.intellij.util.runOnPooledThread @Service(Service.Level.PROJECT) class NewCodePeriodCache(private val project: Project) { var periodAsString: String = "(unknown code period)" fun refreshAsync() { - getService(BackendService::class.java).getNewCodePeriodText(project) - .thenAccept { period -> - periodAsString = period.replaceFirstChar { char -> - char.lowercase( - Locale.getDefault() - ) + runOnPooledThread(project) { + getService(BackendService::class.java).getNewCodePeriodText(project) + .thenAccept { period -> + periodAsString = period.replaceFirstChar { char -> + char.lowercase( + Locale.getDefault() + ) + } } - } + } } } diff --git a/src/main/java/org/sonarlint/intellij/config/global/rules/RuleConfigurationPanel.java b/src/main/java/org/sonarlint/intellij/config/global/rules/RuleConfigurationPanel.java index 87ee7cae27..c8aedf32b1 100644 --- a/src/main/java/org/sonarlint/intellij/config/global/rules/RuleConfigurationPanel.java +++ b/src/main/java/org/sonarlint/intellij/config/global/rules/RuleConfigurationPanel.java @@ -114,6 +114,7 @@ import static org.sonarlint.intellij.config.Settings.getGlobalSettings; import static org.sonarlint.intellij.telemetry.LinkTelemetry.RULE_SELECTION_PAGE; import static org.sonarlint.intellij.ui.UiUtils.runOnUiThread; +import static org.sonarlint.intellij.util.ThreadUtilsKt.runOnPooledThread; public class RuleConfigurationPanel implements Disposable, ConfigurationPanel { private static final String MAIN_SPLITTER_KEY = "sonarlint_rule_configuration_splitter"; @@ -308,7 +309,7 @@ private void restoreDefaults() { r.getCustomParams().clear(); }); updateModel(); - recomputeDirtyState(); + runOnPooledThread(this::recomputeDirtyState); } private void updateModel() { @@ -444,7 +445,7 @@ private JScrollPane initTreeScrollPane() { // create tree table model = new RulesTreeTableModel(new RulesTreeNode.Root()); table = new RulesTreeTable(model); - table.getModel().addTableModelListener(e -> recomputeDirtyState()); + table.getModel().addTableModelListener(e ->runOnPooledThread(this::recomputeDirtyState)); table.setTreeCellRenderer(new RulesTreeTableRenderer(filterModel::getText)); table.setRootVisible(false); TreeUtil.installActions(table.getTree()); @@ -507,42 +508,47 @@ private void updateParamsAndDescriptionPanel() { } private void updateParamsAndDescriptionPanel(RulesTreeNode.Rule singleNode) { - ruleHeaderPanel.updateForRuleConfiguration(singleNode.getKey(), singleNode.type(), singleNode.severity(), singleNode.attribute(), singleNode.impacts()); + ruleHeaderPanel.updateForRuleConfiguration(singleNode.getKey(), singleNode.type(), singleNode.severity(), singleNode.attribute(), + singleNode.impacts()); var fileType = RuleLanguages.Companion.findFileTypeByRuleLanguage(singleNode.language()); - getService(BackendService.class).getStandaloneRuleDetails(new GetStandaloneRuleDescriptionParams(singleNode.getKey())) - .thenAcceptAsync(details -> runOnUiThread(project, ModalityState.stateForComponent(getComponent()), () -> { - details.getDescription().map( - monolithDescription -> { - ruleDescription.addMonolith(monolithDescription, fileType); - return null; - }, - withSections -> { - ruleDescription.addSections(withSections, fileType); - return null; - }); - - myParamsPanel.removeAll(); - final var configPanelAnchor = new JBPanel<>(new GridLayout()); - setConfigPanel(configPanelAnchor, singleNode, details.getRuleDefinition().getParamsByKey()); - if (configPanelAnchor.getComponentCount() != 0) { - rulesParamsSeparator = new RulesParamsSeparator(); - myParamsPanel.add(rulesParamsSeparator, - new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - JBUI.emptyInsets(), 0, 0)); - myParamsPanel.add(configPanelAnchor, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, - JBUI.insetsLeft(2), 0, 0)); - } else { - myParamsPanel.add(configPanelAnchor, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, - JBUI.insetsLeft(2), 0, 0)); - } - myParamsPanel.revalidate(); - myParamsPanel.repaint(); - })) - .exceptionally(error -> { - GlobalLogOutput.get().log("Could not retrieve rule description", ClientLogOutput.Level.ERROR); - return null; - }); + runOnPooledThread(project, () -> + getService(BackendService.class).getStandaloneRuleDetails(new GetStandaloneRuleDescriptionParams(singleNode.getKey())) + .thenAcceptAsync(details -> runOnUiThread(project, ModalityState.stateForComponent(getComponent()), () -> { + details.getDescription().map( + monolithDescription -> { + ruleDescription.addMonolith(monolithDescription, fileType); + return null; + }, + withSections -> { + ruleDescription.addSections(withSections, fileType); + return null; + }); + + myParamsPanel.removeAll(); + final var configPanelAnchor = new JBPanel<>(new GridLayout()); + setConfigPanel(configPanelAnchor, singleNode, details.getRuleDefinition().getParamsByKey()); + if (configPanelAnchor.getComponentCount() != 0) { + rulesParamsSeparator = new RulesParamsSeparator(); + myParamsPanel.add(rulesParamsSeparator, + new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + JBUI.emptyInsets(), 0, 0)); + myParamsPanel.add(configPanelAnchor, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, + GridBagConstraints.BOTH, + JBUI.insetsLeft(2), 0, 0)); + } else { + myParamsPanel.add(configPanelAnchor, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, + GridBagConstraints.BOTH, + JBUI.insetsLeft(2), 0, 0)); + } + myParamsPanel.revalidate(); + myParamsPanel.repaint(); + })) + .exceptionally(error -> { + GlobalLogOutput.get().log("Could not retrieve rule description", ClientLogOutput.Level.ERROR); + return null; + }) + ); } private void setConfigPanel(final JPanel configPanelAnchor, RulesTreeNode.Rule rule, Map paramsByKey) { @@ -642,7 +648,7 @@ private void createBooleanParam(RulesTreeNode.Rule rule, JPanel panel, GridBagCo } else { rule.getCustomParams().remove(param.getKey()); } - recomputeDirtyState(); + runOnPooledThread(this::recomputeDirtyState); rulesParamsSeparator.updateDefaultLinkVisibility(); }); constraints.gridwidth = 2; @@ -662,7 +668,8 @@ public void textChanged(DocumentEvent e) { } else { rule.getCustomParams().remove(param.getKey()); } - recomputeDirtyState(); + runOnPooledThread(project, () -> recomputeDirtyState()); + rulesParamsSeparator.updateDefaultLinkVisibility(); } }); @@ -690,7 +697,7 @@ public void textChanged(DocumentEvent e) { } else { rule.getCustomParams().remove(param.getKey()); } - recomputeDirtyState(); + runOnPooledThread(project, () -> recomputeDirtyState()); rulesParamsSeparator.updateDefaultLinkVisibility(); } catch (ParseException e1) { // No luck this time @@ -803,7 +810,7 @@ private class RulesParamsSeparator extends JPanel { }); myDefaultsLink.setToolTipText("Restore current rule parameters to default values"); add(myDefaultsLink, defaultLabelConstraints); - recomputeDirtyState(); + runOnPooledThread(project, RuleConfigurationPanel.this::recomputeDirtyState); updateDefaultLinkVisibility(); } diff --git a/src/main/java/org/sonarlint/intellij/config/global/wizard/AuthStep.java b/src/main/java/org/sonarlint/intellij/config/global/wizard/AuthStep.java index 2a6181b3b5..f13ad5b578 100644 --- a/src/main/java/org/sonarlint/intellij/config/global/wizard/AuthStep.java +++ b/src/main/java/org/sonarlint/intellij/config/global/wizard/AuthStep.java @@ -57,6 +57,7 @@ import org.sonarsource.sonarlint.core.rpc.protocol.backend.connection.validate.ValidateConnectionResponse; import static org.sonarlint.intellij.util.ThreadUtilsKt.computeOnPooledThread; +import static org.sonarlint.intellij.util.ThreadUtilsKt.runOnPooledThread; public class AuthStep extends AbstractWizardStepEx { private static final String LOGIN_ITEM = "Login / Password"; @@ -199,7 +200,13 @@ public boolean isComplete() { public void commit(CommitType commitType) throws CommitStepException { if (commitType == CommitType.Finish || commitType == CommitType.Next) { save(); - checkConnection(); + runOnPooledThread(() -> { + try { + checkConnection(); + } catch (CommitStepException e) { + throw new RuntimeException(e); + } + }); tryQueryIfNotificationsSupported(); tryQueryOrganizations(); } @@ -234,6 +241,7 @@ private void checkConnection() throws CommitStepException { ConnectionTestTask test = new ConnectionTestTask(tmpServer); var msg = "Failed to connect to the server. Please check the configuration."; ValidateConnectionResponse result; + try { result = ProgressManager.getInstance().run(test); } catch (Exception e) { diff --git a/src/main/java/org/sonarlint/intellij/core/BackendService.kt b/src/main/java/org/sonarlint/intellij/core/BackendService.kt index ec6f8ce4f1..4389fe07e4 100644 --- a/src/main/java/org/sonarlint/intellij/core/BackendService.kt +++ b/src/main/java/org/sonarlint/intellij/core/BackendService.kt @@ -205,7 +205,9 @@ class BackendService : Disposable { } private fun notifyBackend(action: (SonarLintRpcServer) -> Unit) { - ensureBackendInitialized().thenAcceptAsync(action) + runOnPooledThread() { + ensureBackendInitialized().thenAcceptAsync(action) + } } private fun ensureBackendInitialized(): CompletableFuture { @@ -518,7 +520,6 @@ class BackendService : Disposable { ConfigurationScopeDto(projectId(project), null, true, project.name, BindingConfigurationDto(binding?.connectionName, binding?.projectKey, areBindingSuggestionsDisabledFor(project))) - fun projectBound(project: Project, newBinding: ProjectBinding) { notifyBackend { it.configurationService.didUpdateBinding( diff --git a/src/main/java/org/sonarlint/intellij/sharing/ConfigurationSharing.kt b/src/main/java/org/sonarlint/intellij/sharing/ConfigurationSharing.kt index 27d3b74b2d..a69ed998c2 100644 --- a/src/main/java/org/sonarlint/intellij/sharing/ConfigurationSharing.kt +++ b/src/main/java/org/sonarlint/intellij/sharing/ConfigurationSharing.kt @@ -39,6 +39,7 @@ import org.sonarlint.intellij.documentation.SonarLintDocumentation import org.sonarlint.intellij.notifications.SonarLintProjectNotifications.Companion.get import org.sonarlint.intellij.sharing.SonarLintSharedFolderUtils.Companion.findSharedFolder import org.sonarlint.intellij.ui.UiUtils.Companion.runOnUiThread +import org.sonarlint.intellij.util.runOnPooledThread import org.sonarsource.sonarlint.core.rpc.protocol.backend.binding.GetSharedConnectedModeConfigFileResponse import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.ConnectionSuggestionDto @@ -50,7 +51,9 @@ class ConfigurationSharing { if (project == null || project.isDisposed) return if (confirm(project)) { - createFile(project, modalityState) + runOnPooledThread(project) { + createFile(project, modalityState) + } } } diff --git a/src/main/java/org/sonarlint/intellij/tasks/CheckNotificationsSupportedTask.java b/src/main/java/org/sonarlint/intellij/tasks/CheckNotificationsSupportedTask.java index 14cbcfd55e..f5315c3530 100644 --- a/src/main/java/org/sonarlint/intellij/tasks/CheckNotificationsSupportedTask.java +++ b/src/main/java/org/sonarlint/intellij/tasks/CheckNotificationsSupportedTask.java @@ -29,6 +29,7 @@ import org.sonarlint.intellij.core.BackendService; import static org.sonarlint.intellij.util.ProgressUtils.waitForFuture; +import static org.sonarlint.intellij.util.ThreadUtilsKt.computeOnPooledThread; /** * Only useful for SonarQube, since we know notifications are available in SonarCloud @@ -48,7 +49,8 @@ public void run(@NotNull ProgressIndicator indicator) { indicator.setIndeterminate(false); try { indicator.setText("Checking support of notifications"); - notificationsSupported = waitForFuture(indicator, SonarLintUtils.getService(BackendService.class).checkSmartNotificationsSupported(connection)).isSuccess(); + notificationsSupported = Boolean.TRUE.equals(computeOnPooledThread("Get Notification Supported", () -> + waitForFuture(indicator, SonarLintUtils.getService(BackendService.class).checkSmartNotificationsSupported(connection)).isSuccess())); } catch (ProcessCanceledException e) { if (myProject != null) { SonarLintConsole.get(myProject).error("Failed to check notifications", e); diff --git a/src/main/java/org/sonarlint/intellij/tasks/GetOrganizationTask.java b/src/main/java/org/sonarlint/intellij/tasks/GetOrganizationTask.java index 9e94502fad..059daab3f1 100644 --- a/src/main/java/org/sonarlint/intellij/tasks/GetOrganizationTask.java +++ b/src/main/java/org/sonarlint/intellij/tasks/GetOrganizationTask.java @@ -29,6 +29,7 @@ import org.sonarsource.sonarlint.core.rpc.protocol.backend.connection.org.OrganizationDto; import static org.sonarlint.intellij.util.ProgressUtils.waitForFuture; +import static org.sonarlint.intellij.util.ThreadUtilsKt.computeOnPooledThread; public class GetOrganizationTask extends Task.Modal { private final ServerConnection server; @@ -50,7 +51,8 @@ public void run(@NotNull ProgressIndicator indicator) { try { indicator.setText("Searching organization"); - organization = waitForFuture(indicator, SonarLintUtils.getService(BackendService.class).getOrganization(server, organizationKey)).getOrganization(); + organization = computeOnPooledThread("Get User Organizations", () -> + waitForFuture(indicator, SonarLintUtils.getService(BackendService.class).getOrganization(server, organizationKey)).getOrganization()); } catch (Exception e) { SonarLintConsole.get(myProject).error("Failed to fetch organizations", e); exception = e; diff --git a/src/main/java/org/sonarlint/intellij/tasks/GetOrganizationsTask.java b/src/main/java/org/sonarlint/intellij/tasks/GetOrganizationsTask.java index d375335e7d..2ef2f9304a 100644 --- a/src/main/java/org/sonarlint/intellij/tasks/GetOrganizationsTask.java +++ b/src/main/java/org/sonarlint/intellij/tasks/GetOrganizationsTask.java @@ -30,6 +30,7 @@ import org.sonarsource.sonarlint.core.rpc.protocol.backend.connection.org.OrganizationDto; import static org.sonarlint.intellij.util.ProgressUtils.waitForFuture; +import static org.sonarlint.intellij.util.ThreadUtilsKt.computeOnPooledThread; /** * Only useful for SonarCloud @@ -50,7 +51,8 @@ public void run(@NotNull ProgressIndicator indicator) { indicator.setIndeterminate(false); try { - organizations = waitForFuture(indicator, SonarLintUtils.getService(BackendService.class).listUserOrganizations(connection)).getUserOrganizations(); + organizations = computeOnPooledThread("Get User Organizations",() -> + waitForFuture(indicator, SonarLintUtils.getService(BackendService.class).listUserOrganizations(connection)).getUserOrganizations()); } catch (Exception e) { SonarLintConsole.get(myProject).error("Failed to fetch organizations", e); exception = e; diff --git a/src/main/java/org/sonarlint/intellij/ui/review/ReviewSecurityHotspotDialog.kt b/src/main/java/org/sonarlint/intellij/ui/review/ReviewSecurityHotspotDialog.kt index 8688c6bacb..c1c19d1b8e 100644 --- a/src/main/java/org/sonarlint/intellij/ui/review/ReviewSecurityHotspotDialog.kt +++ b/src/main/java/org/sonarlint/intellij/ui/review/ReviewSecurityHotspotDialog.kt @@ -36,6 +36,7 @@ import org.sonarlint.intellij.documentation.SonarLintDocumentation.Intellij.SECU import org.sonarlint.intellij.editor.CodeAnalyzerRestarter import org.sonarlint.intellij.notifications.SonarLintProjectNotifications import org.sonarlint.intellij.ui.UiUtils.Companion.runOnUiThread +import org.sonarlint.intellij.util.runOnPooledThread import org.sonarsource.sonarlint.core.rpc.protocol.backend.hotspot.CheckStatusChangePermittedResponse import org.sonarsource.sonarlint.core.rpc.protocol.backend.hotspot.HotspotStatus @@ -64,7 +65,9 @@ class ReviewSecurityHotspotDialog( override fun doAction(e: ActionEvent) { val status = getStatus() - changeStatus(status, ModalityState.stateForComponent(contentPane)) + runOnPooledThread(project) { + changeStatus(status, ModalityState.stateForComponent(contentPane)) + } } private fun changeStatus(status: HotspotStatus, modalityState: ModalityState) {