diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/ImplicitVariableElementInfoFactory.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/ImplicitVariableElementInfoFactory.java index 912604bdeb52..72f54c44be42 100644 --- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/ImplicitVariableElementInfoFactory.java +++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/ImplicitVariableElementInfoFactory.java @@ -24,7 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.ImplicitVariable; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiIdentifier; -import com.intellij.psi.util.PsiUtilBase; +import com.intellij.psi.util.PsiUtilCore; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -87,7 +87,7 @@ public class ImplicitVariableElementInfoFactory implements SmartPointerElementIn @Override public VirtualFile getVirtualFile() { - return PsiUtilBase.getVirtualFile(myVar); + return PsiUtilCore.getVirtualFile(myVar); } @Override diff --git a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java index f9203b3e3c4a..e0b2ad260fc0 100644 --- a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java @@ -696,6 +696,14 @@ public abstract class CodeInsightTestCase extends PsiTestCase { action.actionPerformed(event); } + public static void ctrlD() { + AnAction action = ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_DUPLICATE); + DataContext dataContext = DataManager.getInstance().getDataContext(); + AnActionEvent event = new AnActionEvent(null, dataContext, "", action.getTemplatePresentation(), ActionManager.getInstance(), 0); + event.setInjectedContext(true); + action.actionPerformed(event); + } + @NotNull protected PsiClass findClass(@NotNull @NonNls final String name) { final PsiClass aClass = myJavaFacade.findClass(name, ProjectScope.getProjectScope(getProject())); diff --git a/platform/lang-api/src/com/intellij/psi/IdentitySmartPointer.java b/platform/lang-api/src/com/intellij/psi/IdentitySmartPointer.java index 2cbbcb1d94dd..2451dd2efa39 100644 --- a/platform/lang-api/src/com/intellij/psi/IdentitySmartPointer.java +++ b/platform/lang-api/src/com/intellij/psi/IdentitySmartPointer.java @@ -25,7 +25,7 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; public class IdentitySmartPointer implements SmartPsiElementPointer { - private T myElement; + private final T myElement; private final PsiFile myFile; public IdentitySmartPointer(@NotNull T element, @NotNull PsiFile file) { @@ -37,6 +37,7 @@ public class IdentitySmartPointer implements SmartPsiEleme this(element, element.getContainingFile()); } + @Override @NotNull public Project getProject() { return myFile.getProject(); @@ -47,6 +48,7 @@ public class IdentitySmartPointer implements SmartPsiEleme return myFile.getVirtualFile(); } + @Override public T getElement() { T element = myElement; if (element != null && !element.isValid()) { @@ -65,6 +67,7 @@ public class IdentitySmartPointer implements SmartPsiEleme && SmartPointerManager.getInstance(getProject()).pointToTheSameElement(this, (SmartPsiElementPointer)obj); } + @Override public PsiFile getContainingFile() { return myFile; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/ClsElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/ClsElementInfo.java index ad9ba5ef4d60..8beb1f7f0389 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/ClsElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/ClsElementInfo.java @@ -31,7 +31,7 @@ import org.jetbrains.annotations.NotNull; public class ClsElementInfo implements SmartPointerElementInfo { private final PsiAnchor.StubIndexReference myStubIndexReference; - public ClsElementInfo(PsiAnchor.StubIndexReference stubReference) { + public ClsElementInfo(@NotNull PsiAnchor.StubIndexReference stubReference) { myStubIndexReference = stubReference; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/HardElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/HardElementInfo.java index aa3bc6d9a8bb..42bbf66f8055 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/HardElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/HardElementInfo.java @@ -22,7 +22,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Segment; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; -import com.intellij.psi.util.PsiUtilBase; +import com.intellij.psi.util.PsiUtilCore; import org.jetbrains.annotations.NotNull; /** @@ -71,7 +71,7 @@ class HardElementInfo implements SmartPointerElementInfo { @Override public VirtualFile getVirtualFile() { - return PsiUtilBase.getVirtualFile(myElement); + return PsiUtilCore.getVirtualFile(myElement); } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java index 931945f3e56c..2c7e5ac35389 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java @@ -277,10 +277,13 @@ public class SelfElementInfo implements SmartPointerElementInfo { @Override public boolean pointsToTheSameElementAs(@NotNull SmartPointerElementInfo other) { if (other instanceof SelfElementInfo) { - return myVirtualFile == ((SelfElementInfo)other).myVirtualFile - && myType == ((SelfElementInfo)other).myType - && mySyncStartOffset == ((SelfElementInfo)other).mySyncStartOffset - && mySyncEndOffset == ((SelfElementInfo)other).mySyncEndOffset + SelfElementInfo otherInfo = (SelfElementInfo)other; + return myVirtualFile == otherInfo.myVirtualFile + && myType == otherInfo.myType + && mySyncMarkerIsValid + && otherInfo.mySyncMarkerIsValid + && mySyncStartOffset == otherInfo.mySyncStartOffset + && mySyncEndOffset == otherInfo.mySyncEndOffset ; } return Comparing.equal(restoreElement(), other.restoreElement()); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerEx.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerEx.java index 900ce1916bf3..986885478be9 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerEx.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerEx.java @@ -18,6 +18,7 @@ package com.intellij.psi.impl.smartPointers; import com.intellij.openapi.editor.RangeMarker; import com.intellij.psi.PsiElement; import com.intellij.psi.SmartPsiElementPointer; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface SmartPointerEx extends SmartPsiElementPointer { @@ -25,4 +26,7 @@ public interface SmartPointerEx extends SmartPsiElementPoi void documentAndPsiInSync(); void unfastenBelt(int offset); + + @NotNull + SmartPointerElementInfo getElementInfo(); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java index a765e70222e8..ac21ec12ebcc 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java @@ -178,7 +178,12 @@ public class SmartPointerManagerImpl extends SmartPointerManager { private static SmartPsiElementPointer getCachedPointer(@NotNull E element) { Reference data = element.getUserData(CACHED_SMART_POINTER_KEY); - return data == null ? null : data.get(); + SmartPsiElementPointer cachedPointer = data == null ? null : data.get(); + if (cachedPointer instanceof SmartPointerEx + && ((SmartPointerEx)cachedPointer).getElementInfo().restoreElement() != element) { + return null; + } + return cachedPointer; } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java index 1c187172da17..e468667881a3 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java @@ -203,16 +203,23 @@ class SmartPsiElementPointerImpl implements SmartPointerEx myElementInfo.fastenBelt(offset, cachedRangeMarker); } + @Override @NotNull - SmartPointerElementInfo getElementInfo() { + public SmartPointerElementInfo getElementInfo() { return myElementInfo; } - protected static boolean pointsToTheSameElementAs(SmartPsiElementPointer pointer1, SmartPsiElementPointer pointer2) { + protected static boolean pointsToTheSameElementAs(@NotNull SmartPsiElementPointer pointer1, @NotNull SmartPsiElementPointer pointer2) { + if (pointer1 == pointer2) return true; if (pointer1 instanceof SmartPsiElementPointerImpl && pointer2 instanceof SmartPsiElementPointerImpl) { - SmartPointerElementInfo elementInfo1 = ((SmartPsiElementPointerImpl)pointer1).getElementInfo(); - SmartPointerElementInfo elementInfo2 = ((SmartPsiElementPointerImpl)pointer2).getElementInfo(); - return elementInfo1.pointsToTheSameElementAs(elementInfo2); + SmartPsiElementPointerImpl impl1 = (SmartPsiElementPointerImpl)pointer1; + SmartPsiElementPointerImpl impl2 = (SmartPsiElementPointerImpl)pointer2; + SmartPointerElementInfo elementInfo1 = impl1.getElementInfo(); + SmartPointerElementInfo elementInfo2 = impl2.getElementInfo(); + if (!elementInfo1.pointsToTheSameElementAs(elementInfo2)) return false; + PsiElement cachedElement1 = impl1.getCachedElement(); + PsiElement cachedElement2 = impl2.getCachedElement(); + return cachedElement1 == null || cachedElement2 == null || cachedElement1 == cachedElement2; } return Comparing.equal(pointer1.getElement(), pointer2.getElement()); }