From ee4f7c8a303d24b37d4474495bd8298b43581caf Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 21 Jun 2016 11:15:16 +0200 Subject: [PATCH] invalidate smart pointers when elements really become invalid (IDEA-157564) --- .../SmartPsiElementPointersTest.java | 20 +++++++++++++++++++ .../SmartPointerManagerImpl.java | 14 ++++++++----- .../SmartPsiElementPointerImpl.java | 12 +++++------ .../tree/injected/MultiHostRegistrarImpl.java | 3 +-- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java index 789066f498b0..37ea37f6c233 100644 --- a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java @@ -877,6 +877,26 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase { return (SmartPointerEx)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 pointer0 = createPointer(fields[0]); + SmartPointerEx 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()); diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java index 54593661e38b..d18fb3ed192c 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java @@ -98,6 +98,13 @@ public class SmartPointerManagerImpl extends SmartPointerManager { @Override @NotNull public SmartPsiElementPointer createSmartPsiElementPointer(@NotNull E element, PsiFile containingFile) { + return createSmartPsiElementPointer(element, containingFile, false); + } + + @NotNull + public SmartPsiElementPointer 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(myProject, element, containingFile); + pointer = new SmartPsiElementPointerImpl(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()); } diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java index 8a0024f61ceb..ee7c4c9c249a 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java @@ -47,8 +47,8 @@ class SmartPsiElementPointerImpl implements SmartPointerEx private final Class 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 implements SmartPointerEx @NotNull private static 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 implements SmartPointerEx @NotNull private static 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 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 diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java index 44d63924b0f1..9cdd73107f87 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java @@ -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; }