mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
a language-independent way of retrieving the original PSI element in completion
This commit is contained in:
@@ -183,55 +183,6 @@ public class JavaCompletionUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiField getOriginalElement(@NotNull PsiField field) {
|
||||
final PsiClass cls = field.getContainingClass();
|
||||
if (cls != null) {
|
||||
final PsiClass newParent = getOriginalElement(cls);
|
||||
if (newParent != cls) {
|
||||
final PsiField original = newParent.findFieldByName(field.getName(), false);
|
||||
if (original != null) {
|
||||
return original;
|
||||
}
|
||||
}
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiTypeParameter getOriginalElement(@NotNull PsiTypeParameter param) {
|
||||
final PsiClass parent = PsiTreeUtil.getParentOfType(param, PsiClass.class, true, PsiMethod.class);
|
||||
if (parent != null) {
|
||||
final PsiClass newParent = getOriginalElement(parent);
|
||||
if (newParent != parent) {
|
||||
for (PsiTypeParameter parameter : newParent.getTypeParameters()) {
|
||||
if (parameter.getName().equals(param.getName())) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiClass getOriginalElement(@NotNull PsiClass cls) {
|
||||
final PsiClass containingClass = cls.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final PsiClass newParent = getOriginalElement(containingClass);
|
||||
if (newParent != containingClass) {
|
||||
return findClassByName(cls, newParent.getInnerClasses());
|
||||
}
|
||||
}
|
||||
|
||||
final PsiFile containingFile = cls.getContainingFile();
|
||||
if (containingFile instanceof PsiClassOwner) {
|
||||
return findClassByName(cls, ((PsiClassOwner)containingFile.getOriginalFile()).getClasses());
|
||||
}
|
||||
|
||||
return cls;
|
||||
}
|
||||
|
||||
private static PsiClass findClassByName(PsiClass defResult, PsiClass[] classes) {
|
||||
String name = defResult.getName();
|
||||
if (name == null) return defResult;
|
||||
@@ -269,7 +220,7 @@ public class JavaCompletionUtil {
|
||||
|
||||
LOG.assertTrue(psiClass.isValid());
|
||||
|
||||
return new PsiImmediateClassType(getOriginalElement(psiClass), originalize(substitutor));
|
||||
return new PsiImmediateClassType(CompletionUtil.getOriginalOrSelf(psiClass), originalize(substitutor));
|
||||
}
|
||||
|
||||
public PsiType visitEllipsisType(final PsiEllipsisType ellipsisType) {
|
||||
@@ -300,7 +251,7 @@ public class JavaCompletionUtil {
|
||||
PsiSubstitutor originalSubstitutor = PsiSubstitutor.EMPTY;
|
||||
for (final Map.Entry<PsiTypeParameter, PsiType> entry : substitutor.getSubstitutionMap().entrySet()) {
|
||||
final PsiType value = entry.getValue();
|
||||
originalSubstitutor = originalSubstitutor.put(getOriginalElement(entry.getKey()), value == null ? null : originalize(value));
|
||||
originalSubstitutor = originalSubstitutor.put(CompletionUtil.getOriginalOrSelf(entry.getKey()), value == null ? null : originalize(value));
|
||||
}
|
||||
return originalSubstitutor;
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
package com.intellij.codeInsight.completion.scope;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.codeInsight.completion.CompletionUtil;
|
||||
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
@@ -112,7 +112,7 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
}
|
||||
|
||||
private static boolean isInitializedImplicitly(PsiField field) {
|
||||
field = JavaCompletionUtil.getOriginalElement(field);
|
||||
field = CompletionUtil.getOriginalOrSelf(field);
|
||||
for(ImplicitUsageProvider provider: ImplicitUsageProvider.EP_NAME.getExtensions()) {
|
||||
if (provider.isImplicitWrite(field)) {
|
||||
return true;
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.intellij.codeInsight.lookup;
|
||||
import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.completion.CodeCompletionFeatures;
|
||||
import com.intellij.codeInsight.completion.CompletionUtil;
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
@@ -94,7 +95,7 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
|
||||
PsiReference reference = context.getFile().findReferenceAt(context.getStartOffset());
|
||||
if (reference instanceof PsiReferenceExpression && !((PsiReferenceExpression) reference).isQualified()) {
|
||||
final PsiVariable target = JavaPsiFacade.getInstance(context.getProject()).getResolveHelper().resolveReferencedVariable(field.getName(), (PsiElement)reference);
|
||||
return !field.getManager().areElementsEquivalent(target, JavaCompletionUtil.getOriginalElement(field));
|
||||
return !field.getManager().areElementsEquivalent(target, CompletionUtil.getOriginalOrSelf(field));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.filters.getters;
|
||||
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.codeInsight.completion.CompletionUtil;
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.psi.*;
|
||||
@@ -38,7 +38,7 @@ public abstract class MembersGetter {
|
||||
|
||||
PsiClass current = PsiTreeUtil.getContextOfType(context, PsiClass.class);
|
||||
while (current != null) {
|
||||
current = JavaCompletionUtil.getOriginalElement(current);
|
||||
current = CompletionUtil.getOriginalOrSelf(current);
|
||||
if (InheritanceUtil.isInheritorOrSelf(current, where, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
+21
-1
@@ -35,6 +35,8 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.editor.ex.RangeMarkerEx;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
@@ -66,6 +68,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -458,7 +461,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
|
||||
Document document = fileCopy.getViewProvider().getDocument();
|
||||
assert document != null : "no document";
|
||||
initContext.getFileCopyPatcher().patchFileCopy(fileCopy, document, initContext.getOffsetMap());
|
||||
patchFileCopy(initContext, fileCopy, document);
|
||||
final Document hostDocument = hostFile.getViewProvider().getDocument();
|
||||
assert hostDocument != null : "no host document";
|
||||
PsiDocumentManager.getInstance(hostFile.getProject()).commitDocument(hostDocument);
|
||||
@@ -489,6 +492,23 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
return context;
|
||||
}
|
||||
|
||||
private static void patchFileCopy(CompletionInitializationContext initContext, PsiFile fileCopy, Document document) {
|
||||
final LinkedList<DocumentEvent> events = new LinkedList<DocumentEvent>();
|
||||
|
||||
final DocumentAdapter listener = new DocumentAdapter() {
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
events.addFirst(e);
|
||||
}
|
||||
};
|
||||
|
||||
document.addDocumentListener(listener);
|
||||
initContext.getFileCopyPatcher().patchFileCopy(fileCopy, document, initContext.getOffsetMap());
|
||||
document.removeDocumentListener(listener);
|
||||
|
||||
document.putUserData(CompletionUtil.RANGE_TRANSLATION, events);
|
||||
}
|
||||
|
||||
private boolean isAutocompleteCommonPrefixOnInvocation() {
|
||||
return invokedExplicitly && CodeInsightSettings.getInstance().AUTOCOMPLETE_COMMON_PREFIX;
|
||||
}
|
||||
|
||||
@@ -24,25 +24,31 @@ import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.filters.TrueFilter;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.character;
|
||||
|
||||
public class CompletionUtil {
|
||||
static final Key<List<DocumentEvent>> RANGE_TRANSLATION = Key.create("completion.rangeTranslation");
|
||||
public static final Key<TailType> TAIL_TYPE_ATTR = LookupItem.TAIL_TYPE_ATTR;
|
||||
|
||||
private static final CompletionData ourGenericCompletionData = new CompletionData() {
|
||||
@@ -205,4 +211,56 @@ public class CompletionUtil {
|
||||
offsetMap.addOffset(CompletionInitializationContext.SELECTION_END_OFFSET, tailOffset);
|
||||
context.setTailOffset(tailOffset);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Integer translateOffset(int offset, DocumentEvent event) {
|
||||
if (event.getOffset() < offset && offset < event.getNewLength()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return offset <= event.getOffset() ? offset : offset - event.getNewLength() + event.getOldLength();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getTargetElement(LookupElement lookupElement) {
|
||||
final Object object = lookupElement.getObject();
|
||||
if (object instanceof PsiElement) {
|
||||
return getOriginalElement((PsiElement)object);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T extends PsiElement> T getOriginalElement(@NotNull T psi) {
|
||||
final PsiFile file = psi.getContainingFile();
|
||||
if (file != null) {
|
||||
final Document document = file.getViewProvider().getDocument();
|
||||
if (document != null) {
|
||||
final List<DocumentEvent> translator = document.getUserData(RANGE_TRANSLATION);
|
||||
if (translator != null) {
|
||||
TextRange range = psi.getTextRange();
|
||||
Integer start = range.getStartOffset();
|
||||
Integer end = range.getEndOffset();
|
||||
for (DocumentEvent event : translator) {
|
||||
start = translateOffset(range.getStartOffset(), event);
|
||||
end = translateOffset(range.getEndOffset(), event);
|
||||
if (start == null || end == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return (T)PsiTreeUtil.findElementOfClassAtRange(file.getOriginalFile(), start, end, psi.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return psi;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PsiElement> T getOriginalOrSelf(@NotNull T psi) {
|
||||
final T element = getOriginalElement(psi);
|
||||
return element == null ? psi : element;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ public class GroovyClassNameInsertHandler implements InsertHandler<JavaPsiClassR
|
||||
((GroovyFileBase)file).addImportForClass(psiClass);
|
||||
return;
|
||||
}
|
||||
else if (aClass == JavaCompletionUtil.getOriginalElement(psiClass)) {
|
||||
else if (aClass == CompletionUtil.getOriginalOrSelf(psiClass)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user