mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-highlighting] Remaining constructor-related fixes migrated
Temporarily moved the rest of HighlightMethodUtil methods to more relevant places Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only) GitOrigin-RevId: 8e3ba89a775de934292709778b78965c45d162d9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
577de68f8a
commit
0eeed91d22
@@ -207,6 +207,7 @@ clash.methods.message.show.classes=''{0}'' in ''{2}'' clashes with ''{1}'' in ''
|
||||
|
||||
constructor.ambiguous.implicit.call=Ambiguous implicit constructor call: both ''{0}'' and ''{1}'' match
|
||||
constructor.no.default=There is no parameterless constructor available in ''{0}''
|
||||
constructor.in.implicit.class=Explicit constructor in implicitly declared class is not allowed
|
||||
|
||||
type.incompatible=Incompatible types. Found: ''{1}'', required: ''{0}''
|
||||
type.incompatible.tooltip.required.type=Required type:
|
||||
|
||||
+2
@@ -1176,6 +1176,8 @@ final class JavaErrorVisitor extends JavaElementVisitor {
|
||||
}
|
||||
if (!hasErrorResults()) myRecordChecker.checkRecordAccessorDeclaration(method);
|
||||
if (!hasErrorResults()) myRecordChecker.checkRecordConstructorDeclaration(method);
|
||||
if (!hasErrorResults()) myMethodChecker.checkConstructorInImplicitClass(method);
|
||||
if (!hasErrorResults()) myMethodChecker.checkConstructorHandleSuperClassExceptions(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+18
@@ -429,6 +429,24 @@ final class MethodChecker {
|
||||
}
|
||||
}
|
||||
|
||||
void checkConstructorInImplicitClass(@NotNull PsiMethod method) {
|
||||
if (!method.isConstructor() || !(method.getContainingClass() instanceof PsiImplicitClass)) return;
|
||||
myVisitor.report(JavaErrorKinds.CONSTRUCTOR_IN_IMPLICIT_CLASS.create(method));
|
||||
}
|
||||
|
||||
void checkConstructorHandleSuperClassExceptions(@NotNull PsiMethod method) {
|
||||
if (!method.isConstructor()) return;
|
||||
PsiCodeBlock body = method.getBody();
|
||||
PsiStatement[] statements = body == null ? null : body.getStatements();
|
||||
if (statements == null) return;
|
||||
|
||||
// if we have unhandled exception inside the method body, we could not have been called here,
|
||||
// so the only problem it can catch here is with super ctr only
|
||||
Collection<PsiClassType> unhandled = ExceptionUtil.collectUnhandledExceptions(method, method.getContainingClass());
|
||||
if (unhandled.isEmpty()) return;
|
||||
myVisitor.report(JavaErrorKinds.EXCEPTION_UNHANDLED.create(method, unhandled));
|
||||
}
|
||||
|
||||
static @Nullable TextRange getCStyleDeclarationRange(@NotNull PsiVariable variable) {
|
||||
PsiIdentifier identifier = variable.getNameIdentifier();
|
||||
TextRange range = null;
|
||||
|
||||
+3
@@ -650,6 +650,9 @@ public final class JavaErrorKinds {
|
||||
parameterized(PsiMember.class, PsiClass.class, "constructor.no.default")
|
||||
.withRawDescription((member, cls) -> message("constructor.no.default", formatClass(requireNonNull(cls))))
|
||||
.withRange((member, ctx) -> getMemberDeclarationTextRange(member));
|
||||
public static final Simple<PsiMethod> CONSTRUCTOR_IN_IMPLICIT_CLASS =
|
||||
error(PsiMethod.class, "constructor.in.implicit.class")
|
||||
.withRange(JavaErrorFormatUtil::getMemberDeclarationTextRange);
|
||||
|
||||
public static final Parameterized<PsiElement, Collection<PsiClassType>> EXCEPTION_UNHANDLED =
|
||||
error(PsiElement.class, "exception.unhandled")
|
||||
|
||||
+137
-2
@@ -20,6 +20,7 @@ import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiClassImplUtil;
|
||||
import com.intellij.psi.impl.light.LightRecordMethod;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
@@ -29,6 +30,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -149,7 +151,7 @@ public final class GenericsHighlightUtil {
|
||||
}
|
||||
if (aClass instanceof PsiTypeParameter) {
|
||||
HighlightInfo.Builder info =
|
||||
HighlightMethodUtil.checkMethodIncompatibleReturnType(signature, signature.getSuperSignatures(), true,
|
||||
checkMethodIncompatibleReturnType(signature, signature.getSuperSignatures(), true,
|
||||
HighlightNamesUtil.getClassDeclarationTextRange(aClass)
|
||||
);
|
||||
if (info != null) {
|
||||
@@ -398,7 +400,7 @@ public final class GenericsHighlightUtil {
|
||||
method.hasModifierProperty(PsiModifier.STATIC) ?
|
||||
"generics.methods.have.same.erasure.hide" :
|
||||
"generics.methods.have.same.erasure.override";
|
||||
String description = JavaErrorBundle.message(key, HighlightMethodUtil.createClashMethodMessage(method, superMethod, !sameClass));
|
||||
String description = JavaErrorBundle.message(key, createClashMethodMessage(method, superMethod, !sameClass));
|
||||
HighlightInfo.Builder info =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description);
|
||||
if (!(method instanceof SyntheticElement)) {
|
||||
@@ -519,4 +521,137 @@ public final class GenericsHighlightUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static @NotNull @NlsContexts.DetailedDescription String createClashMethodMessage(@NotNull PsiMethod method1,
|
||||
@NotNull PsiMethod method2,
|
||||
boolean showContainingClasses) {
|
||||
if (showContainingClasses) {
|
||||
PsiClass class1 = method1.getContainingClass();
|
||||
PsiClass class2 = method2.getContainingClass();
|
||||
if (class1 != null && class2 != null) {
|
||||
return JavaErrorBundle.message("clash.methods.message.show.classes",
|
||||
JavaHighlightUtil.formatMethod(method1),
|
||||
JavaHighlightUtil.formatMethod(method2),
|
||||
HighlightUtil.formatClass(class1),
|
||||
HighlightUtil.formatClass(class2));
|
||||
}
|
||||
}
|
||||
|
||||
return JavaErrorBundle.message("clash.methods.message",
|
||||
JavaHighlightUtil.formatMethod(method1),
|
||||
JavaHighlightUtil.formatMethod(method2));
|
||||
}
|
||||
|
||||
private static HighlightInfo.Builder checkMethodIncompatibleReturnType(@NotNull MethodSignatureBackedByPsiMethod methodSignature,
|
||||
@NotNull List<? extends HierarchicalMethodSignature> superMethodSignatures,
|
||||
boolean includeRealPositionInfo,
|
||||
@Nullable TextRange textRange) {
|
||||
PsiMethod method = methodSignature.getMethod();
|
||||
PsiType returnType = methodSignature.getSubstitutor().substitute(method.getReturnType());
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) return null;
|
||||
for (MethodSignatureBackedByPsiMethod superMethodSignature : superMethodSignatures) {
|
||||
PsiMethod superMethod = superMethodSignature.getMethod();
|
||||
PsiType declaredReturnType = superMethod.getReturnType();
|
||||
PsiType superReturnType = declaredReturnType;
|
||||
if (superMethodSignature.isRaw()) superReturnType = TypeConversionUtil.erasure(declaredReturnType);
|
||||
if (returnType == null || superReturnType == null || method == superMethod) continue;
|
||||
PsiClass superClass = superMethod.getContainingClass();
|
||||
if (superClass == null) continue;
|
||||
if (textRange == null && includeRealPositionInfo) {
|
||||
PsiTypeElement typeElement = method.getReturnTypeElement();
|
||||
if (typeElement != null) {
|
||||
textRange = typeElement.getTextRange();
|
||||
}
|
||||
}
|
||||
if (textRange == null) {
|
||||
textRange = TextRange.EMPTY_RANGE;
|
||||
}
|
||||
HighlightInfo.Builder info = checkSuperMethodSignature(
|
||||
superMethod, superMethodSignature, superReturnType, method, methodSignature, returnType,
|
||||
textRange, PsiUtil.getLanguageLevel(aClass));
|
||||
if (info != null) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static HighlightInfo.Builder checkSuperMethodSignature(@NotNull PsiMethod superMethod,
|
||||
@NotNull MethodSignatureBackedByPsiMethod superMethodSignature,
|
||||
@NotNull PsiType superReturnType,
|
||||
@NotNull PsiMethod method,
|
||||
@NotNull MethodSignatureBackedByPsiMethod methodSignature,
|
||||
@NotNull PsiType returnType,
|
||||
@NotNull TextRange range,
|
||||
@NotNull LanguageLevel languageLevel) {
|
||||
PsiClass superContainingClass = superMethod.getContainingClass();
|
||||
if (superContainingClass != null &&
|
||||
CommonClassNames.JAVA_LANG_OBJECT.equals(superContainingClass.getQualifiedName()) &&
|
||||
!superMethod.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null && containingClass.isInterface() && !superContainingClass.isInterface()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
PsiType substitutedSuperReturnType;
|
||||
boolean hasGenerics = JavaFeature.GENERICS.isSufficient(languageLevel);
|
||||
if (hasGenerics && !superMethodSignature.isRaw() && superMethodSignature.equals(methodSignature)) { //see 8.4.5
|
||||
PsiSubstitutor unifyingSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature,
|
||||
superMethodSignature);
|
||||
substitutedSuperReturnType = unifyingSubstitutor == null
|
||||
? superReturnType
|
||||
: unifyingSubstitutor.substitute(superReturnType);
|
||||
}
|
||||
else {
|
||||
substitutedSuperReturnType = TypeConversionUtil.erasure(superMethodSignature.getSubstitutor().substitute(superReturnType));
|
||||
}
|
||||
|
||||
if (returnType.equals(substitutedSuperReturnType)) return null;
|
||||
if (!(returnType instanceof PsiPrimitiveType) && substitutedSuperReturnType.getDeepComponentType() instanceof PsiClassType) {
|
||||
if (hasGenerics && LambdaUtil.performWithSubstitutedParameterBounds(methodSignature.getTypeParameters(),
|
||||
methodSignature.getSubstitutor(),
|
||||
() -> TypeConversionUtil.isAssignable(substitutedSuperReturnType,
|
||||
returnType))) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return createIncompatibleReturnTypeMessage(method, superMethod, substitutedSuperReturnType, returnType,
|
||||
JavaErrorBundle.message("incompatible.return.type"), range
|
||||
);
|
||||
}
|
||||
|
||||
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) {
|
||||
String description = MessageFormat.format("{0}; {1}", createClashMethodMessage(method, superMethod, true), detailMessage);
|
||||
HighlightInfo.Builder errorResult =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description);
|
||||
if (method instanceof LightRecordMethod recordMethod) {
|
||||
for (IntentionAction fix :
|
||||
HighlightFixUtil.getChangeVariableTypeFixes(recordMethod.getRecordComponent(), substitutedSuperReturnType)) {
|
||||
errorResult.registerFix(fix, null, null, null, null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
IntentionAction action = QuickFixFactory.getInstance().createMethodReturnFix(method, substitutedSuperReturnType, false);
|
||||
errorResult.registerFix(action, null, null, null, null);
|
||||
}
|
||||
IntentionAction action1 = QuickFixFactory.getInstance().createSuperMethodReturnFix(superMethod, returnType);
|
||||
errorResult.registerFix(action1, null, null, null, null);
|
||||
PsiClass returnClass = PsiUtil.resolveClassInClassTypeOnly(returnType);
|
||||
if (returnClass != null && substitutedSuperReturnType instanceof PsiClassType) {
|
||||
IntentionAction action =
|
||||
QuickFixFactory.getInstance().createChangeParameterClassFix(returnClass, (PsiClassType)substitutedSuperReturnType);
|
||||
errorResult.registerFix(action, null, null, null, null);
|
||||
}
|
||||
|
||||
return errorResult;
|
||||
}
|
||||
}
|
||||
+11
-2
@@ -231,6 +231,15 @@ public final class HighlightControlFlowUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static @NotNull TextRange getFixRange(@NotNull PsiElement element) {
|
||||
PsiElement nextSibling = element.getNextSibling();
|
||||
TextRange range = element.getTextRange();
|
||||
if (PsiUtil.isJavaToken(nextSibling, JavaTokenType.SEMICOLON)) {
|
||||
return range.grown(1);
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
private static class ParamWriteProcessor implements Processor<PsiReference> {
|
||||
private volatile boolean myIsWriteRefFound;
|
||||
@Override
|
||||
@@ -300,9 +309,9 @@ public final class HighlightControlFlowUtil {
|
||||
TextRange range = HighlightNamesUtil.getFieldDeclarationTextRange(field);
|
||||
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description);
|
||||
IntentionAction action3 = getQuickFixFactory().createCreateConstructorParameterFromFieldFix(field);
|
||||
builder.registerFix(action3, null, null, HighlightMethodUtil.getFixRange(field), null);
|
||||
builder.registerFix(action3, null, null, getFixRange(field), null);
|
||||
IntentionAction action2 = getQuickFixFactory().createInitializeFinalFieldInConstructorFix(field);
|
||||
builder.registerFix(action2, null, null, HighlightMethodUtil.getFixRange(field), null);
|
||||
builder.registerFix(action2, null, null, getFixRange(field), null);
|
||||
IntentionAction action1 = getQuickFixFactory().createAddVariableInitializerFix(field);
|
||||
builder.registerFix(action1, null, null, null, null);
|
||||
PsiClass containingClass = field.getContainingClass();
|
||||
|
||||
-228
@@ -1,228 +0,0 @@
|
||||
// Copyright 2000-2025 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.ExceptionUtil;
|
||||
import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.codeInspection.LocalQuickFixOnPsiElementAsIntentionAdapter;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightRecordMethod;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public final class HighlightMethodUtil {
|
||||
|
||||
private HighlightMethodUtil() { }
|
||||
|
||||
static @NotNull @NlsContexts.DetailedDescription String createClashMethodMessage(@NotNull PsiMethod method1, @NotNull PsiMethod method2, boolean showContainingClasses) {
|
||||
if (showContainingClasses) {
|
||||
PsiClass class1 = method1.getContainingClass();
|
||||
PsiClass class2 = method2.getContainingClass();
|
||||
if (class1 != null && class2 != null) {
|
||||
return JavaErrorBundle.message("clash.methods.message.show.classes",
|
||||
JavaHighlightUtil.formatMethod(method1),
|
||||
JavaHighlightUtil.formatMethod(method2),
|
||||
HighlightUtil.formatClass(class1),
|
||||
HighlightUtil.formatClass(class2));
|
||||
}
|
||||
}
|
||||
|
||||
return JavaErrorBundle.message("clash.methods.message",
|
||||
JavaHighlightUtil.formatMethod(method1),
|
||||
JavaHighlightUtil.formatMethod(method2));
|
||||
}
|
||||
|
||||
|
||||
static HighlightInfo.Builder checkMethodIncompatibleReturnType(@NotNull MethodSignatureBackedByPsiMethod methodSignature,
|
||||
@NotNull List<? extends HierarchicalMethodSignature> superMethodSignatures,
|
||||
boolean includeRealPositionInfo,
|
||||
@Nullable TextRange textRange) {
|
||||
PsiMethod method = methodSignature.getMethod();
|
||||
PsiType returnType = methodSignature.getSubstitutor().substitute(method.getReturnType());
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) return null;
|
||||
for (MethodSignatureBackedByPsiMethod superMethodSignature : superMethodSignatures) {
|
||||
PsiMethod superMethod = superMethodSignature.getMethod();
|
||||
PsiType declaredReturnType = superMethod.getReturnType();
|
||||
PsiType superReturnType = declaredReturnType;
|
||||
if (superMethodSignature.isRaw()) superReturnType = TypeConversionUtil.erasure(declaredReturnType);
|
||||
if (returnType == null || superReturnType == null || method == superMethod) continue;
|
||||
PsiClass superClass = superMethod.getContainingClass();
|
||||
if (superClass == null) continue;
|
||||
if (textRange == null && includeRealPositionInfo) {
|
||||
PsiTypeElement typeElement = method.getReturnTypeElement();
|
||||
if (typeElement != null) {
|
||||
textRange = typeElement.getTextRange();
|
||||
}
|
||||
}
|
||||
if (textRange == null) {
|
||||
textRange = TextRange.EMPTY_RANGE;
|
||||
}
|
||||
HighlightInfo.Builder info = checkSuperMethodSignature(
|
||||
superMethod, superMethodSignature, superReturnType, method, methodSignature, returnType,
|
||||
textRange, PsiUtil.getLanguageLevel(aClass));
|
||||
if (info != null) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static HighlightInfo.Builder checkSuperMethodSignature(@NotNull PsiMethod superMethod,
|
||||
@NotNull MethodSignatureBackedByPsiMethod superMethodSignature,
|
||||
@NotNull PsiType superReturnType,
|
||||
@NotNull PsiMethod method,
|
||||
@NotNull MethodSignatureBackedByPsiMethod methodSignature,
|
||||
@NotNull PsiType returnType,
|
||||
@NotNull TextRange range,
|
||||
@NotNull LanguageLevel languageLevel) {
|
||||
PsiClass superContainingClass = superMethod.getContainingClass();
|
||||
if (superContainingClass != null &&
|
||||
CommonClassNames.JAVA_LANG_OBJECT.equals(superContainingClass.getQualifiedName()) &&
|
||||
!superMethod.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null && containingClass.isInterface() && !superContainingClass.isInterface()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
PsiType substitutedSuperReturnType;
|
||||
boolean hasGenerics = JavaFeature.GENERICS.isSufficient(languageLevel);
|
||||
if (hasGenerics && !superMethodSignature.isRaw() && superMethodSignature.equals(methodSignature)) { //see 8.4.5
|
||||
PsiSubstitutor unifyingSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature,
|
||||
superMethodSignature);
|
||||
substitutedSuperReturnType = unifyingSubstitutor == null
|
||||
? superReturnType
|
||||
: unifyingSubstitutor.substitute(superReturnType);
|
||||
}
|
||||
else {
|
||||
substitutedSuperReturnType = TypeConversionUtil.erasure(superMethodSignature.getSubstitutor().substitute(superReturnType));
|
||||
}
|
||||
|
||||
if (returnType.equals(substitutedSuperReturnType)) return null;
|
||||
if (!(returnType instanceof PsiPrimitiveType) && substitutedSuperReturnType.getDeepComponentType() instanceof PsiClassType) {
|
||||
if (hasGenerics && LambdaUtil.performWithSubstitutedParameterBounds(methodSignature.getTypeParameters(),
|
||||
methodSignature.getSubstitutor(),
|
||||
() -> TypeConversionUtil.isAssignable(substitutedSuperReturnType, returnType))) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return createIncompatibleReturnTypeMessage(method, superMethod, substitutedSuperReturnType, returnType,
|
||||
JavaErrorBundle.message("incompatible.return.type"), range
|
||||
);
|
||||
}
|
||||
|
||||
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) {
|
||||
String description = MessageFormat.format("{0}; {1}", createClashMethodMessage(method, superMethod, true), detailMessage);
|
||||
HighlightInfo.Builder errorResult =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description);
|
||||
if (method instanceof LightRecordMethod recordMethod) {
|
||||
for (IntentionAction fix :
|
||||
HighlightFixUtil.getChangeVariableTypeFixes(recordMethod.getRecordComponent(), substitutedSuperReturnType)) {
|
||||
errorResult.registerFix(fix, null, null, null, null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
IntentionAction action = QuickFixFactory.getInstance().createMethodReturnFix(method, substitutedSuperReturnType, false);
|
||||
errorResult.registerFix(action, null, null, null, null);
|
||||
}
|
||||
IntentionAction action1 = QuickFixFactory.getInstance().createSuperMethodReturnFix(superMethod, returnType);
|
||||
errorResult.registerFix(action1, null, null, null, null);
|
||||
PsiClass returnClass = PsiUtil.resolveClassInClassTypeOnly(returnType);
|
||||
if (returnClass != null && substitutedSuperReturnType instanceof PsiClassType) {
|
||||
IntentionAction action =
|
||||
QuickFixFactory.getInstance().createChangeParameterClassFix(returnClass, (PsiClassType)substitutedSuperReturnType);
|
||||
errorResult.registerFix(action, null, null, null, null);
|
||||
}
|
||||
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
static HighlightInfo.Builder checkConstructorHandleSuperClassExceptions(@NotNull PsiMethod method) {
|
||||
if (!method.isConstructor()) {
|
||||
return null;
|
||||
}
|
||||
PsiCodeBlock body = method.getBody();
|
||||
PsiStatement[] statements = body == null ? null : body.getStatements();
|
||||
if (statements == null) return null;
|
||||
|
||||
// if we have unhandled exception inside the method body, we could not have been called here,
|
||||
// so the only problem it can catch here is with super ctr only
|
||||
Collection<PsiClassType> unhandled = ExceptionUtil.collectUnhandledExceptions(method, method.getContainingClass());
|
||||
if (unhandled.isEmpty()) return null;
|
||||
String description = HighlightUtil.getUnhandledExceptionsDescriptor(unhandled);
|
||||
TextRange textRange = HighlightNamesUtil.getMethodDeclarationTextRange(method);
|
||||
HighlightInfo.Builder highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description);
|
||||
for (PsiClassType exception : unhandled) {
|
||||
IntentionAction action =
|
||||
new LocalQuickFixOnPsiElementAsIntentionAdapter(QuickFixFactory.getInstance().createMethodThrowsFix(method, exception, true, false));
|
||||
highlightInfo.registerFix(action, null, null, null, null);
|
||||
}
|
||||
return highlightInfo;
|
||||
}
|
||||
|
||||
public static @NotNull TextRange getFixRange(@NotNull PsiElement element) {
|
||||
PsiElement nextSibling = element.getNextSibling();
|
||||
TextRange range = element.getTextRange();
|
||||
if (PsiUtil.isJavaToken(nextSibling, JavaTokenType.SEMICOLON)) {
|
||||
return range.grown(1);
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
static boolean hasSurroundingInferenceError(@NotNull PsiElement context) {
|
||||
PsiCall topCall = LambdaUtil.treeWalkUp(context);
|
||||
if (topCall == null) return false;
|
||||
while (context != topCall) {
|
||||
context = context.getParent();
|
||||
if (context instanceof PsiMethodCallExpression call &&
|
||||
call.resolveMethodGenerics() instanceof MethodCandidateInfo info &&
|
||||
info.getInferenceErrorMessage() != null) {
|
||||
// Possibly inapplicable method reference due to the surrounding call inference failure:
|
||||
// suppress method reference error in order to display more relevant inference error.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static HighlightInfo.@Nullable Builder checkConstructorInImplicitClass(@NotNull PsiMethod method) {
|
||||
if (!method.isConstructor()) {
|
||||
return null;
|
||||
}
|
||||
if (!(method.getContainingClass() instanceof PsiImplicitClass)) {
|
||||
return null;
|
||||
}
|
||||
String description = JavaErrorBundle.message("implicit.class.with.explicit.constructor");
|
||||
TextRange textRange = HighlightNamesUtil.getMethodDeclarationTextRange(method);
|
||||
HighlightInfo.Builder builder =
|
||||
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description);
|
||||
IntentionAction action = QuickFixFactory.getInstance().createDeleteFix(method);
|
||||
builder.registerFix(action, null, null, null, null);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
-10
@@ -27,7 +27,6 @@ import com.intellij.openapi.roots.impl.JavaLanguageLevelPusher;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.HtmlChunk;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
@@ -55,7 +54,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
@@ -127,14 +125,6 @@ public final class HighlightUtil {
|
||||
};
|
||||
}
|
||||
|
||||
public static @NotNull @NlsContexts.DetailedDescription String getUnhandledExceptionsDescriptor(@NotNull Collection<? extends PsiClassType> unhandled) {
|
||||
return JavaErrorBundle.message("unhandled.exceptions", formatTypes(unhandled), unhandled.size());
|
||||
}
|
||||
|
||||
private static @NotNull String formatTypes(@NotNull Collection<? extends PsiClassType> unhandled) {
|
||||
return StringUtil.join(unhandled, JavaHighlightUtil::formatType, ", ");
|
||||
}
|
||||
|
||||
public static HighlightInfo.Builder checkVariableAlreadyDefined(@NotNull PsiVariable variable) {
|
||||
if (variable instanceof ExternallyDefinedPsiElement || variable.isUnnamed()) return null;
|
||||
PsiVariable oldVariable = null;
|
||||
|
||||
-2
@@ -388,9 +388,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
@Override
|
||||
public void visitMethod(@NotNull PsiMethod method) {
|
||||
super.visitMethod(method);
|
||||
if (!hasErrorResults()) add(HighlightMethodUtil.checkConstructorInImplicitClass(method));
|
||||
if (!hasErrorResults()) add(HighlightControlFlowUtil.checkUnreachableStatement(method.getBody()));
|
||||
if (!hasErrorResults()) add(HighlightMethodUtil.checkConstructorHandleSuperClassExceptions(method));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-1
@@ -104,7 +104,8 @@ 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, METHOD_REFERENCE_PARAMETERIZED_QUALIFIER)) {
|
||||
IMPORT_LIST_EXTRA_SEMICOLON, ENUM_CONSTANT_MODIFIER, METHOD_REFERENCE_PARAMETERIZED_QUALIFIER,
|
||||
CONSTRUCTOR_IN_IMPLICIT_CLASS)) {
|
||||
fix(kind, genericRemover);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper;
|
||||
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
|
||||
@@ -51,7 +51,7 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
|
||||
MoveClassToModuleFix.registerFixes(registrar, ref);
|
||||
|
||||
if (ref instanceof PsiReferenceExpression refExpr) {
|
||||
TextRange fixRange = HighlightMethodUtil.getFixRange(ref);
|
||||
TextRange fixRange = HighlightControlFlowUtil.getFixRange(ref);
|
||||
registrar.register(fixRange, new RenameWrongRefFix(refExpr), null);
|
||||
PsiExpression qualifier = refExpr.getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
|
||||
Reference in New Issue
Block a user