diff --git a/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/EndpointsToolWindow.kt b/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/EndpointsToolWindow.kt index 1d2200329..a2fa9a96b 100644 --- a/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/EndpointsToolWindow.kt +++ b/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/EndpointsToolWindow.kt @@ -35,7 +35,6 @@ import com.intellij.openapi.actionSystem.impl.ActionButton import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.ReadAction -import com.intellij.openapi.application.runReadAction import com.intellij.openapi.project.Project import com.intellij.openapi.ui.SimpleToolWindowPanel import com.intellij.psi.PsiElement @@ -149,7 +148,11 @@ class EndpointsToolWindow(private val project: Project) : private fun navigation(closestPathForLocation: TreePath?) { val lastUserObject = TreeUtil.getLastUserObject(closestPathForLocation) - runReadAction { (lastUserObject as? EndpointNavigable)?.navigate() } + val navigable = (lastUserObject as? EndpointNavigable) ?: return + // Schedule navigation on the EDT: invokeLater runs the action under a + // write-intent read action, which is required since 253 to open a file + // editor and at the same time covers PSI read access inside navigate(). + ApplicationManager.getApplication().invokeLater { navigable.navigate() } } private fun createRefreshButton(): JComponent { diff --git a/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/EndpointNavigatable.kt b/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/EndpointNavigatable.kt index 5f7140e7b..6df925bdb 100644 --- a/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/EndpointNavigatable.kt +++ b/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/EndpointNavigatable.kt @@ -18,5 +18,15 @@ package com.explyt.spring.web.view.nodes interface EndpointNavigable { + /** + * Performs navigation to the underlying PSI element. + * + * Implementations access PSI and open a file editor, both of which require + * the EDT under a write-intent read action. Callers must invoke this from + * the EDT (e.g. via [com.intellij.openapi.application.Application.invokeLater]), + * not from a plain read action — opening an editor cannot be performed + * from inside a `ReadAction` ("WriteIntentReadAction can not be called + * from ReadAction", since 253). + */ fun navigate() -} \ No newline at end of file +} diff --git a/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/HttpMethodNode.kt b/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/HttpMethodNode.kt index e2867cb93..c8b134712 100644 --- a/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/HttpMethodNode.kt +++ b/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/HttpMethodNode.kt @@ -56,4 +56,4 @@ class HttpMethodNode( override fun navigate() { (httpElement.psiPointer.element?.navigationElement as? Navigatable)?.navigate(true) } -} \ No newline at end of file +} diff --git a/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/SpringBootClassNode.kt b/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/SpringBootClassNode.kt index e9bacd638..35883f5b7 100644 --- a/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/SpringBootClassNode.kt +++ b/modules/spring-web/src/main/kotlin/com/explyt/spring/web/view/nodes/SpringBootClassNode.kt @@ -40,4 +40,4 @@ class SpringBootClassNode( override fun navigate() { (viewData?.psiPointer?.element?.navigationElement as? Navigatable)?.navigate(true) } -} \ No newline at end of file +}