mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-highlighting] Finish checkMethodCall migration
Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only) GitOrigin-RevId: 68d3ae802d6340854838c680979aba531a778488
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0be0a316f7
commit
7f391af965
@@ -130,6 +130,14 @@ type.parameter.on.annotation.member=@interface members may not have type paramet
|
||||
type.parameter.on.annotation=@interface may not have type parameters
|
||||
type.parameter.duplicate=Duplicate type parameter: ''{0}''
|
||||
type.parameter.incompatible.upper.bounds=Type parameter {0} has incompatible upper bounds: {1}
|
||||
type.parameter.inferred.type.not.within.extend.bound=Inferred type ''{2}'' for type parameter ''{0}'' is not within its bound; should extend ''{1}''
|
||||
type.parameter.inferred.type.not.within.implement.bound=Inferred type ''{2}'' for type parameter ''{0}'' is not within its bound; should implement ''{1}''
|
||||
type.parameter.type.not.within.extend.bound=Type parameter ''{0}'' is not within its bound; should extend ''{1}''
|
||||
type.parameter.type.not.within.implement.bound=Type parameter ''{0}'' is not within its bound; should implement ''{1}''
|
||||
type.parameter.absent.class=Type ''{0}'' does not have type parameters
|
||||
type.parameter.absent.method=Method ''{0}'' does not have type parameters
|
||||
type.parameter.count.mismatch=Wrong number of type arguments: {0}; required: {1}
|
||||
type.parameter.actual.inferred.mismatch=Actual type argument and inferred type contradict each other
|
||||
|
||||
method.duplicate=''{0}'' is already defined in ''{1}''
|
||||
method.throws.class.name.expected=Class name expected
|
||||
@@ -176,6 +184,9 @@ new.expression.qualified.static.class=Qualified new of static class
|
||||
new.expression.qualified.anonymous.implements.interface=Anonymous class implements interface; cannot have qualifier for new
|
||||
new.expression.qualified.qualified.class.reference=Qualified class reference is not allowed in qualified new
|
||||
new.expression.diamond.not.allowed=Diamond operator is not allowed here
|
||||
new.expression.diamond.not.applicable=Diamond operator is not applicable for non-parameterized types
|
||||
new.expression.diamond.inference.failure={0}
|
||||
new.expression.diamond.anonymous.inner.non.private=Cannot use '<>' due to non-private method which doesn't override or implement a method from a supertype
|
||||
|
||||
reference.type.argument.static.class=Type arguments are not allowed here because class ''{0}'' is static
|
||||
reference.type.needs.type.arguments=Improperly formed type: ''{0}'' needs type arguments because its qualifier has type arguments
|
||||
|
||||
+42
-12
@@ -6,6 +6,7 @@ import com.intellij.core.JavaPsiBundle;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaMismatchedCallContext;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.IncompleteModelUtil;
|
||||
@@ -18,10 +19,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
@@ -344,16 +342,48 @@ final class ExpressionChecker {
|
||||
MethodCandidateInfo candidateInfo = resolveResult instanceof MethodCandidateInfo ? (MethodCandidateInfo)resolveResult : null;
|
||||
PsiMethod resolvedMethod = candidateInfo != null ? candidateInfo.getElement() : null;
|
||||
|
||||
if (!resolveResult.isAccessible() || !resolveResult.isStaticsScopeCorrect()) {
|
||||
}
|
||||
else if (candidateInfo != null && !candidateInfo.isApplicable()) {
|
||||
if (candidateInfo.isTypeArgumentsApplicable()) {
|
||||
checkIncompatibleCall(list, candidateInfo);
|
||||
if (resolveResult.isAccessible() && resolveResult.isStaticsScopeCorrect()) {
|
||||
if (candidateInfo != null && !candidateInfo.isApplicable()) {
|
||||
if (candidateInfo.isTypeArgumentsApplicable()) {
|
||||
checkIncompatibleCall(list, candidateInfo);
|
||||
}
|
||||
else {
|
||||
PsiReferenceParameterList typeArgumentList = methodCall.getTypeArgumentList();
|
||||
PsiSubstitutor applicabilitySubstitutor = candidateInfo.getSubstitutor(false);
|
||||
if (typeArgumentList.getTypeArguments().length == 0 && resolvedMethod.hasTypeParameters()) {
|
||||
checkInferredTypeArguments(resolvedMethod, methodCall, applicabilitySubstitutor);
|
||||
}
|
||||
else {
|
||||
myVisitor.myGenericsChecker.checkParameterizedReferenceTypeArguments(resolved, referenceToMethod, applicabilitySubstitutor);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
myVisitor.report(JavaErrorKinds.CALL_EXPECTED.create(methodCall));
|
||||
}
|
||||
}
|
||||
else {
|
||||
myVisitor.report(JavaErrorKinds.CALL_EXPECTED.create(methodCall));
|
||||
}
|
||||
}
|
||||
if (!myVisitor.hasErrorResults()) {
|
||||
myVisitor.myGenericsChecker.checkParameterizedReferenceTypeArguments(resolved, referenceToMethod, substitutor);
|
||||
}
|
||||
}
|
||||
|
||||
void checkInferredTypeArguments(@NotNull PsiTypeParameterListOwner listOwner,
|
||||
@NotNull PsiMethodCallExpression call,
|
||||
@NotNull PsiSubstitutor substitutor) {
|
||||
PsiTypeParameter[] typeParameters = listOwner.getTypeParameters();
|
||||
Pair<PsiTypeParameter, PsiType> inferredTypeArgument = GenericsUtil.findTypeParameterWithBoundError(
|
||||
typeParameters, substitutor, call, false);
|
||||
if (inferredTypeArgument != null) {
|
||||
PsiType extendsType = inferredTypeArgument.second;
|
||||
PsiTypeParameter typeParameter = inferredTypeArgument.first;
|
||||
PsiClass boundClass = extendsType instanceof PsiClassType classType ? classType.resolve() : null;
|
||||
|
||||
var kind = boundClass == null || typeParameter.isInterface() == boundClass.isInterface()
|
||||
? JavaErrorKinds.TYPE_PARAMETER_INFERRED_TYPE_NOT_WITHIN_EXTEND_BOUND
|
||||
: JavaErrorKinds.TYPE_PARAMETER_INFERRED_TYPE_NOT_WITHIN_IMPLEMENT_BOUND;
|
||||
myVisitor.report(kind.create(call, new JavaErrorKinds.TypeParameterBoundMismatchContext(
|
||||
typeParameter, extendsType, Objects.requireNonNull(substitutor.substitute(typeParameter)))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+166
@@ -4,6 +4,7 @@ package com.intellij.java.codeserver.highlighting;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
|
||||
import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.roots.FileIndexFacade;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -12,6 +13,8 @@ import com.intellij.psi.impl.IncompleteModelUtil;
|
||||
import com.intellij.psi.impl.PsiClassImplUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -250,4 +253,167 @@ final class GenericsChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkParameterizedReferenceTypeArguments(@Nullable PsiElement resolved,
|
||||
@NotNull PsiJavaCodeReferenceElement referenceElement,
|
||||
@NotNull PsiSubstitutor substitutor) {
|
||||
if (!(resolved instanceof PsiTypeParameterListOwner typeParameterListOwner)) return;
|
||||
checkReferenceTypeArgumentList(typeParameterListOwner, referenceElement.getParameterList(), substitutor);
|
||||
}
|
||||
|
||||
void checkReferenceTypeArgumentList(@NotNull PsiTypeParameterListOwner typeParameterListOwner,
|
||||
@Nullable PsiReferenceParameterList referenceParameterList,
|
||||
@NotNull PsiSubstitutor substitutor) {
|
||||
PsiDiamondType.DiamondInferenceResult inferenceResult = null;
|
||||
PsiTypeElement[] referenceElements = null;
|
||||
if (referenceParameterList != null) {
|
||||
referenceElements = referenceParameterList.getTypeParameterElements();
|
||||
if (referenceElements.length == 1 && referenceElements[0].getType() instanceof PsiDiamondType diamondType) {
|
||||
if (!typeParameterListOwner.hasTypeParameters()) {
|
||||
myVisitor.report(JavaErrorKinds.NEW_EXPRESSION_DIAMOND_NOT_APPLICABLE.create(referenceParameterList));
|
||||
return;
|
||||
}
|
||||
inferenceResult = diamondType.resolveInferredTypes();
|
||||
String errorMessage = inferenceResult.getErrorMessage();
|
||||
if (errorMessage != null) {
|
||||
PsiType expectedType = detectExpectedType(referenceParameterList);
|
||||
if (!(inferenceResult.failedToInfer() && expectedType instanceof PsiClassType classType && classType.isRaw())) {
|
||||
if (inferenceResult == PsiDiamondType.DiamondInferenceResult.ANONYMOUS_INNER_RESULT ||
|
||||
inferenceResult == PsiDiamondType.DiamondInferenceResult.EXPLICIT_CONSTRUCTOR_TYPE_ARGS) {
|
||||
myVisitor.report(JavaErrorKinds.NEW_EXPRESSION_DIAMOND_INFERENCE_FAILURE.create(referenceParameterList, inferenceResult));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PsiElement parent = referenceParameterList.getParent().getParent();
|
||||
if (parent instanceof PsiAnonymousClass anonymousClass &&
|
||||
ContainerUtil.exists(anonymousClass.getMethods(),
|
||||
method -> !method.hasModifierProperty(PsiModifier.PRIVATE) && method.findSuperMethods().length == 0)) {
|
||||
myVisitor.report(JavaErrorKinds.NEW_EXPRESSION_DIAMOND_ANONYMOUS_INNER_NON_PRIVATE.create(referenceParameterList));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PsiTypeParameter[] typeParameters = typeParameterListOwner.getTypeParameters();
|
||||
int targetParametersNum = typeParameters.length;
|
||||
int refParametersNum = referenceParameterList == null ? 0 : referenceParameterList.getTypeArguments().length;
|
||||
if (targetParametersNum != refParametersNum && refParametersNum != 0) {
|
||||
if (targetParametersNum == 0) {
|
||||
boolean shouldSuppress = PsiTreeUtil.getParentOfType(referenceParameterList, PsiCall.class) != null &&
|
||||
typeParameterListOwner instanceof PsiMethod psiMethod &&
|
||||
(myVisitor.sdkVersion().isAtLeast(JavaSdkVersion.JDK_1_7) || hasSuperMethodsWithTypeParams(psiMethod));
|
||||
if (!shouldSuppress) {
|
||||
if (typeParameterListOwner instanceof PsiMethod psiMethod) {
|
||||
myVisitor.report(JavaErrorKinds.TYPE_PARAMETER_ABSENT_METHOD.create(referenceParameterList, psiMethod));
|
||||
}
|
||||
else if (typeParameterListOwner instanceof PsiClass psiClass) {
|
||||
myVisitor.report(JavaErrorKinds.TYPE_PARAMETER_ABSENT_CLASS.create(referenceParameterList, psiClass));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
myVisitor.report(JavaErrorKinds.TYPE_PARAMETER_COUNT_MISMATCH.create(referenceParameterList, typeParameterListOwner));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// bounds check
|
||||
if (targetParametersNum > 0 && refParametersNum != 0) {
|
||||
if (inferenceResult != null) {
|
||||
PsiType[] types = inferenceResult.getTypes();
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
checkTypeParameterWithinItsBound(typeParameters[i], substitutor, types[i], referenceElements[0], referenceParameterList);
|
||||
if (myVisitor.hasErrorResults()) return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
PsiTypeElement typeElement = referenceElements[i];
|
||||
checkTypeParameterWithinItsBound(typeParameters[i], substitutor, typeElement.getType(), typeElement, referenceParameterList);
|
||||
if (myVisitor.hasErrorResults()) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkTypeParameterWithinItsBound(@NotNull PsiTypeParameter classParameter,
|
||||
@NotNull PsiSubstitutor substitutor,
|
||||
@NotNull PsiType type,
|
||||
@NotNull PsiTypeElement typeElement2Highlight,
|
||||
@Nullable PsiReferenceParameterList referenceParameterList) {
|
||||
PsiClass referenceClass = type instanceof PsiClassType classType ? classType.resolve() : null;
|
||||
PsiType psiType = substitutor.substitute(classParameter);
|
||||
if (psiType instanceof PsiClassType && !(PsiUtil.resolveClassInType(psiType) instanceof PsiTypeParameter)) {
|
||||
if (GenericsUtil.checkNotInBounds(type, psiType, referenceParameterList)) {
|
||||
myVisitor.report(JavaErrorKinds.TYPE_PARAMETER_ACTUAL_INFERRED_MISMATCH.create(typeElement2Highlight));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PsiClassType[] bounds = classParameter.getSuperTypes();
|
||||
for (PsiType bound : bounds) {
|
||||
bound = substitutor.substitute(bound);
|
||||
if (!bound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) && GenericsUtil.checkNotInBounds(type, bound, referenceParameterList)) {
|
||||
PsiClass boundClass = bound instanceof PsiClassType classType ? classType.resolve() : null;
|
||||
|
||||
boolean extend = boundClass == null ||
|
||||
referenceClass == null ||
|
||||
referenceClass.isInterface() == boundClass.isInterface() ||
|
||||
referenceClass instanceof PsiTypeParameter;
|
||||
var kind = extend
|
||||
? JavaErrorKinds.TYPE_PARAMETER_TYPE_NOT_WITHIN_EXTEND_BOUND
|
||||
: JavaErrorKinds.TYPE_PARAMETER_TYPE_NOT_WITHIN_IMPLEMENT_BOUND;
|
||||
myVisitor.report(kind.create(typeElement2Highlight, new JavaErrorKinds.TypeParameterBoundMismatchContext(
|
||||
classParameter, bound, type)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiType detectExpectedType(@NotNull PsiReferenceParameterList referenceParameterList) {
|
||||
PsiNewExpression newExpression = Objects.requireNonNull(PsiTreeUtil.getParentOfType(referenceParameterList, PsiNewExpression.class));
|
||||
PsiElement parent = newExpression.getParent();
|
||||
PsiType expectedType = null;
|
||||
if (parent instanceof PsiVariable psiVariable && newExpression.equals(psiVariable.getInitializer())) {
|
||||
expectedType = psiVariable.getType();
|
||||
}
|
||||
else if (parent instanceof PsiAssignmentExpression expression && newExpression.equals(expression.getRExpression())) {
|
||||
expectedType = expression.getLExpression().getType();
|
||||
}
|
||||
else if (parent instanceof PsiReturnStatement) {
|
||||
PsiElement method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class, PsiLambdaExpression.class);
|
||||
if (method instanceof PsiMethod psiMethod) {
|
||||
expectedType = psiMethod.getReturnType();
|
||||
}
|
||||
}
|
||||
else if (parent instanceof PsiExpressionList) {
|
||||
PsiElement pParent = parent.getParent();
|
||||
if (pParent instanceof PsiCallExpression callExpression) {
|
||||
PsiExpressionList argumentList = callExpression.getArgumentList();
|
||||
if (parent.equals(argumentList)) {
|
||||
PsiMethod method = callExpression.resolveMethod();
|
||||
if (method != null) {
|
||||
PsiExpression[] expressions = argumentList.getExpressions();
|
||||
int idx = ArrayUtilRt.find(expressions, newExpression);
|
||||
if (idx > -1) {
|
||||
PsiParameter parameter = method.getParameterList().getParameter(idx);
|
||||
if (parameter != null) {
|
||||
expectedType = parameter.getType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return expectedType;
|
||||
}
|
||||
|
||||
private static boolean hasSuperMethodsWithTypeParams(@NotNull PsiMethod method) {
|
||||
for (PsiMethod superMethod : method.findDeepestSuperMethods()) {
|
||||
if (superMethod.hasTypeParameters()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -178,4 +178,9 @@ final class JavaErrorFormatUtil {
|
||||
if (element instanceof PsiLabeledStatement statement) return statement.getName() + ':';
|
||||
return ElementDescriptionUtil.getElementDescription(element, HighlightUsagesDescriptionLocation.INSTANCE);
|
||||
}
|
||||
|
||||
static @NotNull String formatClassOrType(@NotNull PsiType type) {
|
||||
PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(type);
|
||||
return psiClass == null ? type.getPresentableText() : formatClass(psiClass);
|
||||
}
|
||||
}
|
||||
|
||||
+48
@@ -385,6 +385,41 @@ public final class JavaErrorKinds {
|
||||
parameterized(PsiMethodCallExpression.class, IncompatibleIntersectionContext.class, "type.parameter.incompatible.upper.bounds")
|
||||
.withRange((call, ctx) -> getRange(call))
|
||||
.withRawDescription((call, ctx) -> message("type.parameter.incompatible.upper.bounds", ctx.parameter().getName(), ctx.message()));
|
||||
public static final Parameterized<PsiMethodCallExpression, TypeParameterBoundMismatchContext>
|
||||
TYPE_PARAMETER_INFERRED_TYPE_NOT_WITHIN_EXTEND_BOUND =
|
||||
parameterized(PsiMethodCallExpression.class, TypeParameterBoundMismatchContext.class,
|
||||
"type.parameter.inferred.type.not.within.extend.bound")
|
||||
.withRawDescription((call, ctx) -> message("type.parameter.inferred.type.not.within.extend.bound", formatClass(ctx.parameter()),
|
||||
formatType(ctx.bound()), formatType(ctx.actualType())));
|
||||
public static final Parameterized<PsiMethodCallExpression, TypeParameterBoundMismatchContext>
|
||||
TYPE_PARAMETER_INFERRED_TYPE_NOT_WITHIN_IMPLEMENT_BOUND =
|
||||
parameterized(PsiMethodCallExpression.class, TypeParameterBoundMismatchContext.class,
|
||||
"type.parameter.inferred.type.not.within.implement.bound")
|
||||
.withRawDescription((call, ctx) -> message("type.parameter.inferred.type.not.within.implement.bound", formatClass(ctx.parameter()),
|
||||
formatType(ctx.bound()), formatType(ctx.actualType())));
|
||||
public static final Parameterized<PsiTypeElement, TypeParameterBoundMismatchContext> TYPE_PARAMETER_TYPE_NOT_WITHIN_EXTEND_BOUND =
|
||||
parameterized(PsiTypeElement.class, TypeParameterBoundMismatchContext.class, "type.parameter.type.not.within.extend.bound")
|
||||
.withRawDescription((call, ctx) -> message("type.parameter.type.not.within.extend.bound",
|
||||
formatClassOrType(ctx.actualType()),
|
||||
formatType(ctx.bound())));
|
||||
public static final Parameterized<PsiTypeElement, TypeParameterBoundMismatchContext> TYPE_PARAMETER_TYPE_NOT_WITHIN_IMPLEMENT_BOUND =
|
||||
parameterized(PsiTypeElement.class, TypeParameterBoundMismatchContext.class, "type.parameter.type.not.within.implement.bound")
|
||||
.withRawDescription((call, ctx) -> message("type.parameter.type.not.within.implement.bound",
|
||||
formatClassOrType(ctx.actualType()),
|
||||
formatType(ctx.bound())));
|
||||
public static final Parameterized<PsiReferenceParameterList, PsiClass> TYPE_PARAMETER_ABSENT_CLASS =
|
||||
parameterized(PsiReferenceParameterList.class, PsiClass.class, "type.parameter.absent.class")
|
||||
.withRawDescription((list, cls) -> message("type.parameter.absent.class", formatClass(cls)));
|
||||
public static final Parameterized<PsiReferenceParameterList, PsiMethod> TYPE_PARAMETER_ABSENT_METHOD =
|
||||
parameterized(PsiReferenceParameterList.class, PsiMethod.class, "type.parameter.absent.method")
|
||||
.withRawDescription((list, method) -> message("type.parameter.absent.method", formatMethod(method)));
|
||||
public static final Parameterized<PsiReferenceParameterList, PsiTypeParameterListOwner> TYPE_PARAMETER_COUNT_MISMATCH =
|
||||
parameterized(PsiReferenceParameterList.class, PsiTypeParameterListOwner.class, "type.parameter.count.mismatch")
|
||||
.withRawDescription((list, owner) -> message("type.parameter.count.mismatch", list.getTypeArgumentCount(),
|
||||
owner.getTypeParameters().length));
|
||||
public static final Simple<PsiTypeElement> TYPE_PARAMETER_ACTUAL_INFERRED_MISMATCH = error("type.parameter.actual.inferred.mismatch");
|
||||
public static final Simple<PsiReferenceParameterList> NEW_EXPRESSION_DIAMOND_NOT_APPLICABLE =
|
||||
error("new.expression.diamond.not.applicable");
|
||||
|
||||
public static final Simple<PsiMethod> METHOD_DUPLICATE =
|
||||
error(PsiMethod.class, "method.duplicate")
|
||||
@@ -567,6 +602,13 @@ public final class JavaErrorKinds {
|
||||
error("new.expression.qualified.qualified.class.reference");
|
||||
public static final Simple<PsiReferenceParameterList> NEW_EXPRESSION_DIAMOND_NOT_ALLOWED =
|
||||
error("new.expression.diamond.not.allowed");
|
||||
public static final Simple<PsiReferenceParameterList> NEW_EXPRESSION_DIAMOND_ANONYMOUS_INNER_NON_PRIVATE =
|
||||
error("new.expression.diamond.anonymous.inner.non.private");
|
||||
public static final Parameterized<PsiReferenceParameterList, PsiDiamondType.DiamondInferenceResult>
|
||||
NEW_EXPRESSION_DIAMOND_INFERENCE_FAILURE =
|
||||
parameterized(PsiReferenceParameterList.class, PsiDiamondType.DiamondInferenceResult.class, "new.expression.diamond.inference.failure")
|
||||
.withRawDescription(
|
||||
(list, inferenceResult) -> message("new.expression.diamond.inference.failure", inferenceResult.getErrorMessage()));
|
||||
|
||||
public static final Parameterized<PsiReferenceParameterList, PsiClass> REFERENCE_TYPE_ARGUMENT_STATIC_CLASS =
|
||||
parameterized(PsiReferenceParameterList.class, PsiClass.class, "reference.type.argument.static.class")
|
||||
@@ -764,4 +806,10 @@ public final class JavaErrorKinds {
|
||||
}
|
||||
|
||||
public record IncompatibleIntersectionContext(@NotNull PsiTypeParameter parameter, @NotNull @Nls String message) {}
|
||||
|
||||
public record TypeParameterBoundMismatchContext(@NotNull PsiTypeParameter parameter,
|
||||
@NotNull PsiType bound,
|
||||
@NotNull PsiType actualType) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+3
-68
@@ -11,7 +11,6 @@ import com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper;
|
||||
import com.intellij.core.JavaPsiBundle;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.openapi.roots.FileIndexFacade;
|
||||
@@ -26,7 +25,6 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiClassImplUtil;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
@@ -45,33 +43,6 @@ public final class GenericsHighlightUtil {
|
||||
|
||||
private GenericsHighlightUtil() { }
|
||||
|
||||
static HighlightInfo.Builder checkInferredTypeArguments(@NotNull PsiTypeParameterListOwner listOwner,
|
||||
@NotNull PsiElement call,
|
||||
@NotNull PsiSubstitutor substitutor) {
|
||||
PsiTypeParameter[] typeParameters = listOwner.getTypeParameters();
|
||||
Pair<PsiTypeParameter, PsiType> inferredTypeArgument = GenericsUtil.findTypeParameterWithBoundError(typeParameters, substitutor,
|
||||
call, false);
|
||||
if (inferredTypeArgument != null) {
|
||||
PsiType extendsType = inferredTypeArgument.second;
|
||||
PsiTypeParameter typeParameter = inferredTypeArgument.first;
|
||||
PsiClass boundClass = extendsType instanceof PsiClassType classType ? classType.resolve() : null;
|
||||
|
||||
@NonNls String messageKey = boundClass == null || typeParameter.isInterface() == boundClass.isInterface()
|
||||
? "generics.inferred.type.for.type.parameter.is.not.within.its.bound.extend"
|
||||
: "generics.inferred.type.for.type.parameter.is.not.within.its.bound.implement";
|
||||
|
||||
String description = JavaErrorBundle.message(
|
||||
messageKey,
|
||||
HighlightUtil.formatClass(typeParameter),
|
||||
JavaHighlightUtil.formatType(extendsType),
|
||||
JavaHighlightUtil.formatType(substitutor.substitute(typeParameter))
|
||||
);
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(call).descriptionAndTooltip(description);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static HighlightInfo.Builder checkParameterizedReferenceTypeArguments(@Nullable PsiElement resolved,
|
||||
@NotNull PsiJavaCodeReferenceElement referenceElement,
|
||||
@NotNull PsiSubstitutor substitutor,
|
||||
@@ -169,7 +140,7 @@ public final class GenericsHighlightUtil {
|
||||
.highPriority(QuickFixFactory.getInstance().createDeleteFix(referenceParameterList));
|
||||
builder.registerFix(action, null, null, null, null);
|
||||
}
|
||||
registerVariableParameterizedTypeFixes(builder, (PsiVariable)variable, referenceParameterList, javaSdkVersion);
|
||||
HighlightFixUtil.registerVariableParameterizedTypeFixes(HighlightUtil.asConsumer(builder), (PsiVariable)variable, referenceParameterList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -333,8 +304,8 @@ public final class GenericsHighlightUtil {
|
||||
if (aClass instanceof PsiTypeParameter) {
|
||||
HighlightInfo.Builder info =
|
||||
HighlightMethodUtil.checkMethodIncompatibleReturnType(signature, signature.getSuperSignatures(), true,
|
||||
HighlightNamesUtil.getClassDeclarationTextRange(aClass),
|
||||
null);
|
||||
HighlightNamesUtil.getClassDeclarationTextRange(aClass)
|
||||
);
|
||||
if (info != null) {
|
||||
overrideEquivalentMethodsErrors.put(aClass, info);
|
||||
}
|
||||
@@ -1076,42 +1047,6 @@ public final class GenericsHighlightUtil {
|
||||
return containingClass != null && PsiUtil.typeParametersIterator(containingClass).hasNext();
|
||||
}
|
||||
|
||||
private static void registerVariableParameterizedTypeFixes(@Nullable HighlightInfo.Builder builder,
|
||||
@NotNull PsiVariable variable,
|
||||
@NotNull PsiReferenceParameterList parameterList,
|
||||
@NotNull JavaSdkVersion version) {
|
||||
PsiType type = variable.getType();
|
||||
if (!(type instanceof PsiClassType classType) || builder == null) return;
|
||||
|
||||
if (DumbService.getInstance(variable.getProject()).isDumb()) return;
|
||||
|
||||
String shortName = classType.getClassName();
|
||||
PsiManager manager = parameterList.getManager();
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
|
||||
PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(parameterList.getProject());
|
||||
PsiClass[] classes = shortNamesCache.getClassesByName(shortName, GlobalSearchScope.allScope(manager.getProject()));
|
||||
PsiElementFactory factory = facade.getElementFactory();
|
||||
for (PsiClass aClass : classes) {
|
||||
if (aClass == null) {
|
||||
LOG.error("null class returned for " + shortName);
|
||||
continue;
|
||||
}
|
||||
if (checkReferenceTypeArgumentList(aClass, parameterList, PsiSubstitutor.EMPTY, false, version) == null) {
|
||||
PsiType[] actualTypeParameters = parameterList.getTypeArguments();
|
||||
PsiTypeParameter[] classTypeParameters = aClass.getTypeParameters();
|
||||
Map<PsiTypeParameter, PsiType> map = new HashMap<>();
|
||||
for (int j = 0; j < Math.min(classTypeParameters.length, actualTypeParameters.length); j++) {
|
||||
PsiTypeParameter classTypeParameter = classTypeParameters[j];
|
||||
PsiType actualTypeParameter = actualTypeParameters[j];
|
||||
map.put(classTypeParameter, actualTypeParameter);
|
||||
}
|
||||
PsiSubstitutor substitutor = factory.createSubstitutor(map);
|
||||
PsiType suggestedType = factory.createType(aClass, substitutor);
|
||||
HighlightFixUtil.registerChangeVariableTypeFixes(variable, suggestedType, variable.getInitializer(), builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static HighlightInfo.Builder checkMemberSignatureTypesAccessibility(@NotNull PsiReferenceExpression ref) {
|
||||
String message = null;
|
||||
|
||||
|
||||
+44
-5
@@ -14,11 +14,16 @@ import com.intellij.lang.jvm.actions.JvmElementActionFactories;
|
||||
import com.intellij.lang.jvm.actions.MemberRequestsKt;
|
||||
import com.intellij.lang.jvm.util.JvmUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -31,10 +36,7 @@ import com.siyeh.ig.psiutils.VariableAccessUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class HighlightFixUtil {
|
||||
@@ -713,7 +715,7 @@ public final class HighlightFixUtil {
|
||||
}
|
||||
}
|
||||
|
||||
static void registerCallInferenceFixes(@NotNull PsiMethodCallExpression callExpression, @NotNull Consumer<CommonIntentionAction> info) {
|
||||
static void registerCallInferenceFixes(@NotNull PsiMethodCallExpression callExpression, @NotNull Consumer<? super CommonIntentionAction> info) {
|
||||
JavaResolveResult result = callExpression.getMethodExpression().advancedResolve(true);
|
||||
if (!(result instanceof MethodCandidateInfo resolveResult)) return;
|
||||
PsiMethod method = resolveResult.getElement();
|
||||
@@ -749,4 +751,41 @@ public final class HighlightFixUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void registerVariableParameterizedTypeFixes(@NotNull Consumer<? super CommonIntentionAction> info,
|
||||
@NotNull PsiVariable variable,
|
||||
@NotNull PsiReferenceParameterList parameterList) {
|
||||
PsiType type = variable.getType();
|
||||
if (!(type instanceof PsiClassType classType)) return;
|
||||
|
||||
if (DumbService.getInstance(variable.getProject()).isDumb()) return;
|
||||
|
||||
String shortName = classType.getClassName();
|
||||
PsiFile file = parameterList.getContainingFile();
|
||||
Project project = file.getProject();
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(project);
|
||||
PsiClass[] classes = shortNamesCache.getClassesByName(shortName, GlobalSearchScope.allScope(project));
|
||||
PsiElementFactory factory = facade.getElementFactory();
|
||||
JavaSdkVersion version = Objects.requireNonNullElse(JavaVersionService.getInstance().getJavaSdkVersion(file),
|
||||
JavaSdkVersion.fromLanguageLevel(PsiUtil.getLanguageLevel(file)));
|
||||
for (PsiClass aClass : classes) {
|
||||
if (aClass == null) {
|
||||
continue;
|
||||
}
|
||||
if (GenericsHighlightUtil.checkReferenceTypeArgumentList(aClass, parameterList, PsiSubstitutor.EMPTY, false, version) == null) {
|
||||
PsiType[] actualTypeParameters = parameterList.getTypeArguments();
|
||||
PsiTypeParameter[] classTypeParameters = aClass.getTypeParameters();
|
||||
Map<PsiTypeParameter, PsiType> map = new HashMap<>();
|
||||
for (int j = 0; j < Math.min(classTypeParameters.length, actualTypeParameters.length); j++) {
|
||||
PsiTypeParameter classTypeParameter = classTypeParameters[j];
|
||||
PsiType actualTypeParameter = actualTypeParameters[j];
|
||||
map.put(classTypeParameter, actualTypeParameter);
|
||||
}
|
||||
PsiSubstitutor substitutor = factory.createSubstitutor(map);
|
||||
PsiType suggestedType = factory.createType(aClass, substitutor);
|
||||
registerChangeVariableTypeFixes(variable, suggestedType, variable.getInitializer(), info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-54
@@ -80,7 +80,7 @@ public final class HighlightMethodUtil {
|
||||
static HighlightInfo.Builder checkMethodIncompatibleReturnType(@NotNull MethodSignatureBackedByPsiMethod methodSignature,
|
||||
@NotNull List<? extends HierarchicalMethodSignature> superMethodSignatures,
|
||||
boolean includeRealPositionInfo,
|
||||
@Nullable TextRange textRange, @Nullable Ref<? super String> description) {
|
||||
@Nullable TextRange textRange) {
|
||||
PsiMethod method = methodSignature.getMethod();
|
||||
PsiType returnType = methodSignature.getSubstitutor().substitute(method.getReturnType());
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
@@ -104,7 +104,7 @@ public final class HighlightMethodUtil {
|
||||
}
|
||||
HighlightInfo.Builder info = checkSuperMethodSignature(
|
||||
superMethod, superMethodSignature, superReturnType, method, methodSignature, returnType,
|
||||
textRange, PsiUtil.getLanguageLevel(aClass), description);
|
||||
textRange, PsiUtil.getLanguageLevel(aClass));
|
||||
if (info != null) {
|
||||
return info;
|
||||
}
|
||||
@@ -120,8 +120,7 @@ public final class HighlightMethodUtil {
|
||||
@NotNull MethodSignatureBackedByPsiMethod methodSignature,
|
||||
@NotNull PsiType returnType,
|
||||
@NotNull TextRange range,
|
||||
@NotNull LanguageLevel languageLevel,
|
||||
@Nullable Ref<? super String> description) {
|
||||
@NotNull LanguageLevel languageLevel) {
|
||||
PsiClass superContainingClass = superMethod.getContainingClass();
|
||||
if (superContainingClass != null &&
|
||||
CommonClassNames.JAVA_LANG_OBJECT.equals(superContainingClass.getQualifiedName()) &&
|
||||
@@ -155,20 +154,17 @@ public final class HighlightMethodUtil {
|
||||
}
|
||||
|
||||
return createIncompatibleReturnTypeMessage(method, superMethod, substitutedSuperReturnType, returnType,
|
||||
JavaErrorBundle.message("incompatible.return.type"), range,
|
||||
description);
|
||||
JavaErrorBundle.message("incompatible.return.type"), range
|
||||
);
|
||||
}
|
||||
|
||||
private static @NotNull HighlightInfo.Builder createIncompatibleReturnTypeMessage(@NotNull PsiMethod method,
|
||||
private static HighlightInfo.@NotNull Builder createIncompatibleReturnTypeMessage(@NotNull PsiMethod method,
|
||||
@NotNull PsiMethod superMethod,
|
||||
@NotNull PsiType substitutedSuperReturnType,
|
||||
@NotNull PsiType returnType,
|
||||
@NotNull @Nls String detailMessage,
|
||||
@NotNull TextRange textRange, @Nullable Ref<? super String> descriptionH) {
|
||||
@NotNull TextRange textRange) {
|
||||
String description = MessageFormat.format("{0}; {1}", createClashMethodMessage(method, superMethod, true), detailMessage);
|
||||
if (descriptionH != null) {
|
||||
descriptionH.set(description);
|
||||
}
|
||||
HighlightInfo.Builder errorResult =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description);
|
||||
if (method instanceof LightRecordMethod recordMethod) {
|
||||
@@ -193,49 +189,6 @@ public final class HighlightMethodUtil {
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
|
||||
static void checkMethodCall(@NotNull PsiMethodCallExpression methodCall,
|
||||
@NotNull PsiResolveHelper resolveHelper,
|
||||
@NotNull JavaSdkVersion javaSdkVersion,
|
||||
@NotNull Consumer<? super HighlightInfo.Builder> errorSink) {
|
||||
PsiExpressionList list = methodCall.getArgumentList();
|
||||
PsiReferenceExpression referenceToMethod = methodCall.getMethodExpression();
|
||||
JavaResolveResult[] results = referenceToMethod.multiResolve(true);
|
||||
JavaResolveResult resolveResult = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
|
||||
boolean isDummy = isDummyConstructorCall(methodCall, resolveHelper, list, referenceToMethod);
|
||||
if (isDummy) return;
|
||||
HighlightInfo.Builder builder = null;
|
||||
|
||||
PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
if (!(resolved instanceof PsiMethod) || !resolveResult.isValidResult()) {
|
||||
MethodCandidateInfo candidateInfo = resolveResult instanceof MethodCandidateInfo ? (MethodCandidateInfo)resolveResult : null;
|
||||
PsiMethod resolvedMethod = candidateInfo != null ? candidateInfo.getElement() : null;
|
||||
|
||||
if (resolveResult.isAccessible() && resolveResult.isStaticsScopeCorrect()) {
|
||||
if (candidateInfo != null && !candidateInfo.isApplicable()) {
|
||||
if (!candidateInfo.isTypeArgumentsApplicable()) {
|
||||
PsiReferenceParameterList typeArgumentList = methodCall.getTypeArgumentList();
|
||||
PsiSubstitutor applicabilitySubstitutor = candidateInfo.getSubstitutor(false);
|
||||
if (typeArgumentList.getTypeArguments().length == 0 && resolvedMethod.hasTypeParameters()) {
|
||||
builder = GenericsHighlightUtil.checkInferredTypeArguments(resolvedMethod, methodCall, applicabilitySubstitutor);
|
||||
}
|
||||
else {
|
||||
builder = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, referenceToMethod, applicabilitySubstitutor, javaSdkVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (builder == null) {
|
||||
builder = GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, referenceToMethod, substitutor, javaSdkVersion);
|
||||
}
|
||||
if (builder != null) {
|
||||
errorSink.accept(builder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* collect highlightInfos per each wrong argument; fixes would be set for the first one with fixRange: methodCall
|
||||
* @return highlight info for the first wrong arg expression
|
||||
|
||||
-9
@@ -770,15 +770,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
@Override
|
||||
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
|
||||
visitElement(expression);
|
||||
if (!hasErrorResults()) {
|
||||
try {
|
||||
HighlightMethodUtil.checkMethodCall(expression, getResolveHelper(), myJavaSdkVersion,
|
||||
myErrorSink);
|
||||
}
|
||||
catch (IndexNotReadyException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasErrorResults()) add(HighlightMethodUtil.checkConstructorCallProblems(expression));
|
||||
if (!hasErrorResults()) add(HighlightMethodUtil.checkSuperAbstractMethodDirectCall(expression));
|
||||
|
||||
|
||||
+36
-1
@@ -23,6 +23,7 @@ import com.intellij.lang.jvm.actions.MemberRequestsKt;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.impl.light.LightRecordMethod;
|
||||
@@ -80,7 +81,7 @@ final class JavaErrorFixProvider {
|
||||
CLASS_IMPLICIT_INITIALIZER, CLASS_IMPLICIT_PACKAGE,
|
||||
RECORD_EXTENDS, ENUM_EXTENDS, RECORD_PERMITS, ENUM_PERMITS, ANNOTATION_PERMITS,
|
||||
NEW_EXPRESSION_DIAMOND_NOT_ALLOWED, REFERENCE_TYPE_ARGUMENT_STATIC_CLASS,
|
||||
STATEMENT_CASE_OUTSIDE_SWITCH)) {
|
||||
STATEMENT_CASE_OUTSIDE_SWITCH, NEW_EXPRESSION_DIAMOND_NOT_APPLICABLE)) {
|
||||
fix(kind, genericRemover);
|
||||
}
|
||||
|
||||
@@ -241,6 +242,40 @@ final class JavaErrorFixProvider {
|
||||
fix(NEW_EXPRESSION_QUALIFIED_ANONYMOUS_IMPLEMENTS_INTERFACE, error -> myFactory.createRemoveNewQualifierFix(error.psi(), null));
|
||||
fix(NEW_EXPRESSION_QUALIFIED_QUALIFIED_CLASS_REFERENCE,
|
||||
error -> myFactory.createDeleteFix(error.psi(), QuickFixBundle.message("remove.qualifier.fix")));
|
||||
fix(NEW_EXPRESSION_DIAMOND_INFERENCE_FAILURE,
|
||||
error -> {
|
||||
if (error.context() == PsiDiamondType.DiamondInferenceResult.ANONYMOUS_INNER_RESULT &&
|
||||
!PsiUtil.isLanguageLevel9OrHigher(error.psi())) {
|
||||
return myFactory.createIncreaseLanguageLevelFix(LanguageLevel.JDK_1_9);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
fix(TYPE_PARAMETER_ABSENT_CLASS, error -> myFactory.createChangeClassSignatureFromUsageFix(error.context(), error.psi()));
|
||||
fix(TYPE_PARAMETER_COUNT_MISMATCH,
|
||||
error -> error.context() instanceof PsiClass cls ? myFactory.createChangeClassSignatureFromUsageFix(cls, error.psi()) : null);
|
||||
JavaFixProvider<PsiTypeElement, TypeParameterBoundMismatchContext> addBoundFix = error -> {
|
||||
if (error.context().bound() instanceof PsiClassType bound) {
|
||||
PsiClass psiClass = bound.resolve();
|
||||
if (psiClass != null) {
|
||||
return myFactory.createExtendsListFix(psiClass, bound, true);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
fix(TYPE_PARAMETER_TYPE_NOT_WITHIN_EXTEND_BOUND, addBoundFix);
|
||||
fix(TYPE_PARAMETER_TYPE_NOT_WITHIN_IMPLEMENT_BOUND, addBoundFix);
|
||||
multi(TYPE_PARAMETER_ABSENT_CLASS, error -> {
|
||||
PsiReferenceParameterList referenceParameterList = error.psi();
|
||||
PsiElement grandParent = referenceParameterList.getParent().getParent();
|
||||
if (!(grandParent instanceof PsiTypeElement)) return List.of();
|
||||
if (!(PsiTreeUtil.skipParentsOfType(grandParent, PsiTypeElement.class) instanceof PsiVariable variable)) return List.of();
|
||||
List<CommonIntentionAction> registrar = new ArrayList<>();
|
||||
if (error.context().getTypeParameters().length == 0) {
|
||||
registrar.add(PriorityIntentionActionWrapper.highPriority(myFactory.createDeleteFix(referenceParameterList)));
|
||||
}
|
||||
HighlightFixUtil.registerVariableParameterizedTypeFixes(registrar::add, variable, referenceParameterList);
|
||||
return registrar;
|
||||
});
|
||||
fix(LITERAL_CHARACTER_TOO_LONG, error -> myFactory.createConvertToStringLiteralAction());
|
||||
fix(LITERAL_CHARACTER_EMPTY, error -> myFactory.createConvertToStringLiteralAction());
|
||||
fix(PATTERN_TYPE_PATTERN_EXPECTED, error -> {
|
||||
|
||||
@@ -12,8 +12,6 @@ annotation.not.allowed.in.permit.list=Annotations not allowed in 'permits' list
|
||||
generics.holder.type=Type
|
||||
generics.holder.method=Method
|
||||
|
||||
generics.inferred.type.for.type.parameter.is.not.within.its.bound.extend=Inferred type ''{2}'' for type parameter ''{0}'' is not within its bound; should extend ''{1}''
|
||||
generics.inferred.type.for.type.parameter.is.not.within.its.bound.implement=Inferred type ''{2}'' for type parameter ''{0}'' is not within its bound; should implement ''{1}''
|
||||
generics.type.parameter.is.not.within.its.bound.extend=Type parameter ''{0}'' is not within its bound; should extend ''{1}''
|
||||
generics.type.parameter.is.not.within.its.bound.implement=Type parameter ''{0}'' is not within its bound; should implement ''{1}''
|
||||
|
||||
|
||||
Reference in New Issue
Block a user