mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java completion: sort/filter suggestions after :: by their matching to the expected type (IDEA-166673)
GitOrigin-RevId: adaefc912e115826280976b23adee38483ca1f71
This commit is contained in:
committed by
intellij-monorepo-bot
parent
e3489f3445
commit
b9525d143e
+21
-8
@@ -7,6 +7,7 @@ import com.intellij.codeInsight.ExpectedTypesProvider;
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.TailTypes;
|
||||
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.LambdaHighlightingUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFix;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
@@ -365,9 +366,6 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
if (CatchTypeProvider.CATCH_CLAUSE_TYPE.accepts(position)) {
|
||||
CatchTypeProvider.addCompletions(parameters, result);
|
||||
}
|
||||
if (psiElement().afterLeaf("::").withParent(PsiMethodReferenceExpression.class).accepts(position)) {
|
||||
MethodReferenceCompletionProvider.addCompletions(parameters, result);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean smartCompleteExpression(CompletionParameters parameters,
|
||||
@@ -561,9 +559,16 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
|
||||
TailType switchLabelTail = !smart && IN_SWITCH_LABEL.accepts(position)
|
||||
? TailTypes.forSwitchLabel(Objects.requireNonNull(PsiTreeUtil.getParentOfType(position, PsiSwitchBlock.class)))
|
||||
: null;
|
||||
boolean inSwitchLabel = IN_SWITCH_LABEL.accepts(position);
|
||||
TailType forcedTail = null;
|
||||
if (!smart) {
|
||||
if (inSwitchLabel) {
|
||||
forcedTail = TailTypes.forSwitchLabel(Objects.requireNonNull(PsiTreeUtil.getParentOfType(position, PsiSwitchBlock.class)));
|
||||
}
|
||||
else if (shouldInsertSemicolon(position)) {
|
||||
forcedTail = TailType.SEMICOLON;
|
||||
}
|
||||
}
|
||||
|
||||
List<LookupElement> items = new ArrayList<>();
|
||||
if (INSIDE_CONSTRUCTOR.accepts(position) &&
|
||||
@@ -589,8 +594,11 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
LookupItem<?> item = element.as(LookupItem.CLASS_CONDITION_KEY);
|
||||
if (switchLabelTail != null) {
|
||||
element = new IndentingDecorator(TailTypeDecorator.withTail(element, switchLabelTail));
|
||||
if (forcedTail != null) {
|
||||
element = TailTypeDecorator.withTail(element, forcedTail);
|
||||
}
|
||||
if (inSwitchLabel && !smart) {
|
||||
element = new IndentingDecorator(element);
|
||||
}
|
||||
if (originalFile instanceof PsiJavaCodeReferenceCodeFragment &&
|
||||
!((PsiJavaCodeReferenceCodeFragment)originalFile).isClassesAccepted() && item != null) {
|
||||
@@ -617,6 +625,11 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
return items;
|
||||
}
|
||||
|
||||
static boolean shouldInsertSemicolon(PsiElement position) {
|
||||
return position.getParent() instanceof PsiMethodReferenceExpression &&
|
||||
LambdaHighlightingUtil.insertSemicolon(position.getParent().getParent());
|
||||
}
|
||||
|
||||
private static List<LookupElement> processLabelReference(PsiLabelReference reference) {
|
||||
return ContainerUtil.map(reference.getVariants(), s -> TailTypeDecorator.withTail(LookupElementBuilder.create(s), TailType.SEMICOLON));
|
||||
}
|
||||
|
||||
@@ -542,10 +542,6 @@ public class JavaCompletionUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (reference instanceof PsiMethodReferenceExpression && completion instanceof PsiMethod && ((PsiMethod)completion).isConstructor()) {
|
||||
return Collections.singletonList(createConstructorReferenceItem((PsiMethod)completion, (PsiMethodReferenceExpression)reference));
|
||||
}
|
||||
|
||||
PsiSubstitutor substitutor = completionElement.getSubstitutor();
|
||||
if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
|
||||
if (completion instanceof PsiClass) {
|
||||
@@ -555,7 +551,8 @@ public class JavaCompletionUtil {
|
||||
}
|
||||
if (completion instanceof PsiMethod) {
|
||||
if (reference instanceof PsiMethodReferenceExpression) {
|
||||
return Collections.singleton(new JavaMethodReferenceElement((PsiMethod)completion, (PsiMethodReferenceExpression)reference));
|
||||
return Collections.singleton((LookupElement)new JavaMethodReferenceElement(
|
||||
(PsiMethod)completion, (PsiMethodReferenceExpression)reference, completionElement.getMethodRefType()));
|
||||
}
|
||||
|
||||
JavaMethodCallElement item = new JavaMethodCallElement((PsiMethod)completion).setQualifierSubstitutor(substitutor);
|
||||
@@ -572,15 +569,6 @@ public class JavaCompletionUtil {
|
||||
return Collections.singletonList(LookupItemUtil.objectToLookupItem(completion));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static LookupElement createConstructorReferenceItem(@NotNull PsiMethod completion, @NotNull PsiMethodReferenceExpression context) {
|
||||
LookupElementBuilder item = JavaLookupElementBuilder
|
||||
.forMethod(completion, "new", PsiSubstitutor.EMPTY, null)
|
||||
.withPresentableText("new")
|
||||
.bold();
|
||||
return LambdaHighlightingUtil.insertSemicolon(context.getParent()) ? TailTypeDecorator.withTail(item, TailType.SEMICOLON) : item;
|
||||
}
|
||||
|
||||
public static boolean hasAccessibleConstructor(@NotNull PsiType type, @NotNull PsiElement place) {
|
||||
if (type instanceof PsiArrayType) return true;
|
||||
|
||||
@@ -821,7 +809,7 @@ public class JavaCompletionUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean insertTail(InsertionContext context, LookupElement item, TailType tailType, boolean hasTail) {
|
||||
private static boolean insertTail(InsertionContext context, LookupElement item, TailType tailType, boolean hasTail) {
|
||||
TailType toInsert = tailType;
|
||||
LookupItem<?> lookupItem = item.as(LookupItem.CLASS_CONDITION_KEY);
|
||||
if (lookupItem == null || lookupItem.getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) {
|
||||
@@ -834,10 +822,7 @@ public class JavaCompletionUtil {
|
||||
boolean insertAdditionalSemicolon = true;
|
||||
PsiElement leaf = context.getFile().findElementAt(context.getStartOffset());
|
||||
PsiElement composite = leaf == null ? null : leaf.getParent();
|
||||
if (composite instanceof PsiMethodReferenceExpression && !LambdaHighlightingUtil.insertSemicolon(composite.getParent())) {
|
||||
insertAdditionalSemicolon = false;
|
||||
}
|
||||
else if (composite instanceof PsiReferenceExpression) {
|
||||
if (composite instanceof PsiReferenceExpression) {
|
||||
PsiElement parent = composite.getParent();
|
||||
if (parent instanceof PsiMethodCallExpression) {
|
||||
parent = parent.getParent();
|
||||
@@ -845,9 +830,6 @@ public class JavaCompletionUtil {
|
||||
if (parent instanceof PsiLambdaExpression && !LambdaHighlightingUtil.insertSemicolonAfter((PsiLambdaExpression)parent)) {
|
||||
insertAdditionalSemicolon = false;
|
||||
}
|
||||
if (parent instanceof PsiMethodReferenceExpression && !LambdaHighlightingUtil.insertSemicolon(parent.getParent())) {
|
||||
insertAdditionalSemicolon = false;
|
||||
}
|
||||
}
|
||||
if (insertAdditionalSemicolon) {
|
||||
toInsert = TailType.SEMICOLON;
|
||||
|
||||
+12
-9
@@ -3,25 +3,30 @@ package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.codeInsight.lookup.TypedLookupItem;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiMethodReferenceExpression;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
class JavaMethodReferenceElement extends LookupElement {
|
||||
class JavaMethodReferenceElement extends LookupElement implements TypedLookupItem {
|
||||
private final PsiMethod myMethod;
|
||||
private final PsiElement myRefPlace;
|
||||
private final PsiType myType;
|
||||
|
||||
JavaMethodReferenceElement(PsiMethod method, PsiElement refPlace) {
|
||||
JavaMethodReferenceElement(PsiMethod method, PsiElement refPlace, @Nullable PsiType type) {
|
||||
myMethod = method;
|
||||
myRefPlace = refPlace;
|
||||
myType = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PsiType getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,7 +74,5 @@ class JavaMethodReferenceElement extends LookupElement {
|
||||
document.insertString(startOffset, qualifiedName + "::");
|
||||
JavaCompletionUtil.shortenReference(context.getFile(), startOffset + qualifiedName.length() - 1);
|
||||
}
|
||||
JavaCompletionUtil
|
||||
.insertTail(context, this, LookupItem.handleCompletionChar(context.getEditor(), this, context.getCompletionChar()), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.completion.impl.BetterPrefixMatcher;
|
||||
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.TailTypeDecorator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
@@ -154,7 +156,12 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
|
||||
if (ref != null) {
|
||||
for (LookupElement item : JavaSmartCompletionContributor.completeReference(position, ref, filter, true, true, parameters,
|
||||
result.getPrefixMatcher())) {
|
||||
qualifiedCollector.addElement(JavaCompletionUtil.highlightIfNeeded(null, new JavaChainLookupElement(base, item, separator), item.getObject(), position));
|
||||
LookupElement chain =
|
||||
JavaCompletionUtil.highlightIfNeeded(null, new JavaChainLookupElement(base, item, separator), item.getObject(), position);
|
||||
if (JavaCompletionContributor.shouldInsertSemicolon(position)) {
|
||||
chain = TailTypeDecorator.withTail(chain, TailType.SEMICOLON);
|
||||
}
|
||||
qualifiedCollector.addElement(chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
import com.intellij.codeInsight.completion.scope.CompletionElement;
|
||||
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.PsiMethodReferenceHighlightingUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.types.AssignableFromFilter;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class MethodReferenceCompletionProvider {
|
||||
private static final Logger LOG = Logger.getInstance(MethodReferenceCompletionProvider.class);
|
||||
|
||||
static void addCompletions(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) {
|
||||
if (!PsiUtil.isLanguageLevel8OrHigher(parameters.getOriginalFile())) return;
|
||||
|
||||
PsiElement position = parameters.getPosition();
|
||||
PsiMethodReferenceExpression refPlace = (PsiMethodReferenceExpression)position.getParent();
|
||||
if (refPlace == null || !LambdaUtil.isValidLambdaContext(refPlace.getParent())) return;
|
||||
|
||||
final ExpectedTypeInfo[] expectedTypes = JavaSmartCompletionContributor.getExpectedTypes(parameters);
|
||||
for (ExpectedTypeInfo expectedType : expectedTypes) {
|
||||
final PsiType defaultType = expectedType.getDefaultType();
|
||||
if (LambdaUtil.isFunctionalType(defaultType)) {
|
||||
final PsiType functionalType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(defaultType);
|
||||
final PsiType returnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalType);
|
||||
if (returnType != null && functionalType != null) {
|
||||
JavaCompletionProcessor processor = new JavaCompletionProcessor(
|
||||
position, new AssignableFromFilter(returnType), JavaCompletionProcessor.Options.DEFAULT_OPTIONS, Conditions.alwaysTrue());
|
||||
refPlace.processVariants(processor);
|
||||
Iterable<PsiMethod> matchingMethods = JBIterable.from(processor.getResults())
|
||||
.map(CompletionElement::getElement)
|
||||
.filter(PsiMethod.class);
|
||||
|
||||
for (PsiMethod method : matchingMethods) {
|
||||
PsiMethodReferenceExpression referenceExpression = createMethodReferenceExpression(method, refPlace);
|
||||
LambdaUtil.performWithTargetType(referenceExpression, functionalType, () -> {
|
||||
if (referenceExpression.isReferenceTo(method) &&
|
||||
PsiMethodReferenceHighlightingUtil.checkMethodReferenceContext(referenceExpression, method, functionalType) == null) {
|
||||
result.addElement(new JavaMethodReferenceElement(method, refPlace));
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiMethodReferenceExpression createMethodReferenceExpression(PsiMethod method, PsiMethodReferenceExpression place) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(method.getProject());
|
||||
PsiMethodReferenceExpression copy = (PsiMethodReferenceExpression)place.copy();
|
||||
PsiElement referenceNameElement = copy.getReferenceNameElement();
|
||||
LOG.assertTrue(referenceNameElement != null, copy);
|
||||
referenceNameElement.replace(method.isConstructor() ? factory.createKeyword("new") : factory.createIdentifier(method.getName()));
|
||||
return copy;
|
||||
}
|
||||
|
||||
}
|
||||
+42
-2
@@ -1,17 +1,22 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInsight.completion.scope;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.PsiMethodReferenceHighlightingUtil;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInspection.SuppressManager;
|
||||
import com.intellij.codeInspection.accessStaticViaInstance.AccessStaticViaInstanceBase;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.filters.getters.ExpectedTypesGetter;
|
||||
import com.intellij.psi.impl.light.LightMethodBuilder;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.scope.ElementClassHint;
|
||||
import com.intellij.psi.scope.JavaScopeProcessorEvent;
|
||||
@@ -28,6 +33,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
public class JavaCompletionProcessor implements PsiScopeProcessor, ElementClassHint {
|
||||
private static final Logger LOG = Logger.getInstance(JavaCompletionProcessor.class);
|
||||
|
||||
private final boolean myInJavaDoc;
|
||||
private boolean myStatic;
|
||||
@@ -46,6 +52,7 @@ public class JavaCompletionProcessor implements PsiScopeProcessor, ElementClassH
|
||||
private final Condition<? super String> myMatcher;
|
||||
private final Options myOptions;
|
||||
private final boolean myAllowStaticWithInstanceQualifier;
|
||||
private final NotNullLazyValue<Collection<PsiType>> myExpectedGroundTypes;
|
||||
|
||||
public JavaCompletionProcessor(@NotNull PsiElement element, ElementFilter filter, Options options, @NotNull Condition<? super String> nameCondition) {
|
||||
myOptions = options;
|
||||
@@ -91,7 +98,9 @@ public class JavaCompletionProcessor implements PsiScopeProcessor, ElementClassH
|
||||
}
|
||||
|
||||
myAllowStaticWithInstanceQualifier = !options.filterStaticAfterInstance || allowStaticAfterInstanceQualifier(element);
|
||||
|
||||
myExpectedGroundTypes = NotNullLazyValue.createValue(
|
||||
() -> ContainerUtil.map(ExpectedTypesGetter.getExpectedTypes(element, false),
|
||||
FunctionalInterfaceParameterizationUtil::getGroundTargetType));
|
||||
}
|
||||
|
||||
private static boolean allowStaticAfterInstanceQualifier(@NotNull PsiElement position) {
|
||||
@@ -175,7 +184,8 @@ public class JavaCompletionProcessor implements PsiScopeProcessor, ElementClassH
|
||||
StaticProblem sp = myElement.getParent() instanceof PsiMethodReferenceExpression ? StaticProblem.none : getStaticProblem(element);
|
||||
if (sp == StaticProblem.instanceAfterStatic) return true;
|
||||
|
||||
CompletionElement completion = new CompletionElement(element, state.get(PsiSubstitutor.KEY), getCallQualifierText(element));
|
||||
CompletionElement completion = new CompletionElement(
|
||||
element, state.get(PsiSubstitutor.KEY), getCallQualifierText(element), getMethodReferenceType(element));
|
||||
CompletionElement prev = myResults.get(completion);
|
||||
if (prev == null || completion.isMoreSpecificThan(prev)) {
|
||||
myResults.put(completion, completion);
|
||||
@@ -187,6 +197,36 @@ public class JavaCompletionProcessor implements PsiScopeProcessor, ElementClassH
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiType getMethodReferenceType(PsiElement completion) {
|
||||
PsiElement parent = myElement.getParent();
|
||||
if (completion instanceof PsiMethod && parent instanceof PsiMethodReferenceExpression) {
|
||||
PsiType matchingType = ContainerUtil.find(myExpectedGroundTypes.getValue(), candidate ->
|
||||
hasSuitableType((PsiMethodReferenceExpression)parent, (PsiMethod)completion, candidate));
|
||||
return matchingType != null ? matchingType : new PsiMethodReferenceType((PsiMethodReferenceExpression)parent);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean hasSuitableType(PsiMethodReferenceExpression refPlace, PsiMethod method, PsiType expectedType) {
|
||||
PsiMethodReferenceExpression referenceExpression = createMethodReferenceExpression(method, refPlace);
|
||||
return LambdaUtil.performWithTargetType(referenceExpression, expectedType, () -> {
|
||||
JavaResolveResult result = referenceExpression.advancedResolve(false);
|
||||
return method.getManager().areElementsEquivalent(method, result.getElement()) &&
|
||||
PsiMethodReferenceUtil.isReturnTypeCompatible(referenceExpression, result, expectedType) &&
|
||||
PsiMethodReferenceHighlightingUtil.checkMethodReferenceContext(referenceExpression, method, expectedType) == null;
|
||||
});
|
||||
}
|
||||
|
||||
private static PsiMethodReferenceExpression createMethodReferenceExpression(PsiMethod method, PsiMethodReferenceExpression place) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(method.getProject());
|
||||
PsiMethodReferenceExpression copy = (PsiMethodReferenceExpression)place.copy();
|
||||
PsiElement referenceNameElement = copy.getReferenceNameElement();
|
||||
LOG.assertTrue(referenceNameElement != null, copy);
|
||||
referenceNameElement.replace(method.isConstructor() ? factory.createKeyword("new") : factory.createIdentifier(method.getName()));
|
||||
return copy;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getCallQualifierText(@NotNull PsiElement element) {
|
||||
if (element instanceof PsiMethod) {
|
||||
|
||||
+19
-2
@@ -22,6 +22,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -32,15 +33,17 @@ public class CompletionElement{
|
||||
private final PsiSubstitutor mySubstitutor;
|
||||
private final Object myEqualityObject;
|
||||
private final String myQualifierText;
|
||||
private final @Nullable PsiType myMethodRefType;
|
||||
|
||||
public CompletionElement(Object element, PsiSubstitutor substitutor) {
|
||||
this(element, substitutor, "");
|
||||
this(element, substitutor, "", null);
|
||||
}
|
||||
|
||||
public CompletionElement(Object element, PsiSubstitutor substitutor, @NotNull String qualifierText) {
|
||||
CompletionElement(Object element, PsiSubstitutor substitutor, @NotNull String qualifierText, @Nullable PsiType methodRefType) {
|
||||
myElement = element;
|
||||
mySubstitutor = substitutor;
|
||||
myQualifierText = qualifierText;
|
||||
myMethodRefType = methodRefType;
|
||||
myEqualityObject = getUniqueId();
|
||||
}
|
||||
|
||||
@@ -67,6 +70,10 @@ public class CompletionElement{
|
||||
return ((PsiPackage)myElement).getQualifiedName();
|
||||
}
|
||||
if(myElement instanceof PsiMethod){
|
||||
if (myMethodRefType != null) {
|
||||
return ((PsiMethod)myElement).isConstructor() ? PsiKeyword.NEW : ((PsiMethod)myElement).getName();
|
||||
}
|
||||
|
||||
return Trinity.create(((PsiMethod)myElement).getName(),
|
||||
Arrays.asList(MethodSignatureUtil.calcErasedParameterTypes(((PsiMethod)myElement).getSignature(mySubstitutor))),
|
||||
myQualifierText);
|
||||
@@ -99,10 +106,20 @@ public class CompletionElement{
|
||||
return myEqualityObject != null ? myEqualityObject.hashCode() : 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ApiStatus.Internal
|
||||
public PsiType getMethodRefType() {
|
||||
return myMethodRefType;
|
||||
}
|
||||
|
||||
public boolean isMoreSpecificThan(@NotNull CompletionElement another) {
|
||||
Object anotherElement = another.getElement();
|
||||
if (!(anotherElement instanceof PsiMethod && myElement instanceof PsiMethod)) return false;
|
||||
|
||||
if (another.myMethodRefType instanceof PsiMethodReferenceType && myMethodRefType instanceof PsiClassType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (anotherElement != myElement &&
|
||||
((PsiMethod)myElement).hasModifierProperty(PsiModifier.ABSTRACT) &&
|
||||
!((PsiMethod)anotherElement).hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import java.util.*;
|
||||
|
||||
class Test {
|
||||
void aaa(Test p) { return 1; }
|
||||
int aaa(Test p) { return 1; }
|
||||
void test() {
|
||||
Comparator<Test> r2 = Test::<caret>
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import java.util.*;
|
||||
|
||||
class Test {
|
||||
void aaa(Test p) { return 1; }
|
||||
int aaa(Test p) { return 1; }
|
||||
void test() {
|
||||
Comparator<Test> r2 = Test::test;
|
||||
Comparator<Test> r2 = Test::aaa;<caret>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ class Bar {
|
||||
|
||||
class Test88 {
|
||||
void foo(Foo9 foo) {
|
||||
foo(Bar::new<caret>);
|
||||
foo(Bar::new);<caret>
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,6 +8,6 @@ class Test {
|
||||
}
|
||||
|
||||
{
|
||||
I i = Test::aa
|
||||
I i = Test::aa;<caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class NewCompletion {
|
||||
private static void vdf(java.util.function.Supplier<java.util.ArrayList<Integer>> supplier) {
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
vdf(java.util.ArrayList::<caret>);
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -100,7 +100,9 @@ public class KeywordCompletionTest extends LightCompletionTestCase {
|
||||
@NeedsIndex.ForStandardLibrary
|
||||
public void testNewInMethodRefs() {
|
||||
doTest(1, "new", "null", "true", "false");
|
||||
assertEquals("new", LookupElementPresentation.renderElement(myItems[0]).getItemText());
|
||||
LookupElementPresentation presentation = LookupElementPresentation.renderElement(myItems[0]);
|
||||
assertEquals("new", presentation.getItemText());
|
||||
assertEmpty(presentation.getTailText());
|
||||
selectItem(myItems[0]);
|
||||
checkResultByTestName();
|
||||
}
|
||||
|
||||
+7
@@ -469,4 +469,11 @@ class Test88 {
|
||||
myFixture.type('\n')
|
||||
checkResultByFileName()
|
||||
}
|
||||
|
||||
@NeedsIndex.ForStandardLibrary
|
||||
void testPreferConstructorReferenceOfExpectedType() {
|
||||
configureByTestName()
|
||||
myFixture.assertPreferredCompletionItems 0, 'new'
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -1989,6 +1989,7 @@ class Bar {{
|
||||
|
||||
void testOnlyResourcesInResourceList5() { doTest('\n') }
|
||||
|
||||
@NeedsIndex.ForStandardLibrary
|
||||
void testMethodReferenceNoStatic() { doTest('\n') }
|
||||
|
||||
void testMethodReferenceCallContext() { doTest('\n') }
|
||||
|
||||
Reference in New Issue
Block a user