smart mode / dumb mode
Hi there,
I have a question about this error message:
Don't invoke waitForSmartMode from inside read action in dumb mode.
What causes this error and how can I fix it in the plugin I wrote?
I use this method for my action:
public void actionPerformed(final AnActionEvent event)
My class is defined as follows:
public class MyAction extends AnAction implements AnAction.TransparentUpdate
Please sign in to leave a comment.
The cause of this error is invoking waitForSmartMode method from a read action during indexing ("dumb mode"). Please provide a full stack trace for "how to fix it".
update failed for AnAction with ID=FinalizeJavaVariables: Don't invoke waitForSmartMode from inside read action in dumb mode
java.lang.AssertionError: Don't invoke waitForSmartMode from inside read action in dumb mode
at com.intellij.openapi.project.DumbServiceImpl.waitForSmartMode(DumbServiceImpl.java:349)
at com.intellij.openapi.project.DumbService.runReadActionInSmartMode(DumbService.java:116)
at com.intellij.openapi.project.DumbService.runReadActionInSmartMode(DumbService.java:84)
at com.intellij.psi.impl.search.PsiSearchHelperImpl.processFilesContainingAllKeys(PsiSearchHelperImpl.java:954)
at com.intellij.psi.impl.search.PsiSearchHelperImpl.intersectionWithContainerNameFiles(PsiSearchHelperImpl.java:831)
at com.intellij.psi.impl.search.PsiSearchHelperImpl.collectFiles(PsiSearchHelperImpl.java:760)
at com.intellij.psi.impl.search.PsiSearchHelperImpl.processGlobalRequestsOptimized(PsiSearchHelperImpl.java:660)
at com.intellij.psi.impl.search.PsiSearchHelperImpl.processRequests(PsiSearchHelperImpl.java:595)
at com.intellij.psi.search.SearchRequestQuery.processResults(SearchRequestQuery.java:45)
at com.intellij.util.AbstractQuery.forEach(AbstractQuery.java:75)
at com.intellij.util.MergeQuery.processSubQuery(MergeQuery.java:84)
at com.intellij.util.MergeQuery.forEach(MergeQuery.java:56)
at com.intellij.util.UniqueResultsQuery.process(UniqueResultsQuery.java:66)
at com.intellij.util.UniqueResultsQuery.forEach(UniqueResultsQuery.java:56)
at com.intellij.util.UniqueResultsQuery.findAll(UniqueResultsQuery.java:78)
at de.autotomat.final.FinalizeJavaVariablesAction.getAssignmentExpressionCount(FinalizeJavaVariablesAction.java:286)
at de.autotomat.final.FinalizeJavaVariablesAction.isFinalEligibleField(FinalizeJavaVariablesAction.java:187)
at de.autotomat.final.FinalizeJavaVariablesAction.isFinalEligible(FinalizeJavaVariablesAction.java:157)
at de.autotomat.final.FinalizeJavaVariablesAction.access$100(FinalizeJavaVariablesAction.java:30)
at de.autotomat.final.FinalizeJavaVariablesAction$2.isAccepted(FinalizeJavaVariablesAction.java:130)
at com.intellij.psi.search.PsiElementProcessor$CollectFilteredElements.execute(PsiElementProcessor.java:88)
at com.intellij.psi.util.PsiTreeUtil$4.visitElement(PsiTreeUtil.java:681)
at com.intellij.psi.impl.source.PsiFieldImpl.accept(PsiFieldImpl.java:389)
at com.intellij.psi.PsiWalkingState.visit(PsiWalkingState.java:64)
at com.intellij.psi.PsiWalkingState.visit(PsiWalkingState.java:26)
at com.intellij.util.WalkingState.walkChildren(WalkingState.java:65)
at com.intellij.util.WalkingState.elementStarted(WalkingState.java:52)
at com.intellij.psi.PsiWalkingState.elementStarted(PsiWalkingState.java:73)
at com.intellij.psi.PsiRecursiveElementWalkingVisitor.visitElement(PsiRecursiveElementWalkingVisitor.java:48)
at com.intellij.psi.util.PsiTreeUtil$4.visitElement(PsiTreeUtil.java:682)
at com.intellij.psi.impl.source.PsiClassImpl.accept(PsiClassImpl.java:476)
at com.intellij.psi.util.PsiTreeUtil.processElements(PsiTreeUtil.java:677)
at com.intellij.psi.util.PsiTreeUtil.collectElements(PsiTreeUtil.java:641)
at de.autotomat.final.FinalizeJavaVariablesAction.getFinalEligibleVariables(FinalizeJavaVariablesAction.java:122)
at de.autotomat.final.FinalizeJavaVariablesAction.update(FinalizeJavaVariablesAction.java:104)
at com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareUpdate(ActionUtil.java:114)
at com.intellij.openapi.actionSystem.impl.Utils.doUpdate(Utils.java:188)
at com.intellij.openapi.actionSystem.impl.Utils.expandActionGroup(Utils.java:139)
at com.intellij.openapi.actionSystem.impl.Utils.expandActionGroup(Utils.java:164)
at com.intellij.openapi.actionSystem.impl.Utils.expandActionGroup(Utils.java:96)
at com.intellij.openapi.actionSystem.impl.ActionToolbarImpl.updateActionsImpl(ActionToolbarImpl.java:937)
at com.intellij.openapi.actionSystem.impl.ActionToolbarImpl.access$000(ActionToolbarImpl.java:64)
at com.intellij.openapi.actionSystem.impl.ActionToolbarImpl$1.updateActionsImpl(ActionToolbarImpl.java:173)
at com.intellij.openapi.actionSystem.impl.ToolbarUpdater$MyUpdateRunnable.run(ToolbarUpdater.java:191)
at com.intellij.openapi.wm.impl.FocusManagerImpl.flushRequest(FocusManagerImpl.java:675)
at com.intellij.openapi.wm.impl.FocusManagerImpl.flushNow(FocusManagerImpl.java:656)
at com.intellij.openapi.wm.impl.FocusManagerImpl.flushIdleRequests(FocusManagerImpl.java:626)
at com.intellij.openapi.wm.impl.FocusManagerImpl.access$200(FocusManagerImpl.java:60)
at com.intellij.openapi.wm.impl.FocusManagerImpl$11.run(FocusManagerImpl.java:522)
at com.intellij.util.ui.UIUtil.invokeLaterIfNeeded(UIUtil.java:2361)
at com.intellij.openapi.wm.impl.FocusManagerImpl.doWhenFocusSettlesDown(FocusManagerImpl.java:500)
at com.intellij.openapi.actionSystem.impl.ToolbarUpdater.updateActions(ToolbarUpdater.java:108)
at com.intellij.openapi.actionSystem.impl.ToolbarUpdater.access$400(ToolbarUpdater.java:40)
at com.intellij.openapi.actionSystem.impl.ToolbarUpdater$MyTimerListener.run(ToolbarUpdater.java:163)
at com.intellij.openapi.actionSystem.impl.WeakTimerListener.run(WeakTimerListener.java:50)
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl$MyTimer.runListenerAction(ActionManagerImpl.java:1502)
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl$MyTimer.notifyListeners(ActionManagerImpl.java:1492)
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl$MyTimer.actionPerformed(ActionManagerImpl.java:1476)
at javax.swing.Timer.fireActionPerformed(Timer.java:313)
at javax.swing.Timer$DoPostEvent.run(Timer.java:245)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:866)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:654)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:381)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Indeed, such situation could be handled better, thanks for reporting! The best way to avoid it is to remove reference search from your action's "update", not only because of this issue, but also because it can take significant time and make the UI unresponsive. You can do this search in "actionPerformed" instead.
I have handled this intricate check in my update method because I enable/disable the (presentation of the) action dynamically. So are you saying I have to remove this check entirely within my update method?
Is there an alternative method which I could use to update the (presentation of the) availability of my action?
The usual practice to avoid lockups is to do lightweight checks in "update" and heavy checks in "actionPerformed". If those heavy checks fail, it's OK to show a dialog that the action can't be invoked here. Many our refactorings work this way.
The problem is that i also need the heavy check, which is performed in “actionPerformed“, in the “update“ method since the check/lookup is the most expensive operation and the actual action which is performed in “actionPerformed“ is just a lightweight operation.
I do not want to lose the feature of enabling/disabling my action on the fly. Is there another way i can perform my check without the error occurring?
What about executing my “update“ code only in smart mode? Would this be a valid solution? If so, how do I know which mode is currently on?
You can check the current mode by using DumbService.isDumb(project). But the main reason for avoiding complex logic in update isn't this check or dumb/smart modes, it's that the check is long and might freeze the UI for a long time at unexpected moments.