From d94d0f404f2791f64b005a0b6a257333cfc64ba2 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 24 Sep 2015 17:43:34 +0200 Subject: [PATCH] PsiFileImpl: fix race condition between AST and stub loading, which resulted in stub elements being not bound to AST --- .../intellij/psi/impl/source/PsiFileImpl.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) 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 d36d802a8008..93faaab938dd 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 @@ -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> bindings = calcStubAstBindings(treeElement, cachedDocument, stub); + while (true) { + StubTree stub = derefStub(); + List> 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> 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(stub)); putUserData(ObjectStubTree.LAST_STUB_TREE_HASH, stub.hashCode());