mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-21 05:51:25 +07:00
[java-highlighting] Most of method-reference problems migrated
Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only) GitOrigin-RevId: 03528950826974c1875e89868dc335c88c2e8149
This commit is contained in:
committed by
intellij-monorepo-bot
parent
17651f8c19
commit
577de68f8a
@@ -55,7 +55,21 @@ lambda.inference.error={0}
|
||||
lambda.return.type.error={0}
|
||||
lambda.target.not.interface=Target type of a lambda conversion must be an interface
|
||||
|
||||
method.reference.not.expected=Method reference expression is not expected here
|
||||
method.reference.sealed=Method reference cannot implement a sealed interface
|
||||
method.reference.return.type.error={0}
|
||||
method.reference.unresolved.constructor=Cannot resolve constructor ''{0}''
|
||||
method.reference.unresolved.method=Cannot resolve method ''{0}''
|
||||
method.reference.inference.error={0}
|
||||
method.reference.raw.constructor=Raw constructor reference with explicit type parameters for constructor
|
||||
method.reference.qualifier.class.unresolved=Cannot find class {0}
|
||||
method.reference.qualifier.wildcard=Unexpected wildcard
|
||||
method.reference.abstract.method=Abstract method ''{0}'' cannot be accessed directly
|
||||
method.reference.non.static.method.in.static.context=Non-static method cannot be referenced from a static context
|
||||
method.reference.static.method.non.static.qualifier=Static method referenced through non-static qualifier
|
||||
method.reference.static.method.receiver=Static method referenced through receiver
|
||||
method.reference.parameterized.qualifier=Parameterized qualifier on static method reference
|
||||
method.reference.enclosing.instance.not.in.scope=An enclosing instance of type {0} is not in scope
|
||||
|
||||
safe.varargs.on.record.component=@SafeVarargs is not allowed on a record component
|
||||
safe.varargs.on.fixed.arity=@SafeVarargs is not allowed on methods with fixed arity
|
||||
|
||||
@@ -10,19 +10,12 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.IncompleteModelUtil;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.psi.LambdaUtil.getFunction;
|
||||
import static com.intellij.psi.LambdaUtil.getTargetMethod;
|
||||
|
||||
final class FunctionChecker {
|
||||
private final @NotNull JavaErrorVisitor myVisitor;
|
||||
@@ -47,6 +40,113 @@ final class FunctionChecker {
|
||||
}
|
||||
}
|
||||
|
||||
void checkMethodReferenceQualifier(@NotNull PsiMethodReferenceExpression expression) {
|
||||
PsiElement referenceNameElement = expression.getReferenceNameElement();
|
||||
PsiElement qualifier = expression.getQualifier();
|
||||
if (referenceNameElement instanceof PsiKeyword) {
|
||||
if (!PsiMethodReferenceUtil.isValidQualifier(expression) && qualifier != null) {
|
||||
boolean pending = qualifier instanceof PsiJavaCodeReferenceElement ref &&
|
||||
IncompleteModelUtil.isIncompleteModel(expression) &&
|
||||
IncompleteModelUtil.canBePendingReference(ref);
|
||||
if (!pending) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_QUALIFIER_CLASS_UNRESOLVED.create(qualifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (qualifier instanceof PsiTypeElement typeElement) {
|
||||
PsiType psiType = typeElement.getType();
|
||||
if (psiType instanceof PsiClassType) {
|
||||
final PsiJavaCodeReferenceElement referenceElement = typeElement.getInnermostComponentReferenceElement();
|
||||
if (referenceElement != null) {
|
||||
PsiType[] typeParameters = referenceElement.getTypeParameters();
|
||||
for (PsiType typeParameter : typeParameters) {
|
||||
if (typeParameter instanceof PsiWildcardType) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_QUALIFIER_WILDCARD.create(typeElement));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkRawConstructorReference(@NotNull PsiMethodReferenceExpression expression) {
|
||||
if (expression.isConstructor()) {
|
||||
PsiType[] typeParameters = expression.getTypeParameters();
|
||||
if (typeParameters.length > 0) {
|
||||
PsiElement qualifier = expression.getQualifier();
|
||||
if (qualifier instanceof PsiReferenceExpression) {
|
||||
PsiElement resolve = ((PsiReferenceExpression)qualifier).resolve();
|
||||
if (resolve instanceof PsiClass && ((PsiClass)resolve).hasTypeParameters()) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_RAW_CONSTRUCTOR.create(expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkMethodReferenceContext(@NotNull PsiMethodReferenceExpression methodRef, @NotNull PsiType functionalInterfaceType) {
|
||||
PsiElement resolve = methodRef.resolve();
|
||||
|
||||
if (resolve == null) return;
|
||||
PsiClass containingClass = resolve instanceof PsiMethod method ? method.getContainingClass() : (PsiClass)resolve;
|
||||
boolean isStaticSelector = PsiMethodReferenceUtil.isStaticallyReferenced(methodRef);
|
||||
PsiElement qualifier = methodRef.getQualifier();
|
||||
|
||||
boolean isConstructor = true;
|
||||
|
||||
if (resolve instanceof PsiMethod method) {
|
||||
boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC);
|
||||
isConstructor = method.isConstructor();
|
||||
|
||||
PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
|
||||
boolean receiverReferenced = PsiMethodReferenceUtil.isResolvedBySecondSearch(
|
||||
methodRef, interfaceMethod != null ? interfaceMethod.getSignature(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult)) : null,
|
||||
method.isVarArgs(), isMethodStatic, method.getParameterList().getParametersCount());
|
||||
|
||||
if (method.hasModifierProperty(PsiModifier.ABSTRACT) && qualifier instanceof PsiSuperExpression) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_ABSTRACT_METHOD.create(methodRef, method));
|
||||
return;
|
||||
}
|
||||
if (!receiverReferenced && isStaticSelector && !isMethodStatic && !isConstructor) {
|
||||
if (functionalInterfaceType instanceof PsiClassType classType && classType.hasParameters()) {
|
||||
// Prefer surrounding error, as it could be more descriptive
|
||||
if (hasSurroundingInferenceError(methodRef)) return;
|
||||
}
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_NON_STATIC_METHOD_IN_STATIC_CONTEXT.create(methodRef, method));
|
||||
return;
|
||||
}
|
||||
if (!receiverReferenced && !isStaticSelector && isMethodStatic) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_STATIC_METHOD_NON_STATIC_QUALIFIER.create(methodRef, method));
|
||||
return;
|
||||
}
|
||||
if (receiverReferenced && isStaticSelector && isMethodStatic) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_STATIC_METHOD_RECEIVER.create(methodRef, method));
|
||||
return;
|
||||
}
|
||||
if (isStaticSelector && isMethodStatic && qualifier instanceof PsiTypeElement) {
|
||||
PsiJavaCodeReferenceElement referenceElement = PsiTreeUtil.getChildOfType(qualifier, PsiJavaCodeReferenceElement.class);
|
||||
if (referenceElement != null) {
|
||||
PsiReferenceParameterList parameterList = referenceElement.getParameterList();
|
||||
if (parameterList != null && parameterList.getTypeArguments().length > 0) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_PARAMETERIZED_QUALIFIER.create(parameterList));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isConstructor) {
|
||||
if (containingClass != null && PsiUtil.isInnerClass(containingClass) && containingClass.isPhysical()) {
|
||||
PsiClass outerClass = containingClass.getContainingClass();
|
||||
if (outerClass != null && !InheritanceUtil.hasEnclosingInstanceInScope(outerClass, methodRef, true, false)) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_ENCLOSING_INSTANCE_NOT_IN_SCOPE.create(methodRef, outerClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable JavaCompilationError<?, ?> getFunctionalInterfaceError(
|
||||
@NotNull PsiFunctionalExpression context, PsiType functionalInterfaceType) {
|
||||
if (functionalInterfaceType instanceof PsiIntersectionType intersection) {
|
||||
@@ -54,14 +154,14 @@ final class FunctionChecker {
|
||||
Map<PsiType, MethodSignature> typeAndSignature = new HashMap<>();
|
||||
for (PsiType type : intersection.getConjuncts()) {
|
||||
if (getFunctionalInterfaceError(context, type) == null) {
|
||||
MethodSignature signature = getFunction(PsiUtil.resolveClassInType(type));
|
||||
MethodSignature signature = LambdaUtil.getFunction(PsiUtil.resolveClassInType(type));
|
||||
signatures.add(signature);
|
||||
typeAndSignature.put(type, signature);
|
||||
}
|
||||
}
|
||||
PsiType baseType = typeAndSignature.entrySet().iterator().next().getKey();
|
||||
MethodSignature baseSignature = typeAndSignature.get(baseType);
|
||||
LambdaUtil.TargetMethodContainer baseContainer = getTargetMethod(baseType, baseSignature, baseType);
|
||||
LambdaUtil.TargetMethodContainer baseContainer = LambdaUtil.getTargetMethod(baseType, baseSignature, baseType);
|
||||
if (baseContainer == null) {
|
||||
return JavaErrorKinds.LAMBDA_NO_TARGET_METHOD.create(context, baseType);
|
||||
}
|
||||
@@ -71,7 +171,7 @@ final class FunctionChecker {
|
||||
if (baseType == entry.getKey()) {
|
||||
continue;
|
||||
}
|
||||
LambdaUtil.TargetMethodContainer container = getTargetMethod(entry.getKey(), baseSignature, baseType);
|
||||
LambdaUtil.TargetMethodContainer container = LambdaUtil.getTargetMethod(entry.getKey(), baseSignature, baseType);
|
||||
if (container == null) {
|
||||
return JavaErrorKinds.LAMBDA_MULTIPLE_TARGET_METHODS.create(context, functionalInterfaceType);
|
||||
}
|
||||
@@ -85,7 +185,7 @@ final class FunctionChecker {
|
||||
if (typeAndSignature.containsKey(type)) {
|
||||
continue;
|
||||
}
|
||||
LambdaUtil.TargetMethodContainer container = getTargetMethod(type, baseSignature, baseType);
|
||||
LambdaUtil.TargetMethodContainer container = LambdaUtil.getTargetMethod(type, baseSignature, baseType);
|
||||
if (container == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -101,7 +201,7 @@ final class FunctionChecker {
|
||||
PsiClass aClass = resolveResult.getElement();
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference
|
||||
MethodSignature functionalMethod = getFunction(aClass);
|
||||
MethodSignature functionalMethod = LambdaUtil.getFunction(aClass);
|
||||
if (functionalMethod != null && functionalMethod.getTypeParameters().length > 0) {
|
||||
return JavaErrorKinds.LAMBDA_SAM_GENERIC.create(context);
|
||||
}
|
||||
@@ -191,4 +291,50 @@ final class FunctionChecker {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void checkMethodReferenceReturnType(@NotNull PsiMethodReferenceExpression expression, @NotNull JavaResolveResult result,
|
||||
@Nullable PsiType functionalInterfaceType) {
|
||||
String badReturnTypeMessage = PsiMethodReferenceUtil.checkReturnType(expression, result, functionalInterfaceType);
|
||||
if (badReturnTypeMessage != null) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_RETURN_TYPE_ERROR.create(expression, badReturnTypeMessage));
|
||||
}
|
||||
}
|
||||
|
||||
void checkMethodReferenceResolve(@NotNull PsiMethodReferenceExpression expression,
|
||||
@NotNull JavaResolveResult @NotNull [] results,
|
||||
@Nullable PsiType functionalInterfaceType) {
|
||||
boolean resolvedButNonApplicable = results.length == 1 && results[0] instanceof MethodCandidateInfo methodInfo &&
|
||||
!methodInfo.isApplicable() &&
|
||||
functionalInterfaceType != null;
|
||||
if (results.length != 1 || resolvedButNonApplicable) {
|
||||
if (results.length == 1 && ((MethodCandidateInfo)results[0]).getInferenceErrorMessage() != null) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_INFERENCE_ERROR.create(expression, (MethodCandidateInfo)results[0]));
|
||||
return;
|
||||
}
|
||||
if (expression.isConstructor()) {
|
||||
PsiClass containingClass = PsiMethodReferenceUtil.getQualifierResolveResult(expression).getContainingClass();
|
||||
|
||||
if (containingClass != null && containingClass.isPhysical()) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_UNRESOLVED_CONSTRUCTOR.create(expression, containingClass));
|
||||
}
|
||||
}
|
||||
else if (results.length > 1) {
|
||||
if (!IncompleteModelUtil.isIncompleteModel(expression) ||
|
||||
!IncompleteModelUtil.isUnresolvedClassType(functionalInterfaceType)) {
|
||||
myVisitor.report(JavaErrorKinds.REFERENCE_AMBIGUOUS.create(expression, Arrays.asList(results)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (IncompleteModelUtil.isIncompleteModel(expression) && IncompleteModelUtil.canBePendingReference(expression)) {
|
||||
PsiElement referenceNameElement = expression.getReferenceNameElement();
|
||||
if (referenceNameElement != null) {
|
||||
myVisitor.report(JavaErrorKinds.REFERENCE_PENDING.create(referenceNameElement));
|
||||
}
|
||||
}
|
||||
else if (!(resolvedButNonApplicable && hasSurroundingInferenceError(expression))) {
|
||||
myVisitor.report(JavaErrorKinds.METHOD_REFERENCE_UNRESOLVED_METHOD.create(expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.IncompleteModelUtil;
|
||||
import com.intellij.psi.impl.source.DummyHolder;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
|
||||
@@ -334,12 +336,23 @@ final class JavaErrorVisitor extends JavaElementVisitor {
|
||||
public void visitMethodReferenceExpression(@NotNull PsiMethodReferenceExpression expression) {
|
||||
visitElement(expression);
|
||||
checkFeature(expression, JavaFeature.METHOD_REFERENCES);
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent());
|
||||
if (toReportFunctionalExpressionProblemOnParent(parent)) return;
|
||||
PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
|
||||
if (functionalInterfaceType != null && !PsiTypesUtil.allTypeParametersResolved(expression, functionalInterfaceType)) return;
|
||||
|
||||
JavaResolveResult[] results = expression.multiResolve(true);
|
||||
JavaResolveResult result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
|
||||
PsiElement method = result.getElement();
|
||||
if (method instanceof PsiJvmMember member && !result.isAccessible()) {
|
||||
myModifierChecker.reportAccessProblem(expression, member, result);
|
||||
return;
|
||||
}
|
||||
if (!(parent instanceof DummyHolder) && !LambdaUtil.isValidLambdaContext(parent)) {
|
||||
report(JavaErrorKinds.METHOD_REFERENCE_NOT_EXPECTED.create(expression));
|
||||
return;
|
||||
}
|
||||
if (!hasErrorResults()) myFunctionChecker.checkMethodReferenceQualifier(expression);
|
||||
if (!hasErrorResults()) {
|
||||
boolean resolvedButNonApplicable = results.length == 1 && results[0] instanceof MethodCandidateInfo methodInfo &&
|
||||
!methodInfo.isApplicable() &&
|
||||
@@ -372,9 +385,19 @@ final class JavaErrorVisitor extends JavaElementVisitor {
|
||||
myExpressionChecker.checkStaticInterfaceCallQualifier(expression, result, containingClass);
|
||||
}
|
||||
}
|
||||
if (!hasErrorResults()) myFunctionChecker.checkRawConstructorReference(expression);
|
||||
if (functionalInterfaceType != null) {
|
||||
if (!hasErrorResults()) myFunctionChecker.checkExtendsSealedClass(expression, functionalInterfaceType);
|
||||
boolean isFunctional = LambdaUtil.isFunctionalType(functionalInterfaceType);
|
||||
if (!hasErrorResults() && !isFunctional &&
|
||||
!(IncompleteModelUtil.isIncompleteModel(expression) &&
|
||||
IncompleteModelUtil.isUnresolvedClassType(functionalInterfaceType))) {
|
||||
report(JavaErrorKinds.LAMBDA_NOT_FUNCTIONAL_INTERFACE.create(expression, functionalInterfaceType));
|
||||
}
|
||||
if (!hasErrorResults()) myFunctionChecker.checkMethodReferenceContext(expression, functionalInterfaceType);
|
||||
}
|
||||
if (!hasErrorResults()) myFunctionChecker.checkMethodReferenceResolve(expression, results, functionalInterfaceType);
|
||||
if (!hasErrorResults()) myFunctionChecker.checkMethodReferenceReturnType(expression, result, functionalInterfaceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -142,8 +142,44 @@ public final class JavaErrorKinds {
|
||||
public static final Parameterized<PsiElement, String> LAMBDA_RETURN_TYPE_ERROR =
|
||||
parameterized(PsiElement.class, String.class, "lambda.return.type.error")
|
||||
.withRawDescription((psi, message) -> message("lambda.return.type.error", message));
|
||||
|
||||
|
||||
public static final Simple<PsiMethodReferenceExpression> METHOD_REFERENCE_SEALED = error("method.reference.sealed");
|
||||
public static final Simple<PsiMethodReferenceExpression> METHOD_REFERENCE_NOT_EXPECTED = error("method.reference.not.expected");
|
||||
public static final Simple<PsiMethodReferenceExpression> METHOD_REFERENCE_RAW_CONSTRUCTOR = error("method.reference.raw.constructor");
|
||||
public static final Simple<PsiElement> METHOD_REFERENCE_QUALIFIER_CLASS_UNRESOLVED =
|
||||
error(PsiElement.class, "method.reference.qualifier.class.unresolved")
|
||||
.withRawDescription(qualifier -> message("method.reference.qualifier.class.unresolved", qualifier.getText()));
|
||||
public static final Simple<PsiTypeElement> METHOD_REFERENCE_QUALIFIER_WILDCARD = error("method.reference.qualifier.wildcard");
|
||||
public static final Parameterized<PsiMethodReferenceExpression, String> METHOD_REFERENCE_RETURN_TYPE_ERROR =
|
||||
parameterized(PsiMethodReferenceExpression.class, String.class, "method.reference.return.type.error")
|
||||
.withRawDescription((psi, message) -> message("method.reference.return.type.error", message));
|
||||
public static final Parameterized<PsiMethodReferenceExpression, MethodCandidateInfo> METHOD_REFERENCE_INFERENCE_ERROR =
|
||||
parameterized(PsiMethodReferenceExpression.class, MethodCandidateInfo.class, "method.reference.inference.error")
|
||||
.withAnchor((ref, candidate) -> requireNonNullElse(ref.getReferenceNameElement(), ref))
|
||||
.withRawDescription((ref, candidate) -> message("method.reference.inference.error", candidate.getInferenceErrorMessage()));
|
||||
public static final Parameterized<PsiMethodReferenceExpression, PsiClass> METHOD_REFERENCE_UNRESOLVED_CONSTRUCTOR =
|
||||
parameterized(PsiMethodReferenceExpression.class, PsiClass.class, "method.reference.unresolved.constructor")
|
||||
.withAnchor((ref, cls) -> requireNonNullElse(ref.getReferenceNameElement(), ref))
|
||||
.withRawDescription((ref, cls) -> message("method.reference.unresolved.constructor", cls.getName()));
|
||||
public static final Simple<PsiMethodReferenceExpression> METHOD_REFERENCE_UNRESOLVED_METHOD =
|
||||
error(PsiMethodReferenceExpression.class, "method.reference.unresolved.method")
|
||||
.withAnchor(ref -> requireNonNullElse(ref.getReferenceNameElement(), ref))
|
||||
.withHighlightType(ref -> JavaErrorHighlightType.WRONG_REF)
|
||||
.withRawDescription(ref -> message("method.reference.unresolved.method", ref.getReferenceName()));
|
||||
public static final Parameterized<PsiMethodReferenceExpression, PsiMethod> METHOD_REFERENCE_ABSTRACT_METHOD =
|
||||
parameterized(PsiMethodReferenceExpression.class, PsiMethod.class, "method.reference.abstract.method")
|
||||
.withRawDescription((psi, method) -> message("method.reference.abstract.method", method.getName()));
|
||||
public static final Parameterized<PsiMethodReferenceExpression, PsiMethod> METHOD_REFERENCE_NON_STATIC_METHOD_IN_STATIC_CONTEXT =
|
||||
parameterized(PsiMethodReferenceExpression.class, PsiMethod.class, "method.reference.non.static.method.in.static.context");
|
||||
public static final Parameterized<PsiMethodReferenceExpression, PsiMethod> METHOD_REFERENCE_STATIC_METHOD_NON_STATIC_QUALIFIER =
|
||||
parameterized(PsiMethodReferenceExpression.class, PsiMethod.class, "method.reference.static.method.non.static.qualifier");
|
||||
public static final Parameterized<PsiMethodReferenceExpression, PsiMethod> METHOD_REFERENCE_STATIC_METHOD_RECEIVER =
|
||||
parameterized(PsiMethodReferenceExpression.class, PsiMethod.class, "method.reference.static.method.receiver");
|
||||
public static final Parameterized<PsiMethodReferenceExpression, PsiClass> METHOD_REFERENCE_ENCLOSING_INSTANCE_NOT_IN_SCOPE =
|
||||
parameterized(PsiMethodReferenceExpression.class, PsiClass.class, "method.reference.enclosing.instance.not.in.scope")
|
||||
.withRawDescription((psi, cls) -> message("method.reference.enclosing.instance.not.in.scope", formatClass(cls)));
|
||||
public static final Simple<PsiReferenceParameterList> METHOD_REFERENCE_PARAMETERIZED_QUALIFIER =
|
||||
error("method.reference.parameterized.qualifier");
|
||||
|
||||
public static final Parameterized<PsiAnnotation, @NotNull List<PsiAnnotation.@NotNull TargetType>> ANNOTATION_NOT_APPLICABLE =
|
||||
error(PsiAnnotation.class, "annotation.not.applicable").<@NotNull List<PsiAnnotation.@NotNull TargetType>>parameterized()
|
||||
|
||||
@@ -6,22 +6,13 @@ import com.intellij.codeInsight.daemon.impl.DefaultHighlightUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightVisitor;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.AdjustFunctionContextFix;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
|
||||
import com.intellij.codeInspection.ex.GlobalInspectionContextBase;
|
||||
import com.intellij.core.JavaPsiBundle;
|
||||
import com.intellij.java.codeserver.highlighting.JavaErrorCollector;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaCompilationError;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaErrorHighlightType;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.lang.jvm.JvmModifier;
|
||||
import com.intellij.lang.jvm.JvmModifiersOwner;
|
||||
import com.intellij.lang.jvm.actions.JvmElementActionFactories;
|
||||
import com.intellij.lang.jvm.actions.MemberRequestsKt;
|
||||
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsUtil;
|
||||
@@ -30,17 +21,14 @@ import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.HtmlChunk;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.ControlFlowUtil;
|
||||
import com.intellij.psi.impl.IncompleteModelUtil;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
@@ -60,7 +48,6 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds.*;
|
||||
import static java.util.Objects.*;
|
||||
|
||||
// java highlighting: problems in java code like unresolved/incompatible symbols/methods etc.
|
||||
public class HighlightVisitorImpl extends JavaElementVisitor implements HighlightVisitor {
|
||||
@@ -605,160 +592,16 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
|
||||
if (functionalInterfaceType != null && !PsiTypesUtil.allTypeParametersResolved(expression, functionalInterfaceType)) return;
|
||||
|
||||
JavaResolveResult result;
|
||||
JavaResolveResult[] results;
|
||||
try {
|
||||
results = expression.multiResolve(true);
|
||||
result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
return;
|
||||
}
|
||||
JavaResolveResult[] results = expression.multiResolve(true);
|
||||
JavaResolveResult result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
|
||||
PsiElement method = result.getElement();
|
||||
if (method instanceof PsiJvmMember && !result.isAccessible()) {
|
||||
String accessProblem = HighlightUtil.accessProblemDescription(expression, method, result);
|
||||
HighlightInfo.Builder info =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(accessProblem);
|
||||
HighlightFixUtil.registerAccessQuickFixAction(HighlightUtil.asConsumer(info), (PsiJvmMember)method, expression, result.getCurrentFileResolveScope());
|
||||
add(info);
|
||||
}
|
||||
|
||||
if (!LambdaUtil.isValidLambdaContext(parent)) {
|
||||
String description = JavaErrorBundle.message("method.reference.expression.is.not.expected");
|
||||
add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description));
|
||||
}
|
||||
|
||||
if (!hasErrorResults()) {
|
||||
PsiElement referenceNameElement = expression.getReferenceNameElement();
|
||||
if (referenceNameElement instanceof PsiKeyword) {
|
||||
if (!PsiMethodReferenceUtil.isValidQualifier(expression)) {
|
||||
PsiElement qualifier = expression.getQualifier();
|
||||
if (qualifier != null) {
|
||||
boolean pending = qualifier instanceof PsiJavaCodeReferenceElement ref &&
|
||||
IncompleteModelUtil.isIncompleteModel(expression) &&
|
||||
IncompleteModelUtil.canBePendingReference(ref);
|
||||
if (!pending) {
|
||||
String description = JavaErrorBundle.message("cannot.find.class", qualifier.getText());
|
||||
add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(description));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (functionalInterfaceType != null) {
|
||||
if (!hasErrorResults()) {
|
||||
boolean isFunctional = LambdaUtil.isFunctionalType(functionalInterfaceType);
|
||||
if (!isFunctional && !(IncompleteModelUtil.isIncompleteModel(expression) &&
|
||||
IncompleteModelUtil.isUnresolvedClassType(functionalInterfaceType))) {
|
||||
String description =
|
||||
JavaErrorBundle.message("not.a.functional.interface", functionalInterfaceType.getPresentableText());
|
||||
add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description));
|
||||
}
|
||||
}
|
||||
if (!hasErrorResults()) {
|
||||
add(LambdaHighlightingUtil.checkFunctionalInterfaceTypeAccessible(myFile.getProject(), expression, functionalInterfaceType));
|
||||
}
|
||||
if (!hasErrorResults()) {
|
||||
String errorMessage = PsiMethodReferenceHighlightingUtil.checkMethodReferenceContext(expression);
|
||||
if (errorMessage != null) {
|
||||
HighlightInfo.Builder info =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(errorMessage);
|
||||
if (method instanceof PsiMethod psiMethod &&
|
||||
!psiMethod.isConstructor() &&
|
||||
!psiMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
boolean shouldHave = !psiMethod.hasModifierProperty(PsiModifier.STATIC);
|
||||
QuickFixAction.registerQuickFixActions(info, null, JvmElementActionFactories.createModifierActions(
|
||||
(JvmModifiersOwner)method, MemberRequestsKt.modifierRequest(JvmModifier.STATIC, shouldHave)));
|
||||
}
|
||||
add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasErrorResults()) {
|
||||
PsiElement qualifier = expression.getQualifier();
|
||||
if (qualifier instanceof PsiTypeElement typeElement) {
|
||||
PsiType psiType = typeElement.getType();
|
||||
String wildcardMessage = checkTypeArguments(typeElement, psiType);
|
||||
if (wildcardMessage != null) {
|
||||
add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(wildcardMessage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasErrorResults()) {
|
||||
add(PsiMethodReferenceHighlightingUtil.checkRawConstructorReference(expression));
|
||||
}
|
||||
|
||||
if (!hasErrorResults()) {
|
||||
boolean resolvedButNonApplicable = results.length == 1 && results[0] instanceof MethodCandidateInfo methodInfo &&
|
||||
!methodInfo.isApplicable() &&
|
||||
functionalInterfaceType != null;
|
||||
if (results.length != 1 || resolvedButNonApplicable) {
|
||||
String description = null;
|
||||
if (results.length == 1) {
|
||||
description = ((MethodCandidateInfo)results[0]).getInferenceErrorMessage();
|
||||
}
|
||||
if (expression.isConstructor()) {
|
||||
PsiClass containingClass = PsiMethodReferenceUtil.getQualifierResolveResult(expression).getContainingClass();
|
||||
|
||||
if (containingClass != null &&
|
||||
containingClass.isPhysical() &&
|
||||
description == null) {
|
||||
description = JavaErrorBundle.message("cannot.resolve.constructor", containingClass.getName());
|
||||
}
|
||||
}
|
||||
else if (description == null) {
|
||||
if (results.length > 1) {
|
||||
if (IncompleteModelUtil.isIncompleteModel(expression) &&
|
||||
IncompleteModelUtil.isUnresolvedClassType(functionalInterfaceType)) {
|
||||
return;
|
||||
}
|
||||
String t1 = HighlightUtil.format(requireNonNull(results[0].getElement()));
|
||||
String t2 = HighlightUtil.format(requireNonNull(results[1].getElement()));
|
||||
description = JavaErrorBundle.message("ambiguous.reference", expression.getReferenceName(), t1, t2);
|
||||
}
|
||||
else {
|
||||
if (IncompleteModelUtil.isIncompleteModel(expression) && IncompleteModelUtil.canBePendingReference(expression)) {
|
||||
PsiElement referenceNameElement = expression.getReferenceNameElement();
|
||||
if (referenceNameElement != null) {
|
||||
add(HighlightUtil.getPendingReferenceHighlightInfo(referenceNameElement));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(resolvedButNonApplicable && HighlightMethodUtil.hasSurroundingInferenceError(expression))) {
|
||||
description = JavaErrorBundle.message("cannot.resolve.method", expression.getReferenceName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (description != null) {
|
||||
PsiElement referenceNameElement = ObjectUtils.notNull(expression.getReferenceNameElement(), expression);
|
||||
HighlightInfoType type = results.length == 0 ? HighlightInfoType.WRONG_REF : HighlightInfoType.ERROR;
|
||||
HighlightInfo.Builder highlightInfo =
|
||||
HighlightInfo.newHighlightInfo(type).descriptionAndTooltip(description).range(referenceNameElement);
|
||||
TextRange fixRange = HighlightMethodUtil.getFixRange(referenceNameElement);
|
||||
IntentionAction action = QuickFixFactory.getInstance().createCreateMethodFromUsageFix(expression);
|
||||
highlightInfo.registerFix(action, null, null, fixRange, null);
|
||||
add(highlightInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasErrorResults()) {
|
||||
String badReturnTypeMessage = PsiMethodReferenceUtil.checkReturnType(expression, result, functionalInterfaceType);
|
||||
if (badReturnTypeMessage != null) {
|
||||
HighlightInfo.Builder info =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(badReturnTypeMessage);
|
||||
IntentionAction action = AdjustFunctionContextFix.createFix(expression);
|
||||
if (action != null) {
|
||||
info.registerFix(action, null, null, null, null);
|
||||
}
|
||||
add(info);
|
||||
}
|
||||
}
|
||||
if (!hasErrorResults() && method instanceof PsiModifierListOwner) {
|
||||
PreviewFeatureUtil.checkPreviewFeature(expression, myPreviewFeatureVisitor);
|
||||
}
|
||||
@@ -895,19 +738,4 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
private @Nullable HighlightInfo.Builder checkFeature(@NotNull PsiElement element, @NotNull JavaFeature feature) {
|
||||
return HighlightUtil.checkFeature(element, feature, myLanguageLevel, myFile);
|
||||
}
|
||||
|
||||
private static @NlsContexts.DetailedDescription String checkTypeArguments(PsiTypeElement qualifier, PsiType psiType) {
|
||||
if (psiType instanceof PsiClassType) {
|
||||
final PsiJavaCodeReferenceElement referenceElement = qualifier.getInnermostComponentReferenceElement();
|
||||
if (referenceElement != null) {
|
||||
PsiType[] typeParameters = referenceElement.getTypeParameters();
|
||||
for (PsiType typeParameter : typeParameters) {
|
||||
if (typeParameter instanceof PsiWildcardType) {
|
||||
return JavaPsiBundle.message("error.message.wildcard.not.expected");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ final class JavaErrorFixProvider {
|
||||
NEW_EXPRESSION_ANONYMOUS_IMPLEMENTS_INTERFACE_WITH_TYPE_ARGUMENTS,
|
||||
CALL_DIRECT_ABSTRACT_METHOD_ACCESS, RECORD_SPECIAL_METHOD_TYPE_PARAMETERS,
|
||||
RECORD_SPECIAL_METHOD_THROWS, ARRAY_TYPE_ARGUMENTS, ARRAY_EMPTY_DIAMOND,
|
||||
IMPORT_LIST_EXTRA_SEMICOLON, ENUM_CONSTANT_MODIFIER)) {
|
||||
IMPORT_LIST_EXTRA_SEMICOLON, ENUM_CONSTANT_MODIFIER, METHOD_REFERENCE_PARAMETERIZED_QUALIFIER)) {
|
||||
fix(kind, genericRemover);
|
||||
}
|
||||
|
||||
@@ -536,6 +536,13 @@ final class JavaErrorFixProvider {
|
||||
}
|
||||
return null;
|
||||
});
|
||||
fix(METHOD_REFERENCE_RETURN_TYPE_ERROR, error -> AdjustFunctionContextFix.createFix(error.psi()));
|
||||
fix(METHOD_REFERENCE_UNRESOLVED_METHOD, error -> myFactory.createCreateMethodFromUsageFix(error.psi()));
|
||||
fix(METHOD_REFERENCE_UNRESOLVED_CONSTRUCTOR, error -> myFactory.createCreateMethodFromUsageFix(error.psi()));
|
||||
fix(METHOD_REFERENCE_INFERENCE_ERROR, error -> myFactory.createCreateMethodFromUsageFix(error.psi()));
|
||||
fix(METHOD_REFERENCE_STATIC_METHOD_NON_STATIC_QUALIFIER, error -> removeModifierFix(error.context(), PsiModifier.STATIC));
|
||||
fix(METHOD_REFERENCE_STATIC_METHOD_RECEIVER, error -> removeModifierFix(error.context(), PsiModifier.STATIC));
|
||||
fix(METHOD_REFERENCE_NON_STATIC_METHOD_IN_STATIC_CONTEXT, error -> addModifierFix(error.context(), PsiModifier.STATIC));
|
||||
}
|
||||
|
||||
private void createAccessFixes() {
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.java.analysis.JavaAnalysisBundle;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class PsiMethodReferenceHighlightingUtil {
|
||||
static HighlightInfo.Builder checkRawConstructorReference(@NotNull PsiMethodReferenceExpression expression) {
|
||||
if (expression.isConstructor()) {
|
||||
PsiType[] typeParameters = expression.getTypeParameters();
|
||||
if (typeParameters.length > 0) {
|
||||
PsiElement qualifier = expression.getQualifier();
|
||||
if (qualifier instanceof PsiReferenceExpression) {
|
||||
PsiElement resolve = ((PsiReferenceExpression)qualifier).resolve();
|
||||
if (resolve instanceof PsiClass && ((PsiClass)resolve).hasTypeParameters()) {
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
|
||||
.descriptionAndTooltip(JavaAnalysisBundle.message("text.raw.ctor.reference.with.type.parameters"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static @NlsContexts.DetailedDescription String checkMethodReferenceContext(@NotNull PsiMethodReferenceExpression methodRef) {
|
||||
PsiElement resolve = methodRef.resolve();
|
||||
|
||||
if (resolve == null) return null;
|
||||
return checkMethodReferenceContext(methodRef, resolve, methodRef.getFunctionalInterfaceType());
|
||||
}
|
||||
|
||||
public static @NlsContexts.DetailedDescription String checkMethodReferenceContext(@NotNull PsiMethodReferenceExpression methodRef,
|
||||
@NotNull PsiElement resolve,
|
||||
PsiType functionalInterfaceType) {
|
||||
PsiClass containingClass = resolve instanceof PsiMethod method ? method.getContainingClass() : (PsiClass)resolve;
|
||||
boolean isStaticSelector = PsiMethodReferenceUtil.isStaticallyReferenced(methodRef);
|
||||
PsiElement qualifier = methodRef.getQualifier();
|
||||
|
||||
boolean isMethodStatic = false;
|
||||
boolean receiverReferenced = false;
|
||||
boolean isConstructor = true;
|
||||
|
||||
if (resolve instanceof PsiMethod method) {
|
||||
isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC);
|
||||
isConstructor = method.isConstructor();
|
||||
|
||||
PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
|
||||
receiverReferenced = PsiMethodReferenceUtil.isResolvedBySecondSearch(methodRef,
|
||||
interfaceMethod != null ? interfaceMethod.getSignature(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult)) : null,
|
||||
method.isVarArgs(),
|
||||
isMethodStatic,
|
||||
method.getParameterList().getParametersCount());
|
||||
|
||||
if (method.hasModifierProperty(PsiModifier.ABSTRACT) && qualifier instanceof PsiSuperExpression) {
|
||||
return JavaErrorBundle.message("abstract.method.0.cannot.be.accessed.directly.method.reference.context", method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (!receiverReferenced) {
|
||||
if (isStaticSelector && !isMethodStatic && !isConstructor) {
|
||||
if (functionalInterfaceType instanceof PsiClassType classType && classType.hasParameters()) {
|
||||
// Prefer surrounding error, as it could be more descriptive
|
||||
if (HighlightMethodUtil.hasSurroundingInferenceError(methodRef)) return null;
|
||||
}
|
||||
return JavaErrorBundle.message("non.static.method.cannot.be.referenced.from.a.static.context.method.reference.context");
|
||||
}
|
||||
if (!isStaticSelector && isMethodStatic) {
|
||||
return JavaErrorBundle.message("static.method.referenced.through.non.static.qualifier.method.reference.context");
|
||||
}
|
||||
}
|
||||
else if (isStaticSelector && isMethodStatic) {
|
||||
return JavaErrorBundle.message("static.method.referenced.through.receiver.method.reference.context");
|
||||
}
|
||||
|
||||
if (isMethodStatic && isStaticSelector && qualifier instanceof PsiTypeElement) {
|
||||
PsiJavaCodeReferenceElement referenceElement = PsiTreeUtil.getChildOfType(qualifier, PsiJavaCodeReferenceElement.class);
|
||||
if (referenceElement != null) {
|
||||
PsiReferenceParameterList parameterList = referenceElement.getParameterList();
|
||||
if (parameterList != null && parameterList.getTypeArguments().length > 0) {
|
||||
return JavaErrorBundle.message("parameterized.qualifier.on.static.method.reference.context");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isConstructor) {
|
||||
if (containingClass != null && PsiUtil.isInnerClass(containingClass) && containingClass.isPhysical()) {
|
||||
PsiClass outerClass = containingClass.getContainingClass();
|
||||
if (outerClass != null && !InheritanceUtil.hasEnclosingInstanceInScope(outerClass, methodRef, true, false)) {
|
||||
return JavaErrorBundle.message("an.enclosing.instance.of.type.not.in.scope.method.reference.context",
|
||||
PsiFormatUtil.formatClass(outerClass, PsiFormatUtilBase.SHOW_NAME));
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion.scope;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.PsiMethodReferenceHighlightingUtil;
|
||||
import com.intellij.codeInspection.SuppressManager;
|
||||
import com.intellij.codeInspection.accessStaticViaInstance.AccessStaticViaInstanceBase;
|
||||
import com.intellij.java.codeserver.highlighting.JavaErrorCollector;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
@@ -235,8 +235,8 @@ public final class JavaCompletionProcessor implements PsiScopeProcessor, Element
|
||||
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;
|
||||
PsiMethodReferenceUtil.isReturnTypeCompatible(referenceExpression, result, expectedType) &&
|
||||
JavaErrorCollector.findSingleError(referenceExpression) == null;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ public final class PsiMethodReferenceUtil {
|
||||
|
||||
public static boolean isReturnTypeCompatible(PsiMethodReferenceExpression expression,
|
||||
JavaResolveResult result,
|
||||
PsiType functionalInterfaceType) {
|
||||
@Nullable PsiType functionalInterfaceType) {
|
||||
return isReturnTypeCompatible(expression, result, functionalInterfaceType, null);
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ public final class PsiMethodReferenceUtil {
|
||||
|
||||
private static boolean isReturnTypeCompatible(PsiMethodReferenceExpression expression,
|
||||
JavaResolveResult result,
|
||||
PsiType functionalInterfaceType,
|
||||
@Nullable PsiType functionalInterfaceType,
|
||||
Ref<@Nls String> errorMessage) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
|
||||
@@ -302,7 +302,8 @@ public final class PsiMethodReferenceUtil {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static @NlsContexts.DetailedDescription String checkReturnType(PsiMethodReferenceExpression expression, JavaResolveResult result, PsiType functionalInterfaceType) {
|
||||
public static @NlsContexts.DetailedDescription String checkReturnType(PsiMethodReferenceExpression expression, JavaResolveResult result,
|
||||
@Nullable PsiType functionalInterfaceType) {
|
||||
final Ref<@Nls String> errorMessage = Ref.create();
|
||||
if (!isReturnTypeCompatible(expression, result, functionalInterfaceType, errorMessage)) {
|
||||
return errorMessage.get();
|
||||
|
||||
@@ -28,7 +28,7 @@ class AlienTest {
|
||||
IInt i3 = MyTest::<error descr="Cannot resolve method 'bar'">bar</error>;
|
||||
IIntInt i4 = MyTest::<error descr="Reference to 'bar' is ambiguous, both 'bar(Integer, Number)' and 'bar(Number, Integer)' match">bar</error>;
|
||||
IInt i5 = <error descr="Non-static method cannot be referenced from a static context">MyTest::baz</error>;
|
||||
IInt i6 = <error descr="'foo(int)' is not public in 'MyTest.Foo'. Cannot be accessed from outside package">MyTest.foo::foo</error>;
|
||||
IInt i6 = MyTest.foo::<error descr="'foo(int)' is not public in 'MyTest.Foo'. Cannot be accessed from outside package">foo</error>;
|
||||
IInt i7 = MyTest.<error descr="'MyTest.Foo' has private access in 'MyTest'">Foo</error>::foo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,5 +38,5 @@ class Test2 {
|
||||
|
||||
void foo(Integer i) {}
|
||||
|
||||
Object o = <error descr="Object is not a functional interface">Test2::foo</error>;
|
||||
Object o = <error descr="java.lang.Object is not a functional interface">Test2::foo</error>;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ class Test<X> {
|
||||
}
|
||||
|
||||
void test() {
|
||||
I i1 = <error descr="Parameterized qualifier on static method reference">Test<String>::foo</error>;
|
||||
I i1 = Test<error descr="Parameterized qualifier on static method reference"><String></error>::foo;
|
||||
I i2 = Test::foo;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.util.function.Function;
|
||||
|
||||
class Main {
|
||||
{
|
||||
List<Optional<Function<String, String>>> list = asList(of(<error descr="Object is not a functional interface">Main::identity</error>));
|
||||
List<Optional<Function<String, String>>> list = asList(of(<error descr="java.lang.Object is not a functional interface">Main::identity</error>));
|
||||
}
|
||||
|
||||
static <T> List<T> asList(T a) { return null;}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class Test {
|
||||
{
|
||||
asList(<error descr="Target type of a lambda conversion must be an interface">o -> {}</error>, 1, 2, 3);
|
||||
asList(<error descr="Integer is not a functional interface">Test::foo</error>, 1, 2, 3);
|
||||
asList(<error descr="java.lang.Integer is not a functional interface">Test::foo</error>, 1, 2, 3);
|
||||
}
|
||||
|
||||
void foo() {}
|
||||
|
||||
Reference in New Issue
Block a user