diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 7954469dd8..70a37820c6 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -317,13 +317,13 @@ private static HighlightInfo checkTypeParameterWithinItsBound( PsiElement typeElement2Highlight, PsiReferenceParameterList referenceParameterList ) { - PsiClass referenceClass = type instanceof PsiClassType ? ((PsiClassType)type).resolve() : null; + PsiClass referenceClass = type instanceof PsiClassType classType ? classType.resolve() : null; PsiType psiType = substitutor.substitute(classParameter); if (psiType instanceof PsiClassType && !(PsiUtil.resolveClassInType(psiType) instanceof PsiTypeParameter) && GenericsUtil.checkNotInBounds(type, psiType, referenceParameterList)) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(typeElement2Highlight) - .descriptionAndTooltip(LocalizeValue.localizeTODO("Actual type argument and inferred type contradict each other")) + .descriptionAndTooltip(JavaErrorLocalize.actualTypeArgumentContradictInferredType()) .create(); } @@ -407,7 +407,7 @@ else if (referenceElements.length != 0 && element != referenceElements[0] .createType(extendFrom, resolveResult.getSubstitutor()); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(element) - .descriptionAndTooltip(JavaErrorBundle.message("type.parameter.cannot.be.followed.by.other.bounds")) + .descriptionAndTooltip(JavaErrorLocalize.typeParameterCannotBeFollowedByOtherBounds()) .registerFix(QuickFixFactory.getInstance().createExtendsListFix(aClass, type, false), null, null, null, null) .create(); } @@ -608,18 +608,20 @@ public static HighlightInfo checkUnrelatedDefaultMethods(@Nonnull PsiClass aClas continue; } + String c = HighlightUtil.formatClass(aClass); + String m = JavaHighlightUtil.formatMethod(defaultMethod); + LocalizeValue description = unrelatedDefaults != null + ? JavaErrorLocalize.textClassInheritsUnrelatedDefaults(c, m, unrelatedDefaults) + : JavaErrorLocalize.textClassInheritsAbstractAndDefault( + c, + m, + HighlightUtil.formatClass(defaultMethodContainingClass), + HighlightUtil.formatClass(unrelatedMethodContainingClass) + ); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(classIdentifier) - .descriptionAndTooltip(LocalizeValue.localizeTODO( - HighlightUtil.formatClass(aClass) + - (unrelatedDefaults != null ? " inherits unrelated defaults for " : " inherits abstract and default for ") + - JavaHighlightUtil.formatMethod(defaultMethod) + " from types " + ( - unrelatedDefaults != null - ? unrelatedDefaults - : HighlightUtil.formatClass(defaultMethodContainingClass) + " and " + - HighlightUtil.formatClass(unrelatedMethodContainingClass) - ) - )) + .descriptionAndTooltip(description) .registerFix(QuickFixFactory.getInstance().createImplementMethodsFix(aClass), null, null, null, null) .create(); } @@ -899,24 +901,23 @@ public static HighlightInfo checkTypeParameterInstantiation(PsiNewExpression exp public static HighlightInfo checkWildcardUsage(PsiTypeElement typeElement) { PsiType type = typeElement.getType(); if (type instanceof PsiWildcardType) { - if (typeElement.getParent() instanceof PsiReferenceParameterList) { - PsiElement parent = typeElement.getParent().getParent(); + if (typeElement.getParent() instanceof PsiReferenceParameterList refParamList) { + PsiElement parent = refParamList.getParent(); LOG.assertTrue(parent instanceof PsiJavaCodeReferenceElement, parent); PsiElement refParent = parent.getParent(); - if (refParent instanceof PsiAnonymousClass) { - refParent = refParent.getParent(); + if (refParent instanceof PsiAnonymousClass anonymousClass) { + refParent = anonymousClass.getParent(); } - if (refParent instanceof PsiNewExpression) { - PsiNewExpression newExpression = (PsiNewExpression)refParent; - if (!(newExpression.getType() instanceof PsiArrayType)) { + if (refParent instanceof PsiNewExpression newExpr) { + if (!(newExpr.getType() instanceof PsiArrayType)) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(typeElement) .descriptionAndTooltip(JavaErrorLocalize.wildcardTypeCannotBeInstantiated(JavaHighlightUtil.formatType(type))) .create(); } } - else if (refParent instanceof PsiReferenceList) { - if (!(refParent.getParent() instanceof PsiTypeParameter typeParam) || refParent != typeParam.getExtendsList()) { + else if (refParent instanceof PsiReferenceList refList) { + if (!(refList.getParent() instanceof PsiTypeParameter typeParam) || refList != typeParam.getExtendsList()) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(typeElement) .descriptionAndTooltip(JavaErrorLocalize.genericsWildcardNotExpected()) @@ -1051,11 +1052,9 @@ else if (field.getContainingClass() != aClass) { return null; } - if (!JavaVersionService.getInstance().isAtLeast(field, JavaSdkVersion.JDK_1_6)) { - PsiType type = field.getType(); - if (type instanceof PsiClassType && ((PsiClassType)type).resolve() == aClass) { - return null; - } + if (!JavaVersionService.getInstance().isAtLeast(field, JavaSdkVersion.JDK_1_6) + && field.getType() instanceof PsiClassType classType && classType.resolve() == aClass) { + return null; } if (PsiUtil.isCompileTimeConstant((PsiVariable)field)) { @@ -1160,11 +1159,10 @@ public static HighlightInfo checkTypeParametersList( } if (!level.isAtLeast(LanguageLevel.JDK_1_7)) { for (PsiJavaCodeReferenceElement referenceElement : typeParameter1.getExtendsList().getReferenceElements()) { - PsiElement resolve = referenceElement.resolve(); - if (resolve instanceof PsiTypeParameter && ArrayUtil.find(parameters, resolve) > i) { + if (referenceElement.resolve() instanceof PsiTypeParameter typeParam && ArrayUtil.find(parameters, typeParam) > i) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(referenceElement.getTextRange()) - .descriptionAndTooltip(LocalizeValue.localizeTODO("Illegal forward reference")) + .descriptionAndTooltip(JavaErrorLocalize.illegalForwardReference()) .create(); } } @@ -1210,8 +1208,7 @@ public static HighlightInfo checkInstanceOfGenericType(PsiInstanceOfExpression e */ @RequiredReadAction private static HighlightInfo isIllegalForInstanceOf(PsiType type, PsiTypeElement typeElement) { - PsiClass resolved = PsiUtil.resolveClassInClassTypeOnly(type); - if (resolved instanceof PsiTypeParameter) { + if (PsiUtil.resolveClassInClassTypeOnly(type) instanceof PsiTypeParameter) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(typeElement) .descriptionAndTooltip(JavaErrorLocalize.genericsCannotInstanceofTypeParameters()) @@ -1244,8 +1241,7 @@ public static HighlightInfo checkClassObjectAccessExpression(PsiClassObjectAcces @Nullable @RequiredReadAction private static HighlightInfo canSelectFrom(PsiClassType type, PsiTypeElement operand) { - PsiClass aClass = type.resolve(); - if (aClass instanceof PsiTypeParameter) { + if (type.resolve() instanceof PsiTypeParameter) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(operand) .descriptionAndTooltip(JavaErrorLocalize.cannotSelectDotClassFromTypeVariable()) @@ -1254,7 +1250,7 @@ private static HighlightInfo canSelectFrom(PsiClassType type, PsiTypeElement ope if (type.getParameters().length > 0) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(operand) - .descriptionAndTooltip("Cannot select from parameterized type") + .descriptionAndTooltip(JavaErrorLocalize.cannotSelectFromParameterizedType()) .create(); } return null; @@ -1268,7 +1264,8 @@ public static HighlightInfo checkOverrideAnnotation( @Nonnull LanguageLevel languageLevel ) { try { - MethodSignatureBackedByPsiMethod superMethod = SuperMethodsSearch.search(method, null, true, false).findFirst(); + MethodSignatureBackedByPsiMethod superMethod = + SuperMethodsSearch.search(method, null, true, false).findFirst(); if (superMethod != null && method.getContainingClass().isInterface()) { PsiMethod psiMethod = superMethod.getMethod(); PsiClass containingClass = psiMethod.getContainingClass(); @@ -1315,7 +1312,7 @@ public static HighlightInfo checkOverrideAnnotation( @RequiredReadAction public static HighlightInfo checkSafeVarargsAnnotation(PsiMethod method, LanguageLevel languageLevel) { PsiModifierList list = method.getModifierList(); - PsiAnnotation safeVarargsAnnotation = list.findAnnotation("java.lang.SafeVarargs"); + PsiAnnotation safeVarargsAnnotation = list.findAnnotation(JavaClassNames.JAVA_LANG_SAFE_VARARGS); if (safeVarargsAnnotation == null) { return null; } @@ -1323,36 +1320,34 @@ public static HighlightInfo checkSafeVarargsAnnotation(PsiMethod method, Languag if (!method.isVarArgs()) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(safeVarargsAnnotation) - .descriptionAndTooltip("@SafeVarargs is not allowed on methods with fixed arity") + .descriptionAndTooltip(JavaErrorLocalize.safevarargsNotAllowedOnMethodsWithFixedArity()) .create(); } if (!isSafeVarargsNoOverridingCondition(method, languageLevel)) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(safeVarargsAnnotation) - .descriptionAndTooltip("@SafeVarargs is not allowed on non-final instance methods") + .descriptionAndTooltip(JavaErrorLocalize.safevarargsNotAllowedNonFinalInstanceMethods()) .create(); } PsiParameter varParameter = method.getParameterList().getParameters()[method.getParameterList().getParametersCount() - 1]; for (PsiReference reference : ReferencesSearch.search(varParameter)) { - PsiElement element = reference.getElement(); - if (element instanceof PsiExpression && !PsiUtil.isAccessedForReading((PsiExpression)element)) { + if (reference.getElement() instanceof PsiExpression expression && !PsiUtil.isAccessedForReading(expression)) { return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING) - .range(element) - .descriptionAndTooltip("@SafeVarargs do not suppress potentially unsafe operations") + .range(expression) + .descriptionAndTooltip(JavaErrorLocalize.safevarargsNotSuppressPotentiallyUnsafeOperations()) .create(); } } - LOG.assertTrue(varParameter.isVarArgs()); PsiEllipsisType ellipsisType = (PsiEllipsisType)varParameter.getType(); PsiType componentType = ellipsisType.getComponentType(); if (JavaGenericsUtil.isReifiableType(componentType)) { return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING) .range(varParameter.getTypeElement()) - .descriptionAndTooltip("@SafeVarargs is not applicable for reifiable types") + .descriptionAndTooltip(JavaErrorLocalize.safevarargsNotApplicableForReifiableTypes()) .create(); } return null; @@ -1572,24 +1567,21 @@ public static HighlightInfo checkGenericCannotExtendException(PsiReferenceList l PsiJavaCodeReferenceElement[] referenceElements = list.getReferenceElements(); PsiClass throwableClass = null; for (PsiJavaCodeReferenceElement referenceElement : referenceElements) { - PsiElement resolved = referenceElement.resolve(); - if (!(resolved instanceof PsiClass)) { + if (!(referenceElement.resolve() instanceof PsiClass psiClass)) { continue; } if (throwableClass == null) { - throwableClass = JavaPsiFacade.getInstance(aClass.getProject()).findClass("java.lang.Throwable", aClass.getResolveScope()); + throwableClass = JavaPsiFacade.getInstance(aClass.getProject()) + .findClass(JavaClassNames.JAVA_LANG_THROWABLE, aClass.getResolveScope()); } - if (InheritanceUtil.isInheritorOrSelf((PsiClass)resolved, throwableClass, true)) { - HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + if (InheritanceUtil.isInheritorOrSelf(psiClass, throwableClass, true)) { + PsiClassType classType = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory() + .createType(psiClass); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(referenceElement) - .descriptionAndTooltip(JavaErrorBundle.message("generic.extend.exception")) + .descriptionAndTooltip(JavaErrorLocalize.genericExtendException()) + .registerFix(QuickFixFactory.getInstance().createExtendsListFix(aClass, classType, false), null, null, null, null) .create(); - PsiClassType classType = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType((PsiClass)resolved); - QuickFixAction.registerQuickFixAction( - highlightInfo, - QuickFixFactory.getInstance().createExtendsListFix(aClass, classType, false) - ); - return highlightInfo; } } return null; @@ -1650,14 +1642,11 @@ public static HighlightInfo checkSelectStaticClassFromParameterizedType(PsiEleme } @RequiredReadAction - public static HighlightInfo checkCannotInheritFromTypeParameter( - PsiClass superClass, - PsiJavaCodeReferenceElement toHighlight - ) { + public static HighlightInfo checkCannotInheritFromTypeParameter(PsiClass superClass, PsiJavaCodeReferenceElement toHighlight) { if (superClass instanceof PsiTypeParameter) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(toHighlight) - .descriptionAndTooltip(JavaErrorBundle.message("class.cannot.inherit.from.its.type.parameter")) + .descriptionAndTooltip(JavaErrorLocalize.classCannotInheritFromItsTypeParameter()) .create(); } return null; @@ -1672,14 +1661,14 @@ public static HighlightInfo checkRawOnParameterizedType(@Nonnull PsiJavaCodeRefe if (list == null || list.getTypeArguments().length > 0) { return null; } - if (parent.getQualifier() instanceof PsiJavaCodeReferenceElement javaCodeRef - && javaCodeRef.getTypeParameters().length > 0 + if (parent.getQualifier() instanceof PsiJavaCodeReferenceElement ref + && ref.getTypeParameters().length > 0 && resolved instanceof PsiTypeParameterListOwner typeParamListOwner && typeParamListOwner.hasTypeParameters() && !typeParamListOwner.isStatic()) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(parent) - .descriptionAndTooltip(LocalizeValue.localizeTODO("Improper formed type; some type parameters are missing")) + .descriptionAndTooltip(JavaErrorLocalize.textImproperFormedType()) .create(); } return null; @@ -1751,15 +1740,12 @@ private static void registerVariableParameterizedTypeFixes( @Nonnull JavaSdkVersion version ) { PsiType type = variable.getType(); - if (!(type instanceof PsiClassType) || highlightInfo == null) { + if (!(type instanceof PsiClassType classType) || highlightInfo == null + || DumbService.getInstance(variable.getProject()).isDumb()) { return; } - if (DumbService.getInstance(variable.getProject()).isDumb()) { - return; - } - - String shortName = ((PsiClassType)type).getClassName(); + String shortName = classType.getClassName(); PsiManager manager = parameterList.getManager(); JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject()); PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(parameterList.getProject()); @@ -1786,14 +1772,13 @@ private static void registerVariableParameterizedTypeFixes( public static HighlightInfo checkInferredIntersections(PsiSubstitutor substitutor, TextRange ref) { for (Map.Entry typeEntry : substitutor.getSubstitutionMap().entrySet()) { String parameterName = typeEntry.getKey().getName(); - PsiType type = typeEntry.getValue(); - if (type instanceof PsiIntersectionType) { - String conflictingConjunctsMessage = ((PsiIntersectionType)type).getConflictingConjunctsMessage(); + if (typeEntry.getValue() instanceof PsiIntersectionType intersectionType) { + String conflictingConjunctsMessage = intersectionType.getConflictingConjunctsMessage(); if (conflictingConjunctsMessage != null) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) - .descriptionAndTooltip(LocalizeValue.localizeTODO( - "Type parameter " + parameterName + " has incompatible upper bounds: " + conflictingConjunctsMessage - )) + .descriptionAndTooltip( + JavaErrorLocalize.typeParameterHasIncompatibleUpperBounds(parameterName, conflictingConjunctsMessage) + ) .range(ref) .create(); } @@ -1816,8 +1801,8 @@ public static HighlightInfo areSupersAccessible(@Nonnull PsiClass aClass, PsiRef String message = null; PsiElement parent = ref.getParent(); - if (parent instanceof PsiMethodCallExpression) { - JavaResolveResult resolveResult = ((PsiMethodCallExpression)parent).resolveMethodGenerics(); + if (parent instanceof PsiMethodCallExpression methodCall) { + JavaResolveResult resolveResult = methodCall.resolveMethodGenerics(); PsiMethod method = (PsiMethod)resolveResult.getElement(); if (method != null) { HashSet classes = new HashSet<>(); @@ -1901,8 +1886,8 @@ private static String isSuperTypeAccessible( if (checkParameters) { boolean isInLibrary = !index.isInContent(vFile); - if (superType instanceof PsiClassType) { - for (PsiType psiType : ((PsiClassType)superType).getParameters()) { + if (superType instanceof PsiClassType classType) { + for (PsiType psiType : classType.getParameters()) { String notAccessibleMessage = isSuperTypeAccessible(psiType, classes, true, resolveScope, factory); if (notAccessibleMessage != null) { return notAccessibleMessage; diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightMessageUtil.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightMessageUtil.java index edd360bee2..8189a471b5 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightMessageUtil.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightMessageUtil.java @@ -18,47 +18,48 @@ import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.PsiFormatUtil; import com.intellij.java.language.psi.util.PsiFormatUtilBase; -import consulo.language.LangBundle; +import consulo.annotation.access.RequiredReadAction; +import consulo.language.localize.LanguageLocalize; import consulo.language.psi.PsiDirectory; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; +import consulo.localize.LocalizeValue; import jakarta.annotation.Nonnull; -import jakarta.annotation.Nullable; public class HighlightMessageUtil { - private HighlightMessageUtil() { - } + private static final LocalizeValue QUESTION_MARK = LocalizeValue.of("?"); - @Nullable - public static String getSymbolName(@Nonnull PsiElement symbol, PsiSubstitutor substitutor) { - String symbolName = null; - - if (symbol instanceof PsiClass) { - if (symbol instanceof PsiAnonymousClass) { - symbolName = LangBundle.message("java.terms.anonymous.class"); - } else { - symbolName = ((PsiClass) symbol).getQualifiedName(); - if (symbolName == null) { - symbolName = ((PsiClass) symbol).getName(); - } - } - } else if (symbol instanceof PsiMethod) { - symbolName = PsiFormatUtil.formatMethod((PsiMethod) symbol, - substitutor, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, - PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES); - } else if (symbol instanceof PsiVariable) { - symbolName = ((PsiVariable) symbol).getName(); - } else if (symbol instanceof PsiJavaPackage) { - symbolName = ((PsiJavaPackage) symbol).getQualifiedName(); - } else if (symbol instanceof PsiFile) { - PsiDirectory directory = ((PsiFile) symbol).getContainingDirectory(); - PsiJavaPackage aPackage = directory == null ? null : JavaDirectoryService.getInstance().getPackage(directory); - symbolName = aPackage == null ? null : aPackage.getQualifiedName(); - } else if (symbol instanceof PsiDirectory) { - symbolName = ((PsiDirectory) symbol).getName(); + private HighlightMessageUtil() { } - return symbolName; - } + @Nonnull + @RequiredReadAction + public static LocalizeValue getSymbolName(@Nonnull PsiElement symbol, PsiSubstitutor substitutor) { + return switch (symbol) { + case PsiAnonymousClass ac -> LanguageLocalize.javaTermsAnonymousClass(); + case PsiClass c -> { + String n = c.getQualifiedName(); + if (n == null) { + n = c.getName(); + } + yield LocalizeValue.of(n); + } + case PsiMethod m -> LocalizeValue.of(PsiFormatUtil.formatMethod( + m, + substitutor, + PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, + PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES + )); + case PsiVariable v -> LocalizeValue.of(v.getName()); + case PsiJavaPackage jp -> LocalizeValue.of(jp.getQualifiedName()); + case PsiFile f -> { + PsiDirectory directory = f.getContainingDirectory(); + PsiJavaPackage aPackage = directory == null ? null : JavaDirectoryService.getInstance().getPackage(directory); + yield aPackage == null ? QUESTION_MARK : LocalizeValue.of(aPackage.getQualifiedName()); + } + case PsiDirectory d -> LocalizeValue.of(d.getName()); + default -> QUESTION_MARK; + }; + } } diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index 2675e94020..9f88815c66 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -563,9 +563,10 @@ public static HighlightInfo checkMethodCall( } else if (candidateInfo != null && !candidateInfo.isApplicable()) { if (candidateInfo.isTypeArgumentsApplicable()) { - String methodName = HighlightMessageUtil.getSymbolName(resolved, substitutor); + LocalizeValue methodName = HighlightMessageUtil.getSymbolName(resolved, substitutor); PsiElement parent = resolved.getParent(); - String containerName = parent == null ? "" : HighlightMessageUtil.getSymbolName(parent, substitutor); + LocalizeValue containerName = + parent == null ? LocalizeValue.empty() : HighlightMessageUtil.getSymbolName(parent, substitutor); String argTypes = buildArgTypesList(list); String description = JavaErrorLocalize.wrongMethodArguments(methodName, containerName, argTypes).get(); SimpleReference elementToHighlight = SimpleReference.create(list); @@ -2192,8 +2193,8 @@ else if (classReference != null && (!result.isAccessible() holder.add(buildAccessProblem(classReference, result, constructor)); } else if (!applicable) { - String constructorName = HighlightMessageUtil.getSymbolName(constructor, result.getSubstitutor()); - String containerName = HighlightMessageUtil.getSymbolName(constructor.getContainingClass(), result.getSubstitutor()); + LocalizeValue constructorName = HighlightMessageUtil.getSymbolName(constructor, result.getSubstitutor()); + LocalizeValue containerName = HighlightMessageUtil.getSymbolName(constructor.getContainingClass(), result.getSubstitutor()); String argTypes = buildArgTypesList(list); String toolTip = createMismatchedArgumentsHtmlTooltip(result, list); diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightUtil.java index 5d0b9faa8d..840bdc8b8b 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -2193,9 +2193,10 @@ private static boolean resolvesToImmediateSuperInterface( } @Nonnull + @RequiredReadAction public static LocalizeValue buildProblemWithStaticDescription(@Nonnull PsiElement refElement) { String type = FindUsagesProvider.forLanguage(JavaLanguage.INSTANCE).getType(refElement); - String name = HighlightMessageUtil.getSymbolName(refElement, PsiSubstitutor.EMPTY); + LocalizeValue name = HighlightMessageUtil.getSymbolName(refElement, PsiSubstitutor.EMPTY); return JavaErrorLocalize.nonStaticSymbolReferencedFromStaticContext(type, name); } @@ -2268,14 +2269,14 @@ private static LocalizeValue buildProblemWithAccessDescription( ) { assert resolved instanceof PsiModifierListOwner : resolved; PsiModifierListOwner refElement = (PsiModifierListOwner)resolved; - String symbolName = HighlightMessageUtil.getSymbolName(refElement, result.getSubstitutor()); + LocalizeValue symbolName = HighlightMessageUtil.getSymbolName(refElement, result.getSubstitutor()); if (refElement.hasModifierProperty(PsiModifier.PRIVATE)) { - String containerName = getContainerName(refElement, result.getSubstitutor()); + LocalizeValue containerName = getContainerName(refElement, result.getSubstitutor()); return JavaErrorLocalize.privateSymbol(symbolName, containerName); } else if (refElement.hasModifierProperty(PsiModifier.PROTECTED)) { - String containerName = getContainerName(refElement, result.getSubstitutor()); + LocalizeValue containerName = getContainerName(refElement, result.getSubstitutor()); return JavaErrorLocalize.protectedSymbol(symbolName, containerName); } else { @@ -2285,11 +2286,11 @@ else if (refElement.hasModifierProperty(PsiModifier.PROTECTED)) { symbolName = HighlightMessageUtil.getSymbolName(refElement, result.getSubstitutor()); } if (refElement.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) || packageLocalClass != null) { - String containerName = getContainerName(refElement, result.getSubstitutor()); + LocalizeValue containerName = getContainerName(refElement, result.getSubstitutor()); return JavaErrorLocalize.packageLocalSymbol(symbolName, containerName); } else { - String containerName = getContainerName(refElement, result.getSubstitutor()); + LocalizeValue containerName = getContainerName(refElement, result.getSubstitutor()); return JavaErrorLocalize.visibilityAccessProblem(symbolName, containerName); } } @@ -2305,9 +2306,9 @@ private static PsiElement getContainer(PsiModifierListOwner refElement) { return refElement.getParent(); } - private static String getContainerName(PsiModifierListOwner refElement, PsiSubstitutor substitutor) { - PsiElement container = getContainer(refElement); - return container == null ? "?" : HighlightMessageUtil.getSymbolName(container, substitutor); + @RequiredReadAction + private static LocalizeValue getContainerName(PsiModifierListOwner refElement, PsiSubstitutor substitutor) { + return HighlightMessageUtil.getSymbolName(getContainer(refElement), substitutor); } @Nullable diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index efdeceed40..2e8fad10c0 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -2041,6 +2041,7 @@ public void visitResourceExpression(@Nonnull PsiResourceExpression resource) { } @Override + @RequiredReadAction public void visitTypeElement(@Nonnull PsiTypeElement type) { if (!myHolder.hasErrorResults()) { myHolder.add(HighlightUtil.checkIllegalType(type)); @@ -2054,7 +2055,8 @@ public void visitTypeElement(@Nonnull PsiTypeElement type) { } @Override - public void visitTypeCastExpression(PsiTypeCastExpression typeCast) { + @RequiredReadAction + public void visitTypeCastExpression(@Nonnull PsiTypeCastExpression typeCast) { super.visitTypeCastExpression(typeCast); try { if (!myHolder.hasErrorResults()) { @@ -2069,6 +2071,7 @@ public void visitTypeCastExpression(PsiTypeCastExpression typeCast) { } @Override + @RequiredReadAction public void visitTypeParameterList(PsiTypeParameterList list) { PsiTypeParameter[] typeParameters = list.getTypeParameters(); if (typeParameters.length > 0) { @@ -2080,7 +2083,8 @@ public void visitTypeParameterList(PsiTypeParameterList list) { } @Override - public void visitVariable(PsiVariable variable) { + @RequiredReadAction + public void visitVariable(@Nonnull PsiVariable variable) { super.visitVariable(variable); try { if (!myHolder.hasErrorResults()) { @@ -2109,20 +2113,21 @@ private boolean isReassigned(@Nonnull PsiVariable variable) { } @Override - public void visitConditionalExpression(PsiConditionalExpression expression) { + @RequiredReadAction + public void visitConditionalExpression(@Nonnull PsiConditionalExpression expression) { super.visitConditionalExpression(expression); if (myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) && PsiPolyExpressionUtil.isPolyExpression(expression)) { - final PsiExpression thenExpression = expression.getThenExpression(); - final PsiExpression elseExpression = expression.getElseExpression(); + PsiExpression thenExpression = expression.getThenExpression(); + PsiExpression elseExpression = expression.getElseExpression(); if (thenExpression != null && elseExpression != null) { - final PsiType conditionalType = expression.getType(); + PsiType conditionalType = expression.getType(); if (conditionalType != null) { - final PsiExpression[] sides = { + PsiExpression[] sides = { thenExpression, elseExpression }; for (PsiExpression side : sides) { - final PsiType sideType = side.getType(); + PsiType sideType = side.getType(); if (sideType != null && !TypeConversionUtil.isAssignable(conditionalType, sideType)) { myHolder.add(HighlightUtil.checkAssignability(conditionalType, sideType, side, side)); } diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java index dbb08e2dc0..ba63a015da 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java @@ -20,7 +20,6 @@ import com.intellij.java.analysis.impl.codeInsight.daemon.impl.quickfix.GoToSymbolFix; import com.intellij.java.analysis.impl.codeInsight.daemon.impl.quickfix.MergeModuleStatementsFix; import com.intellij.java.analysis.impl.codeInsight.daemon.impl.quickfix.MoveFileFix; -import com.intellij.java.language.impl.codeInsight.daemon.JavaErrorBundle; import com.intellij.java.language.impl.psi.impl.light.AutomaticJavaModule; import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.PsiPackageAccessibilityStatement.Role; @@ -28,9 +27,11 @@ import com.intellij.java.language.psi.util.ClassUtil; import com.intellij.java.language.psi.util.InheritanceUtil; import com.intellij.java.language.psi.util.PsiUtil; -import consulo.application.ApplicationManager; +import consulo.annotation.access.RequiredReadAction; +import consulo.application.Application; import consulo.document.util.TextRange; -import consulo.java.analysis.impl.JavaQuickFixBundle; +import consulo.java.analysis.impl.localize.JavaQuickFixLocalize; +import consulo.java.language.impl.localize.JavaErrorLocalize; import consulo.language.editor.intention.QuickFixAction; import consulo.language.editor.rawHighlight.HighlightInfo; import consulo.language.editor.rawHighlight.HighlightInfoType; @@ -39,6 +40,7 @@ import consulo.language.psi.search.FilenameIndex; import consulo.language.psi.util.PsiTreeUtil; import consulo.language.util.ModuleUtilCore; +import consulo.localize.LocalizeValue; import consulo.module.Module; import consulo.module.content.ProjectFileIndex; import consulo.project.Project; @@ -48,10 +50,9 @@ import consulo.util.lang.StringUtil; import consulo.util.lang.Trinity; import consulo.virtualFileSystem.VirtualFile; -import org.jetbrains.annotations.PropertyKey; - import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; + import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -60,409 +61,569 @@ import static com.intellij.java.language.psi.PsiJavaModule.MODULE_INFO_FILE; public class ModuleHighlightUtil { - @Nullable - public static PsiJavaModule getModuleDescriptor(@Nonnull PsiFileSystemItem fsItem) { - VirtualFile file = fsItem.getVirtualFile(); - if (file == null) { - return null; - } - - return JavaPsiFacade.getInstance(fsItem.getProject()).findModule(file); - } + @Nullable + public static PsiJavaModule getModuleDescriptor(@Nonnull PsiFileSystemItem fsItem) { + VirtualFile file = fsItem.getVirtualFile(); + if (file == null) { + return null; + } - public static HighlightInfo checkPackageStatement(@Nonnull PsiPackageStatement statement, @Nonnull PsiFile file, @Nullable PsiJavaModule module) { - if (PsiUtil.isModuleFile(file)) { - String message = JavaErrorBundle.message("module.no.package"); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(info, factory().createDeleteFix(statement)); - return info; + return JavaPsiFacade.getInstance(fsItem.getProject()).findModule(file); } - if (module != null) { - String packageName = statement.getPackageName(); - if (packageName != null) { - PsiJavaModule origin = JavaModuleGraphUtil.findOrigin(module, packageName); - if (origin != null) { - String message = JavaErrorBundle.message("module.conflicting.packages", packageName, origin.getName()); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create(); + @RequiredReadAction + public static HighlightInfo checkPackageStatement( + @Nonnull PsiPackageStatement statement, + @Nonnull PsiFile file, + @Nullable PsiJavaModule module + ) { + if (PsiUtil.isModuleFile(file)) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(statement) + .descriptionAndTooltip(JavaErrorLocalize.moduleNoPackage()) + .registerFix(factory().createDeleteFix(statement), null, null, null, null) + .create(); } - } - } - return null; - } + if (module != null) { + String packageName = statement.getPackageName(); + if (packageName != null) { + PsiJavaModule origin = JavaModuleGraphUtil.findOrigin(module, packageName); + if (origin != null) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(statement) + .descriptionAndTooltip(JavaErrorLocalize.moduleConflictingPackages(packageName, origin.getName())) + .create(); + } + } + } - @Nullable - public static HighlightInfo checkFileName(@Nonnull PsiJavaModule element, @Nonnull PsiFile file) { - if (!MODULE_INFO_FILE.equals(file.getName())) { - String message = JavaErrorBundle.message("module.file.wrong.name"); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(element)).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(info, factory().createRenameFileFix(MODULE_INFO_FILE)); - return info; + return null; } - return null; - } - - @Nullable - public static HighlightInfo checkFileDuplicates(@Nonnull PsiJavaModule element, @Nonnull PsiFile file) { - Module module = findModule(file); - if (module != null) { - Project project = file.getProject(); - Collection others = FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, GlobalSearchScope.moduleScope(module)); - if (others.size() > 1) { - String message = JavaErrorBundle.message("module.file.duplicate"); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(element)).descriptionAndTooltip(message).create(); - others.stream().map(f -> PsiManager.getInstance(project).findFile(f)).filter(f -> f != file).findFirst().ifPresent(duplicate -> QuickFixAction.registerQuickFixAction(info, new - GoToSymbolFix(duplicate, JavaErrorBundle.message("module.open.duplicate.text")))); - return info; - } + @Nullable + @RequiredReadAction + public static HighlightInfo checkFileName(@Nonnull PsiJavaModule element, @Nonnull PsiFile file) { + if (!MODULE_INFO_FILE.equals(file.getName())) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(element)) + .descriptionAndTooltip(JavaErrorLocalize.moduleFileWrongName()) + .registerFix(factory().createRenameFileFix(MODULE_INFO_FILE), null, null, null, null) + .create(); + } + + return null; } - return null; - } + @Nullable + @RequiredReadAction + public static HighlightInfo checkFileDuplicates(@Nonnull PsiJavaModule element, @Nonnull PsiFile file) { + Module module = findModule(file); + if (module != null) { + Project project = file.getProject(); + Collection others = + FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, GlobalSearchScope.moduleScope(module)); + if (others.size() > 1) { + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(element)) + .descriptionAndTooltip(JavaErrorLocalize.moduleFileDuplicate().get()) + .create(); + others.stream() + .map(f -> PsiManager.getInstance(project).findFile(f)) + .filter(f -> f != file) + .findFirst() + .ifPresent(duplicate -> QuickFixAction.registerQuickFixAction( + info, + new GoToSymbolFix(duplicate, JavaErrorLocalize.moduleOpenDuplicateText().get()) + )); + return info; + } + } - @Nonnull - public static List checkDuplicateStatements(@Nonnull PsiJavaModule module) { - List results = new ArrayList<>(); + return null; + } - checkDuplicateRefs(module.getRequires(), st -> Optional.ofNullable(st.getReferenceElement()).map(PsiJavaModuleReferenceElement::getReferenceText), "module.duplicate.requires", results); + @Nonnull + @RequiredReadAction + public static List checkDuplicateStatements(@Nonnull PsiJavaModule module) { + List results = new ArrayList<>(); + + checkDuplicateRefs( + module.getRequires(), + st -> Optional.ofNullable(st.getReferenceElement()).map(PsiJavaModuleReferenceElement::getReferenceText), + JavaErrorLocalize::moduleDuplicateRequires, + results + ); + + checkDuplicateRefs( + module.getExports(), + st -> Optional.ofNullable(st.getPackageReference()).map(ModuleHighlightUtil::refText), + JavaErrorLocalize::moduleDuplicateExports, + results + ); + + checkDuplicateRefs( + module.getOpens(), + st -> Optional.ofNullable(st.getPackageReference()).map(ModuleHighlightUtil::refText), + JavaErrorLocalize::moduleDuplicateOpens, + results + ); + + checkDuplicateRefs( + module.getUses(), + st -> Optional.ofNullable(st.getClassReference()).map(ModuleHighlightUtil::refText), + JavaErrorLocalize::moduleDuplicateUses, + results + ); + + checkDuplicateRefs( + module.getProvides(), + st -> Optional.ofNullable(st.getInterfaceReference()).map(ModuleHighlightUtil::refText), + JavaErrorLocalize::moduleDuplicateProvides, + results + ); + + return results; + } - checkDuplicateRefs(module.getExports(), st -> Optional.ofNullable(st.getPackageReference()).map(ModuleHighlightUtil::refText), "module.duplicate.exports", results); + @RequiredReadAction + private static void checkDuplicateRefs( + Iterable statements, + @RequiredReadAction Function> ref, + @Nonnull Function descriptionTemplate, + List results + ) { + Set filter = new HashSet<>(); + for (T statement : statements) { + String refText = ref.apply(statement).orElse(null); + if (refText != null && !filter.add(refText)) { + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(statement) + .descriptionAndTooltip(descriptionTemplate.apply(refText)) + .registerFix(factory().createDeleteFix(statement), null, null, null, null) + .registerFix(MergeModuleStatementsFix.createFix(statement), null, null, null, null) + .create(); + results.add(info); + } + } + } - checkDuplicateRefs(module.getOpens(), st -> Optional.ofNullable(st.getPackageReference()).map(ModuleHighlightUtil::refText), "module.duplicate.opens", results); + @Nonnull + @RequiredReadAction + public static List checkUnusedServices(@Nonnull PsiJavaModule module) { + List results = new ArrayList<>(); + + Set exports = JBIterable.from(module.getExports()) + .map(st -> refText(st.getPackageReference())) + .filter(Objects::nonNull) + .toSet(); + Set uses = JBIterable.from(module.getUses()) + .map(st -> refText(st.getClassReference())) + .filter(Objects::nonNull) + .toSet(); + + Module host = findModule(module); + for (PsiProvidesStatement statement : module.getProvides()) { + PsiJavaCodeReferenceElement ref = statement.getInterfaceReference(); + if (ref != null && ref.resolve() instanceof PsiClass psiClass && findModule(psiClass) == host) { + String className = refText(ref), packageName = StringUtil.getPackageName(className); + if (!exports.contains(packageName) && !uses.contains(className)) { + results.add( + HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING) + .range(range(ref)) + .descriptionAndTooltip(JavaErrorLocalize.moduleServiceUnused()) + .create() + ); + } + } + } - checkDuplicateRefs(module.getUses(), st -> Optional.ofNullable(st.getClassReference()).map(ModuleHighlightUtil::refText), "module.duplicate.uses", results); + return results; + } - checkDuplicateRefs(module.getProvides(), st -> Optional.ofNullable(st.getInterfaceReference()).map(ModuleHighlightUtil::refText), "module.duplicate.provides", results); + @RequiredReadAction + private static String refText(PsiJavaCodeReferenceElement ref) { + return ref != null ? PsiNameHelper.getQualifiedClassName(ref.getText(), true) : null; + } - return results; - } + @Nullable + @RequiredReadAction + public static HighlightInfo checkFileLocation(@Nonnull PsiJavaModule element, @Nonnull PsiFile file) { + VirtualFile vFile = file.getVirtualFile(); + if (vFile != null) { + VirtualFile root = ProjectFileIndex.SERVICE.getInstance(file.getProject()).getSourceRootForFile(vFile); + if (root != null && !root.equals(vFile.getParent())) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING) + .range(range(element)) + .descriptionAndTooltip(JavaErrorLocalize.moduleFileWrongLocation()) + .registerFix(new MoveFileFix(vFile, root, JavaQuickFixLocalize.moveFileToSourceRootText().get()), null, null, null, null) + .create(); + } + } - private static void checkDuplicateRefs(Iterable statements, - Function> ref, - @PropertyKey(resourceBundle = JavaErrorBundle.BUNDLE) String key, - List results) { - Set filter = new HashSet<>(); - for (T statement : statements) { - String refText = ref.apply(statement).orElse(null); - if (refText != null && !filter.add(refText)) { - String message = JavaErrorBundle.message(key, refText); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(info, factory().createDeleteFix(statement)); - QuickFixAction.registerQuickFixAction(info, MergeModuleStatementsFix.createFix(statement)); - results.add(info); - } + return null; } - } - - @Nonnull - public static List checkUnusedServices(@Nonnull PsiJavaModule module) { - List results = new ArrayList<>(); - - Set exports = JBIterable.from(module.getExports()).map(st -> refText(st.getPackageReference())).filter(Objects::nonNull).toSet(); - Set uses = JBIterable.from(module.getUses()).map(st -> refText(st.getClassReference())).filter(Objects::nonNull).toSet(); - - Module host = findModule(module); - for (PsiProvidesStatement statement : module.getProvides()) { - PsiJavaCodeReferenceElement ref = statement.getInterfaceReference(); - if (ref != null) { - PsiElement target = ref.resolve(); - if (target instanceof PsiClass && findModule(target) == host) { - String className = refText(ref), packageName = StringUtil.getPackageName(className); - if (!exports.contains(packageName) && !uses.contains(className)) { - String message = JavaErrorBundle.message("module.service.unused"); - results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(range(ref)).descriptionAndTooltip(message).create()); - } + + @Nullable + @RequiredReadAction + public static HighlightInfo checkModuleReference(@Nullable PsiJavaModuleReferenceElement refElement, @Nonnull PsiJavaModule container) { + if (refElement != null) { + PsiPolyVariantReference ref = refElement.getReference(); + assert ref != null : refElement.getParent(); + PsiElement target = ref.resolve(); + if (!(target instanceof PsiJavaModule)) { + return moduleResolveError(refElement, ref); + } + else if (target == container) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(refElement) + .descriptionAndTooltip(JavaErrorLocalize.moduleCyclicDependence(container.getName())) + .create(); + } + else { + Collection cycle = JavaModuleGraphUtil.findCycle((PsiJavaModule)target); + if (cycle != null && cycle.contains(container)) { + Stream stream = cycle.stream().map(PsiJavaModule::getName); + if (Application.get().isUnitTestMode()) { + stream = stream.sorted(); + } + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(refElement) + .descriptionAndTooltip(JavaErrorLocalize.moduleCyclicDependence(stream.collect(Collectors.joining(", ")))) + .create(); + } + } } - } - } - return results; - } - - private static String refText(PsiJavaCodeReferenceElement ref) { - return ref != null ? PsiNameHelper.getQualifiedClassName(ref.getText(), true) : null; - } - - @Nullable - public static HighlightInfo checkFileLocation(@Nonnull PsiJavaModule element, @Nonnull PsiFile file) { - VirtualFile vFile = file.getVirtualFile(); - if (vFile != null) { - VirtualFile root = ProjectFileIndex.SERVICE.getInstance(file.getProject()).getSourceRootForFile(vFile); - if (root != null && !root.equals(vFile.getParent())) { - String message = JavaErrorBundle.message("module.file.wrong.location"); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(range(element)).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(info, new MoveFileFix(vFile, root, JavaQuickFixBundle.message("move.file.to.source.root.text"))); - return info; - } + return null; } - return null; - } - - @Nullable - public static HighlightInfo checkModuleReference(@Nullable PsiJavaModuleReferenceElement refElement, @Nonnull PsiJavaModule container) { - if (refElement != null) { - PsiPolyVariantReference ref = refElement.getReference(); - assert ref != null : refElement.getParent(); - PsiElement target = ref.resolve(); - if (!(target instanceof PsiJavaModule)) { - return moduleResolveError(refElement, ref); - } else if (target == container) { - String message = JavaErrorBundle.message("module.cyclic.dependence", container.getName()); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(refElement).descriptionAndTooltip(message).create(); - } else { - Collection cycle = JavaModuleGraphUtil.findCycle((PsiJavaModule) target); - if (cycle != null && cycle.contains(container)) { - Stream stream = cycle.stream().map(PsiJavaModule::getName); - if (ApplicationManager.getApplication().isUnitTestMode()) { - stream = stream.sorted(); - } - String message = JavaErrorBundle.message("module.cyclic.dependence", stream.collect(Collectors.joining(", "))); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(refElement).descriptionAndTooltip(message).create(); + @Nullable + @RequiredReadAction + public static HighlightInfo checkHostModuleStrength(@Nonnull PsiPackageAccessibilityStatement statement) { + if (statement.getRole() == Role.OPENS && statement.getParent() instanceof PsiJavaModule javaModule + && javaModule.hasModifierProperty(PsiModifier.OPEN)) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(statement) + .descriptionAndTooltip(JavaErrorLocalize.moduleOpensInWeakModule()) + .registerFix(factory().createModifierListFix(javaModule, PsiModifier.OPEN, false, false), null, null, null, null) + .registerFix(factory().createDeleteFix(statement), null, null, null, null) + .create(); } - } - } - return null; - } - - @Nullable - public static HighlightInfo checkHostModuleStrength(@Nonnull PsiPackageAccessibilityStatement statement) { - PsiElement parent; - if (statement.getRole() == Role.OPENS && (parent = statement.getParent()) instanceof PsiJavaModule && ((PsiJavaModule) parent).hasModifierProperty(PsiModifier.OPEN)) { - String message = JavaErrorBundle.message("module.opens.in.weak.module"); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(info, factory().createModifierListFix((PsiModifierListOwner) parent, PsiModifier.OPEN, false, false)); - QuickFixAction.registerQuickFixAction(info, factory().createDeleteFix(statement)); - return info; + return null; } - return null; - } - - @Nullable - public static HighlightInfo checkPackageReference(@Nonnull PsiPackageAccessibilityStatement statement) { - PsiJavaCodeReferenceElement refElement = statement.getPackageReference(); - if (refElement != null) { - PsiElement target = refElement.resolve(); - Module module = findModule(refElement); - PsiDirectory[] directories = target instanceof PsiPackage && module != null ? ((PsiPackage) target).getDirectories(GlobalSearchScope.moduleScope(module, false)) : null; - String packageName = refText(refElement); - HighlightInfoType type = statement.getRole() == Role.OPENS ? HighlightInfoType.WARNING : HighlightInfoType.ERROR; - if (directories == null || directories.length == 0) { - String message = JavaErrorBundle.message("package.not.found", packageName); - return HighlightInfo.newHighlightInfo(type).range(refElement).descriptionAndTooltip(message).create(); - } - if (PsiUtil.isPackageEmpty(directories, packageName)) { - String message = JavaErrorBundle.message("package.is.empty", packageName); - return HighlightInfo.newHighlightInfo(type).range(refElement).descriptionAndTooltip(message).create(); - } - } + @Nullable + @RequiredReadAction + public static HighlightInfo checkPackageReference(@Nonnull PsiPackageAccessibilityStatement statement) { + PsiJavaCodeReferenceElement refElement = statement.getPackageReference(); + if (refElement != null) { + PsiElement target = refElement.resolve(); + Module module = findModule(refElement); + PsiDirectory[] directories = target instanceof PsiPackage psiPackage && module != null + ? psiPackage.getDirectories(GlobalSearchScope.moduleScope(module, false)) + : null; + String packageName = refText(refElement); + HighlightInfoType type = statement.getRole() == Role.OPENS ? HighlightInfoType.WARNING : HighlightInfoType.ERROR; + if (directories == null || directories.length == 0) { + return HighlightInfo.newHighlightInfo(type) + .range(refElement) + .descriptionAndTooltip(JavaErrorLocalize.packageNotFound(packageName)) + .create(); + } + if (PsiUtil.isPackageEmpty(directories, packageName)) { + return HighlightInfo.newHighlightInfo(type) + .range(refElement) + .descriptionAndTooltip(JavaErrorLocalize.packageIsEmpty(packageName)) + .create(); + } + } - return null; - } - - @Nonnull - public static List checkPackageAccessTargets(@Nonnull PsiPackageAccessibilityStatement statement) { - List results = new ArrayList<>(); - - Set targets = new HashSet<>(); - for (PsiJavaModuleReferenceElement refElement : statement.getModuleReferences()) { - String refText = refElement.getReferenceText(); - PsiPolyVariantReference ref = refElement.getReference(); - assert ref != null : statement; - if (!targets.add(refText)) { - boolean exports = statement.getRole() == Role.EXPORTS; - String message = JavaErrorBundle.message(exports ? "module.duplicate.exports.target" : "module.duplicate.opens.target", refText); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(refElement).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(info, factory().createDeleteFix(refElement, JavaQuickFixBundle.message("delete.reference.fix.text"))); - results.add(info); - } else if (ref.multiResolve(true).length == 0) { - String message = JavaErrorBundle.message("module.not.found", refElement.getReferenceText()); - results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(refElement).descriptionAndTooltip(message).create()); - } + return null; } - return results; - } - - @Nullable - public static HighlightInfo checkServiceReference(@Nullable PsiJavaCodeReferenceElement refElement) { - if (refElement != null) { - PsiElement target = refElement.resolve(); - if (target == null) { - String message = JavaErrorBundle.message("cannot.resolve.symbol", refElement.getReferenceName()); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(refElement)).descriptionAndTooltip(message).create(); - } else if (target instanceof PsiClass && ((PsiClass) target).isEnum()) { - String message = JavaErrorBundle.message("module.service.enum", ((PsiClass) target).getName()); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(refElement)).descriptionAndTooltip(message).create(); - } + @Nonnull + @RequiredReadAction + public static List checkPackageAccessTargets(@Nonnull PsiPackageAccessibilityStatement statement) { + List results = new ArrayList<>(); + + Set targets = new HashSet<>(); + for (PsiJavaModuleReferenceElement refElement : statement.getModuleReferences()) { + String refText = refElement.getReferenceText(); + PsiPolyVariantReference ref = refElement.getReference(); + assert ref != null : statement; + if (!targets.add(refText)) { + boolean exports = statement.getRole() == Role.EXPORTS; + LocalizeValue message = exports + ? JavaErrorLocalize.moduleDuplicateExportsTarget(refText) + : JavaErrorLocalize.moduleDuplicateOpensTarget(refText); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(refElement) + .descriptionAndTooltip(message) + .registerFix( + factory().createDeleteFix(refElement, JavaQuickFixLocalize.deleteReferenceFixText().get()), + null, + null, + null, + null + ) + .create(); + results.add(info); + } + else if (ref.multiResolve(true).length == 0) { + results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING) + .range(refElement) + .descriptionAndTooltip(JavaErrorLocalize.moduleNotFound(refElement.getReferenceText())) + .create()); + } + } + + return results; } - return null; - } + @Nullable + @RequiredReadAction + public static HighlightInfo checkServiceReference(@Nullable PsiJavaCodeReferenceElement refElement) { + if (refElement != null) { + PsiElement target = refElement.resolve(); + if (target == null) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(refElement)) + .descriptionAndTooltip(JavaErrorLocalize.cannotResolveSymbol(refElement.getReferenceName())) + .create(); + } + else if (target instanceof PsiClass psiClass && psiClass.isEnum()) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(refElement)) + .descriptionAndTooltip(JavaErrorLocalize.moduleServiceEnum(psiClass.getName())) + .create(); + } + } - @Nonnull - public static List checkServiceImplementations(@Nonnull PsiProvidesStatement statement) { - PsiReferenceList implRefList = statement.getImplementationList(); - if (implRefList == null) { - return Collections.emptyList(); + return null; } - List results = new ArrayList<>(); - PsiJavaCodeReferenceElement intRef = statement.getInterfaceReference(); - PsiElement intTarget = intRef != null ? intRef.resolve() : null; - - Set filter = new HashSet<>(); - for (PsiJavaCodeReferenceElement implRef : implRefList.getReferenceElements()) { - String refText = refText(implRef); - if (!filter.add(refText)) { - String message = JavaErrorBundle.message("module.duplicate.impl", refText); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(implRef).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(info, factory().createDeleteFix(implRef, JavaQuickFixBundle.message("delete.reference.fix.text"))); - results.add(info); - continue; - } - - if (!(intTarget instanceof PsiClass)) { - continue; - } - - PsiElement implTarget = implRef.resolve(); - if (implTarget instanceof PsiClass) { - PsiClass implClass = (PsiClass) implTarget; - - if (findModule(statement) != findModule(implClass)) { - String message = JavaErrorBundle.message("module.service.alien"); - results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(implRef)).descriptionAndTooltip(message).create()); + @Nonnull + @RequiredReadAction + public static List checkServiceImplementations(@Nonnull PsiProvidesStatement statement) { + PsiReferenceList implRefList = statement.getImplementationList(); + if (implRefList == null) { + return Collections.emptyList(); } - PsiMethod provider = ContainerUtil.find(implClass.findMethodsByName("provider", false), m -> m.hasModifierProperty(PsiModifier.PUBLIC) && m.hasModifierProperty(PsiModifier.STATIC) && - m.getParameterList().getParametersCount() == 0); - if (provider != null) { - PsiType type = provider.getReturnType(); - PsiClass typeClass = type instanceof PsiClassType ? ((PsiClassType) type).resolve() : null; - if (!InheritanceUtil.isInheritorOrSelf(typeClass, (PsiClass) intTarget, true)) { - String message = JavaErrorBundle.message("module.service.provider.type", implClass.getName()); - results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(implRef)).descriptionAndTooltip(message).create()); - } - } else if (InheritanceUtil.isInheritorOrSelf(implClass, (PsiClass) intTarget, true)) { - if (implClass.hasModifierProperty(PsiModifier.ABSTRACT)) { - String message = JavaErrorBundle.message("module.service.abstract", implClass.getName()); - results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(implRef)).descriptionAndTooltip(message).create()); - } else if (!(ClassUtil.isTopLevelClass(implClass) || implClass.hasModifierProperty(PsiModifier.STATIC))) { - String message = JavaErrorBundle.message("module.service.inner", implClass.getName()); - results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(implRef)).descriptionAndTooltip(message).create()); - } else if (!PsiUtil.hasDefaultConstructor(implClass)) { - String message = JavaErrorBundle.message("module.service.no.ctor", implClass.getName()); - results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(implRef)).descriptionAndTooltip(message).create()); - } - } else { - String message = JavaErrorBundle.message("module.service.impl"); - results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(implRef)).descriptionAndTooltip(message).create()); + List results = new ArrayList<>(); + PsiJavaCodeReferenceElement intRef = statement.getInterfaceReference(); + PsiElement intTarget = intRef != null ? intRef.resolve() : null; + + Set filter = new HashSet<>(); + for (PsiJavaCodeReferenceElement implRef : implRefList.getReferenceElements()) { + String refText = refText(implRef); + if (!filter.add(refText)) { + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(implRef) + .descriptionAndTooltip(JavaErrorLocalize.moduleDuplicateImpl(refText)) + .registerFix(factory().createDeleteFix(implRef, JavaQuickFixLocalize.deleteReferenceFixText().get()), null, null, null, null) + .create(); + results.add(info); + continue; + } + + if (!(intTarget instanceof PsiClass)) { + continue; + } + + PsiElement implTarget = implRef.resolve(); + if (implTarget instanceof PsiClass implClass) { + if (findModule(statement) != findModule(implClass)) { + results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(implRef)) + .descriptionAndTooltip(JavaErrorLocalize.moduleServiceAlien()) + .create()); + } + + PsiMethod provider = ContainerUtil.find( + implClass.findMethodsByName("provider", false), + m -> m.isPublic() && m.isStatic() + && m.getParameterList().getParametersCount() == 0 + ); + if (provider != null) { + PsiType type = provider.getReturnType(); + PsiClass typeClass = type instanceof PsiClassType classType ? classType.resolve() : null; + if (!InheritanceUtil.isInheritorOrSelf(typeClass, (PsiClass)intTarget, true)) { + results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(implRef)) + .descriptionAndTooltip(JavaErrorLocalize.moduleServiceProviderType(implClass.getName())) + .create()); + } + } + else if (InheritanceUtil.isInheritorOrSelf(implClass, (PsiClass)intTarget, true)) { + if (implClass.isAbstract()) { + results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(implRef)) + .descriptionAndTooltip(JavaErrorLocalize.moduleServiceAbstract(implClass.getName())) + .create()); + } + else if (!(ClassUtil.isTopLevelClass(implClass) || implClass.isStatic())) { + results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(implRef)) + .descriptionAndTooltip(JavaErrorLocalize.moduleServiceInner(implClass.getName())) + .create()); + } + else if (!PsiUtil.hasDefaultConstructor(implClass)) { + results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(implRef)) + .descriptionAndTooltip(JavaErrorLocalize.moduleServiceNoCtor(implClass.getName())) + .create()); + } + } + else { + results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(implRef)) + .descriptionAndTooltip(JavaErrorLocalize.moduleServiceImpl()) + .create()); + } + } } - } + + return results; } - return results; - } - - @Nullable - public static HighlightInfo checkPackageAccessibility(@Nonnull PsiJavaCodeReferenceElement ref, @Nonnull PsiElement target, @Nonnull PsiJavaModule refModule) { - if (PsiTreeUtil.getParentOfType(ref, PsiDocComment.class) == null) { - Module module = findModule(refModule); - if (module != null) { - if (target instanceof PsiClass) { - PsiElement targetFile = target.getParent(); - if (targetFile instanceof PsiClassOwner) { - PsiJavaModule targetModule = getModuleDescriptor((PsiFileSystemItem) targetFile); - String packageName = ((PsiClassOwner) targetFile).getPackageName(); - return checkPackageAccessibility(ref, refModule, targetModule, packageName); - } - } else if (target instanceof PsiPackage) { - PsiElement refImport = ref.getParent(); - if (refImport instanceof PsiImportStatementBase && ((PsiImportStatementBase) refImport).isOnDemand()) { - PsiDirectory[] dirs = ((PsiPackage) target).getDirectories(GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false)); - if (dirs.length == 1) { - PsiJavaModule targetModule = getModuleDescriptor(dirs[0]); - String packageName = ((PsiPackage) target).getQualifiedName(); - return checkPackageAccessibility(ref, refModule, targetModule, packageName); + @Nullable + @RequiredReadAction + public static HighlightInfo checkPackageAccessibility( + @Nonnull PsiJavaCodeReferenceElement ref, + @Nonnull PsiElement target, + @Nonnull PsiJavaModule refModule + ) { + if (PsiTreeUtil.getParentOfType(ref, PsiDocComment.class) == null) { + Module module = findModule(refModule); + if (module != null) { + if (target instanceof PsiClass psiClass) { + if (psiClass.getParent() instanceof PsiClassOwner targetFile) { + PsiJavaModule targetModule = getModuleDescriptor(targetFile); + String packageName = targetFile.getPackageName(); + return checkPackageAccessibility(ref, refModule, targetModule, packageName); + } + } + else if (target instanceof PsiPackage psiPackage) { + PsiElement refImport = ref.getParent(); + if (refImport instanceof PsiImportStatementBase importStatementBase && importStatementBase.isOnDemand()) { + PsiDirectory[] dirs = + psiPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false)); + if (dirs.length == 1) { + PsiJavaModule targetModule = getModuleDescriptor(dirs[0]); + String packageName = psiPackage.getQualifiedName(); + return checkPackageAccessibility(ref, refModule, targetModule, packageName); + } + } + } } - } } - } + + return null; } - return null; - } - - private static HighlightInfo checkPackageAccessibility(PsiJavaCodeReferenceElement ref, PsiJavaModule refModule, PsiJavaModule targetModule, String packageName) { - if (!refModule.equals(targetModule)) { - if (targetModule == null) { - String message = JavaErrorBundle.message("module.package.on.classpath"); - return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).descriptionAndTooltip(message).create(); - } - - String refModuleName = refModule.getName(); - String requiredName = targetModule.getName(); - if (!(targetModule instanceof AutomaticJavaModule || JavaModuleGraphUtil.exports(targetModule, packageName, refModule))) { - String message = JavaErrorBundle.message("module.package.not.exported", requiredName, packageName, refModuleName); - return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).descriptionAndTooltip(message).create(); - } - - if (!(PsiJavaModule.JAVA_BASE.equals(requiredName) || JavaModuleGraphUtil.reads(refModule, targetModule))) { - String message = JavaErrorBundle.message("module.not.in.requirements", refModuleName, requiredName); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(info, new AddRequiredModuleFix(refModule, requiredName)); - return info; - } + @RequiredReadAction + private static HighlightInfo checkPackageAccessibility( + PsiJavaCodeReferenceElement ref, + PsiJavaModule refModule, + PsiJavaModule targetModule, + String packageName + ) { + if (!refModule.equals(targetModule)) { + if (targetModule == null) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF) + .range(ref) + .descriptionAndTooltip(JavaErrorLocalize.modulePackageOnClasspath()) + .create(); + } + + String refModuleName = refModule.getName(); + String requiredName = targetModule.getName(); + if (!(targetModule instanceof AutomaticJavaModule || JavaModuleGraphUtil.exports(targetModule, packageName, refModule))) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF) + .range(ref) + .descriptionAndTooltip(JavaErrorLocalize.modulePackageNotExported(requiredName, packageName, refModuleName)) + .create(); + } + + if (!(PsiJavaModule.JAVA_BASE.equals(requiredName) || JavaModuleGraphUtil.reads(refModule, targetModule))) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF) + .range(ref) + .descriptionAndTooltip(JavaErrorLocalize.moduleNotInRequirements(refModuleName, requiredName)) + .registerFix(new AddRequiredModuleFix(refModule, requiredName), null, null, null, null) + .create(); + } + } + + return null; } - return null; - } + @Nullable + @RequiredReadAction + public static HighlightInfo checkClashingReads(@Nonnull PsiJavaModule module) { + Trinity conflict = JavaModuleGraphUtil.findConflict(module); + if (conflict != null) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(range(module)) + .descriptionAndTooltip(JavaErrorLocalize.moduleConflictingReads( + module.getName(), + conflict.first, + conflict.second.getName(), + conflict.third.getName() + )) + .create(); + } - @Nullable - public static HighlightInfo checkClashingReads(@Nonnull PsiJavaModule module) { - Trinity conflict = JavaModuleGraphUtil.findConflict(module); - if (conflict != null) { - String message = JavaErrorBundle.message("module.conflicting.reads", module.getName(), conflict.first, conflict.second.getName(), conflict.third.getName()); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(module)).descriptionAndTooltip(message).create(); + return null; } - return null; - } - - private static Module findModule(PsiElement element) { - return Optional.ofNullable(element.getContainingFile()).map(PsiFile::getVirtualFile).map(f -> ModuleUtilCore.findModuleForFile(f, element.getProject())).orElse(null); - } - - private static HighlightInfo moduleResolveError(PsiJavaModuleReferenceElement refElement, PsiPolyVariantReference ref) { - if (ref.multiResolve(true).length == 0) { - String message = JavaErrorBundle.message("module.not.found", refElement.getReferenceText()); - return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(refElement).descriptionAndTooltip(message).create(); - } else if (ref.multiResolve(false).length > 1) { - String message = JavaErrorBundle.message("module.ambiguous", refElement.getReferenceText()); - return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(refElement).descriptionAndTooltip(message).create(); - } else { - String message = JavaErrorBundle.message("module.not.on.path", refElement.getReferenceText()); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(refElement).descriptionAndTooltip(message).create(); - factory().registerOrderEntryFixes(ref); - return info; + private static Module findModule(PsiElement element) { + return Optional.ofNullable(element.getContainingFile()) + .map(PsiFile::getVirtualFile) + .map(f -> ModuleUtilCore.findModuleForFile(f, element.getProject())) + .orElse(null); } - } - private static QuickFixFactory factory() { - return QuickFixFactory.getInstance(); - } + @RequiredReadAction + private static HighlightInfo moduleResolveError(PsiJavaModuleReferenceElement refElement, PsiPolyVariantReference ref) { + if (ref.multiResolve(true).length == 0) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF) + .range(refElement) + .descriptionAndTooltip(JavaErrorLocalize.moduleNotFound(refElement.getReferenceText())) + .create(); + } + else if (ref.multiResolve(false).length > 1) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING) + .range(refElement) + .descriptionAndTooltip(JavaErrorLocalize.moduleAmbiguous(refElement.getReferenceText())) + .create(); + } + else { + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF) + .range(refElement) + .descriptionAndTooltip(JavaErrorLocalize.moduleNotOnPath(refElement.getReferenceText())) + .create(); + factory().registerOrderEntryFixes(ref); + return info; + } + } - private static TextRange range(PsiJavaModule module) { - PsiKeyword kw = PsiTreeUtil.getChildOfType(module, PsiKeyword.class); - return new TextRange(kw != null ? kw.getTextOffset() : module.getTextOffset(), module.getNameIdentifier().getTextRange().getEndOffset()); - } + private static QuickFixFactory factory() { + return QuickFixFactory.getInstance(); + } - private static PsiElement range(PsiJavaCodeReferenceElement refElement) { - return ObjectUtil.notNull(refElement.getReferenceNameElement(), refElement); - } + @RequiredReadAction + private static TextRange range(PsiJavaModule module) { + PsiKeyword kw = PsiTreeUtil.getChildOfType(module, PsiKeyword.class); + return new TextRange( + kw != null ? kw.getTextOffset() : module.getTextOffset(), + module.getNameIdentifier().getTextRange().getEndOffset() + ); + } + + private static PsiElement range(PsiJavaCodeReferenceElement refElement) { + return ObjectUtil.notNull(refElement.getReferenceNameElement(), refElement); + } } \ No newline at end of file diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/PostHighlightingVisitor.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/PostHighlightingVisitor.java index fa69c6e755..5714704446 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/PostHighlightingVisitor.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInsight/daemon/impl/analysis/PostHighlightingVisitor.java @@ -63,6 +63,7 @@ import consulo.language.pom.PomNamedTarget; import consulo.language.psi.*; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import consulo.logging.Logger; import consulo.project.Project; import jakarta.annotation.Nonnull; @@ -525,7 +526,7 @@ private HighlightInfo processMethod( else { key = method.isConstructor() ? "constructor.is.not.used" : "method.is.not.used"; } - String symbolName = HighlightMessageUtil.getSymbolName(method, PsiSubstitutor.EMPTY); + LocalizeValue symbolName = HighlightMessageUtil.getSymbolName(method, PsiSubstitutor.EMPTY); String message = JavaErrorBundle.message(key, symbolName); final HighlightInfo highlightInfo = UnusedSymbolUtil.createUnusedSymbolInfo(identifier, message, myDeadCodeInfoType); QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(method), myDeadCodeKey); diff --git a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/deprecation/DeprecationInspection.java b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/deprecation/DeprecationInspection.java index b2b411a2c7..b707c5d362 100644 --- a/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/deprecation/DeprecationInspection.java +++ b/java-analysis-impl/src/main/java/com/intellij/java/analysis/impl/codeInspection/deprecation/DeprecationInspection.java @@ -35,6 +35,7 @@ import consulo.language.psi.PsiElementVisitor; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import java.util.List; @@ -311,7 +312,7 @@ public static void checkDeprecated(PsiElement refElement, String description = null; - String symbolName = HighlightMessageUtil.getSymbolName(refElement, PsiSubstitutor.EMPTY); + LocalizeValue symbolName = HighlightMessageUtil.getSymbolName(refElement, PsiSubstitutor.EMPTY); PsiAnnotation annotation = AnnotationUtil.findAnnotation((PsiModifierListOwner) refElement, DeprecationInfo.class.getName()); if (annotation != null) { String value = AnnotationUtil.getStringAttributeValue(annotation, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME); diff --git a/java-language-impl/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.language.impl.JavaErrorLocalize.yaml b/java-language-impl/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.language.impl.JavaErrorLocalize.yaml index f1f15b0bbc..6cd86d92c1 100644 --- a/java-language-impl/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.language.impl.JavaErrorLocalize.yaml +++ b/java-language-impl/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.language.impl.JavaErrorLocalize.yaml @@ -774,3 +774,31 @@ error.cannot.resolve.class: text: Cannot resolve class ''{0}'' error.cannot.resolve.class.or.package: text: Cannot resolve class or package ''{0}'' +generic.extend.exception: + text: Generic class may not extend 'java.lang.Throwable' +type.parameter.has.incompatible.upper.bounds: + text: "Type parameter {0} has incompatible upper bounds: {1}" +actual.type.argument.contradict.inferred.type: + text: Actual type argument and inferred type contradict each other +type.parameter.cannot.be.followed.by.other.bounds: + text: Type parameter cannot be followed by other bounds +text.class.inherits.abstract.and.default: + text: "{0} inherits abstract and default for {1} from types {2} and {3}" +text.class.inherits.unrelated.defaults: + text: "{0} inherits unrelated defaults for {1} from types {2}" +cannot.select.from.parameterized.type: + text: Cannot access class object of parameterized type +class.cannot.inherit.from.its.type.parameter: + text: Class cannot inherit from its type parameter +text.improper.formed.type: + text: Improper formed type; some type parameters are missing +safevarargs.not.allowed.on.methods.with.fixed.arity: + text: "@SafeVarargs is not allowed on methods with fixed arity" +safevararg.annotation.cannot.be.applied.for.record.component: + text: "@SafeVarargs is not allowed on a record component" +safevarargs.not.suppress.potentially.unsafe.operations: + text: "@SafeVarargs do not suppress potentially unsafe operations" +safevarargs.not.applicable.for.reifiable.types: + text: "@SafeVarargs is not applicable for reifiable types" +safevarargs.not.allowed.non.final.instance.methods: + text: "@SafeVarargs is not allowed on non-final instance methods" \ No newline at end of file