@Override public ASTNode findTreeForStub(StubTree tree, StubElement<?> stub) { final Iterator<StubElement<?>> stubs = tree.getPlainList().iterator(); final StubElement<?> root = stubs.next(); final CompositeElement ast = calcTreeElement(); if (root == stub) return ast; return findTreeForStub(ast, stubs, stub); }
protected void reportStubAstMismatch(String message, StubTree stubTree, Document cachedDocument) { rebuildStub(); clearStub("stub-psi mismatch"); scheduleDropCachesWithInvalidStubPsi(); String msg = message; msg += "\n file=" + this; msg += ", modStamp=" + getModificationStamp(); msg += "\n stub debugInfo=" + stubTree.getDebugInfo(); msg += "\n document before=" + cachedDocument; ObjectStubTree latestIndexedStub = StubTreeLoader.getInstance().readFromVFile(getProject(), getVirtualFile()); msg += "\nlatestIndexedStub=" + latestIndexedStub; if (latestIndexedStub != null) { msg += "\n same size=" + (stubTree.getPlainList().size() == latestIndexedStub.getPlainList().size()); msg += "\n debugInfo=" + latestIndexedStub.getDebugInfo(); } FileViewProvider viewProvider = getViewProvider(); msg += "\n viewProvider=" + viewProvider; msg += "\n viewProvider stamp: " + viewProvider.getModificationStamp(); VirtualFile file = viewProvider.getVirtualFile(); msg += "; file stamp: " + file.getModificationStamp(); msg += "; file modCount: " + file.getModificationCount(); Document document = FileDocumentManager.getInstance().getCachedDocument(file); if (document != null) { msg += "\n doc saved: " + !FileDocumentManager.getInstance().isDocumentUnsaved(document); msg += "; doc stamp: " + document.getModificationStamp(); msg += "; doc size: " + document.getTextLength(); msg += "; committed: " + PsiDocumentManager.getInstance(getProject()).isCommitted(document); } throw new AssertionError(msg + "\n------------\n"); }
private List<Pair<StubBasedPsiElementBase, CompositeElement>> calcStubAstBindings( final ASTNode root, final Document cachedDocument) { final StubTree stubTree = derefStub(); if (stubTree == null) { return Collections.emptyList(); } final Iterator<StubElement<?>> stubs = stubTree.getPlainList().iterator(); stubs.next(); // Skip file stub; final List<Pair<StubBasedPsiElementBase, CompositeElement>> result = ContainerUtil.newArrayList(); final StubBuilder builder = ((IStubFileElementType) getContentElementType()).getBuilder(); LazyParseableElement.setSuppressEagerPsiCreation(true); try { ((TreeElement) root) .acceptTree( new RecursiveTreeElementWalkingVisitor() { @Override protected void visitNode(TreeElement node) { CompositeElement parent = node.getTreeParent(); if (parent != null && builder.skipChildProcessingWhenBuildingStubs(parent, node)) { return; } IElementType type = node.getElementType(); if (type instanceof IStubElementType && ((IStubElementType) type).shouldCreateStub(node)) { if (!stubs.hasNext()) { reportStubAstMismatch( "Stub list is less than AST, last AST element: " + node.getElementType() + " " + node, stubTree, cachedDocument); } final StubElement stub = stubs.next(); if (stub.getStubType() != node.getElementType()) { reportStubAstMismatch( "Stub and PSI element type mismatch in " + getName() + ": stub " + stub + ", AST " + node.getElementType() + "; " + node, stubTree, cachedDocument); } PsiElement psi = stub.getPsi(); assert psi != null : "Stub " + stub + " (" + stub.getClass() + ") has returned null PSI"; result.add(Pair.create((StubBasedPsiElementBase) psi, (CompositeElement) node)); } super.visitNode(node); } }); } finally { LazyParseableElement.setSuppressEagerPsiCreation(false); } if (stubs.hasNext()) { reportStubAstMismatch( "Stub list in " + getName() + " has more elements than PSI", stubTree, cachedDocument); } return result; }