diff --git a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy index 8451b419dd7d..84ef157983b7 100644 --- a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy +++ b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy @@ -218,4 +218,15 @@ class B { assert !file.treeElement } + void "test node is not deeply parsed when loaded in green stub presence"() { + PsiFileImpl file = (PsiFileImpl)myFixture.addFileToProject("a.java", "class A{}") + def stubTree = file.stubTree + PsiClass psiClass = ((PsiJavaFile)file).classes[0] + assert psiClass.nameIdentifier + GCUtil.tryGcSoftlyReachableObjects() + + assert stubTree.is(file.greenStubTree) + assert !file.node.parsed + } + } 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 5298f2468a71..b92cf84896df 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 @@ -70,7 +70,6 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF protected PsiFile myOriginalFile; private final FileViewProvider myViewProvider; private volatile Reference myStub; - private volatile Reference myGreenStub; private boolean myInvalidated; private volatile boolean myAstLoaded; private volatile boolean myUseStrongRefs; @@ -216,12 +215,10 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF } if (stub != null) { - myGreenStub = new SoftReference(stub); putUserData(ObjectStubTree.LAST_STUB_TREE_HASH, stub.hashCode()); } switchFromStubToAst(bindings); - myStub = null; myTreeElementPointer = createTreeElementPointer(treeElement); myAstLoaded = true; @@ -284,7 +281,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF private List> calcStubAstBindings(@NotNull FileElement root, @Nullable final Document cachedDocument, @Nullable final StubTree stubTree) { - if (stubTree == null) { + if (stubTree == null || myAstLoaded) { // don't bind green stub to AST: the PSI should already be cached in myRefToPsi return Collections.emptyList(); } @@ -376,12 +373,11 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF } private void clearStub(@NotNull String reason) { - StubTree stubHolder = SoftReference.dereference(myStub); + StubTree stubHolder = derefStub(); if (stubHolder != null) { ((PsiFileStubImpl)stubHolder.getRoot()).clearPsi(reason); } myStub = null; - myGreenStub = null; } public void clearCaches() { @@ -695,21 +691,23 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF */ @Nullable public final StubElement getGreenStub() { - StubTree stubHolder = getStubTree(); - if (stubHolder == null) stubHolder = getGreenStubTree(); + StubTree stubHolder = getGreenStubTree(); return stubHolder != null ? stubHolder.getRoot() : null; } + /** + * @return a stub tree, if this file has it, and only if AST isn't loaded + */ @Override @Nullable public StubTree getStubTree() { ApplicationManager.getApplication().assertReadAccessAllowed(); + if (myAstLoaded) return null; if (Boolean.TRUE.equals(getUserData(BUILDING_STUB))) return null; final StubTree derefd = derefStub(); if (derefd != null) return derefd; - if (myAstLoaded) return null; if (getElementTypeForStubBuilder() == null) return null; @@ -1045,18 +1043,19 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF */ @Nullable public final StubTree getGreenStubTree() { - return SoftReference.dereference(myGreenStub); + StubTree result = derefStub(); + return result != null ? result : getStubTree(); } @NotNull public StubTree calcStubTree() { - StubTree tree = SoftReference.dereference(myGreenStub); + StubTree tree = derefStub(); if (tree != null) { return tree; } FileElement fileElement = calcTreeElement(); synchronized (myStubFromTreeLock) { - tree = SoftReference.dereference(myGreenStub); + tree = derefStub(); if (tree == null) { ApplicationManager.getApplication().assertReadAccessAllowed(); @@ -1087,7 +1086,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF throw new RuntimeException("Stub and PSI element type mismatch in " + getName(), e); } - myGreenStub = new SoftReference(tree); + myStub = new SoftReference(tree); } return tree;