don't suggest expected type members twice when they are statically imported (IDEA-79426)

This commit is contained in:
peter
2011-12-29 16:48:36 +01:00
parent 8484fde96f
commit a48a9f5efe
9 changed files with 81 additions and 27 deletions

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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>
}

View File

@@ -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')

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);
}
}
}