ReferencesSearch: Assertion Error

I am trying to use ReferencesSearch.search() to find references to various elements in multiple PsiTreeChangeListeners under certain conditions.

In particular, I am trying to find references to a parameter to a method and references to a class type inside another class.

However, I cannot seem to find the cause of the following assertion error that appears, either when iterating over results, or when I call findAll() on the Query<PsiReference> that is returned by the search() method.

14:07:35 AssertionError: Range for element: 'PsiJavaFile:KingExample.java' = (0,563) is out of file 'PsiJavaFile:KingExample.java' range: (0,563); file contents length: 554; file provider: SingleRootFileViewProvider{myVirtualFile=file:///Users/Simon/workspace/interview-practice/src/singleton/KingExample.java, content=DocumentContent{size=554}}

I am also running the search earlier on in the code to find calls to a new method. In that case it works flawlessly. Is there something obvious I am doing wrong here? Thanks so much in advance!

Here is the stacktrace:

Range for element: 'PsiJavaFile:KingExample.java' = (0,563) is out of file 'PsiJavaFile:KingExample.java' range: (0,563); file contents length: 554; file provider: SingleRootFileViewProvider{myVirtualFile=file:///Users/Simon/workspace/interview-practice/src/singleton/KingExample.java, content=DocumentContent{size=554}} java.lang.AssertionError: Range for element: 'PsiJavaFile:KingExample.java' = (0,563) is out of file 'PsiJavaFile:KingExample.java' range: (0,563); file contents length: 554; file provider: SingleRootFileViewProvider{myVirtualFile=file:///Users/Simon/workspace/interview-practice/src/singleton/KingExample.java, content=DocumentContent{size=554}}      at com.intellij.psi.impl.search.LowLevelSearchUtil.processElementsContainingWordInElement(LowLevelSearchUtil.java:187)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$3$1.compute(PsiSearchHelperImpl.java:206)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$3$1.compute(PsiSearchHelperImpl.java:203)      at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:920)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$3.process(PsiSearchHelperImpl.java:203)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$3.process(PsiSearchHelperImpl.java:200)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$16.process(PsiSearchHelperImpl.java:721)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$16.process(PsiSearchHelperImpl.java:715)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$7.compute(PsiSearchHelperImpl.java:363)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$7.compute(PsiSearchHelperImpl.java:348)      at com.intellij.openapi.application.ex.ApplicationUtil$1.run(ApplicationUtil.java:30)      at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1146)      at com.intellij.openapi.application.ex.ApplicationUtil.tryRunReadAction(ApplicationUtil.java:27)      at com.intellij.psi.impl.search.PsiSearchHelperImpl.processVirtualFile(PsiSearchHelperImpl.java:348)      at com.intellij.psi.impl.search.PsiSearchHelperImpl.access$000(PsiSearchHelperImpl.java:66)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$4.process(PsiSearchHelperImpl.java:296)      at com.intellij.psi.impl.search.PsiSearchHelperImpl$4.process(PsiSearchHelperImpl.java:291)      at com.intellij.concurrency.JobLauncherImpl$2$1.run(JobLauncherImpl.java:142)      at com.intellij.openapi.progress.impl.ProgressManagerImpl.registerIndicatorAndRun(ProgressManagerImpl.java:281)      at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:233)      at com.intellij.concurrency.JobLauncherImpl$2.run(JobLauncherImpl.java:136)      at com.intellij.concurrency.JobLauncherImpl.invokeConcurrentlyUnderProgress(JobLauncherImpl.java:155)      at com.intellij.psi.impl.search.PsiSearchHelperImpl.processPsiFileRoots(PsiSearchHelperImpl.java:290)      at com.intellij.psi.impl.search.PsiSearchHelperImpl.processCandidates(PsiSearchHelperImpl.java:715)      at com.intellij.psi.impl.search.PsiSearchHelperImpl.processGlobalRequestsOptimized(PsiSearchHelperImpl.java:689)      at com.intellij.psi.impl.search.PsiSearchHelperImpl.processRequestsAsync(PsiSearchHelperImpl.java:613)      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 com.simonstuck.vignelli.refactoring.steps.ExtractInterfaceRefactoringStep$InterfaceExtractedAndUsedChecker.currentClassContainsReferencesToClassUpForInterfaceExtraction(ExtractInterfaceRefactoringStep.java:120)      at com.simonstuck.vignelli.refactoring.steps.ExtractInterfaceRefactoringStep$InterfaceExtractedAndUsedChecker.computeResult(ExtractInterfaceRefactoringStep.java:111)      at com.simonstuck.vignelli.refactoring.steps.RefactoringStepGoalChecker.performCheck(RefactoringStepGoalChecker.java:45)      at com.simonstuck.vignelli.refactoring.steps.RefactoringStepGoalChecker.childReplaced(RefactoringStepGoalChecker.java:107)      at com.intellij.psi.impl.PsiManagerImpl.fireEvent(PsiManagerImpl.java:436)      at com.intellij.psi.impl.PsiManagerImpl.childReplaced(PsiManagerImpl.java:337)      at com.intellij.pom.wrappers.PsiEventWrapperAspect.sendAfterEvents(PsiEventWrapperAspect.java:103)      at com.intellij.pom.wrappers.PsiEventWrapperAspect.update(PsiEventWrapperAspect.java:50)      at com.intellij.pom.core.impl.PomModelImpl.runTransaction(PomModelImpl.java:175)      at com.intellij.psi.impl.source.tree.ChangeUtil.prepareAndRunChangeAction(ChangeUtil.java:165)      at com.intellij.psi.impl.source.tree.CompositeElement.replaceChild(CompositeElement.java:703)      at com.intellij.psi.impl.source.codeStyle.CodeEditUtil.replaceChild(CodeEditUtil.java:205)      at com.intellij.psi.impl.source.tree.CompositeElement.replaceChildInternal(CompositeElement.java:548)      at com.intellij.psi.impl.source.tree.java.ExpressionPsiElement.replaceChildInternal(ExpressionPsiElement.java:42)      at com.intellij.psi.impl.source.tree.SharedImplUtil.doReplace(SharedImplUtil.java:207)      at com.intellij.psi.impl.source.tree.CompositePsiElement.replace(CompositePsiElement.java:210)      at com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer.restoreExpression(AbstractJavaInplaceIntroducer.java:150)      at com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer.restoreExpression(AbstractJavaInplaceIntroducer.java:91)      at com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer.restoreExpression(AbstractJavaInplaceIntroducer.java:32)      at com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer$4.run(AbstractInplaceIntroducer.java:475)      at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:977)      at com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer.restoreState(AbstractInplaceIntroducer.java:469)      at com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer.restoreState(AbstractJavaInplaceIntroducer.java:97)      at com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer.restoreState(AbstractJavaInplaceIntroducer.java:32)      at com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer.finish(AbstractInplaceIntroducer.java:386)      at com.intellij.refactoring.rename.inplace.InplaceRefactoring$MyTemplateListener.beforeTemplateFinished(InplaceRefactoring.java:836)      at com.intellij.codeInsight.template.impl.TemplateState.fireBeforeTemplateFinished(TemplateState.java:1251)      at com.intellij.codeInsight.template.impl.TemplateState.cleanupTemplateState(TemplateState.java:963)      at com.intellij.codeInsight.template.impl.TemplateState.finishTemplateEditing(TemplateState.java:924)      at com.intellij.codeInsight.template.impl.TemplateState.nextTab(TemplateState.java:823)      at com.intellij.codeInsight.template.impl.actions.NextVariableAction$Handler.executeWriteAction(NextVariableAction.java:51)      at com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler$1.run(EditorWriteActionHandler.java:64)      at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:977)      at com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler.doExecute(EditorWriteActionHandler.java:47)      at com.intellij.openapi.editor.actionSystem.EditorActionHandler$4.perform(EditorActionHandler.java:215)      at com.intellij.openapi.editor.actionSystem.EditorActionHandler.doIfEnabled(EditorActionHandler.java:107)      at com.intellij.openapi.editor.actionSystem.EditorActionHandler.execute(EditorActionHandler.java:212)      at com.intellij.openapi.editor.actionSystem.EditorAction$1.run(EditorAction.java:97)      at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:124)      at com.intellij.openapi.editor.actionSystem.EditorAction.actionPerformed(EditorAction.java:108)      at com.intellij.openapi.editor.actionSystem.EditorAction.actionPerformed(EditorAction.java:82)      at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher$3.performAction(IdeKeyEventDispatcher.java:614)      at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.processAction(IdeKeyEventDispatcher.java:663)      at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.inInitState(IdeKeyEventDispatcher.java:513)      at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.dispatchKeyEvent(IdeKeyEventDispatcher.java:211)      at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:546)      at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:384)      at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)      at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)      at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

6 comments
Comment actions Permalink

This looks quite strange. Do you also have your own reference contributors in your plugin?

0
Comment actions Permalink

I don't.

I have tracked the problem down a little further though and it seems to be quite deep. Here's what I've found so far:

scope.getTextLength() == 567
scope.getText().length() == 549


That seems odd.

scope is of type PsiJavaFileImpl.

Its implementation of getTextLength() is that of PsiFileImpl:

 
@Override
public int getTextLength() {
  final ASTNode tree = derefTreeElement();
  if
(tree != null) return tree.getTextLength();

  return
getViewProvider().getContents().length();
}


Here it seems that it is indeed the case that tree != null. scope.derefTreeElement() returns an AST node, let's call it m. Now though:

m.getTextLength() == 567
m.getText().length() == 567

Therefore, it seems as though the underlying AST is ahead of the text stored in the PsiTree as far as I can tell.

Could this be an issue in the API?

EDIT:

I am now hacking around the issue by first checking whether it is the case that:

 
clazzFile.getViewProvider().getContents().length() == clazzFile.getTextLength()


This is of course not nice but it works for now. I am of course still interested in whether I'm doing something wrong in another place. If it helps I could also make some of my code available ;)

Message was edited by: Simon Stückemann

0
Comment actions Permalink

I see that you initiate the search directly from a PSI event handler, which is called synchronously during PSI modification. The structure could be in an inconsistent state at that moment. Can you perform the activities you need at a later point (for example, after the end of the current write action)?

0
Comment actions Permalink

I see, I wasn't aware that it is a synchronous action, so trying to run the search inside a write action doesn't have any effect as the lock is already aquired.

Is there a way to schedule another action until after the current one or find out whether a write action is currently in progress?

I don't need to run my code during modification, so I would be happy to run it whenever a write action has finished. Is there an API to do just that?

Thanks,
Simon

0
Comment actions Permalink

If a PSI tree change event listener is called, a write action is by definition in progress - otherwise it wouldn't be possible to perform the modifications which the listener is notified about.

You can use Application.addApplicationListener() and implement ApplicationListener.writeActionFinished() to execute your code when a write action is finished.

0
Comment actions Permalink

I feel silly now, that makes a lot of sense

I've now removed the hack and am using an ApplicationListener instead. It's workign well, thanks so much!

0

Please sign in to leave a comment.