mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
smart pointers on import lists should survive adding new imports (IDEA-161409)
This commit is contained in:
@@ -30,16 +30,14 @@ public class JavaAnchorProvider extends SmartPointerAnchorProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (element instanceof PsiClass) {
|
||||
if (element instanceof PsiAnonymousClass) {
|
||||
return ((PsiAnonymousClass)element).getBaseClassReference().getReferenceNameElement();
|
||||
} else {
|
||||
return ((PsiClass)element).getNameIdentifier();
|
||||
}
|
||||
} else if (element instanceof PsiMethod) {
|
||||
return ((PsiMethod)element).getNameIdentifier();
|
||||
} else if (element instanceof PsiVariable) {
|
||||
return ((PsiVariable)element).getNameIdentifier();
|
||||
if (element instanceof PsiAnonymousClass) {
|
||||
return ((PsiAnonymousClass)element).getBaseClassReference().getReferenceNameElement();
|
||||
}
|
||||
if (element instanceof PsiClass || element instanceof PsiMethod || element instanceof PsiVariable) {
|
||||
return ((PsiNameIdentifierOwner)element).getNameIdentifier();
|
||||
}
|
||||
if (element instanceof PsiImportList) {
|
||||
return element.getContainingFile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -55,6 +53,9 @@ public class JavaAnchorProvider extends SmartPointerAnchorProvider {
|
||||
|
||||
return parent;
|
||||
}
|
||||
if (anchor instanceof PsiJavaFile) {
|
||||
return ((PsiJavaFile)anchor).getImportList();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -996,7 +996,7 @@ class Foo {
|
||||
assertTopLevelFoldRegionsState "[FoldRegion +(49:92), placeholder='otherMethod() → { ', FoldRegion +(113:123), placeholder=' }']"
|
||||
}
|
||||
|
||||
public void "disabled - test imports remain collapsed when new item is added at the end"() {
|
||||
public void "test imports remain collapsed when new item is added at the end"() {
|
||||
boolean oldValue = CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY
|
||||
CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY = true
|
||||
DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(true); // tests disable this by default
|
||||
|
||||
+22
@@ -931,4 +931,26 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
|
||||
assertFalse(createPointer(clazz).hashCode() == createPointer(clazz.getMethods()[0]).hashCode());
|
||||
}
|
||||
|
||||
public void testImportListPointerSurvivesImportAddition() throws Exception {
|
||||
PsiJavaFile file = (PsiJavaFile)createFile("a.java", "import foo.Bar;\nclass Foo {}");
|
||||
SmartPointerEx<PsiImportList> pointer = createPointer(file.getImportList());
|
||||
Document document = file.getViewProvider().getDocument();
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(myProject, () -> {
|
||||
document.insertString(document.getText().indexOf("class"), "import foo.Goo;\n");
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
});
|
||||
assertEquals(file.getImportList(), pointer.getElement());
|
||||
assertSize(2, file.getImportList().getImportStatements());
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(myProject, () -> {
|
||||
document.insertString(0, " ");
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
document.deleteString(0, document.getText().indexOf("\nimport"));
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
});
|
||||
assertEquals(file.getImportList(), pointer.getElement());
|
||||
assertSize(1, file.getImportList().getImportStatements());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ class AnchorElementInfo extends SelfElementInfo {
|
||||
|
||||
AnchorElementInfo(@NotNull PsiElement anchor, @NotNull PsiFile containingFile, Identikit.ByAnchor identikit) {
|
||||
super(containingFile.getProject(), ProperTextRange.create(anchor.getTextRange()), identikit, containingFile, false);
|
||||
assert !(anchor instanceof PsiFile) : "FileElementInfo must be used for file: "+anchor;
|
||||
myStubElementTypeAndId = pack(-1, null);
|
||||
}
|
||||
// will restore by stub index until file tree get loaded
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.IFileElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.containers.WeakInterner;
|
||||
@@ -41,6 +42,8 @@ public abstract class Identikit {
|
||||
@NotNull
|
||||
public abstract Language getFileLanguage();
|
||||
|
||||
public abstract boolean isForPsiFile();
|
||||
|
||||
public static ByType fromPsi(@NotNull PsiElement element, @NotNull Language fileLanguage) {
|
||||
return fromTypes(element.getClass(), PsiUtilCore.getElementType(element), fileLanguage);
|
||||
}
|
||||
@@ -156,6 +159,11 @@ public abstract class Identikit {
|
||||
return myFileLanguage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForPsiFile() {
|
||||
return myElementType instanceof IFileElementType;
|
||||
}
|
||||
|
||||
private boolean isAcceptable(@NotNull PsiElement element) {
|
||||
return myElementClass == element.getClass() && myElementType == PsiUtilCore.getElementType(element);
|
||||
}
|
||||
@@ -204,6 +212,11 @@ public abstract class Identikit {
|
||||
public Language getFileLanguage() {
|
||||
return myAnchorInfo.getFileLanguage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForPsiFile() {
|
||||
return myAnchorInfo.isForPsiFile();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class MarkerCache {
|
||||
o2 = info2.getPsiEndOffset();
|
||||
if (o1 != o2) return o1 > o2 ? 1 : -1;
|
||||
|
||||
return (info1.isForInjected() ? 1 : 0) - (info2.isForInjected() ? 1 : 0);
|
||||
return (info1.isGreedy() ? 1 : 0) - (info2.isGreedy() ? 1 : 0);
|
||||
}
|
||||
};
|
||||
private final SmartPointerTracker myPointers;
|
||||
@@ -83,13 +83,13 @@ class MarkerCache {
|
||||
int i = 0;
|
||||
while (i < markers.length) {
|
||||
SelfElementInfo info = infos.get(i);
|
||||
boolean forInjected = info.isForInjected();
|
||||
boolean greedy = info.isGreedy();
|
||||
int start = info.getPsiStartOffset();
|
||||
int end = info.getPsiEndOffset();
|
||||
markers[i] = new ManualRangeMarker(start, end, forInjected, forInjected, !forInjected, null);
|
||||
markers[i] = new ManualRangeMarker(start, end, greedy, greedy, !greedy, null);
|
||||
|
||||
i++;
|
||||
while (i < markers.length && rangeEquals(infos.get(i), start, end, forInjected)) {
|
||||
while (i < markers.length && rangeEquals(infos.get(i), start, end, greedy)) {
|
||||
markers[i] = markers[i - 1];
|
||||
i++;
|
||||
}
|
||||
@@ -97,8 +97,8 @@ class MarkerCache {
|
||||
return markers;
|
||||
}
|
||||
|
||||
private static boolean rangeEquals(SelfElementInfo info, int start, int end, boolean injected) {
|
||||
return start == info.getPsiStartOffset() && end == info.getPsiEndOffset() && injected == info.isForInjected();
|
||||
private static boolean rangeEquals(SelfElementInfo info, int start, int end, boolean greedy) {
|
||||
return start == info.getPsiStartOffset() && end == info.getPsiEndOffset() && greedy == info.isGreedy();
|
||||
}
|
||||
|
||||
private static UpdatedRanges applyEvents(@NotNull List<DocumentEvent> events, final UpdatedRanges struct) {
|
||||
|
||||
@@ -89,8 +89,8 @@ public class SelfElementInfo extends SmartPointerElementInfo {
|
||||
return myEndOffset;
|
||||
}
|
||||
|
||||
boolean isForInjected() {
|
||||
return myForInjected;
|
||||
boolean isGreedy() {
|
||||
return myForInjected || myIdentikit.isForPsiFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user