mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 20:39:40 +07:00
don't suggest expected type members twice when they are statically imported (IDEA-79426)
This commit is contained in:
@@ -528,7 +528,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
!BasicExpressionCompletionContributor.AFTER_DOT.accepts(position) &&
|
||||
!(position.getParent() instanceof PsiLiteralExpression)) {
|
||||
for (final ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) {
|
||||
new JavaMembersGetter(info.getDefaultType(), position).addMembers(position, parameters.getInvocationCount() > 1, new Consumer<LookupElement>() {
|
||||
new JavaMembersGetter(info.getDefaultType(), position).addMembers(parameters, parameters.getInvocationCount() > 1, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
result.addElement(element);
|
||||
|
||||
@@ -356,9 +356,9 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
PsiElement position = params.getPosition();
|
||||
if (!BasicExpressionCompletionContributor.AFTER_DOT.accepts(position)) {
|
||||
for (ExpectedTypeInfo info : mergedInfos) {
|
||||
new JavaMembersGetter(info.getType(), position).addMembers(position, !quick, consumer);
|
||||
new JavaMembersGetter(info.getType(), position).addMembers(params, !quick, consumer);
|
||||
if (!info.getDefaultType().equals(info.getType())) {
|
||||
new JavaMembersGetter(info.getDefaultType(), position).addMembers(position, !quick, consumer);
|
||||
new JavaMembersGetter(info.getDefaultType(), position).addMembers(params, !quick, consumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
package com.intellij.psi.filters.getters;
|
||||
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.codeInsight.completion.JavaMethodCallElement;
|
||||
import com.intellij.codeInsight.completion.ReferenceExpressionCompletionContributor;
|
||||
import com.intellij.codeInsight.completion.SmartCompletionDecorator;
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.TailTypeDecorator;
|
||||
import com.intellij.codeInsight.lookup.VariableLookupItem;
|
||||
@@ -47,10 +44,12 @@ public class JavaMembersGetter extends MembersGetter {
|
||||
myExpectedType = JavaCompletionUtil.originalize(expectedType);
|
||||
}
|
||||
|
||||
public void addMembers(PsiElement position, boolean searchInheritors, final Consumer<LookupElement> results) {
|
||||
public void addMembers(CompletionParameters parameters, boolean searchInheritors, final Consumer<LookupElement> results) {
|
||||
final StaticMemberProcessor processor = JavaGlobalMemberNameCompletionContributor.completeStaticMembers(parameters);
|
||||
final PsiElement position = parameters.getPosition();
|
||||
if (myExpectedType instanceof PsiPrimitiveType && PsiType.DOUBLE.isAssignableFrom(myExpectedType)) {
|
||||
addConstantsFromTargetClass(position, results, searchInheritors);
|
||||
addConstantsFromReferencedClassesInSwitch(position, results);
|
||||
addConstantsFromTargetClass(position, results, searchInheritors, processor);
|
||||
addConstantsFromReferencedClassesInSwitch(position, results, processor);
|
||||
}
|
||||
|
||||
if (position.getParent().getParent() instanceof PsiSwitchLabelStatement) {
|
||||
@@ -58,10 +57,10 @@ public class JavaMembersGetter extends MembersGetter {
|
||||
}
|
||||
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInType(myExpectedType);
|
||||
processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, searchInheritors);
|
||||
processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, searchInheritors, processor);
|
||||
}
|
||||
|
||||
private void addConstantsFromReferencedClassesInSwitch(PsiElement position, final Consumer<LookupElement> results) {
|
||||
private void addConstantsFromReferencedClassesInSwitch(PsiElement position, final Consumer<LookupElement> results, final StaticMemberProcessor processor) {
|
||||
final Set<PsiField> fields = ReferenceExpressionCompletionContributor.findConstantsUsedInSwitch(position);
|
||||
final Set<PsiClass> classes = new HashSet<PsiClass>();
|
||||
for (PsiField field : fields) {
|
||||
@@ -76,11 +75,13 @@ public class JavaMembersGetter extends MembersGetter {
|
||||
results.consume(TailTypeDecorator.withTail(element, TailType.CASE_COLON));
|
||||
}
|
||||
}
|
||||
}, aClass, false, false);
|
||||
}, aClass, false, false, processor);
|
||||
}
|
||||
}
|
||||
|
||||
private void addConstantsFromTargetClass(PsiElement position, Consumer<LookupElement> results, boolean searchInheritors) {
|
||||
private void addConstantsFromTargetClass(PsiElement position,
|
||||
Consumer<LookupElement> results,
|
||||
boolean searchInheritors, final StaticMemberProcessor processor) {
|
||||
PsiElement parent = position.getParent();
|
||||
if (!(parent instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
@@ -93,7 +94,8 @@ public class JavaMembersGetter extends MembersGetter {
|
||||
final IElementType op = binaryExpression.getOperationTokenType();
|
||||
if (JavaTokenType.EQEQ == op || JavaTokenType.NE == op) {
|
||||
if (prev == binaryExpression.getROperand()) {
|
||||
processMembers(position, results, getCalledClass(binaryExpression.getLOperand()), false, searchInheritors);
|
||||
processMembers(position, results, getCalledClass(binaryExpression.getLOperand()), false, searchInheritors,
|
||||
processor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -101,7 +103,7 @@ public class JavaMembersGetter extends MembersGetter {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof PsiExpressionList) {
|
||||
processMembers(position, results, getCalledClass(parent.getParent()), false, searchInheritors);
|
||||
processMembers(position, results, getCalledClass(parent.getParent()), false, searchInheritors, processor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.psi.filters.getters;
|
||||
import com.intellij.codeInsight.CodeInsightUtil;
|
||||
import com.intellij.codeInsight.completion.CompletionUtil;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.codeInsight.completion.StaticMemberProcessor;
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
@@ -28,11 +29,14 @@ import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.PairConsumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author ik
|
||||
@@ -40,7 +44,9 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class MembersGetter {
|
||||
|
||||
public void processMembers(@NotNull final PsiElement context, final Consumer<LookupElement> results, @Nullable final PsiClass where, final boolean acceptMethods, boolean searchInheritors) {
|
||||
public void processMembers(@NotNull final PsiElement context, final Consumer<LookupElement> results, @Nullable final PsiClass where,
|
||||
final boolean acceptMethods, boolean searchInheritors,
|
||||
StaticMemberProcessor processor) {
|
||||
if (where == null) return;
|
||||
|
||||
final List<PsiClass> placeClasses = new ArrayList<PsiClass>();
|
||||
@@ -52,6 +58,31 @@ public abstract class MembersGetter {
|
||||
current = PsiTreeUtil.getContextOfType(current, PsiClass.class);
|
||||
}
|
||||
|
||||
final Set<PsiMember> importedStatically = new HashSet<PsiMember>();
|
||||
processor.processMembersOfRegisteredClasses(null, new PairConsumer<PsiMember, PsiClass>() {
|
||||
@Override
|
||||
public void consume(PsiMember member, PsiClass psiClass) {
|
||||
importedStatically.add(member);
|
||||
}
|
||||
});
|
||||
|
||||
final Condition<PsiClass> mayProcessMembers = new Condition<PsiClass>() {
|
||||
@Override
|
||||
public boolean value(PsiClass psiClass) {
|
||||
if (psiClass == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
psiClass = CompletionUtil.getOriginalOrSelf(psiClass);
|
||||
for (PsiClass placeClass : placeClasses) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(placeClass, psiClass, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(context.getProject()).getResolveHelper();
|
||||
|
||||
PsiClassType baseType = JavaPsiFacade.getElementFactory(where.getProject()).createType(where);
|
||||
@@ -59,14 +90,14 @@ public abstract class MembersGetter {
|
||||
@Override
|
||||
public void consume(PsiType psiType) {
|
||||
PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
|
||||
if (psiClass != null) {
|
||||
if (mayProcessMembers.value(psiClass)) {
|
||||
psiClass = CompletionUtil.getOriginalOrSelf(psiClass);
|
||||
for (PsiClass placeClass : placeClasses) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(placeClass, where, true)) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(placeClass, psiClass, true)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
processClassDeclaredMembers(psiClass, context, acceptMethods, results, resolveHelper);
|
||||
processClassDeclaredMembers(psiClass, context, acceptMethods, results, resolveHelper, importedStatically);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -79,14 +110,14 @@ public abstract class MembersGetter {
|
||||
private void processClassDeclaredMembers(PsiClass where,
|
||||
PsiElement context,
|
||||
boolean acceptMethods,
|
||||
Consumer<LookupElement> results, final PsiResolveHelper resolveHelper) {
|
||||
Consumer<LookupElement> results, final PsiResolveHelper resolveHelper, final Set<PsiMember> importedStatically) {
|
||||
final FilterScopeProcessor<PsiElement> processor = new FilterScopeProcessor<PsiElement>(TrueFilter.INSTANCE);
|
||||
where.processDeclarations(processor, ResolveState.initial(), null, context);
|
||||
|
||||
for (final PsiElement result : processor.getResults()) {
|
||||
if (result instanceof PsiMember && !(result instanceof PsiClass)) {
|
||||
final PsiMember member = (PsiMember)result;
|
||||
if (JavaCompletionUtil.isInExcludedPackage(member)) continue;
|
||||
if (JavaCompletionUtil.isInExcludedPackage(member) || importedStatically.contains(member)) continue;
|
||||
if (member.hasModifierProperty(PsiModifier.STATIC) && resolveHelper.isAccessible(member, context, null)) {
|
||||
if (result instanceof PsiField && !member.hasModifierProperty(PsiModifier.FINAL)) continue;
|
||||
if (result instanceof PsiMethod && acceptMethods) continue;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import static Super.FOO;
|
||||
|
||||
class Super {
|
||||
public static final Super FOO = null;
|
||||
public static final Super FOX = true;
|
||||
}
|
||||
|
||||
class Intermediate {
|
||||
Super s = FO<caret>
|
||||
}
|
||||
|
||||
|
||||
@@ -938,6 +938,11 @@ public class ListUtils {
|
||||
public void testSuggestExpectedTypeMembersInCall() throws Throwable { doTest('\n') }
|
||||
public void testExpectedTypesDotSelectsItem() throws Throwable { doTest('.') }
|
||||
|
||||
public void testExpectedTypeMembersVersusStaticImports() throws Throwable {
|
||||
configure()
|
||||
assertStringItems('FOO', 'FOX')
|
||||
}
|
||||
|
||||
public void testDoubleExpectedTypeFactoryMethod() throws Throwable {
|
||||
configure()
|
||||
assertStringItems('Key', 'create', 'create')
|
||||
|
||||
@@ -552,7 +552,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
|
||||
private static StaticMemberProcessor completeStaticMembers(CompletionParameters parameters) {
|
||||
static StaticMemberProcessor completeStaticMembers(CompletionParameters parameters) {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
final PsiElement originalPosition = parameters.getOriginalPosition();
|
||||
final StaticMemberProcessor processor = new StaticMemberProcessor(position) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.psi.*;
|
||||
@@ -31,14 +32,17 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt
|
||||
class GroovyMembersGetter extends MembersGetter {
|
||||
private final PsiClassType myExpectedType;
|
||||
private final GroovyPsiElement myContext;
|
||||
private final CompletionParameters myParameters;
|
||||
|
||||
GroovyMembersGetter(PsiClassType expectedType, PsiElement context) {
|
||||
GroovyMembersGetter(PsiClassType expectedType, PsiElement context, CompletionParameters parameters) {
|
||||
myParameters = parameters;
|
||||
myExpectedType = JavaCompletionUtil.originalize(expectedType);
|
||||
myContext = (GroovyPsiElement)context;
|
||||
}
|
||||
|
||||
public void processMembers(boolean searchInheritors, final Consumer<LookupElement> results) {
|
||||
processMembers(myContext, results, myExpectedType.resolve(), PsiTreeUtil.getParentOfType(myContext, GrAnnotation.class) != null, searchInheritors);
|
||||
processMembers(myContext, results, myExpectedType.resolve(), PsiTreeUtil.getParentOfType(myContext, GrAnnotation.class) != null, searchInheritors,
|
||||
GroovyCompletionContributor.completeStaticMembers(myParameters));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -220,10 +220,10 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
|
||||
PsiType defType = info.getDefaultType();
|
||||
boolean searchInheritors = params.getInvocationCount() > 1;
|
||||
if (type instanceof PsiClassType) {
|
||||
new GroovyMembersGetter((PsiClassType)type, reference).processMembers(searchInheritors, consumer);
|
||||
new GroovyMembersGetter((PsiClassType)type, reference, params).processMembers(searchInheritors, consumer);
|
||||
}
|
||||
if (!defType.equals(type) && defType instanceof PsiClassType) {
|
||||
new GroovyMembersGetter((PsiClassType)defType, reference).processMembers(searchInheritors, consumer);
|
||||
new GroovyMembersGetter((PsiClassType)defType, reference, params).processMembers(searchInheritors, consumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user