diagnose invalid stub-based PsiAnchor (IDEA-100526, IDEA-100962)

This commit is contained in:
peter
2013-02-14 15:01:31 +01:00
parent b72950d544
commit 66ca47b829
2 changed files with 38 additions and 10 deletions
@@ -58,7 +58,7 @@ class AnchorElementInfo extends SelfElementInfo {
if (stubId != -1) {
PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject);
if (!(file instanceof PsiFileWithStubSupport)) return null;
return PsiAnchor.restoreFromStubIndex((PsiFileWithStubSupport)file, stubId, myStubElementType);
return PsiAnchor.restoreFromStubIndex((PsiFileWithStubSupport)file, stubId, myStubElementType, false);
}
if (!mySyncMarkerIsValid) return null;
PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject);
@@ -327,8 +327,11 @@ public abstract class PsiAnchor {
@Nullable
public static PsiElement restoreFromStubIndex(PsiFileWithStubSupport fileImpl,
int index,
@NotNull IStubElementType elementType) {
if (fileImpl == null) return null;
@NotNull IStubElementType elementType, boolean throwIfNull) {
if (fileImpl == null) {
if (throwIfNull) throw new AssertionError("Null file");
return null;
}
StubTree tree = fileImpl.getStubTree();
boolean foreign = tree == null;
@@ -338,26 +341,36 @@ public abstract class PsiAnchor {
tree = ((PsiFileImpl)fileImpl).calcStubTree();
}
else {
if (throwIfNull) throw new AssertionError("Not PsiFileImpl: " + fileImpl.getClass());
return null;
}
}
List<StubElement<?>> list = tree.getPlainList();
if (index >= list.size()) return null;
if (index >= list.size()) {
if (throwIfNull) throw new AssertionError("Too large index: " + index + ">=" + list.size());
return null;
}
StubElement stub = list.get(index);
if (stub.getStubType() != elementType) return null;
if (stub.getStubType() != elementType) {
if (throwIfNull) throw new AssertionError("Element type mismatch: " + stub.getStubType() + "!=" + elementType);
return null;
}
if (foreign) {
final PsiElement cachedPsi = ((StubBase)stub).getCachedPsi();
if (cachedPsi != null) return cachedPsi;
final ASTNode ast = fileImpl.findTreeForStub(tree, stub);
return ast != null ? ast.getPsi() : null;
}
else {
return stub.getPsi();
if (ast != null) {
return ast.getPsi();
}
if (throwIfNull) throw new AssertionError("No AST for stub");
return null;
}
return stub.getPsi();
}
public static class StubIndexReference extends PsiAnchor {
@@ -396,11 +409,26 @@ public abstract class PsiAnchor {
return ApplicationManager.getApplication().runReadAction(new NullableComputable<PsiElement>() {
@Override
public PsiElement compute() {
return restoreFromStubIndex((PsiFileWithStubSupport)getFile(), myIndex, myElementType);
return restoreFromStubIndex((PsiFileWithStubSupport)getFile(), myIndex, myElementType, false);
}
});
}
public String diagnoseNull() {
try {
PsiElement element = ApplicationManager.getApplication().runReadAction(new NullableComputable<PsiElement>() {
@Override
public PsiElement compute() {
return restoreFromStubIndex((PsiFileWithStubSupport)getFile(), myIndex, myElementType, true);
}
});
return "No diagnostics, element=" + element + "@" + (element == null ? 0 : System.identityHashCode(element));
}
catch (AssertionError e) {
return e.getMessage();
}
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;