invalidate stub-based psi on stub replacement

This commit is contained in:
peter
2012-03-21 08:35:39 +01:00
parent 9555e57bff
commit 6a7dd8b435
3 changed files with 40 additions and 8 deletions
@@ -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<SoftReference<PsiClass>> classList = (0..<count).collect { new SoftReference(myFixture.addClass("class Foo$it {}")) }
System.gc()
System.gc()
System.gc()
assert classList.every {
def cls = it.get()
if (!cls || cls.valid) return true
cls.text //load AST
return cls.valid
}
}
}
@@ -154,11 +154,11 @@ public class StubBasedPsiElementBase<T extends StubElement> 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();
@@ -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<StubElement<?>> stubs, final StubElement stub) {
final IElementType type = tree.getElementType();