mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-58766 Recognize dot as completion prefix part for chained call suggestions, groovy
This commit is contained in:
@@ -65,7 +65,11 @@ public class JavaChainLookupElement extends LookupElementDecorator<LookupElement
|
||||
}
|
||||
|
||||
private String maybeAddParentheses(String s) {
|
||||
return myQualifier.getObject() instanceof PsiMethod ? s + "()" : s;
|
||||
Object qObject = myQualifier.getObject();
|
||||
if (qObject instanceof ResolveResult) {
|
||||
qObject = ((ResolveResult)qObject).getElement();
|
||||
}
|
||||
return qObject instanceof PsiMethod ? s + "()" : s;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,7 +103,7 @@ public class JavaChainLookupElement extends LookupElementDecorator<LookupElement
|
||||
CompletionUtil.emulateInsertion(getDelegate(), context.getTailOffset(), context);
|
||||
}
|
||||
|
||||
private static boolean shouldParenthesizeQualifier(final PsiFile file, final int startOffset, final int endOffset) {
|
||||
protected boolean shouldParenthesizeQualifier(final PsiFile file, final int startOffset, final int endOffset) {
|
||||
PsiElement element = file.findElementAt(startOffset);
|
||||
if (element == null) {
|
||||
return false;
|
||||
|
||||
@@ -346,6 +346,9 @@ public class JavaCompletionUtil {
|
||||
|
||||
@Nullable
|
||||
private static PsiType getPsiType(final Object o) {
|
||||
if (o instanceof ResolveResult) {
|
||||
return getPsiType(((ResolveResult)o).getElement());
|
||||
}
|
||||
if (o instanceof PsiVariable) {
|
||||
return ((PsiVariable)o).getType();
|
||||
}
|
||||
|
||||
+68
-35
@@ -46,6 +46,7 @@ import com.intellij.util.ProcessingContext;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyBundle;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
@@ -64,18 +65,18 @@ import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatem
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.CompleteReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.DefaultGroovyVariableNameValidator;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.inline.InlineMethodConflictSolver;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
import static com.intellij.patterns.PsiJavaPatterns.elementType;
|
||||
import static com.intellij.util.containers.CollectionFactory.arrayList;
|
||||
import static com.intellij.util.containers.CollectionFactory.hashMap;
|
||||
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
|
||||
import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.SEPARATORS;
|
||||
@@ -176,18 +177,20 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
|
||||
|
||||
private static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritors) {
|
||||
addAllClasses(parameters, result, new Consumer<LookupElement>() {
|
||||
addAllClasses(parameters, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
result.addElement(element);
|
||||
}
|
||||
}, inheritors);
|
||||
}, inheritors, result.getPrefixMatcher());
|
||||
}
|
||||
|
||||
public static void addAllClasses(CompletionParameters parameters, CompletionResultSet result, final Consumer<LookupElement> consumer, final InheritorsHolder inheritors) {
|
||||
public static void addAllClasses(CompletionParameters parameters,
|
||||
final Consumer<LookupElement> consumer,
|
||||
final InheritorsHolder inheritors, final PrefixMatcher matcher) {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
final ElementFilter filter = getClassFilter(position);
|
||||
AllClassesGetter.processJavaClasses(parameters, result.getPrefixMatcher(), parameters.getInvocationCount() <= 1,
|
||||
AllClassesGetter.processJavaClasses(parameters, matcher, parameters.getInvocationCount() <= 1,
|
||||
new Consumer<PsiClass>() {
|
||||
@Override
|
||||
public void consume(PsiClass psiClass) {
|
||||
@@ -324,12 +327,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
GroovySmartCompletionContributor.generateInheritorVariants(parameters, result.getPrefixMatcher(), inheritors);
|
||||
}
|
||||
|
||||
completeReference(parameters, reference, inheritors, result.getPrefixMatcher(), new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
result.addElement(element);
|
||||
}
|
||||
});
|
||||
result.addAllElements(completeReference(parameters, reference, inheritors, result.getPrefixMatcher()));
|
||||
|
||||
if (reference.getQualifier() == null) {
|
||||
GroovySmartCompletionContributor.addExpectedClassMembers(parameters, result);
|
||||
@@ -424,16 +422,30 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
super.fillCompletionVariants(parameters, result);
|
||||
}
|
||||
|
||||
private static void completeReference(final CompletionParameters parameters,
|
||||
GrReferenceElement reference, final InheritorsHolder inheritorsHolder, final PrefixMatcher matcher, final Consumer<LookupElement> result) {
|
||||
static LinkedHashSet<LookupElement> completeReference(final CompletionParameters parameters,
|
||||
GrReferenceElement reference, final InheritorsHolder inheritorsHolder, final PrefixMatcher matcher) {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
|
||||
final Map<PsiModifierListOwner, LookupElement> staticMembers = hashMap();
|
||||
final PsiElement qualifier = reference.getQualifier();
|
||||
final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null;
|
||||
|
||||
LinkedHashSet<LookupElement> result = new LinkedHashSet<LookupElement>();
|
||||
if (reference instanceof GrReferenceExpression && (qualifier instanceof GrExpression || qualifier == null)) {
|
||||
for (String string : CompleteReferenceExpression.getVariantsWithSameQualifier(matcher, (GrExpression)qualifier, (GrReferenceExpression)reference)) {
|
||||
result.add(GroovyCompletionUtil.getLookupElement(string));
|
||||
}
|
||||
if (parameters.getInvocationCount() < 2 && qualifier != null && qualifierType == null) {
|
||||
if (parameters.getInvocationCount() == 1) {
|
||||
showInfo();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
final ElementFilter classFilter = getClassFilter(position);
|
||||
|
||||
final List<LookupElement> items = arrayList();
|
||||
reference.processVariants(matcher, parameters, new Consumer<Object>() {
|
||||
public void consume(Object element) {
|
||||
if (element instanceof PsiClass && inheritorsHolder.alreadyProcessed((PsiClass)element)) {
|
||||
@@ -448,22 +460,20 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
LookupElement lookupElement = element instanceof PsiClass
|
||||
? GroovyCompletionUtil.createClassLookupItem(CompletionUtil.getOriginalOrSelf((PsiClass)element))
|
||||
: GroovyCompletionUtil.getLookupElement(element);
|
||||
? GroovyCompletionUtil.createClassLookupItem(CompletionUtil.getOriginalOrSelf((PsiClass)element))
|
||||
: GroovyCompletionUtil.getLookupElement(element);
|
||||
Object object = lookupElement.getObject();
|
||||
PsiSubstitutor substitutor = null;
|
||||
GroovyResolveResult resolveResult = null;
|
||||
if (object instanceof GroovyResolveResult) {
|
||||
resolveResult = (GroovyResolveResult)object;
|
||||
substitutor = resolveResult.getSubstitutor();
|
||||
object = ((GroovyResolveResult)object).getElement();
|
||||
}
|
||||
|
||||
if (object instanceof PsiMember && JavaCompletionUtil.isInExcludedPackage((PsiMember)object, true)) {
|
||||
return;
|
||||
}
|
||||
lookupElement = tweakPriority(lookupElement, object, substitutor, resolveResult, qualifierType);
|
||||
|
||||
int priority = assignPriority(lookupElement, qualifierType);
|
||||
lookupElement = JavaCompletionUtil.highlightIfNeeded(qualifierType,
|
||||
PrioritizedLookupElement.withPriority(lookupElement, priority), object);
|
||||
|
||||
if ((object instanceof PsiMethod || object instanceof PsiField) &&
|
||||
((PsiModifierListOwner)object).hasModifierProperty(PsiModifier.STATIC)) {
|
||||
@@ -475,7 +485,8 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
if (object instanceof PsiClass && !classFilter.isAcceptable(object, position)) {
|
||||
return;
|
||||
}
|
||||
result.consume(JavaCompletionUtil.highlightIfNeeded(qualifierType, lookupElement, object));
|
||||
|
||||
items.add(lookupElement);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -497,8 +508,25 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
});
|
||||
|
||||
}
|
||||
for (LookupElement element : staticMembers.values()) {
|
||||
result.consume(element);
|
||||
items.addAll(staticMembers.values());
|
||||
|
||||
for (Iterator<LookupElement> iterator = items.iterator(); iterator.hasNext(); ) {
|
||||
LookupElement element = iterator.next();
|
||||
PrioritizedLookupElement prio = element.as(PrioritizedLookupElement.CLASS_CONDITION_KEY);
|
||||
if (prio == null || prio.getPriority() >= 0) {
|
||||
result.add(element);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
result.addAll(items);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void showInfo() {
|
||||
if (StringUtil.isEmpty(CompletionService.getCompletionService().getAdvertisementText())) {
|
||||
CompletionService.getCompletionService()
|
||||
.setAdvertisementText(GroovyBundle.message("invoke.completion.second.time.to.show.skipped.methods"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,33 +541,38 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
|
||||
private static LookupElement tweakPriority(LookupElement lookupElement,
|
||||
Object object,
|
||||
PsiSubstitutor substitutor,
|
||||
GroovyResolveResult resolveResult,
|
||||
PsiType qualifierType) {
|
||||
private static int assignPriority(LookupElement lookupElement, PsiType qualifierType) {
|
||||
Object object = lookupElement.getObject();
|
||||
PsiSubstitutor substitutor = null;
|
||||
GroovyResolveResult resolveResult = null;
|
||||
if (object instanceof GroovyResolveResult) {
|
||||
resolveResult = (GroovyResolveResult)object;
|
||||
substitutor = resolveResult.getSubstitutor();
|
||||
object = ((GroovyResolveResult)object).getElement();
|
||||
}
|
||||
|
||||
// default groovy methods
|
||||
if (object instanceof GrGdkMethod &&
|
||||
GroovyCompletionUtil.skipDefGroovyMethod((GrGdkMethod)object, substitutor, qualifierType)) {
|
||||
return PrioritizedLookupElement.withPriority(lookupElement, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// operator methods
|
||||
if (object instanceof PsiMethod &&
|
||||
GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(((PsiMethod)object).getName()) && !checkForIterator((PsiMethod)object)) {
|
||||
return PrioritizedLookupElement.withPriority(lookupElement, -3);
|
||||
return -3;
|
||||
}
|
||||
|
||||
// accessors if there is no get, set, is prefix
|
||||
if (object instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)object)) {
|
||||
return PrioritizedLookupElement.withPriority(lookupElement, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// inaccessible elements
|
||||
if (resolveResult != null && !resolveResult.isAccessible()) {
|
||||
return PrioritizedLookupElement.withPriority(lookupElement, -2);
|
||||
return -2;
|
||||
}
|
||||
return lookupElement;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static StaticMemberProcessor completeStaticMembers(CompletionParameters parameters) {
|
||||
|
||||
+119
-20
@@ -16,9 +16,21 @@
|
||||
package org.jetbrains.plugins.groovy.lang.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -27,27 +39,114 @@ public class GroovyNoVariantsDelegator extends NoVariantsDelegator {
|
||||
|
||||
@Override
|
||||
protected void delegate(CompletionParameters parameters, CompletionResultSet result, Consumer<CompletionResult> passResult) {
|
||||
if (parameters.getCompletionType() == CompletionType.BASIC &&
|
||||
parameters.getInvocationCount() <= 1 &&
|
||||
JavaCompletionContributor.mayStartClassName(result, false) &&
|
||||
GroovyCompletionContributor.isClassNamePossible(parameters.getPosition()) &&
|
||||
!MapArgumentCompletionProvider.isMapKeyCompletion(parameters)) {
|
||||
final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result);
|
||||
|
||||
GroovyCompletionContributor.addAllClasses(parameters, result,
|
||||
new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
|
||||
if (classElement != null) {
|
||||
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
}
|
||||
merger.consume(classElement);
|
||||
}
|
||||
}, new InheritorsHolder(parameters.getPosition(), result));
|
||||
|
||||
merger.finishedClassProcessing();
|
||||
if (parameters.getCompletionType() == CompletionType.BASIC) {
|
||||
if (parameters.getInvocationCount() <= 1 &&
|
||||
JavaCompletionContributor.mayStartClassName(result, false) &&
|
||||
GroovyCompletionContributor.isClassNamePossible(parameters.getPosition()) &&
|
||||
!MapArgumentCompletionProvider.isMapKeyCompletion(parameters)) {
|
||||
suggestNonImportedClasses(parameters, result);
|
||||
}
|
||||
|
||||
suggestChainedCalls(parameters, result);
|
||||
}
|
||||
}
|
||||
|
||||
private static void suggestNonImportedClasses(CompletionParameters parameters, CompletionResultSet result) {
|
||||
final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result);
|
||||
|
||||
GroovyCompletionContributor.addAllClasses(parameters, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
JavaPsiClassReferenceElement classElement =
|
||||
element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
|
||||
if (classElement != null) {
|
||||
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
}
|
||||
merger.consume(classElement);
|
||||
}
|
||||
}, new InheritorsHolder(parameters.getPosition(), result), result.getPrefixMatcher());
|
||||
|
||||
merger.finishedClassProcessing();
|
||||
}
|
||||
|
||||
private static void suggestChainedCalls(CompletionParameters parameters, CompletionResultSet result) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
PsiElement parent = position.getParent();
|
||||
if (!(parent instanceof GrReferenceElement)) {
|
||||
return;
|
||||
}
|
||||
PsiElement qualifier = ((GrReferenceElement)parent).getQualifier();
|
||||
if (!(qualifier instanceof GrReferenceElement) ||
|
||||
((GrReferenceElement)qualifier).getQualifier() != null ||
|
||||
((GrReferenceElement)qualifier).resolve() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fullPrefix = position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset());
|
||||
final CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix);
|
||||
InheritorsHolder inheritors = new InheritorsHolder(position, result);
|
||||
for (final LookupElement base : suggestQualifierItems(parameters, (GrReferenceElement)qualifier, inheritors)) {
|
||||
final PsiType type = JavaCompletionUtil.getLookupElementType(base);
|
||||
if (type != null && !PsiType.VOID.equals(type)) {
|
||||
GrReferenceElement ref = createMockReference(position, type, base);
|
||||
PsiElement refName = ref.getReferenceNameElement();
|
||||
assert refName != null;
|
||||
for (LookupElement element : GroovyCompletionContributor.completeReference(
|
||||
parameters.withPosition(refName, refName.getTextRange().getStartOffset()), ref, inheritors, qualifiedCollector.getPrefixMatcher())) {
|
||||
qualifiedCollector.addElement(new JavaChainLookupElement(base, element) {
|
||||
@Override
|
||||
protected boolean shouldParenthesizeQualifier(PsiFile file, int startOffset, int endOffset) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static GrReferenceElement createMockReference(final PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) {
|
||||
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(place.getProject());
|
||||
if (qualifierItem.getObject() instanceof PsiClass) {
|
||||
return factory
|
||||
.createReferenceExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place);
|
||||
}
|
||||
|
||||
return factory.createReferenceExpressionFromText("xxx.xxx",
|
||||
ReferenceExpressionCompletionContributor
|
||||
.createContextWithXxxVariable(place, qualifierType));
|
||||
}
|
||||
|
||||
|
||||
private static Set<LookupElement> suggestQualifierItems(CompletionParameters _parameters,
|
||||
GrReferenceElement qualifier,
|
||||
InheritorsHolder inheritors) {
|
||||
CompletionParameters parameters =
|
||||
_parameters.withPosition(qualifier.getReferenceNameElement(), qualifier.getTextRange().getEndOffset());
|
||||
String referenceName = qualifier.getReferenceName();
|
||||
if (referenceName == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
final PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName);
|
||||
final Set<LookupElement> variants = new LinkedHashSet<LookupElement>();
|
||||
for (LookupElement element : GroovyCompletionContributor.completeReference(parameters, qualifier, inheritors, qMatcher)) {
|
||||
if (qMatcher.prefixMatches(element)) {
|
||||
variants.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
if (variants.isEmpty()) {
|
||||
GroovyCompletionContributor.addAllClasses(parameters, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
if (qMatcher.prefixMatches(element)) {
|
||||
variants.add(element);
|
||||
}
|
||||
}
|
||||
}, inheritors, qMatcher);
|
||||
}
|
||||
return variants;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+8
-13
@@ -25,7 +25,6 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -48,7 +47,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrRe
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
@@ -88,7 +86,6 @@ public class CompleteReferenceExpression {
|
||||
|
||||
private static void getVariantsImpl(PrefixMatcher matcher, GrReferenceExpression refExpr, CompleteReferenceProcessor processor) {
|
||||
GrExpression qualifier = refExpr.getQualifierExpression();
|
||||
getVariantsWithSameQualifier(matcher, qualifier, refExpr, processor);
|
||||
if (qualifier == null) {
|
||||
ResolveUtil.treeWalkUp(refExpr, processor, true);
|
||||
|
||||
@@ -228,7 +225,8 @@ public class CompleteReferenceExpression {
|
||||
return;
|
||||
}
|
||||
}
|
||||
getVariantsFromQualifierType(refExpr, processor, GrClassImplUtil.getGroovyObjectType(refExpr), project);
|
||||
getVariantsFromQualifierType(refExpr, processor,
|
||||
PsiType.getJavaLangObject(refExpr.getManager(), qualifier.getResolveScope()), project);
|
||||
}
|
||||
else if (qualifierType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) {
|
||||
@@ -256,20 +254,19 @@ public class CompleteReferenceExpression {
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] getVariantsWithSameQualifier(PrefixMatcher matcher,GrExpression qualifier, GrReferenceExpression refExpr, CompleteReferenceProcessor processor) {
|
||||
if (qualifier != null && qualifier.getType() != null) return ArrayUtil.EMPTY_STRING_ARRAY;
|
||||
public static Set<String> getVariantsWithSameQualifier(PrefixMatcher matcher, @Nullable GrExpression qualifier, GrReferenceExpression refExpr) {
|
||||
if (qualifier != null && qualifier.getType() != null) return Collections.emptySet();
|
||||
|
||||
final PsiElement scope = PsiTreeUtil.getParentOfType(refExpr, GrMember.class, PsiFile.class);
|
||||
Set<String> result = new LinkedHashSet<String>();
|
||||
addVariantsWithSameQualifier(matcher, scope, refExpr, qualifier, result, processor);
|
||||
return ArrayUtil.toStringArray(result);
|
||||
addVariantsWithSameQualifier(matcher, scope, refExpr, qualifier, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void addVariantsWithSameQualifier(PrefixMatcher matcher, PsiElement element,
|
||||
GrReferenceExpression patternExpression,
|
||||
GrExpression patternQualifier,
|
||||
Set<String> result,
|
||||
CompleteReferenceProcessor processor) {
|
||||
Set<String> result) {
|
||||
if (element instanceof GrReferenceExpression && element != patternExpression && !PsiUtil.isLValue((GroovyPsiElement)element)) {
|
||||
final GrReferenceExpression refExpr = (GrReferenceExpression)element;
|
||||
final String refName = refExpr.getReferenceName();
|
||||
@@ -279,21 +276,19 @@ public class CompleteReferenceExpression {
|
||||
if (PsiEquivalenceUtil.areElementsEquivalent(hisQualifier, patternQualifier)) {
|
||||
if (refExpr.resolve() == null) {
|
||||
result.add(refName);
|
||||
processor.consume(refName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hisQualifier == null && patternQualifier == null) {
|
||||
if (refExpr.resolve() == null) {
|
||||
result.add(refName);
|
||||
processor.consume(refName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
|
||||
addVariantsWithSameQualifier(matcher, child, patternExpression, patternQualifier, result, processor);
|
||||
addVariantsWithSameQualifier(matcher, child, patternExpression, patternQualifier, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -56,7 +56,7 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
public void testNoLookupFocusOnUnresolvedQualifier() {
|
||||
myFixture.configureByText("a.groovy", """xxx.<caret>""")
|
||||
type 'h' //hashCode
|
||||
assert !lookup.focused
|
||||
assert !lookup
|
||||
}
|
||||
|
||||
public void testNoLookupFocusOnUntypedQualifier() {
|
||||
@@ -65,7 +65,7 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
xxx.<caret>
|
||||
}""")
|
||||
type 'h'
|
||||
assert !lookup.focused
|
||||
assert !lookup
|
||||
}
|
||||
|
||||
public void testPossibleClosureParameter() {
|
||||
|
||||
+12
@@ -1108,6 +1108,18 @@ public class KeyVO {
|
||||
checkSingleItemCompletion 'class Foo impl<caret> {}', 'class Foo implements <caret> {}'
|
||||
}
|
||||
|
||||
public void testAmbiguousClassQualifier() {
|
||||
myFixture.addClass("package foo; public class Util { public static void foo() {} }")
|
||||
myFixture.addClass("package bar; public class Util { public static void bar() {} }")
|
||||
myFixture.configureByText 'a.groovy', 'Util.<caret>'
|
||||
myFixture.completeBasic()
|
||||
assert myFixture.lookupElementStrings[0..1] == ['Util.bar', 'Util.foo']
|
||||
myFixture.type 'f\n'
|
||||
myFixture.checkResult '''import foo.Util
|
||||
|
||||
Util.foo()<caret>'''
|
||||
}
|
||||
|
||||
public void testPreferInterfacesInImplements() {
|
||||
myFixture.addClass('interface FooIntf {}')
|
||||
myFixture.addClass('class FooClass {}')
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
def (street, home, postCode)
|
||||
def s = street.toS<caret>
|
||||
-----
|
||||
toString
|
||||
-----
|
||||
@@ -1,3 +1,2 @@
|
||||
unknown.metaCl<caret>
|
||||
-----
|
||||
metaClass
|
||||
-----
|
||||
Reference in New Issue
Block a user