PsiFileImpl: fix race condition between AST and stub loading, which resulted in stub elements being not bound to AST

This commit is contained in:
peter
2015-09-24 18:13:41 +02:00
parent 9f59a40bee
commit d94d0f404f
@@ -186,15 +186,32 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
FileElement treeElement = createFileElement(viewProvider.getContents());
treeElement.setPsi(this);
final StubTree stub = derefStub();
List<Pair<StubBasedPsiElementBase, CompositeElement>> bindings = calcStubAstBindings(treeElement, cachedDocument, stub);
while (true) {
StubTree stub = derefStub();
List<Pair<StubBasedPsiElementBase, CompositeElement>> bindings = calcStubAstBindings(treeElement, cachedDocument, stub);
FileElement savedTree = ensureTreeElement(viewProvider, treeElement, stub, bindings);
if (savedTree != null) {
return savedTree;
}
}
}
@Nullable
private FileElement ensureTreeElement(@NotNull FileViewProvider viewProvider,
@NotNull FileElement treeElement,
@Nullable StubTree stub,
@NotNull List<Pair<StubBasedPsiElementBase, CompositeElement>> bindings) {
synchronized (PsiLock.LOCK) {
FileElement existing = derefTreeElement();
if (existing != null) {
return existing;
}
if (stub != derefStub()) {
return null; // stub has been just loaded by another thread, it needs to be bound to AST
}
if (stub != null) {
treeElement.putUserData(STUB_TREE_IN_PARSED_TREE, new SoftReference<StubTree>(stub));
putUserData(ObjectStubTree.LAST_STUB_TREE_HASH, stub.hashCode());