diff --git a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy index a996ce26aecf..3ad83a0f32bd 100644 --- a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy +++ b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy @@ -17,7 +17,9 @@ package com.intellij.psi import com.intellij.openapi.application.ApplicationManager import com.intellij.psi.impl.source.PsiFileImpl +import com.intellij.psi.util.PsiTreeUtil import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.reference.SoftReference /** * @author peter @@ -30,13 +32,29 @@ class StubAstSwitchTest extends LightCodeInsightFixtureTestCase { def cls = ((PsiJavaFile)file).classes[0] assert file.stub + def oldCount = psiManager.modificationTracker.javaStructureModificationCount + ApplicationManager.application.runWriteAction { file.virtualFile.setBinaryContent(file.virtualFile.contentsToByteArray()) } assert file.stub - //todo - //either: assert !cls.valid - //or: assert cls == PsiTreeUtil.findElementOfClassAtOffset(file, 1, PsiClass, false) - //assert !file.stub + assert psiManager.modificationTracker.javaStructureModificationCount != oldCount + assert !cls.valid + assert cls != PsiTreeUtil.findElementOfClassAtOffset(file, 1, PsiClass, false) + assert !file.stub + } + + public void "test reachable psi classes remain valid when nothing changes"() { + int count = 1000 + List> classList = (0.. extends ASTDelegateP public boolean isValid() { T stub = myStub; if (stub != null) { - if (stub instanceof PsiFileStub) { - return stub.getPsi().isValid(); + PsiElement parentPsi = stub.getParentStub().getPsi(); + if (parentPsi instanceof PsiFileImpl) { + return ((PsiFileImpl) parentPsi).isStubBasedChildValid(this); } - - return stub.getParentStub().getPsi().isValid(); + return parentPsi.isValid(); } return super.isValid(); 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 dd202dd57883..d3ff3e9ae771 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 @@ -249,6 +249,20 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF return findTreeForStub(ast, stubs, stub); } + public boolean isStubBasedChildValid(@NotNull StubBasedPsiElementBase psi) { + StubElement fileStub = getStub(); + if (fileStub != null) { + synchronized (myStubLock) { + fileStub = getStub(); + StubElement childStub = psi.getStub(); + if (fileStub != null && childStub != null && fileStub != childStub.getParentStub()) { + return false; + } + } + } + return isValid(); + } + @Nullable private static ASTNode findTreeForStub(ASTNode tree, final Iterator> stubs, final StubElement stub) { final IElementType type = tree.getElementType();