From b82f6dd943a8cec0dab0848e110f7327ae0678eb Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 7 Jun 2013 22:44:09 +0200 Subject: [PATCH] more diagnostics on stub-ast mismatch --- .../extapi/psi/StubBasedPsiElementBase.java | 1 + .../psi/SingleRootFileViewProvider.java | 2 +- .../intellij/psi/impl/source/PsiFileImpl.java | 66 ++++++++++--------- .../intellij/psi/stubs/ObjectStubTree.java | 17 ++++- .../com/intellij/psi/stubs/StubIndexImpl.java | 2 +- .../psi/stubs/StubTreeLoaderImpl.java | 8 ++- 6 files changed, 60 insertions(+), 36 deletions(-) diff --git a/platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java b/platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java index 73bcfa820984..2dfe323c27bf 100644 --- a/platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java +++ b/platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java @@ -176,6 +176,7 @@ public class StubBasedPsiElementBase extends ASTDelegateP if (psi != null) { return psi; } + ApplicationManager.getApplication().assertReadAccessAllowed(); synchronized (PsiLock.LOCK) { if (myStub != null) { throw new PsiInvalidElementAccessException(this, "no psi for file stub " + stub, null); diff --git a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java index 3e76a9fb60ca..abbd7258f3cc 100644 --- a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java @@ -472,7 +472,7 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi @Override public String toString() { - return getClass().getSimpleName() + "{myVirtualFile=" + myVirtualFile + '}'; + return getClass().getSimpleName() + "{myVirtualFile=" + myVirtualFile + ", content=" + getContent() + '}'; } private interface Content { diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index 4994f4233890..41ff455caab9 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -35,7 +35,6 @@ import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileWithId; import com.intellij.psi.*; @@ -260,23 +259,15 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF } private List> calcStubAstBindings(final ASTNode root) { - StubTree stubTree = derefStub(); + final StubTree stubTree = derefStub(); if (stubTree == null) { return Collections.emptyList(); } final Iterator> stubs = stubTree.getPlainList().iterator(); stubs.next(); // Skip file stub; - final IElementType contentElementType = getContentElementType(); - if (!(contentElementType instanceof IStubFileElementType)) { - final VirtualFile vFile = getVirtualFile(); - throw new AssertionError("A stub in a non-stub file '" + vFile + "'; isValid()=" + (vFile != null ? vFile.isValid() : "null") + - " type: " + contentElementType + "; content:<<<\n" + - StringUtil.first(getViewProvider().getContents(), 200, true) + - "\n>>>; stubs=" + ContainerUtil.collect(stubs)); - } final List> result = ContainerUtil.newArrayList(); - final StubBuilder builder = ((IStubFileElementType)contentElementType).getBuilder(); + final StubBuilder builder = ((IStubFileElementType)getContentElementType()).getBuilder(); ((TreeElement)root).acceptTree(new RecursiveTreeElementWalkingVisitor() { @Override @@ -290,16 +281,13 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF IElementType type = node.getElementType(); if (type instanceof IStubElementType && ((IStubElementType)type).shouldCreateStub(node)) { if (!stubs.hasNext()) { - rebuildStub(); - throw new AssertionError("Stub list in " + getName() + " has fewer elements than PSI. Last AST element: " + - node.getElementType() + " " + node); + reportStubAstMismatch("Stub list is less than AST, last AST element: " + node.getElementType() + " " + node, stubTree); } final StubElement stub = stubs.next(); if (stub.getStubType() != node.getElementType()) { - rebuildStub(); - throw new AssertionError("Stub and PSI element type mismatch in " + getName() + ": stub " + stub + ", AST " + - node.getElementType() + "; " + node); + reportStubAstMismatch("Stub and PSI element type mismatch in " + getName() + ": stub " + stub + ", AST " + + node.getElementType() + "; " + node, stubTree); } PsiElement psi = stub.getPsi(); @@ -310,9 +298,37 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF super.visitNode(node); } }); + if (stubs.hasNext()) { + reportStubAstMismatch("Stub list in " + getName() + " has more elements than PSI", stubTree); + } return result; } + private void reportStubAstMismatch(String message, StubTree stubTree) { + rebuildStub(); + String msg = message; + msg += "\n file=" + this; + msg += "\n name=" + getName(); + msg += "\n stub debugInfo=" + stubTree.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 += "; committed: " + PsiDocumentManager.getInstance(getProject()).isCommitted(document); + } + + throw new AssertionError(msg); + } + protected FileElement createFileElement(final CharSequence docText) { final FileElement treeElement; final TreeElement contentLeaf = createContentLeafElement(docText); @@ -649,6 +665,8 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF if (derefd != null) return derefd; if (getTreeElement() != null) return null; + if (!(getContentElementType() instanceof IStubFileElementType)) return null; + final VirtualFile vFile = getVirtualFile(); if (!(vFile instanceof VirtualFileWithId)) return null; @@ -656,19 +674,6 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF if (!(tree instanceof StubTree)) return null; StubTree stubHolder = (StubTree)tree; - final IElementType contentElementType = getContentElementType(); - if (!(contentElementType instanceof IStubFileElementType)) { - final FileViewProvider viewProvider = getViewProvider(); - throw new AssertionError("A stub in a non-stub file '" + vFile +"'; isValid()=" + vFile.isValid() + - "; IndexStamp="+ StubTreeLoader.getInstance().getStubTreeTimestamp(vFile) + - "; Type: " + contentElementType + "; " + - "Psi roots: " + viewProvider.getAllFiles() + "; " + - " StubUpdatingIndex.canHaveStub(vFile)=" + StubTreeLoader.getInstance().canHaveStub(vFile) + - " content:<<<\n"+ - StringUtil.first(viewProvider.getContents(),200,true)+ - "\n>>>; stubs=" + stubHolder.getPlainList()); - } - synchronized (PsiLock.LOCK) { if (getTreeElement() != null) return null; @@ -965,6 +970,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF StubElement currentStubTree = ((IStubFileElementType)contentElementType).getBuilder().buildStubTree(this); tree = new StubTree((PsiFileStub)currentStubTree); + tree.setDebugInfo("created in calcStubTree"); try { TreeUtil.bindStubsToTree(this, tree); } diff --git a/platform/core-impl/src/com/intellij/psi/stubs/ObjectStubTree.java b/platform/core-impl/src/com/intellij/psi/stubs/ObjectStubTree.java index 2ae9950c92ad..7d597b70c0bd 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/ObjectStubTree.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/ObjectStubTree.java @@ -30,9 +30,9 @@ import java.util.Map; * Date: 8/3/12 */ public class ObjectStubTree { - - protected static final Key STUB_TO_TREE_REFERENCE = Key.create("stub to tree reference"); + private static final Key STUB_TO_TREE_REFERENCE = Key.create("stub to tree reference"); protected final ObjectStubBase myRoot; + private String myDebugInfo; protected final List myPlainList = new ArrayList(); public ObjectStubTree(@NotNull final ObjectStubBase root, final boolean withBackReference) { @@ -73,6 +73,19 @@ public class ObjectStubTree { } } + public void setDebugInfo(String info) { + ObjectStubTree ref = myRoot.getUserData(STUB_TO_TREE_REFERENCE); + if (ref != null) { + assert ref == this; + info += "; with backReference"; + } + myDebugInfo = info; + } + + public String getDebugInfo() { + return myDebugInfo; + } + private static class StubIndexSink implements IndexSink, TObjectProcedure>,TObjectObjectProcedure { private final THashMap> myResult = new THashMap>(); private int myStubIdx; diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index aae4a42a1e77..9f3ab4b161d9 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -437,7 +437,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe msg += "; file stamp: " + file.getModificationStamp(); msg += "; file modCount: " + file.getModificationCount(); - Document document = FileDocumentManager.getInstance().getDocument(file); + Document document = FileDocumentManager.getInstance().getCachedDocument(file); if (document != null) { msg += "\nsaved: " + !FileDocumentManager.getInstance().isDocumentUnsaved(document); msg += "; doc stamp: " + document.getModificationStamp(); diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubTreeLoaderImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubTreeLoaderImpl.java index fa74ecd53774..511d176cd78e 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubTreeLoaderImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubTreeLoaderImpl.java @@ -70,7 +70,9 @@ public class StubTreeLoaderImpl extends StubTreeLoader { } } if (element instanceof PsiFileStub) { - return new StubTree((PsiFileStub)element); + StubTree tree = new StubTree((PsiFileStub)element); + tree.setDebugInfo("created from file content, timestamp=" + vFile.getTimeStamp()); + return tree; } } catch (IOException e) { @@ -104,7 +106,9 @@ public class StubTreeLoaderImpl extends StubTreeLoader { catch (SerializerNotFoundException e) { return processError(vFile, "No stub serializer: " + vFile.getPresentableUrl() + ": " + e.getMessage(), e); } - return stub instanceof PsiFileStub ? new StubTree((PsiFileStub)stub) : new ObjectStubTree((ObjectStubBase)stub, true); + ObjectStubTree tree = stub instanceof PsiFileStub ? new StubTree((PsiFileStub)stub) : new ObjectStubTree((ObjectStubBase)stub, true); + tree.setDebugInfo("created from index, index creation stamp=" + IndexInfrastructure.getIndexCreationStamp(StubUpdatingIndex.INDEX_ID) + "; index stamp=" + IndexingStamp.getIndexStamp(vFile, StubUpdatingIndex.INDEX_ID)); + return tree; } else if (size != 0) { return processError(vFile, "Twin stubs: " + vFile.getPresentableUrl() + " has " + size + " stub versions. Should only have one. id=" + id,