diff --git a/java/codeserver/highlighting/resources/messages/JavaCompilationErrorBundle.properties b/java/codeserver/highlighting/resources/messages/JavaCompilationErrorBundle.properties index 0c1b55f13317..6cdcaf69848b 100644 --- a/java/codeserver/highlighting/resources/messages/JavaCompilationErrorBundle.properties +++ b/java/codeserver/highlighting/resources/messages/JavaCompilationErrorBundle.properties @@ -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: diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java index 02ea2f0b7051..24a4409b0c2a 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java @@ -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 diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/MethodChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/MethodChecker.java index cf006558d208..1a0df83a22ad 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/MethodChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/MethodChecker.java @@ -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 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; diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java index bd0ab7d852d4..4fcb03a076bb 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java @@ -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 CONSTRUCTOR_IN_IMPLICIT_CLASS = + error(PsiMethod.class, "constructor.in.implicit.class") + .withRange(JavaErrorFormatUtil::getMemberDeclarationTextRange); public static final Parameterized> EXCEPTION_UNHANDLED = error(PsiElement.class, "exception.unhandled") diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 2f622e8fc848..2416c2ba66c3 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -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 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; + } } \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java index e9adc8a26708..ac3267dcb892 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java @@ -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 { 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(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java deleted file mode 100644 index 223afd9c7944..000000000000 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ /dev/null @@ -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 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 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; - } -} \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 28215146d187..9033e7ad50e4 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -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 unhandled) { - return JavaErrorBundle.message("unhandled.exceptions", formatTypes(unhandled), unhandled.size()); - } - - private static @NotNull String formatTypes(@NotNull Collection 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; diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 98ce16970f1d..f12e482d6804 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -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 diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaErrorFixProvider.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaErrorFixProvider.java index 9310ea4ca51a..f9ebded9f229 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaErrorFixProvider.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaErrorFixProvider.java @@ -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); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java index f0b6fe72aa44..ab65e1dc5f64 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java @@ -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) {