invalidate smart pointers when elements really become invalid (IDEA-157564)

This commit is contained in:
peter
2016-06-21 11:15:16 +02:00
parent ac1445a35e
commit ee4f7c8a30
4 changed files with 36 additions and 13 deletions
@@ -877,6 +877,26 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
return (SmartPointerEx<T>)getPointerManager().createSmartPsiElementPointer(element);
}
public void testCommentingField() throws Exception {
PsiJavaFile file = (PsiJavaFile)createFile("a.java", "class A {\n" +
" int x;\n" +
" int y;\n" +
"}");
PsiField[] fields = file.getClasses()[0].getFields();
SmartPointerEx<PsiField> pointer0 = createPointer(fields[0]);
SmartPointerEx<PsiField> pointer1 = createPointer(fields[1]);
WriteCommandAction.runWriteCommandAction(myProject, () -> {
Document document = file.getViewProvider().getDocument();
assert document != null;
document.insertString(file.getText().indexOf("int"), "//");
commitDocument(document);
});
assertNull(pointer0.getElement());
assertEquals("y", pointer1.getElement().getName());
}
public void testAnchorInfoHasRange() throws Exception {
PsiJavaFile file = (PsiJavaFile)createFile("a.java", "class C1{}");
assertNotNull(((PsiFileImpl) file).getStubTree());
@@ -98,6 +98,13 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
@Override
@NotNull
public <E extends PsiElement> SmartPsiElementPointer<E> createSmartPsiElementPointer(@NotNull E element, PsiFile containingFile) {
return createSmartPsiElementPointer(element, containingFile, false);
}
@NotNull
public <E extends PsiElement> SmartPsiElementPointer<E> createSmartPsiElementPointer(@NotNull E element,
PsiFile containingFile,
boolean forInjected) {
if (containingFile != null && !containingFile.isValid() || containingFile == null && !element.isValid()) {
PsiUtilCore.ensureValid(element);
LOG.error("Invalid element:" + element);
@@ -108,7 +115,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
return pointer;
}
pointer = new SmartPsiElementPointerImpl<E>(myProject, element, containingFile);
pointer = new SmartPsiElementPointerImpl<E>(myProject, element, containingFile, forInjected);
if (containingFile != null) {
trackPointer(pointer, containingFile.getViewProvider().getVirtualFile());
}
@@ -245,10 +252,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
return;
}
E newTarget = pointer.doRestoreElement();
if (newTarget != null) {
pointer.cacheElement(newTarget);
}
pointer.cacheElement(pointer.doRestoreElement());
}
@@ -47,8 +47,8 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
private final Class<? extends PsiElement> myElementClass;
private byte myReferenceCount = 1;
SmartPsiElementPointerImpl(@NotNull Project project, @NotNull E element, @Nullable PsiFile containingFile) {
this(element, createElementInfo(project, element, containingFile), element.getClass());
SmartPsiElementPointerImpl(@NotNull Project project, @NotNull E element, @Nullable PsiFile containingFile, boolean forInjected) {
this(element, createElementInfo(project, element, containingFile, forInjected), element.getClass());
}
SmartPsiElementPointerImpl(@NotNull E element,
@NotNull SmartPointerElementInfo elementInfo,
@@ -142,8 +142,8 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
@NotNull
private static <E extends PsiElement> SmartPointerElementInfo createElementInfo(@NotNull Project project,
@NotNull E element,
PsiFile containingFile) {
SmartPointerElementInfo elementInfo = doCreateElementInfo(project, element, containingFile);
PsiFile containingFile, boolean forInjected) {
SmartPointerElementInfo elementInfo = doCreateElementInfo(project, element, containingFile, forInjected);
if (ApplicationManager.getApplication().isUnitTestMode() && !element.equals(elementInfo.restoreElement())) {
// likely cause: PSI having isPhysical==true, but which can't be restored by containing file and range. To fix, make isPhysical return false
LOG.error("Cannot restore " + element + " of " + element.getClass() + " from " + elementInfo);
@@ -154,7 +154,7 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
@NotNull
private static <E extends PsiElement> SmartPointerElementInfo doCreateElementInfo(@NotNull Project project,
@NotNull E element,
PsiFile containingFile) {
PsiFile containingFile, boolean forInjected) {
if (element instanceof PsiDirectory) {
return new DirElementInfo((PsiDirectory)element);
}
@@ -201,7 +201,7 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
}
ProperTextRange proper = ProperTextRange.create(elementRange);
return new SelfElementInfo(project, proper, AnchorTypeInfo.obtainInfo(element, LanguageUtil.getRootLanguage(element)), containingFile, false);
return new SelfElementInfo(project, proper, AnchorTypeInfo.obtainInfo(element, LanguageUtil.getRootLanguage(element)), containingFile, forInjected);
}
@NotNull
@@ -55,7 +55,6 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.Function;
import com.intellij.util.PathUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
@@ -199,7 +198,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT
TextRange relevantRangeInHost = relevantRange.shiftRight(hostTextRange.getStartOffset());
SmartPointerManagerImpl manager = (SmartPointerManagerImpl)SmartPointerManager.getInstance(myProject);
shreds.add(new ShredImpl(manager.createSmartPsiFileRangePointer(myHostPsiFile, relevantRangeInHost, true),
manager.createSmartPsiElementPointer(host, myHostPsiFile),
manager.createSmartPsiElementPointer(host, myHostPsiFile, true),
prefix, suffix, new ProperTextRange(startOffset, endOffset), false));
return this;
}