mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-26 19:06:24 +07:00
IDEA-58766 Recognize dot as completion prefix part for chained call suggestions
This commit is contained in:
+4
-3
@@ -57,7 +57,8 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
CompletionResultSet result = _result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
|
||||
addAllClasses(parameters, JavaCompletionSorting.addJavaSorting(parameters, result), parameters.getInvocationCount() <= 1, new Consumer<LookupElement>() {
|
||||
addAllClasses(parameters, parameters.getInvocationCount() <= 1,
|
||||
JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
_result.addElement(element);
|
||||
@@ -68,8 +69,8 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
public static void addAllClasses(CompletionParameters parameters,
|
||||
final CompletionResultSet result,
|
||||
final boolean filterByScope,
|
||||
@NotNull final PrefixMatcher matcher,
|
||||
@NotNull final Consumer<LookupElement> consumer) {
|
||||
final PsiElement insertedElement = parameters.getPosition();
|
||||
|
||||
@@ -110,7 +111,7 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
final boolean lookingForAnnotations = PsiJavaPatterns.psiElement().afterLeaf("@").accepts(insertedElement);
|
||||
AllClassesGetter.processJavaClasses(parameters, result.getPrefixMatcher(), filterByScope, new Consumer<PsiClass>() {
|
||||
AllClassesGetter.processJavaClasses(parameters, matcher, filterByScope, new Consumer<PsiClass>() {
|
||||
@Override
|
||||
public void consume(PsiClass psiClass) {
|
||||
if (lookingForAnnotations && !psiClass.isAnnotationType()) return;
|
||||
|
||||
+2
-2
@@ -106,7 +106,7 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
withParent(or(psiElement(PsiResourceVariable.class), psiElement(PsiResourceList.class)))));
|
||||
|
||||
@Nullable
|
||||
private static ElementFilter getReferenceFilter(PsiElement position) {
|
||||
public static ElementFilter getReferenceFilter(PsiElement position) {
|
||||
// Completion after extends in interface, type parameter and implements in class
|
||||
final PsiClass containingClass = PsiTreeUtil.getParentOfType(position, PsiClass.class, false, PsiCodeBlock.class, PsiMethod.class, PsiExpressionList.class, PsiVariable.class);
|
||||
if (containingClass != null && psiElement().afterLeaf(PsiKeyword.EXTENDS, PsiKeyword.IMPLEMENTS, ",", "&").accepts(position)) {
|
||||
@@ -239,7 +239,7 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
if (!isClassNamePossible(parameters.getPosition()) || !mayStartClassName(result, parameters.isRelaxedMatching())) return;
|
||||
|
||||
if (mayShowAllClasses(parameters)) {
|
||||
JavaClassNameCompletionContributor.addAllClasses(parameters, result, parameters.getInvocationCount() <= 2, new Consumer<LookupElement>() {
|
||||
JavaClassNameCompletionContributor.addAllClasses(parameters, parameters.getInvocationCount() <= 2, result.getPrefixMatcher(), new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
if (!inheritors.alreadyProcessed(element)) {
|
||||
|
||||
+80
-18
@@ -15,10 +15,21 @@
|
||||
*/
|
||||
package 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.PsiElement;
|
||||
import com.intellij.psi.PsiJavaCodeReferenceElement;
|
||||
import com.intellij.psi.PsiReferenceExpression;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.util.CollectConsumer;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
@@ -26,29 +37,80 @@ public class JavaNoVariantsDelegator 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) &&
|
||||
JavaCompletionContributor.isClassNamePossible(parameters.getPosition())) {
|
||||
final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result);
|
||||
if (parameters.getCompletionType() == CompletionType.BASIC) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
if (parameters.getInvocationCount() <= 1 &&
|
||||
JavaCompletionContributor.mayStartClassName(result, false) &&
|
||||
JavaCompletionContributor.isClassNamePossible(position)) {
|
||||
suggestNonImportedClasses(parameters, result);
|
||||
return;
|
||||
}
|
||||
|
||||
JavaClassNameCompletionContributor.addAllClasses(parameters, JavaCompletionSorting.addJavaSorting(parameters, result),
|
||||
true, 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);
|
||||
PsiElement parent = position.getParent();
|
||||
if (parent instanceof PsiJavaCodeReferenceElement) {
|
||||
PsiElement qualifier = ((PsiJavaCodeReferenceElement)parent).getQualifier();
|
||||
if (qualifier instanceof PsiJavaCodeReferenceElement &&
|
||||
!((PsiJavaCodeReferenceElement)qualifier).isQualified() &&
|
||||
((PsiJavaCodeReferenceElement)qualifier).resolve() == null) {
|
||||
CompletionResultSet qualifiedCollector = result.withPrefixMatcher(position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset()));
|
||||
ElementFilter filter = JavaCompletionContributor.getReferenceFilter(position);
|
||||
for (LookupElement base : suggestQualifierItems(parameters, result, (PsiJavaCodeReferenceElement)qualifier, filter)) {
|
||||
PsiType type = JavaCompletionUtil.getLookupElementType(base);
|
||||
if (type != null) {
|
||||
PsiReferenceExpression ref = ReferenceExpressionCompletionContributor.createMockReference(position, type, base);
|
||||
for (final LookupElement item : JavaSmartCompletionContributor.completeReference(position, ref, filter, true, true, parameters,
|
||||
result.getPrefixMatcher())) {
|
||||
qualifiedCollector.addElement(new JavaChainLookupElement(base, item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
merger.consume(classElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
merger.finishedClassProcessing();
|
||||
|
||||
} else if (parameters.getCompletionType() == CompletionType.SMART && parameters.getInvocationCount() == 2) {
|
||||
if (parameters.getCompletionType() == CompletionType.SMART && parameters.getInvocationCount() == 2) {
|
||||
result.runRemainingContributors(parameters.withInvocationCount(3), passResult);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<LookupElement> suggestQualifierItems(CompletionParameters parameters,
|
||||
CompletionResultSet result,
|
||||
PsiJavaCodeReferenceElement qualifier,
|
||||
ElementFilter filter) {
|
||||
String referenceName = qualifier.getReferenceName();
|
||||
if (referenceName == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName);
|
||||
Set<LookupElement> plainVariants =
|
||||
JavaSmartCompletionContributor.completeReference(qualifier, qualifier, filter, true, true, parameters, qMatcher);
|
||||
if (!plainVariants.isEmpty()) {
|
||||
return plainVariants;
|
||||
}
|
||||
|
||||
final Set<LookupElement> allClasses = new LinkedHashSet<LookupElement>();
|
||||
JavaClassNameCompletionContributor.addAllClasses(parameters.withPosition(qualifier.getReferenceNameElement(), qualifier.getTextRange().getEndOffset()),
|
||||
true, qMatcher, new CollectConsumer<LookupElement>(allClasses));
|
||||
return allClasses;
|
||||
}
|
||||
|
||||
private static void suggestNonImportedClasses(CompletionParameters parameters, CompletionResultSet result) {
|
||||
final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result);
|
||||
|
||||
JavaClassNameCompletionContributor.addAllClasses(parameters,
|
||||
true, JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), 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);
|
||||
}
|
||||
});
|
||||
|
||||
merger.finishedClassProcessing();
|
||||
}
|
||||
}
|
||||
|
||||
+19
-10
@@ -155,14 +155,15 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
final ElementFilter filter = getReferenceFilter(element);
|
||||
if (filter != null) {
|
||||
final List<ExpectedTypeInfo> infos = Arrays.asList(getExpectedTypes(parameters));
|
||||
for (final LookupElement item : completeReference(element, reference, filter, true, parameters)) {
|
||||
for (final LookupElement item : completeReference(element, reference, filter, true, false, parameters, result.getPrefixMatcher())) {
|
||||
if (item.getObject() instanceof PsiClass) {
|
||||
result.addElement(decorate(LookupElementDecorator.withInsertHandler((LookupItem)item, ConstructorInsertHandler.SMART_INSTANCE), infos));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (INSIDE_TYPECAST_EXPRESSION.accepts(element)) {
|
||||
for (final LookupElement item : completeReference(element, reference, new GeneratorFilter(AssignableToFilter.class, new CastTypeGetter()), false, parameters)) {
|
||||
for (final LookupElement item : completeReference(element, reference, new GeneratorFilter(AssignableToFilter.class, new CastTypeGetter()), false, true, parameters,
|
||||
result.getPrefixMatcher())) {
|
||||
result.addElement(item);
|
||||
}
|
||||
}
|
||||
@@ -182,7 +183,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
final PsiElement element = parameters.getPosition();
|
||||
final PsiReference reference = element.getContainingFile().findReferenceAt(parameters.getOffset());
|
||||
assert reference != null;
|
||||
for (final LookupElement item : completeReference(element, reference, THROWABLES_FILTER, true, parameters)) {
|
||||
for (final LookupElement item : completeReference(element, reference, THROWABLES_FILTER, true, false, parameters, result.getPrefixMatcher())) {
|
||||
result.addElement(item);
|
||||
}
|
||||
}
|
||||
@@ -456,7 +457,12 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
return ExpectedTypesProvider.getExpectedTypes(expression, true, parameters.getCompletionType() == CompletionType.SMART, false);
|
||||
}
|
||||
|
||||
static Set<LookupElement> completeReference(final PsiElement element, PsiReference reference, final ElementFilter filter, final boolean acceptClasses, CompletionParameters parameters) {
|
||||
static Set<LookupElement> completeReference(final PsiElement element,
|
||||
PsiReference reference,
|
||||
final ElementFilter filter,
|
||||
final boolean acceptClasses,
|
||||
final boolean acceptMembers,
|
||||
CompletionParameters parameters, @Nullable final PrefixMatcher matcher) {
|
||||
if (reference instanceof PsiMultiReference) {
|
||||
reference = ContainerUtil.findInstance(((PsiMultiReference) reference).getReferences(), PsiJavaReference.class);
|
||||
}
|
||||
@@ -470,15 +476,18 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
public boolean isClassAcceptable(Class hintClass) {
|
||||
if (acceptClasses) {
|
||||
return ReflectionCache.isAssignable(PsiClass.class, hintClass);
|
||||
if (ReflectionCache.isAssignable(PsiClass.class, hintClass)) {
|
||||
return acceptClasses;
|
||||
}
|
||||
|
||||
return ReflectionCache.isAssignable(PsiVariable.class, hintClass) ||
|
||||
ReflectionCache.isAssignable(PsiMethod.class, hintClass) ||
|
||||
ReflectionCache.isAssignable(CandidateInfo.class, hintClass);
|
||||
if (ReflectionCache.isAssignable(PsiVariable.class, hintClass) ||
|
||||
ReflectionCache.isAssignable(PsiMethod.class, hintClass) ||
|
||||
ReflectionCache.isAssignable(CandidateInfo.class, hintClass)) {
|
||||
return acceptMembers;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, true, parameters.getInvocationCount() <= 1, null, parameters);
|
||||
}, true, parameters.getInvocationCount() <= 1, matcher, parameters);
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
|
||||
+10
-4
@@ -122,7 +122,7 @@ public class ReferenceExpressionCompletionContributor {
|
||||
final boolean secondTime = parameters.getParameters().getInvocationCount() >= 2;
|
||||
|
||||
final Set<LookupElement> base =
|
||||
JavaSmartCompletionContributor.completeReference(element, reference, filter, false, parameters.getParameters());
|
||||
JavaSmartCompletionContributor.completeReference(element, reference, filter, false, true, parameters.getParameters(), null);
|
||||
for (final LookupElement item : base) {
|
||||
addSingleArrayElementAccess(element, item, parameters, result);
|
||||
}
|
||||
@@ -177,7 +177,7 @@ public class ReferenceExpressionCompletionContributor {
|
||||
public boolean isClassAcceptable(Class hintClass) {
|
||||
return true;
|
||||
}
|
||||
}), false, parameters.getParameters());
|
||||
}), false, true, parameters.getParameters(), null);
|
||||
for (LookupElement lookupElement : elements) {
|
||||
if (lookupElement.getObject() instanceof PsiMethod) {
|
||||
final JavaMethodCallElement item = lookupElement.as(JavaMethodCallElement.CLASS_CONDITION_KEY);
|
||||
@@ -419,7 +419,7 @@ public class ReferenceExpressionCompletionContributor {
|
||||
final Consumer<LookupElement> result,
|
||||
PsiType qualifierType,
|
||||
final PsiType expectedType, JavaSmartCompletionParameters parameters) throws IncorrectOperationException {
|
||||
final PsiReferenceExpression mockRef = createMockReference(place, qualifierType);
|
||||
final PsiReferenceExpression mockRef = createMockReference(place, qualifierType, qualifierItem);
|
||||
|
||||
final ElementFilter filter = getReferenceFilter(place, true);
|
||||
for (final LookupElement item : completeFinalReference(place, mockRef, filter, parameters)) {
|
||||
@@ -429,7 +429,13 @@ public class ReferenceExpressionCompletionContributor {
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiReferenceExpression createMockReference(PsiElement place, PsiType qualifierType) {
|
||||
public static PsiReferenceExpression createMockReference(PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) {
|
||||
if (qualifierItem.getObject() instanceof PsiClass) {
|
||||
return (PsiReferenceExpression)JavaPsiFacade.getElementFactory(place.getProject())
|
||||
.createExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place);
|
||||
|
||||
}
|
||||
|
||||
final JavaCodeFragmentFactory factory = JavaCodeFragmentFactory.getInstance(place.getProject());
|
||||
PsiType varType = qualifierType;
|
||||
if (varType instanceof PsiEllipsisType) {
|
||||
|
||||
Reference in New Issue
Block a user