diff --git a/java-analysis-api/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.analysis.JavaAnalysisLocalize.yaml b/java-analysis-api/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.analysis.JavaAnalysisLocalize.yaml index 67b1f0856..275842ee7 100644 --- a/java-analysis-api/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.analysis.JavaAnalysisLocalize.yaml +++ b/java-analysis-api/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.analysis.JavaAnalysisLocalize.yaml @@ -44,8 +44,8 @@ contract.return.validator.return.type.must.be.boolean: text: method return type must be 'boolean' contract.return.validator.too.few.parameters: text: not applicable for method that has {0, choice, 0#no parameters|1#one parameter|2#{0} parameters} -contract.return.value.validation.prefix: - text: 'Contract return value ''''{0}'''':' +contract.return.value.validation.problem: + text: 'Contract return value ''''{0}'''': {1}' convert.0.to.float: text: Convert ''{0}'' to float custom.exception.class.should.have.a.constructor: @@ -663,9 +663,9 @@ inspection.message.nullable.method.implements.non.null.method: inspection.module.exports.package.to.itself: text: Module exports/opens package to itself inspection.non.final.field.in.immutable.display.name: - text: Non-final field in @Immutable class + text: Non-final field in '@Immutable' class inspection.non.final.guard.display.name: - text: Non-final @GuardedBy field + text: Non-final '@GuardedBy' field inspection.nullable.problems.NotNull.parameter.overrides.Nullable: text: Parameter annotated @{0} must not override @{1} parameter inspection.nullable.problems.NotNull.parameter.overrides.not.annotated: @@ -877,11 +877,11 @@ mutation.signature.problem.static.method.cannot.mutate.this: navigate.to.overridden.methods.title: text: Overriding methods of {0} non.final.field.code.ref.code.in.immutable.class.loc: - text: 'Non-final field #ref in @Immutable class #loc' + text: 'Non-final field #ref in ''@Immutable'' class #loc' non.final.guarded.by.field.0.loc: - text: 'Non-final @GuardedBy field "{0}" #loc' + text: 'Non-final ''@GuardedBy'' field "{0}" #loc' non.final.guarded.by.field.ref.loc: - text: 'Non-final @GuardedBy field #ref #loc' + text: 'Non-final ''@GuardedBy'' field #ref #loc' non.null.type.argument.is.expected: text: Non-null type argument is expected not.annotated.method.is.used.as.an.override.for.a.method.annotated.with.0: diff --git a/java-analysis-impl/src/main/java/org/jetbrains/java/generate/inspection/ClassHasNoToStringMethodInspection.java b/java-analysis-impl/src/main/java/org/jetbrains/java/generate/inspection/ClassHasNoToStringMethodInspection.java index c36592637..e23f8724f 100644 --- a/java-analysis-impl/src/main/java/org/jetbrains/java/generate/inspection/ClassHasNoToStringMethodInspection.java +++ b/java-analysis-impl/src/main/java/org/jetbrains/java/generate/inspection/ClassHasNoToStringMethodInspection.java @@ -18,9 +18,9 @@ import com.intellij.java.language.codeInsight.TestFrameworks; import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.InheritanceUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.language.editor.inspection.LocalInspectionToolSession; -import consulo.language.editor.inspection.ProblemHighlightType; import consulo.language.editor.inspection.ProblemsHolder; import consulo.language.psi.PsiElementVisitor; import consulo.localize.LocalizeValue; @@ -37,107 +37,112 @@ */ @ExtensionImpl public class ClassHasNoToStringMethodInspection extends AbstractToStringInspection { - @Override - @Nonnull - public LocalizeValue getDisplayName() { - return LocalizeValue.localizeTODO("Class does not override 'toString()' method"); - } + @Override + @Nonnull + public LocalizeValue getDisplayName() { + return LocalizeValue.localizeTODO("Class does not override 'toString()' method"); + } - @Override - @Nonnull - public String getShortName() { - return "ClassHasNoToStringMethod"; - } + @Override + @Nonnull + public String getShortName() { + return "ClassHasNoToStringMethod"; + } - @Nonnull - @Override - public PsiElementVisitor buildVisitor(@Nonnull final ProblemsHolder holder, - boolean isOnTheFly, - LocalInspectionToolSession session, - Object state) { - ClassHasNoToStringMethodInspectionState inspectionState = (ClassHasNoToStringMethodInspectionState)state; - return new JavaElementVisitor() { - @Override - public void visitClass(PsiClass clazz) { - if (AbstractToStringInspection.log.isDebugEnabled()) { - AbstractToStringInspection.log.debug("checkClass: clazz=" + clazz); - } + @Nonnull + @Override + public PsiElementVisitor buildVisitor( + @Nonnull final ProblemsHolder holder, + boolean isOnTheFly, + @Nonnull LocalInspectionToolSession session, + @Nonnull Object state + ) { + ClassHasNoToStringMethodInspectionState inspectionState = (ClassHasNoToStringMethodInspectionState) state; + return new JavaElementVisitor() { + @Override + @RequiredReadAction + public void visitClass(@Nonnull PsiClass clazz) { + if (AbstractToStringInspection.log.isDebugEnabled()) { + AbstractToStringInspection.log.debug("checkClass: clazz=" + clazz); + } - // must be a class - final PsiIdentifier nameIdentifier = clazz.getNameIdentifier(); - if (nameIdentifier == null || clazz.getName() == null) { - return; - } + // must be a class + PsiIdentifier nameIdentifier = clazz.getNameIdentifier(); + if (nameIdentifier == null || clazz.getName() == null) { + return; + } - if (inspectionState.excludeException && InheritanceUtil.isInheritor(clazz, CommonClassNames.JAVA_LANG_THROWABLE)) { - return; - } - if (inspectionState.excludeDeprecated && clazz.isDeprecated()) { - return; - } - if (inspectionState.excludeEnum && clazz.isEnum()) { - return; - } - if (inspectionState.excludeAbstract && clazz.hasModifierProperty(PsiModifier.ABSTRACT)) { - return; - } - if (inspectionState.excludeTestCode && TestFrameworks.getInstance().isTestClass(clazz)) { - return; - } - if (inspectionState.excludeInnerClasses && clazz.getContainingClass() != null) { - return; - } + if (inspectionState.excludeException && InheritanceUtil.isInheritor(clazz, CommonClassNames.JAVA_LANG_THROWABLE)) { + return; + } + if (inspectionState.excludeDeprecated && clazz.isDeprecated()) { + return; + } + if (inspectionState.excludeEnum && clazz.isEnum()) { + return; + } + if (inspectionState.excludeAbstract && clazz.isAbstract()) { + return; + } + if (inspectionState.excludeTestCode && TestFrameworks.getInstance().isTestClass(clazz)) { + return; + } + if (inspectionState.excludeInnerClasses && clazz.getContainingClass() != null) { + return; + } - // if it is an excluded class - then skip - if (StringUtil.isNotEmpty(inspectionState.excludeClassNames)) { - String name = clazz.getName(); - if (name != null && name.matches(inspectionState.excludeClassNames)) { - return; - } - } + // if it is an excluded class - then skip + if (StringUtil.isNotEmpty(inspectionState.excludeClassNames)) { + String name = clazz.getName(); + if (name != null && name.matches(inspectionState.excludeClassNames)) { + return; + } + } - // must have fields - PsiField[] fields = clazz.getFields(); - if (fields.length == 0) { - return; - } + // must have fields + PsiField[] fields = clazz.getFields(); + if (fields.length == 0) { + return; + } - // get list of fields and getter methods supposed to be dumped in the toString method - fields = GenerateToStringUtils.filterAvailableFields(clazz, GenerateToStringContext.getConfig().getFilterPattern()); - PsiMethod[] methods = null; - if (GenerateToStringContext.getConfig().isEnableMethods()) { - // okay 'getters in code generation' is enabled so check - methods = GenerateToStringUtils.filterAvailableMethods(clazz, GenerateToStringContext.getConfig().getFilterPattern()); - } + // get list of fields and getter methods supposed to be dumped in the toString method + fields = GenerateToStringUtils.filterAvailableFields(clazz, GenerateToStringContext.getConfig().getFilterPattern()); + PsiMethod[] methods = null; + if (GenerateToStringContext.getConfig().isEnableMethods()) { + // okay 'getters in code generation' is enabled so check + methods = GenerateToStringUtils.filterAvailableMethods(clazz, GenerateToStringContext.getConfig().getFilterPattern()); + } - // there should be any fields - if (Math.max(fields.length, methods == null ? 0 : methods.length) == 0) { - return; - } + // there should be any fields + if (Math.max(fields.length, methods == null ? 0 : methods.length) == 0) { + return; + } - // okay some fields/getter methods are supposed to dumped, does a toString method exist - final PsiMethod[] toStringMethods = clazz.findMethodsByName("toString", false); - for (PsiMethod method : toStringMethods) { - final PsiParameterList parameterList = method.getParameterList(); - if (parameterList.getParametersCount() == 0) { - // toString() method found - return; - } - } - final PsiMethod[] superMethods = clazz.findMethodsByName("toString", true); - for (PsiMethod method : superMethods) { - final PsiParameterList parameterList = method.getParameterList(); - if (parameterList.getParametersCount() != 0) { - continue; - } - if (method.hasModifierProperty(PsiModifier.FINAL)) { - // final toString() in super class found - return; - } - } - holder.registerProblem(nameIdentifier, "Class '" + clazz.getName() + "' does not override 'toString()' method", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, GenerateToStringQuickFix.getInstance()); - } - }; - } + // okay some fields/getter methods are supposed to dumped, does a toString method exist + PsiMethod[] toStringMethods = clazz.findMethodsByName("toString", false); + for (PsiMethod method : toStringMethods) { + PsiParameterList parameterList = method.getParameterList(); + if (parameterList.getParametersCount() == 0) { + // toString() method found + return; + } + } + PsiMethod[] superMethods = clazz.findMethodsByName("toString", true); + for (PsiMethod method : superMethods) { + PsiParameterList parameterList = method.getParameterList(); + if (parameterList.getParametersCount() != 0) { + continue; + } + if (method.isFinal()) { + // final toString() in super class found + return; + } + } + holder.newProblem(LocalizeValue.of("Class '" + clazz.getName() + "' does not override 'toString()' method")) + .range(nameIdentifier) + .withFixes(GenerateToStringQuickFix.getInstance()) + .create(); + } + }; + } } diff --git a/java-analysis-impl/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.analysis.impl.JavaInspectionsLocalize.yaml b/java-analysis-impl/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.analysis.impl.JavaInspectionsLocalize.yaml index 2135c61d0..dcec36dd9 100644 --- a/java-analysis-impl/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.analysis.impl.JavaInspectionsLocalize.yaml +++ b/java-analysis-impl/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.analysis.impl.JavaInspectionsLocalize.yaml @@ -1592,3 +1592,5 @@ xml.suppressable.for.file.title: text: Suppress for file xml.suppressable.for.tag.title: text: Suppress for tag +inspection.message.redundant.default.parameter.value.assignment: + text: Redundant default parameter value assignment \ No newline at end of file diff --git a/java-intellilang/src/main/java/consulo/java/impl/intelliLang/pattern/PatternAnnotationNotApplicable.java b/java-intellilang/src/main/java/consulo/java/impl/intelliLang/pattern/PatternAnnotationNotApplicable.java index 11a4f53a8..3e96910f1 100644 --- a/java-intellilang/src/main/java/consulo/java/impl/intelliLang/pattern/PatternAnnotationNotApplicable.java +++ b/java-intellilang/src/main/java/consulo/java/impl/intelliLang/pattern/PatternAnnotationNotApplicable.java @@ -31,80 +31,87 @@ import consulo.localize.LocalizeValue; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import org.jetbrains.annotations.NonNls; @ExtensionImpl public class PatternAnnotationNotApplicable extends LocalInspectionTool { + @Nullable + @Override + public Language getLanguage() { + return JavaLanguage.INSTANCE; + } - @Nullable - @Override - public Language getLanguage() { - return JavaLanguage.INSTANCE; - } + @Nonnull + @Override + public HighlightDisplayLevel getDefaultLevel() { + return HighlightDisplayLevel.ERROR; + } - @Nonnull - public HighlightDisplayLevel getDefaultLevel() { - return HighlightDisplayLevel.ERROR; - } + @Override + public boolean isEnabledByDefault() { + return true; + } - public boolean isEnabledByDefault() { - return true; - } + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return PatternValidator.PATTERN_VALIDATION; + } - @Nonnull - public LocalizeValue getGroupDisplayName() { - return PatternValidator.PATTERN_VALIDATION; - } + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return LocalizeValue.localizeTODO("Pattern Annotation not applicable"); + } - @Nonnull - public LocalizeValue getDisplayName() { - return LocalizeValue.localizeTODO("Pattern Annotation not applicable"); - } + @Nonnull + @Override + public PsiElementVisitor buildVisitor(@Nonnull final ProblemsHolder holder, boolean isOnTheFly) { + return new JavaElementVisitor() { + final String annotationName = + Configuration.getProjectInstance(holder.getProject()).getAdvancedConfiguration().getPatternAnnotationClass(); - @Nonnull - public PsiElementVisitor buildVisitor(@Nonnull final ProblemsHolder holder, boolean isOnTheFly) { - return new JavaElementVisitor() { - final String annotationName = Configuration.getProjectInstance(holder.getProject()).getAdvancedConfiguration().getPatternAnnotationClass(); + @Override + public void visitAnnotation(@Nonnull PsiAnnotation annotation) { + String name = annotation.getQualifiedName(); + if (annotationName.equals(name)) { + checkAnnotation(annotation, holder); + } + else if (name != null) { + PsiClass psiClass = JavaPsiFacade.getInstance(annotation.getProject()).findClass(name, annotation.getResolveScope()); + if (psiClass != null && AnnotationUtil.isAnnotated(psiClass, annotationName, false, false)) { + checkAnnotation(annotation, holder); + } + } + } + }; + } - @Override - public void visitAnnotation(PsiAnnotation annotation) { - final String name = annotation.getQualifiedName(); - if (annotationName.equals(name)) { - checkAnnotation(annotation, holder); + private void checkAnnotation(PsiAnnotation annotation, ProblemsHolder holder) { + PsiModifierListOwner owner = PsiTreeUtil.getParentOfType(annotation, PsiModifierListOwner.class); + if (owner instanceof PsiVariable variable) { + PsiType type = variable.getType(); + if (!PsiUtilEx.isString(type)) { + registerProblem(annotation, holder); + } } - else if (name != null) { - final PsiClass psiClass = JavaPsiFacade.getInstance(annotation.getProject()).findClass(name, annotation.getResolveScope()); - if (psiClass != null && AnnotationUtil.isAnnotated(psiClass, annotationName, false, false)) { - checkAnnotation(annotation, holder); - } + else if (owner instanceof PsiMethod method) { + PsiType type = method.getReturnType(); + if (type != null && !PsiUtilEx.isString(type)) { + registerProblem(annotation, holder); + } } - } - }; - } - - private void checkAnnotation(PsiAnnotation annotation, ProblemsHolder holder) { - final PsiModifierListOwner owner = PsiTreeUtil.getParentOfType(annotation, PsiModifierListOwner.class); - if (owner instanceof PsiVariable) { - final PsiType type = ((PsiVariable)owner).getType(); - if (!PsiUtilEx.isString(type)) { - registerProblem(annotation, holder); - } - } - else if (owner instanceof PsiMethod) { - final PsiType type = ((PsiMethod)owner).getReturnType(); - if (type != null && !PsiUtilEx.isString(type)) { - registerProblem(annotation, holder); - } } - } - private void registerProblem(PsiAnnotation annotation, ProblemsHolder holder) { - holder.registerProblem(annotation, "Pattern Annotation is only applicable to elements of type String", new RemoveAnnotationFix(this)); - } + private void registerProblem(PsiAnnotation annotation, ProblemsHolder holder) { + holder.newProblem(LocalizeValue.localizeTODO("Pattern Annotation is only applicable to elements of type String")) + .range(annotation) + .withFix(new RemoveAnnotationFix(this)) + .create(); + } - @Nonnull - @NonNls - public String getShortName() { - return "PatternNotApplicable"; - } + @Nonnull + @Override + public String getShortName() { + return "PatternNotApplicable"; + } } diff --git a/java-intellilang/src/main/java/consulo/java/impl/intelliLang/pattern/PatternValidator.java b/java-intellilang/src/main/java/consulo/java/impl/intelliLang/pattern/PatternValidator.java index e6e7185ec..2b706fcc7 100644 --- a/java-intellilang/src/main/java/consulo/java/impl/intelliLang/pattern/PatternValidator.java +++ b/java-intellilang/src/main/java/consulo/java/impl/intelliLang/pattern/PatternValidator.java @@ -17,6 +17,7 @@ import com.intellij.java.analysis.refactoring.JavaRefactoringActionHandlerFactory; import com.intellij.java.language.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.application.util.CachedValue; import consulo.application.util.CachedValueProvider; @@ -83,45 +84,50 @@ public HighlightDisplayLevel getDefaultLevel() { return HighlightDisplayLevel.WARNING; } - @Override @Nonnull + @Override public LocalizeValue getGroupDisplayName() { return PATTERN_VALIDATION; } - @Override @Nonnull + @Override public LocalizeValue getDisplayName() { return LocalizeValue.localizeTODO("Validate Annotated Patterns"); } - @Override @Nonnull + @Override public String getShortName() { return "PatternValidation"; } - @Override @Nonnull - public PsiElementVisitor buildVisitor(@Nonnull final ProblemsHolder holder, boolean isOnTheFly, LocalInspectionToolSession session, Object state) { + @Override + public PsiElementVisitor buildVisitor( + @Nonnull final ProblemsHolder holder, + boolean isOnTheFly, + @Nonnull LocalInspectionToolSession session, + @Nonnull Object state + ) { PatternValidatorState inspectionState = (PatternValidatorState) state; return new JavaElementVisitor() { - @Override - public final void visitReferenceExpression(PsiReferenceExpression expression) { + @RequiredReadAction + public final void visitReferenceExpression(@Nonnull PsiReferenceExpression expression) { visitExpression(expression); } @Override + @RequiredReadAction public void visitExpression(PsiExpression expression) { - final PsiElement element = expression.getParent(); + PsiElement element = expression.getParent(); if (element instanceof PsiExpressionList) { // this checks method arguments check(expression, holder, false); } - else if (element instanceof PsiNameValuePair) { - final PsiNameValuePair valuePair = (PsiNameValuePair) element; - final String name = valuePair.getName(); + else if (element instanceof PsiNameValuePair valuePair) { + String name = valuePair.getName(); if (name == null || name.equals(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME)) { // check whether @Subst complies with pattern check(expression, holder, true); @@ -130,16 +136,18 @@ else if (element instanceof PsiNameValuePair) { } @Override - public void visitReturnStatement(PsiReturnStatement statement) { - final PsiExpression returnValue = statement.getReturnValue(); + @RequiredReadAction + public void visitReturnStatement(@Nonnull PsiReturnStatement statement) { + PsiExpression returnValue = statement.getReturnValue(); if (returnValue != null) { check(returnValue, holder, false); } } @Override - public void visitVariable(PsiVariable var) { - final PsiExpression initializer = var.getInitializer(); + @RequiredReadAction + public void visitVariable(@Nonnull PsiVariable var) { + PsiExpression initializer = var.getInitializer(); if (initializer != null) { // variable/field initializer check(initializer, holder, false); @@ -147,34 +155,36 @@ public void visitVariable(PsiVariable var) { } @Override - public void visitAssignmentExpression(PsiAssignmentExpression expression) { - final PsiExpression e = expression.getRExpression(); + @RequiredReadAction + public void visitAssignmentExpression(@Nonnull PsiAssignmentExpression expression) { + PsiExpression e = expression.getRExpression(); if (e != null) { check(e, holder, false); } visitExpression(expression); } + @RequiredReadAction private void check(@Nonnull PsiExpression expression, ProblemsHolder holder, boolean isAnnotationValue) { - if (expression instanceof PsiConditionalExpression) { - final PsiConditionalExpression expr = (PsiConditionalExpression) expression; - PsiExpression e = expr.getThenExpression(); + if (expression instanceof PsiConditionalExpression conditional) { + PsiExpression e = conditional.getThenExpression(); if (e != null) { check(e, holder, isAnnotationValue); } - e = expr.getElseExpression(); + e = conditional.getElseExpression(); if (e != null) { check(e, holder, isAnnotationValue); } } else { - final PsiType type = expression.getType(); - // optimiziation: only check expressions of type String + PsiType type = expression.getType(); + // optimization: only check expressions of type String if (type != null && PsiUtilEx.isString(type)) { - final PsiModifierListOwner element; + PsiModifierListOwner element; if (isAnnotationValue) { - final PsiAnnotation psiAnnotation = PsiTreeUtil.getParentOfType(expression, PsiAnnotation.class); - if (psiAnnotation != null && myConfiguration.getAdvancedConfiguration() + PsiAnnotation psiAnnotation = PsiTreeUtil.getParentOfType(expression, PsiAnnotation.class); + if (psiAnnotation != null + && myConfiguration.getAdvancedConfiguration() .getSubstAnnotationClass() .equals(psiAnnotation.getQualifiedName())) { element = PsiTreeUtil.getParentOfType(expression, PsiModifierListOwner.class); @@ -188,7 +198,11 @@ private void check(@Nonnull PsiExpression expression, ProblemsHolder holder, boo } if (element != null && PsiUtilEx.isLanguageAnnotationTarget(element)) { PsiAnnotation[] annotations = - AnnotationUtilEx.getAnnotationFrom(element, myConfiguration.getAdvancedConfiguration().getPatternAnnotationPair(), true); + AnnotationUtilEx.getAnnotationFrom( + element, + myConfiguration.getAdvancedConfiguration().getPatternAnnotationPair(), + true + ); checkExpression(expression, annotations, holder, inspectionState); } } @@ -197,97 +211,111 @@ private void check(@Nonnull PsiExpression expression, ProblemsHolder holder, boo }; } - private void checkExpression(PsiExpression expression, final PsiAnnotation[] annotations, ProblemsHolder holder, PatternValidatorState state) { + @RequiredReadAction + private void checkExpression( + PsiExpression expression, + PsiAnnotation[] annotations, + ProblemsHolder holder, + PatternValidatorState state + ) { if (annotations.length == 0) { return; } - final PsiAnnotation psiAnnotation = annotations[0]; + PsiAnnotation psiAnnotation = annotations[0]; // cache compiled pattern with annotation CachedValue p = psiAnnotation.getUserData(COMPLIED_PATTERN); if (p == null) { - final CachedValueProvider provider = new CachedValueProvider() { - @Override - public Result compute() { - final String pattern = AnnotationUtilEx.calcAnnotationValue(psiAnnotation, "value"); - Pattern p = null; - if (pattern != null) { - try { - p = Pattern.compile(pattern); - } - catch (PatternSyntaxException e) { - // pattern stays null - } + CachedValueProvider provider = () -> { + String pattern = AnnotationUtilEx.calcAnnotationValue(psiAnnotation, "value"); + Pattern p1 = null; + if (pattern != null) { + try { + p1 = Pattern.compile(pattern); + } + catch (PatternSyntaxException e) { + // pattern stays null } - return Result.create(p, (Object[]) annotations); } + return CachedValueProvider.Result.create(p1, (Object[]) annotations); }; p = CachedValuesManager.getManager(expression.getProject()).createCachedValue(provider, false); psiAnnotation.putUserData(COMPLIED_PATTERN, p); } - final Pattern pattern = p.getValue(); + Pattern pattern = p.getValue(); if (pattern == null) { return; } - List nonConstantElements = new SmartList(); - final Object result = new SubstitutedExpressionEvaluationHelper(expression.getProject()).computeExpression(expression, - myConfiguration.getAdvancedConfiguration() - .getDfaOption(), + List nonConstantElements = new SmartList<>(); + Object result = new SubstitutedExpressionEvaluationHelper(expression.getProject()).computeExpression( + expression, + myConfiguration.getAdvancedConfiguration().getDfaOption(), false, - nonConstantElements); - final String o = result == null ? null : String.valueOf(result); + nonConstantElements + ); + String o = result == null ? null : String.valueOf(result); if (o != null) { if (!pattern.matcher(o).matches()) { if (annotations.length > 1) { // the last element contains the element's actual annotation - final String fqn = annotations[annotations.length - 1].getQualifiedName(); + String fqn = annotations[annotations.length - 1].getQualifiedName(); assert fqn != null; - final String name = StringUtil.getShortName(fqn); - holder.registerProblem(expression, - MessageFormat.format("Expression ''{0}'' doesn''t match ''{1}'' pattern: {2}", - o, - name, - pattern.pattern())); + String name = StringUtil.getShortName(fqn); + holder.newProblem(LocalizeValue.localizeTODO( + MessageFormat.format("Expression ''{0}'' doesn''t match ''{1}'' pattern: {2}", o, name, pattern.pattern()) + )) + .range(expression) + .create(); } else { - holder.registerProblem(expression, MessageFormat.format("Expression ''{0}'' doesn''t match pattern: {1}", o, pattern.pattern())); + holder.newProblem(LocalizeValue.localizeTODO( + MessageFormat.format("Expression ''{0}'' doesn''t match pattern: {1}", o, pattern.pattern()) + )) + .range(expression) + .create(); } } } else if (state.CHECK_NON_CONSTANT_VALUES) { for (PsiExpression expr : nonConstantElements) { - final PsiElement e; - if (expr instanceof PsiReferenceExpression) { - e = ((PsiReferenceExpression) expr).resolve(); + PsiElement e; + if (expr instanceof PsiReferenceExpression refExpr) { + e = refExpr.resolve(); } - else if (expr instanceof PsiMethodCallExpression) { - e = ((PsiMethodCallExpression) expr).getMethodExpression().resolve(); + else if (expr instanceof PsiMethodCallExpression call) { + e = call.getMethodExpression().resolve(); } else { e = expr; } - final PsiModifierListOwner owner = e instanceof PsiModifierListOwner ? (PsiModifierListOwner) e : null; + PsiModifierListOwner owner = e instanceof PsiModifierListOwner modifierListOwner ? modifierListOwner : null; LocalQuickFix quickFix; if (owner != null && PsiUtilEx.isLanguageAnnotationTarget(owner)) { - PsiAnnotation[] resolvedAnnos = - AnnotationUtilEx.getAnnotationFrom(owner, myConfiguration.getAdvancedConfiguration().getPatternAnnotationPair(), true); - if (resolvedAnnos.length == 2 && annotations.length == 2 && Comparing.strEqual(resolvedAnnos[1].getQualifiedName(), - annotations[1].getQualifiedName())) { + PsiAnnotation[] resolvedAnnos = AnnotationUtilEx.getAnnotationFrom( + owner, + myConfiguration.getAdvancedConfiguration().getPatternAnnotationPair(), + true + ); + if (resolvedAnnos.length == 2 && annotations.length == 2 + && Comparing.strEqual(resolvedAnnos[1].getQualifiedName(), annotations[1].getQualifiedName())) { // both target and source annotated indirectly with the same anno return; } - final String classname = myConfiguration.getAdvancedConfiguration().getSubstAnnotationPair().first; - final AnnotateFix fix = new AnnotateFix((PsiModifierListOwner) e, classname); + String className = myConfiguration.getAdvancedConfiguration().getSubstAnnotationPair().first; + AnnotateFix fix = new AnnotateFix((PsiModifierListOwner) e, className); quickFix = fix.canApply() ? fix : new IntroduceVariableFix(expr); } else { quickFix = new IntroduceVariableFix(expr); } - holder.registerProblem(expr, "Unsubstituted expression", quickFix); + holder.newProblem(LocalizeValue.of("Unsubstituted expression")) + .range(expr) + .withFix(quickFix) + .create(); } } } @@ -306,12 +334,10 @@ public LocalizeValue getName() { } @Override - public void applyFix(@Nonnull final Project project, @Nonnull ProblemDescriptor descriptor) { - final RefactoringActionHandler handler = JavaRefactoringActionHandlerFactory.getInstance().createIntroduceVariableHandler(); - final AsyncResult dataContextContainer = DataManager.getInstance().getDataContextFromFocus(); - dataContextContainer.doWhenDone(dataContext -> { - handler.invoke(project, new PsiElement[]{myExpr}, dataContext); - }); + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { + RefactoringActionHandler handler = JavaRefactoringActionHandlerFactory.getInstance().createIntroduceVariableHandler(); + AsyncResult dataContextContainer = DataManager.getInstance().getDataContextFromFocus(); + dataContextContainer.doWhenDone(dataContext -> handler.invoke(project, new PsiElement[]{myExpr}, dataContext)); // how to automatically annotate the variable after it has been introduced? } } diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/DefaultAnnotationParamInspection.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/DefaultAnnotationParamInspection.java index 768cb1758..0a125b927 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/DefaultAnnotationParamInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/DefaultAnnotationParamInspection.java @@ -5,10 +5,11 @@ import com.intellij.java.language.codeInsight.AnnotationUtil; import com.intellij.java.language.psi.*; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.annotation.component.ExtensionImpl; -import consulo.application.Application; import consulo.codeEditor.Editor; -import consulo.java.impl.JavaBundle; +import consulo.component.extension.ExtensionPoint; +import consulo.java.analysis.impl.localize.JavaInspectionsLocalize; import consulo.java.localize.JavaLocalize; import consulo.language.editor.inspection.*; import consulo.language.editor.inspection.localize.InspectionLocalize; @@ -18,102 +19,100 @@ import consulo.language.psi.PsiReference; import consulo.localize.LocalizeValue; import consulo.project.Project; -import consulo.util.collection.ContainerUtil; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import org.jetbrains.annotations.Nls; /** * @author Dmitry Avdeev */ @ExtensionImpl public final class DefaultAnnotationParamInspection extends AbstractBaseJavaLocalInspectionTool { - @Nonnull - @Override - public LocalizeValue getDisplayName() { - return JavaLocalize.inspectionDefaultAnnotationParam(); - } + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaLocalize.inspectionDefaultAnnotationParam(); + } - @Override - public boolean isEnabledByDefault() { - return true; - } + @Override + public boolean isEnabledByDefault() { + return true; + } - @Nonnull - @Override - public LocalizeValue getGroupDisplayName() { - return InspectionLocalize.groupNamesDeclarationRedundancy(); - } + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.groupNamesDeclarationRedundancy(); + } - @Nonnull - @Override - public String getShortName() { - return "DefaultAnnotationParam"; - } + @Nonnull + @Override + public String getShortName() { + return "DefaultAnnotationParam"; + } - @Nonnull - @Override - public PsiElementVisitor buildVisitorImpl( - @Nonnull ProblemsHolder holder, - boolean isOnTheFly, - LocalInspectionToolSession session, - Object o - ) { - return new JavaElementVisitor() { - @Override - @RequiredReadAction - public void visitNameValuePair(final @Nonnull PsiNameValuePair pair) { - PsiAnnotationMemberValue value = pair.getValue(); - PsiReference reference = pair.getReference(); - if (reference == null) return; - PsiElement element = reference.resolve(); - if (!(element instanceof PsiAnnotationMethod)) return; + @Nonnull + @Override + public PsiElementVisitor buildVisitorImpl( + @Nonnull ProblemsHolder holder, + boolean isOnTheFly, + LocalInspectionToolSession session, + Object o + ) { + return new JavaElementVisitor() { + @Override + @RequiredReadAction + public void visitNameValuePair(@Nonnull PsiNameValuePair pair) { + PsiAnnotationMemberValue value = pair.getValue(); + PsiReference reference = pair.getReference(); + if (!(reference != null && reference.resolve() instanceof PsiAnnotationMethod annotationMethod)) { + return; + } - PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod)element).getDefaultValue(); - if (defaultValue == null) return; + PsiAnnotationMemberValue defaultValue = annotationMethod.getDefaultValue(); + if (defaultValue == null) { + return; + } - if (AnnotationUtil.equal(value, defaultValue)) { - PsiElement elementParent = element.getParent(); - if (elementParent instanceof PsiClass psiClass) { - final String qualifiedName = psiClass.getQualifiedName(); - final String name = ((PsiAnnotationMethod)element).getName(); - if (ContainerUtil.exists( - Application.get().getExtensionList(DefaultAnnotationParamIgnoreFilter.class), - ext -> ext.ignoreAnnotationParam(qualifiedName, name) - )) { - return; + if (AnnotationUtil.equal(value, defaultValue)) { + if (annotationMethod.getParent() instanceof PsiClass psiClass) { + String qualifiedName = psiClass.getQualifiedName(); + String name = annotationMethod.getName(); + ExtensionPoint filters = + psiClass.getApplication().getExtensionPoint(DefaultAnnotationParamIgnoreFilter.class); + if (filters.anyMatchSafe(ext -> ext.ignoreAnnotationParam(qualifiedName, name))) { + return; + } + } + holder.newProblem(JavaInspectionsLocalize.inspectionMessageRedundantDefaultParameterValueAssignment()) + .range(value) + .highlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL) + .withFix(createRemoveParameterFix(value)) + .create(); + } } - } - holder.registerProblem( - value, - JavaBundle.message("inspection.message.redundant.default.parameter.value.assignment"), - ProblemHighlightType.LIKE_UNUSED_SYMBOL, - createRemoveParameterFix(value) - ); - } - } - }; - } + }; + } - @Nonnull - private static LocalQuickFix createRemoveParameterFix(PsiAnnotationMemberValue value) { - return new LocalQuickFixAndIntentionActionOnPsiElement(value) { - @Nonnull - @Override - public LocalizeValue getText() { - return JavaLocalize.quickfixFamilyRemoveRedundantParameter(); - } + @Nonnull + private static LocalQuickFix createRemoveParameterFix(PsiAnnotationMemberValue value) { + return new LocalQuickFixAndIntentionActionOnPsiElement(value) { + @Nonnull + @Override + public LocalizeValue getText() { + return JavaLocalize.quickfixFamilyRemoveRedundantParameter(); + } - @Override - public void invoke( - @Nonnull Project project, - @Nonnull PsiFile psiFile, - @Nullable Editor editor, - @Nonnull PsiElement psiElement, - @Nonnull PsiElement psiElement1 - ) { - psiElement.getParent().delete(); - } - }; - } + @Override + @RequiredWriteAction + public void invoke( + @Nonnull Project project, + @Nonnull PsiFile psiFile, + @Nullable Editor editor, + @Nonnull PsiElement startElement, + @Nonnull PsiElement endElement + ) { + startElement.getParent().delete(); + } + }; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/InstanceGuardedByStaticInspection.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/InstanceGuardedByStaticInspection.java index 14418227a..0e0360849 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/InstanceGuardedByStaticInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/InstanceGuardedByStaticInspection.java @@ -19,7 +19,9 @@ import com.intellij.java.analysis.impl.codeInspection.concurrencyAnnotations.JCiPUtil; import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.javadoc.PsiDocTag; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.java.analysis.localize.JavaAnalysisLocalize; import consulo.language.editor.inspection.LocalInspectionToolSession; import consulo.language.editor.inspection.ProblemsHolder; import consulo.language.editor.inspection.localize.InspectionLocalize; @@ -30,105 +32,108 @@ @ExtensionImpl public class InstanceGuardedByStaticInspection extends BaseJavaLocalInspectionTool { + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.groupNamesConcurrencyAnnotationIssues(); + } - @Override - @Nonnull - public LocalizeValue getGroupDisplayName() { - return InspectionLocalize.groupNamesConcurrencyAnnotationIssues(); - } - - @Override - @Nonnull - public LocalizeValue getDisplayName() { - return LocalizeValue.localizeTODO("Instance member guarded by static field"); - } - - @Override - @Nonnull - public String getShortName() { - return "InstanceGuardedByStatic"; - } - - @Override - @Nonnull - public PsiElementVisitor buildVisitorImpl(@Nonnull ProblemsHolder holder, - boolean isOnTheFly, - LocalInspectionToolSession session, - Object state) { - return new Visitor(holder); - } + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return JavaAnalysisLocalize.inspectionInstanceGuardedByStaticDisplayName(); + } - private static class Visitor extends JavaElementVisitor { - private final ProblemsHolder myHolder; + @Nonnull + @Override + public String getShortName() { + return "InstanceGuardedByStatic"; + } - public Visitor(ProblemsHolder holder) { - myHolder = holder; + @Nonnull + @Override + public PsiElementVisitor buildVisitorImpl( + @Nonnull ProblemsHolder holder, + boolean isOnTheFly, + LocalInspectionToolSession session, + Object state + ) { + return new Visitor(holder); } + private static class Visitor extends JavaElementVisitor { + private final ProblemsHolder myHolder; - @Override - public void visitDocTag(PsiDocTag psiDocTag) { - super.visitDocTag(psiDocTag); - if (!JCiPUtil.isGuardedByTag(psiDocTag)) { - return; - } - final PsiMember member = PsiTreeUtil.getParentOfType(psiDocTag, PsiMember.class); - if (member == null) { - return; - } - if (member.hasModifierProperty(PsiModifier.STATIC)) { - return; - } - final String guardValue = JCiPUtil.getGuardValue(psiDocTag); + public Visitor(ProblemsHolder holder) { + myHolder = holder; + } - final PsiClass containingClass = PsiTreeUtil.getParentOfType(psiDocTag, PsiClass.class); - if (containingClass == null) { - return; - } - final PsiField guardField = containingClass.findFieldByName(guardValue, true); - if (guardField == null) { - return; - } - if (!guardField.hasModifierProperty(PsiModifier.STATIC)) { - return; - } - myHolder.registerProblem(psiDocTag, "Instance member guarded by static \"" + guardValue + "\" #loc"); - } + @Override + @RequiredReadAction + public void visitDocTag(@Nonnull PsiDocTag psiDocTag) { + super.visitDocTag(psiDocTag); + if (!JCiPUtil.isGuardedByTag(psiDocTag)) { + return; + } + PsiMember member = PsiTreeUtil.getParentOfType(psiDocTag, PsiMember.class); + if (member == null) { + return; + } + if (member.isStatic()) { + return; + } + String guardValue = JCiPUtil.getGuardValue(psiDocTag); - @Override - public void visitAnnotation(PsiAnnotation annotation) { - super.visitAnnotation(annotation); - if (!JCiPUtil.isGuardedByAnnotation(annotation)) { - return; - } - final PsiMember member = PsiTreeUtil.getParentOfType(annotation, PsiMember.class); - if (member == null) { - return; - } - if (member.hasModifierProperty(PsiModifier.STATIC)) { - return; - } - final String guardValue = JCiPUtil.getGuardValue(annotation); - if (guardValue == null) { - return; - } + PsiClass containingClass = PsiTreeUtil.getParentOfType(psiDocTag, PsiClass.class); + if (containingClass == null) { + return; + } + PsiField guardField = containingClass.findFieldByName(guardValue, true); + if (!(guardField != null && guardField.isStatic())) { + return; + } + myHolder.newProblem(JavaAnalysisLocalize.instanceMemberGuardedByStatic0Loc(guardValue)) + .range(psiDocTag) + .create(); + } + + @Override + @RequiredReadAction + public void visitAnnotation(@Nonnull PsiAnnotation annotation) { + super.visitAnnotation(annotation); + if (!JCiPUtil.isGuardedByAnnotation(annotation)) { + return; + } + PsiMember member = PsiTreeUtil.getParentOfType(annotation, PsiMember.class); + if (member == null) { + return; + } + if (member.isStatic()) { + return; + } + String guardValue = JCiPUtil.getGuardValue(annotation); + if (guardValue == null) { + return; + } - final PsiAnnotationMemberValue guardRef = annotation.findAttributeValue("value"); - if (guardRef == null) { - return; - } - final PsiClass containingClass = PsiTreeUtil.getParentOfType(annotation, PsiClass.class); - if (containingClass == null) { - return; - } - final PsiField guardField = containingClass.findFieldByName(guardValue, true); - if (guardField == null) { - return; - } - if (!guardField.hasModifierProperty(PsiModifier.STATIC)) { - return; - } - myHolder.registerProblem(guardRef, "Instance member guarded by static #ref #loc"); + PsiAnnotationMemberValue guardRef = annotation.findAttributeValue("value"); + if (guardRef == null) { + return; + } + PsiClass containingClass = PsiTreeUtil.getParentOfType(annotation, PsiClass.class); + if (containingClass == null) { + return; + } + PsiField guardField = containingClass.findFieldByName(guardValue, true); + if (guardField == null) { + return; + } + if (!guardField.isStatic()) { + return; + } + myHolder.newProblem(JavaAnalysisLocalize.instanceMemberGuardedByStaticRefLoc()) + .range(guardRef) + .create(); + } } - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/NonFinalFieldInImmutableInspection.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/NonFinalFieldInImmutableInspection.java index 46bf858e6..0e7262c96 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/NonFinalFieldInImmutableInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/NonFinalFieldInImmutableInspection.java @@ -20,8 +20,8 @@ import com.intellij.java.language.psi.JavaElementVisitor; import com.intellij.java.language.psi.PsiClass; import com.intellij.java.language.psi.PsiField; -import com.intellij.java.language.psi.PsiModifier; import consulo.annotation.component.ExtensionImpl; +import consulo.java.analysis.localize.JavaAnalysisLocalize; import consulo.language.editor.inspection.LocalInspectionToolSession; import consulo.language.editor.inspection.ProblemsHolder; import consulo.language.editor.inspection.localize.InspectionLocalize; @@ -40,17 +40,17 @@ public LocalizeValue getGroupDisplayName() { @Nonnull @Override public LocalizeValue getDisplayName() { - return LocalizeValue.localizeTODO("Non-final field in @Immutable class"); + return JavaAnalysisLocalize.inspectionNonFinalFieldInImmutableDisplayName(); } - @Override @Nonnull + @Override public String getShortName() { return "NonFinalFieldInImmutable"; } - @Override @Nonnull + @Override public PsiElementVisitor buildVisitorImpl( @Nonnull final ProblemsHolder holder, boolean isOnTheFly, @@ -59,17 +59,19 @@ public PsiElementVisitor buildVisitorImpl( ) { return new JavaElementVisitor() { @Override - public void visitField(PsiField field) { + public void visitField(@Nonnull PsiField field) { super.visitField(field); - if (field.hasModifierProperty(PsiModifier.FINAL)) { + if (field.isFinal()) { return; } - final PsiClass containingClass = field.getContainingClass(); + PsiClass containingClass = field.getContainingClass(); if (containingClass != null) { if (!JCiPUtil.isImmutable(containingClass)) { return; } - holder.registerProblem(field, "Non-final field #ref in @Immutable class #loc"); + holder.newProblem(JavaAnalysisLocalize.nonFinalFieldCodeRefCodeInImmutableClassLoc()) + .range(field) + .create(); } } }; diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/NonFinalGuardInspection.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/NonFinalGuardInspection.java index 94cb9d860..1704c54f8 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/NonFinalGuardInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/concurrencyAnnotations/NonFinalGuardInspection.java @@ -19,7 +19,9 @@ import com.intellij.java.analysis.impl.codeInspection.concurrencyAnnotations.JCiPUtil; import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.javadoc.PsiDocTag; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; +import consulo.java.analysis.localize.JavaAnalysisLocalize; import consulo.language.editor.inspection.LocalInspectionToolSession; import consulo.language.editor.inspection.ProblemsHolder; import consulo.language.editor.inspection.localize.InspectionLocalize; @@ -39,7 +41,7 @@ public LocalizeValue getGroupDisplayName() { @Nonnull @Override public LocalizeValue getDisplayName() { - return LocalizeValue.localizeTODO("Non-final @GuardedBy field"); + return JavaAnalysisLocalize.inspectionNonFinalGuardDisplayName(); } @Override @@ -64,60 +66,62 @@ private static class Visitor extends JavaElementVisitor { private final ProblemsHolder myHolder; public Visitor(ProblemsHolder holder) { - myHolder = holder; } @Override - public void visitAnnotation(PsiAnnotation annotation) { + @RequiredReadAction + public void visitAnnotation(@Nonnull PsiAnnotation annotation) { super.visitAnnotation(annotation); if (!JCiPUtil.isGuardedByAnnotation(annotation)) { return; } - final String guardValue = JCiPUtil.getGuardValue(annotation); + String guardValue = JCiPUtil.getGuardValue(annotation); if (guardValue == null || "this".equals(guardValue)) { return; } - final PsiClass containingClass = PsiTreeUtil.getParentOfType(annotation, PsiClass.class); + PsiClass containingClass = PsiTreeUtil.getParentOfType(annotation, PsiClass.class); if (containingClass == null) { return; } - final PsiField guardField = containingClass.findFieldByName(guardValue, true); + PsiField guardField = containingClass.findFieldByName(guardValue, true); if (guardField == null) { return; } - if (guardField.hasModifierProperty(PsiModifier.FINAL)) { + if (guardField.isFinal()) { return; } - final PsiAnnotationMemberValue member = annotation.findAttributeValue("value"); + PsiAnnotationMemberValue member = annotation.findAttributeValue("value"); if (member == null) { return; } - myHolder.registerProblem(member, "Non-final @GuardedBy field #ref #loc"); + myHolder.newProblem(JavaAnalysisLocalize.nonFinalGuardedByFieldRefLoc()) + .range(member) + .create(); } @Override - public void visitDocTag(PsiDocTag psiDocTag) { + @RequiredReadAction + public void visitDocTag(@Nonnull PsiDocTag psiDocTag) { super.visitDocTag(psiDocTag); if (!JCiPUtil.isGuardedByTag(psiDocTag)) { return; } - final String guardValue = JCiPUtil.getGuardValue(psiDocTag); + String guardValue = JCiPUtil.getGuardValue(psiDocTag); if ("this".equals(guardValue)) { return; } - final PsiClass containingClass = PsiTreeUtil.getParentOfType(psiDocTag, PsiClass.class); + PsiClass containingClass = PsiTreeUtil.getParentOfType(psiDocTag, PsiClass.class); if (containingClass == null) { return; } - final PsiField guardField = containingClass.findFieldByName(guardValue, true); - if (guardField == null) { - return; - } - if (guardField.hasModifierProperty(PsiModifier.FINAL)) { + PsiField guardField = containingClass.findFieldByName(guardValue, true); + if (guardField == null || guardField.isFinal()) { return; } - myHolder.registerProblem(psiDocTag, "Non-final @GuardedBy field \"" + guardValue + "\" #loc"); + myHolder.newProblem(JavaAnalysisLocalize.nonFinalGuardedByField0Loc(guardValue)) + .range(psiDocTag) + .create(); } } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/dataFlow/ContractInspection.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/dataFlow/ContractInspection.java index 06ddfd8b8..cee5fc305 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/dataFlow/ContractInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/dataFlow/ContractInspection.java @@ -8,7 +8,6 @@ import com.intellij.java.language.psi.*; import com.siyeh.ig.psiutils.ExpressionUtils; import consulo.annotation.access.RequiredReadAction; -import consulo.application.Application; import consulo.document.util.TextRange; import consulo.language.editor.inspection.LocalInspectionToolSession; import consulo.language.editor.inspection.ProblemsHolder; @@ -36,23 +35,25 @@ public abstract class ContractInspection extends AbstractBaseJavaLocalInspection @Nonnull public PsiElementVisitor buildVisitorImpl( @Nonnull final ProblemsHolder holder, - final boolean isOnTheFly, + boolean isOnTheFly, LocalInspectionToolSession session, Object state ) { return new JavaElementVisitor() { @Override + @RequiredReadAction public void visitMethod(@Nonnull PsiMethod method) { PsiAnnotation annotation = JavaMethodContractUtil.findContractAnnotation(method); - if (annotation == null || (!Application.get().isInternal() && AnnotationUtil.isInferredAnnotation(annotation))) { + if (annotation == null || (!method.getApplication().isInternal() && AnnotationUtil.isInferredAnnotation(annotation))) { return; } boolean ownContract = annotation.getOwner() == method.getModifierList(); for (StandardMethodContract contract : JavaMethodContractUtil.getMethodContracts(method)) { - Map errors = ContractChecker.checkContractClause(method, contract, ownContract); - for (Map.Entry entry : errors.entrySet()) { - PsiElement element = entry.getKey(); - holder.registerProblem(element, entry.getValue()); + Map errors = ContractChecker.checkContractClause(method, contract, ownContract); + for (Map.Entry entry : errors.entrySet()) { + holder.newProblem(entry.getValue()) + .range(entry.getKey()) + .create(); } } } @@ -83,7 +84,9 @@ public void visitAnnotation(@Nonnull PsiAnnotation annotation) { error.getRange().getEndOffset() ); } - holder.registerProblem(value, actualRange, error.getMessage()); + holder.newProblem(LocalizeValue.of(error.getMessage())) + .range(value, actualRange) + .create(); } } checkMutationContract(annotation, method); @@ -93,17 +96,19 @@ private void checkMutationContract(PsiAnnotation annotation, PsiMethod method) { String mutationContract = AnnotationUtil.getStringAttributeValue(annotation, MutationSignature.ATTR_MUTATES); if (StringUtil.isNotEmpty(mutationContract)) { boolean pure = Boolean.TRUE.equals(AnnotationUtil.getBooleanAttributeValue(annotation, "pure")); - String error; + LocalizeValue error; if (pure) { - error = "Pure method cannot have mutation contract"; + error = LocalizeValue.localizeTODO("Pure method cannot have mutation contract"); } else { error = MutationSignature.checkSignature(mutationContract, method); } - if (error != null) { + if (error != LocalizeValue.empty()) { PsiAnnotationMemberValue value = annotation.findAttributeValue(MutationSignature.ATTR_MUTATES); assert value != null; - holder.registerProblem(value, error); + holder.newProblem(error) + .range(value) + .create(); } } } @@ -155,15 +160,15 @@ public static ParseException checkContract(PsiMethod method, String text) { if (!PsiType.BOOLEAN.equals(type) && !type.equalsToText(CommonClassNames.JAVA_LANG_BOOLEAN)) { LocalizeValue message = LocalizeValue.localizeTODO( "Contract clause '" + contract + "': parameter #" + (i + 1) + " has '" + - type.getPresentableText() + "' type (expected boolean)" + type.getPresentableText() + "' type (expected boolean)" ); return ParseException.forConstraint(message, text, clauseIndex, i); } break; } } - LocalizeValue problem = LocalizeValue.localizeTODO(contract.getReturnValue().getMethodCompatibilityProblem(method)); - if (problem != null) { + LocalizeValue problem = contract.getReturnValue().getMethodCompatibilityProblem(method); + if (problem != LocalizeValue.empty()) { return ParseException.forReturnValue(problem, text, clauseIndex); } if (possibleContracts != null) { diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/dataFlow/EditContractIntention.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/dataFlow/EditContractIntention.java index d0b51adc1..42106cdea 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/dataFlow/EditContractIntention.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/dataFlow/EditContractIntention.java @@ -12,26 +12,25 @@ import com.intellij.java.language.psi.PsiAnnotation; import com.intellij.java.language.psi.PsiMethod; import com.intellij.java.language.psi.PsiModifierListOwner; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; -import consulo.application.ApplicationManager; import consulo.codeEditor.Editor; import consulo.language.editor.DaemonCodeAnalyzer; import consulo.language.editor.intention.BaseIntentionAction; import consulo.language.editor.intention.IntentionMetaData; import consulo.language.editor.intention.LowPriorityAction; -import consulo.language.psi.PsiElement; import consulo.language.psi.PsiFile; import consulo.language.util.IncorrectOperationException; import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.*; import consulo.ui.ex.awt.event.DocumentAdapter; import consulo.util.lang.StringUtil; +import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import org.jetbrains.annotations.Contract; -import jakarta.annotation.Nonnull; - import javax.swing.*; import javax.swing.event.DocumentEvent; import java.awt.*; @@ -43,172 +42,182 @@ @ExtensionImpl @IntentionMetaData(ignoreId = "id.EditContractIntention", fileExtensions = "java", categories = {"Java", "Annotations"}) public class EditContractIntention extends BaseIntentionAction implements LowPriorityAction { - private static final String ourPrompt = "Please specify the contract text

" + - "Example: _, null -> false
" + - "See intention action description for more details"; - - public EditContractIntention() { - setText(LocalizeValue.localizeTODO("Edit method contract")); - } - - @Nullable - private static PsiMethod getTargetMethod(Editor editor, PsiFile file) { - final PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(file, editor.getCaretModel().getOffset(), true); - if (owner instanceof PsiMethod && ExternalAnnotationsManagerImpl.areExternalAnnotationsApplicable(owner)) { - PsiElement original = owner.getOriginalElement(); - return original instanceof PsiMethod ? (PsiMethod)original : (PsiMethod)owner; + private static final String ourPrompt = "Please specify the contract text

" + + "Example: _, null -> false
" + + "See intention action description for more details"; + + public EditContractIntention() { + setText(LocalizeValue.localizeTODO("Edit method contract")); } - return null; - } - - @Override - public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { - final PsiMethod method = getTargetMethod(editor, file); - if (method != null) { - boolean hasContract = JavaMethodContractUtil.findContractAnnotation(method) != null; - setText(LocalizeValue.localizeTODO(hasContract ? "Edit method contract of '" + method.getName() + "'" : "Add method contract to '" + method.getName() + "'")); - return true; + + @Nullable + @RequiredReadAction + private static PsiMethod getTargetMethod(Editor editor, PsiFile file) { + PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(file, editor.getCaretModel().getOffset(), true); + if (owner instanceof PsiMethod ownerMethod && ExternalAnnotationsManagerImpl.areExternalAnnotationsApplicable(owner)) { + return owner.getOriginalElement() instanceof PsiMethod originalMethod ? originalMethod : ownerMethod; + } + return null; } - return false; - } - - @Override - public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - final PsiMethod method = getTargetMethod(editor, file); - assert method != null; - PsiAnnotation existingAnno = AnnotationUtil.findAnnotationInHierarchy(method, Collections.singleton(Contract.class.getName())); - String oldContract = existingAnno == null ? null : AnnotationUtil.getStringAttributeValue(existingAnno, "value"); - boolean oldPure = existingAnno != null && Boolean.TRUE.equals(AnnotationUtil.getBooleanAttributeValue(existingAnno, "pure")); - String oldMutates = existingAnno == null ? null : AnnotationUtil.getStringAttributeValue(existingAnno, "mutates"); - - JBTextField contractText = new JBTextField(oldContract); - JBTextField mutatesText = new JBTextField(oldMutates); - JCheckBox pureCB = createPureCheckBox(oldPure); - DialogBuilder builder = createDialog(project, contractText, pureCB, mutatesText); - DocumentAdapter validator = new DocumentAdapter() { - @Override - protected void textChanged(@Nonnull DocumentEvent e) { - String contractError = getContractErrorMessage(contractText.getText(), method); - if (contractError != null) { - builder.setOkActionEnabled(false); - builder.setErrorText(contractError, contractText); + + @Override + @RequiredReadAction + public boolean isAvailable(@Nonnull Project project, Editor editor, PsiFile file) { + PsiMethod method = getTargetMethod(editor, file); + if (method != null) { + boolean hasContract = JavaMethodContractUtil.findContractAnnotation(method) != null; + setText(LocalizeValue.localizeTODO( + hasContract ? "Edit method contract of '" + method.getName() + "'" : "Add method contract to '" + method.getName() + "'" + )); + return true; } - else { - String mutatesError = getMutatesErrorMessage(mutatesText.getText(), method); - if (mutatesError != null) { - builder.setOkActionEnabled(false); - builder.setErrorText(mutatesError, mutatesText); - } - else { - builder.setOkActionEnabled(true); - builder.setErrorText(null); - } + return false; + } + + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + final PsiMethod method = getTargetMethod(editor, file); + assert method != null; + PsiAnnotation existingAnno = AnnotationUtil.findAnnotationInHierarchy(method, Collections.singleton(Contract.class.getName())); + String oldContract = existingAnno == null ? null : AnnotationUtil.getStringAttributeValue(existingAnno, "value"); + boolean oldPure = existingAnno != null && Boolean.TRUE.equals(AnnotationUtil.getBooleanAttributeValue(existingAnno, "pure")); + String oldMutates = existingAnno == null ? null : AnnotationUtil.getStringAttributeValue(existingAnno, "mutates"); + + JBTextField contractText = new JBTextField(oldContract); + JBTextField mutatesText = new JBTextField(oldMutates); + JCheckBox pureCB = createPureCheckBox(oldPure); + DialogBuilder builder = createDialog(project, contractText, pureCB, mutatesText); + DocumentAdapter validator = new DocumentAdapter() { + @Override + protected void textChanged(@Nonnull DocumentEvent e) { + String contractError = getContractErrorMessage(contractText.getText(), method); + if (contractError != null) { + builder.setOkActionEnabled(false); + builder.setErrorText(contractError, contractText); + } + else { + LocalizeValue mutatesError = getMutatesErrorMessage(mutatesText.getText(), method); + if (mutatesError != LocalizeValue.empty()) { + builder.setOkActionEnabled(false); + builder.setErrorText(mutatesError.get(), mutatesText); + } + else { + builder.setOkActionEnabled(true); + builder.setErrorText(null); + } + } + } + }; + Runnable updateControls = () -> { + if (pureCB.isSelected()) { + mutatesText.setText(""); + mutatesText.setEnabled(false); + } + else { + mutatesText.setEnabled(true); + } + }; + pureCB.addChangeListener(e -> updateControls.run()); + contractText.getDocument().addDocumentListener(validator); + mutatesText.getDocument().addDocumentListener(validator); + updateControls.run(); + if (builder.showAndGet()) { + updateContract(method, contractText.getText(), pureCB.isSelected(), mutatesText.getText()); } - } - }; - Runnable updateControls = () -> { - if (pureCB.isSelected()) { - mutatesText.setText(""); - mutatesText.setEnabled(false); - } - else { - mutatesText.setEnabled(true); - } - }; - pureCB.addChangeListener(e -> updateControls.run()); - contractText.getDocument().addDocumentListener(validator); - mutatesText.getDocument().addDocumentListener(validator); - updateControls.run(); - if (builder.showAndGet()) { - updateContract(method, contractText.getText(), pureCB.isSelected(), mutatesText.getText()); } - } - - private static DialogBuilder createDialog(@Nonnull Project project, - JBTextField contractText, - JCheckBox pureCB, - JBTextField mutatesText) { - JPanel panel = new JPanel(new GridBagLayout()); - - GridBagConstraints constraints = - new GridBagConstraints(0, 0, 2, 1, 4.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, JBUI.insets(2), 0, 0); - panel.add(Messages.configureMessagePaneUi(new JTextPane(), ourPrompt), constraints); - constraints.gridx = 0; - constraints.gridy = 1; - constraints.gridwidth = 1; - constraints.weightx = 1; - JLabel contractLabel = new JLabel("Contract:"); - contractLabel.setDisplayedMnemonic('c'); - contractLabel.setLabelFor(contractText); - panel.add(contractLabel, constraints); - constraints.gridx = 1; - constraints.weightx = 3; - panel.add(contractText, constraints); - constraints.gridx = 0; - constraints.gridy = 2; - constraints.gridwidth = 2; - constraints.weightx = 4; - panel.add(pureCB, constraints); - panel.add(pureCB, constraints); - if (ApplicationManager.getApplication().isInternal()) { - constraints.gridx = 0; - constraints.gridy = 3; - constraints.weightx = 1; - constraints.gridwidth = 1; - JLabel mutatesLabel = new JLabel("Mutates:"); - mutatesLabel.setDisplayedMnemonic('m'); - mutatesLabel.setLabelFor(mutatesText); - panel.add(mutatesLabel, constraints); - constraints.gridx = 1; - constraints.weightx = 3; - panel.add(mutatesText, constraints); + + private static DialogBuilder createDialog( + @Nonnull Project project, + JBTextField contractText, + JCheckBox pureCB, + JBTextField mutatesText + ) { + JPanel panel = new JPanel(new GridBagLayout()); + + GridBagConstraints constraints = + new GridBagConstraints(0, 0, 2, 1, 4.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, JBUI.insets(2), 0, 0); + panel.add(Messages.configureMessagePaneUi(new JTextPane(), ourPrompt), constraints); + constraints.gridx = 0; + constraints.gridy = 1; + constraints.gridwidth = 1; + constraints.weightx = 1; + JLabel contractLabel = new JLabel("Contract:"); + contractLabel.setDisplayedMnemonic('c'); + contractLabel.setLabelFor(contractText); + panel.add(contractLabel, constraints); + constraints.gridx = 1; + constraints.weightx = 3; + panel.add(contractText, constraints); + constraints.gridx = 0; + constraints.gridy = 2; + constraints.gridwidth = 2; + constraints.weightx = 4; + panel.add(pureCB, constraints); + panel.add(pureCB, constraints); + if (project.getApplication().isInternal()) { + constraints.gridx = 0; + constraints.gridy = 3; + constraints.weightx = 1; + constraints.gridwidth = 1; + JLabel mutatesLabel = new JLabel("Mutates:"); + mutatesLabel.setDisplayedMnemonic('m'); + mutatesLabel.setLabelFor(mutatesText); + panel.add(mutatesLabel, constraints); + constraints.gridx = 1; + constraints.weightx = 3; + panel.add(mutatesText, constraints); + } + + DialogBuilder builder = new DialogBuilder(project).setNorthPanel(panel).title("Edit Method Contract"); + builder.setPreferredFocusComponent(contractText); + builder.setHelpId("define_contract_dialog"); + return builder; + } + + private static JCheckBox createPureCheckBox(boolean selected) { + JCheckBox pureCB = new NonFocusableCheckBox("Method is pure (has no side effects)"); + pureCB.setMnemonic('p'); + pureCB.setSelected(selected); + return pureCB; + } + + private static void updateContract(PsiMethod method, String contract, boolean pure, String mutates) { + Project project = method.getProject(); + ExternalAnnotationsManager manager = ExternalAnnotationsManager.getInstance(project); + manager.deannotate(method, JavaMethodContractUtil.ORG_JETBRAINS_ANNOTATIONS_CONTRACT); + PsiAnnotation mockAnno = DefaultInferredAnnotationProvider.createContractAnnotation(project, pure, contract, mutates); + if (mockAnno != null) { + try { + manager.annotateExternally( + method, + JavaMethodContractUtil.ORG_JETBRAINS_ANNOTATIONS_CONTRACT, + method.getContainingFile(), + mockAnno.getParameterList().getAttributes() + ); + } + catch (ExternalAnnotationsManager.CanceledConfigurationException ignored) { + } + } + DaemonCodeAnalyzer.getInstance(project).restart(); } - DialogBuilder builder = new DialogBuilder(project).setNorthPanel(panel).title("Edit Method Contract"); - builder.setPreferredFocusComponent(contractText); - builder.setHelpId("define_contract_dialog"); - return builder; - } - - private static JCheckBox createPureCheckBox(boolean selected) { - JCheckBox pureCB = new NonFocusableCheckBox("Method is pure (has no side effects)"); - pureCB.setMnemonic('p'); - pureCB.setSelected(selected); - return pureCB; - } - - private static void updateContract(PsiMethod method, String contract, boolean pure, String mutates) { - Project project = method.getProject(); - ExternalAnnotationsManager manager = ExternalAnnotationsManager.getInstance(project); - manager.deannotate(method, JavaMethodContractUtil.ORG_JETBRAINS_ANNOTATIONS_CONTRACT); - PsiAnnotation mockAnno = DefaultInferredAnnotationProvider.createContractAnnotation(project, pure, contract, mutates); - if (mockAnno != null) { - try { - manager.annotateExternally(method, JavaMethodContractUtil.ORG_JETBRAINS_ANNOTATIONS_CONTRACT, method.getContainingFile(), - mockAnno.getParameterList().getAttributes()); - } - catch (ExternalAnnotationsManager.CanceledConfigurationException ignored) { - } + @Nonnull + private static LocalizeValue getMutatesErrorMessage(String mutates, PsiMethod method) { + return StringUtil.isEmpty(mutates) ? LocalizeValue.empty() : MutationSignature.checkSignature(mutates, method); } - DaemonCodeAnalyzer.getInstance(project).restart(); - } - - @Nullable - private static String getMutatesErrorMessage(String mutates, PsiMethod method) { - return StringUtil.isEmpty(mutates) ? null : MutationSignature.checkSignature(mutates, method); - } - - @Nullable - private static String getContractErrorMessage(String contract, PsiMethod method) { - if (StringUtil.isEmpty(contract)) { - return null; + + @Nullable + private static String getContractErrorMessage(String contract, PsiMethod method) { + if (StringUtil.isEmpty(contract)) { + return null; + } + StandardMethodContract.ParseException error = ContractInspection.checkContract(method, contract); + return error != null ? error.getMessage() : null; + } + + @Override + public boolean startInWriteAction() { + return false; } - StandardMethodContract.ParseException error = ContractInspection.checkContract(method, contract); - return error != null ? error.getMessage() : null; - } - - @Override - public boolean startInWriteAction() { - return false; - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/defUse/DefUseInspectionBase.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/defUse/DefUseInspectionBase.java index e519b350a..abc56b13b 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/defUse/DefUseInspectionBase.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/defUse/DefUseInspectionBase.java @@ -29,7 +29,6 @@ import consulo.localize.LocalizeValue; import consulo.ui.ex.awt.JBUI; import jakarta.annotation.Nonnull; -import org.jetbrains.annotations.NonNls; import javax.swing.*; import java.awt.*; @@ -39,208 +38,204 @@ import java.util.Set; public abstract class DefUseInspectionBase extends BaseJavaBatchLocalInspectionTool { - public boolean REPORT_PREFIX_EXPRESSIONS = false; - public boolean REPORT_POSTFIX_EXPRESSIONS = true; - public boolean REPORT_REDUNDANT_INITIALIZER = true; - - @NonNls - public static final String SHORT_NAME = "UnusedAssignment"; - - @Override - @Nonnull - public PsiElementVisitor buildVisitorImpl(@Nonnull final ProblemsHolder holder, - final boolean isOnTheFly, - LocalInspectionToolSession session, - Object state) { - return new JavaElementVisitor() { - @Override - @RequiredReadAction - public void visitMethod(PsiMethod method) { - checkCodeBlock(method.getBody(), holder, isOnTheFly); - } - - @Override - public void visitClassInitializer(PsiClassInitializer initializer) { - checkCodeBlock(initializer.getBody(), holder, isOnTheFly); - } - }; - } - - @RequiredReadAction - private void checkCodeBlock( - final PsiCodeBlock body, - final ProblemsHolder holder, - final boolean isOnTheFly - ) { - if (body == null) return; - final Set usedVariables = new HashSet<>(); - List unusedDefs = DefUseUtil.getUnusedDefs(body, usedVariables); - - if (unusedDefs != null && !unusedDefs.isEmpty()) { - Collections.sort( - unusedDefs, - (o1, o2) -> { - int offset1 = o1.getContext().getTextOffset(); - int offset2 = o2.getContext().getTextOffset(); - - if (offset1 == offset2) return 0; - if (offset1 < offset2) return -1; - - return 1; - } - ); - - for (DefUseUtil.Info info : unusedDefs) { - PsiElement context = info.getContext(); - PsiVariable psiVariable = info.getVariable(); - - if (context instanceof PsiDeclarationStatement || context instanceof PsiResourceVariable) { - if (!info.isRead()) { - if (!isOnTheFly) { - holder.registerProblem( - psiVariable.getNameIdentifier(), - InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor1("#ref #loc").get(), - ProblemHighlightType.LIKE_UNUSED_SYMBOL - ); + public boolean REPORT_PREFIX_EXPRESSIONS = false; + public boolean REPORT_POSTFIX_EXPRESSIONS = true; + public boolean REPORT_REDUNDANT_INITIALIZER = true; + + public static final String SHORT_NAME = "UnusedAssignment"; + + @Override + @Nonnull + public PsiElementVisitor buildVisitorImpl( + @Nonnull final ProblemsHolder holder, + final boolean isOnTheFly, + LocalInspectionToolSession session, + Object state + ) { + return new JavaElementVisitor() { + @Override + @RequiredReadAction + public void visitMethod(@Nonnull PsiMethod method) { + checkCodeBlock(method.getBody(), holder, isOnTheFly); } - } else { - if (REPORT_REDUNDANT_INITIALIZER) { - holder.registerProblem( - psiVariable.getInitializer(), - InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor2( - "" + psiVariable.getName() + "", - "#ref #loc" - ).get(), - ProblemHighlightType.LIKE_UNUSED_SYMBOL, - createRemoveInitializerFix() - ); + + @Override + @RequiredReadAction + public void visitClassInitializer(@Nonnull PsiClassInitializer initializer) { + checkCodeBlock(initializer.getBody(), holder, isOnTheFly); } - } - } else if (context instanceof PsiAssignmentExpression assignment) { - holder.registerProblem( - assignment.getLExpression(), - InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor3( - assignment.getRExpression().getText(), - "#ref" + " #loc" - ).get(), - ProblemHighlightType.LIKE_UNUSED_SYMBOL - ); - } else { - if (context instanceof PsiPrefixExpression && REPORT_PREFIX_EXPRESSIONS || - context instanceof PsiPostfixExpression && REPORT_POSTFIX_EXPRESSIONS) { - holder.registerProblem( - context, - InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor4("#ref #loc").get() - ); - } - } - } + }; } - body.accept(new JavaRecursiveElementWalkingVisitor() { - @Override - public void visitClass(PsiClass aClass) { - } - - @Override - public void visitLocalVariable(PsiLocalVariable variable) { - if (!usedVariables.contains(variable) && variable.getInitializer() == null && !isOnTheFly) { - holder.registerProblem( - variable.getNameIdentifier(), - InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor5("#ref #loc").get(), - ProblemHighlightType.LIKE_UNUSED_SYMBOL - ); + @RequiredReadAction + private void checkCodeBlock(PsiCodeBlock body, final ProblemsHolder holder, final boolean isOnTheFly) { + if (body == null) { + return; } - } - - @Override - @RequiredReadAction - public void visitAssignmentExpression(PsiAssignmentExpression expression) { - PsiExpression lExpression = expression.getLExpression(); - PsiExpression rExpression = expression.getRExpression(); - - if (lExpression instanceof PsiReferenceExpression lRef && rExpression instanceof PsiReferenceExpression rRef) { - if (lRef.resolve() != rRef.resolve()) return; - PsiExpression lQualifier = lRef.getQualifierExpression(); - PsiExpression rQualifier = rRef.getQualifierExpression(); - - if ((lQualifier == null && rQualifier == null || - lQualifier instanceof PsiThisExpression && rQualifier instanceof PsiThisExpression || - lQualifier instanceof PsiThisExpression && rQualifier == null || - lQualifier == null && rQualifier instanceof PsiThisExpression) && !isOnTheFly) { - holder.registerProblem( - expression, - InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor6("#ref").get() + final Set usedVariables = new HashSet<>(); + List unusedDefs = DefUseUtil.getUnusedDefs(body, usedVariables); + + if (unusedDefs != null && !unusedDefs.isEmpty()) { + Collections.sort( + unusedDefs, + (o1, o2) -> { + int offset1 = o1.getContext().getTextOffset(); + int offset2 = o2.getContext().getTextOffset(); + + if (offset1 == offset2) { + return 0; + } + if (offset1 < offset2) { + return -1; + } + + return 1; + } ); - } + + for (DefUseUtil.Info info : unusedDefs) { + PsiElement context = info.getContext(); + PsiVariable psiVariable = info.getVariable(); + + if (context instanceof PsiDeclarationStatement || context instanceof PsiResourceVariable) { + if (!info.isRead()) { + if (!isOnTheFly) { + holder.newProblem(InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor1("#ref #loc")) + .range(psiVariable.getNameIdentifier()) + .highlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL) + .create(); + } + } + else if (REPORT_REDUNDANT_INITIALIZER) { + holder.newProblem(InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor2( + "" + psiVariable.getName() + "", + "#ref #loc" + )) + .range(psiVariable.getInitializer()) + .highlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL) + .withFix(createRemoveInitializerFix()) + .create(); + } + } + else if (context instanceof PsiAssignmentExpression assignment) { + holder.newProblem(InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor3( + assignment.getRExpression().getText(), + "#ref" + " #loc" + )) + .range(assignment.getLExpression()) + .highlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL) + .create(); + } + else if (context instanceof PsiPrefixExpression && REPORT_PREFIX_EXPRESSIONS + || context instanceof PsiPostfixExpression && REPORT_POSTFIX_EXPRESSIONS) { + holder.newProblem(InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor4("#ref #loc")) + .range(context) + .create(); + } + } } - } - }); - } - - protected LocalQuickFix createRemoveInitializerFix() { - return null; - } - - @Override - public JComponent createOptionsPanel() { - return new OptionsPanel(); - } - - private class OptionsPanel extends JPanel { - private final JCheckBox myReportPrefix; - private final JCheckBox myReportPostfix; - private final JCheckBox myReportInitializer; - - private OptionsPanel() { - super(new GridBagLayout()); - - GridBagConstraints gc = new GridBagConstraints(); - gc.weighty = 0; - gc.weightx = 1; - gc.fill = GridBagConstraints.HORIZONTAL; - gc.anchor = GridBagConstraints.NORTHWEST; - - myReportInitializer = new JCheckBox(InspectionLocalize.inspectionUnusedAssignmentOption2().get()); - myReportInitializer.setSelected(REPORT_REDUNDANT_INITIALIZER); - myReportInitializer.getModel().addChangeListener(e -> REPORT_REDUNDANT_INITIALIZER = myReportInitializer.isSelected()); - gc.insets = JBUI.insetsBottom(15); - gc.gridy = 0; - add(myReportInitializer, gc); - - myReportPrefix = new JCheckBox(InspectionLocalize.inspectionUnusedAssignmentOption().get()); - myReportPrefix.setSelected(REPORT_PREFIX_EXPRESSIONS); - myReportPrefix.getModel().addChangeListener(e -> REPORT_PREFIX_EXPRESSIONS = myReportPrefix.isSelected()); - gc.insets = JBUI.emptyInsets(); - gc.gridy++; - add(myReportPrefix, gc); - - myReportPostfix = new JCheckBox(InspectionLocalize.inspectionUnusedAssignmentOption1().get()); - myReportPostfix.setSelected(REPORT_POSTFIX_EXPRESSIONS); - myReportPostfix.getModel().addChangeListener(e-> REPORT_POSTFIX_EXPRESSIONS = myReportPostfix.isSelected()); - - gc.weighty = 1; - gc.gridy++; - add(myReportPostfix, gc); + + body.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitClass(@Nonnull PsiClass aClass) { + } + + @Override + public void visitLocalVariable(@Nonnull PsiLocalVariable variable) { + if (!usedVariables.contains(variable) && variable.getInitializer() == null && !isOnTheFly) { + holder.newProblem(InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor5("#ref #loc")) + .range(variable.getNameIdentifier()) + .highlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL) + .create(); + } + } + + @Override + @RequiredReadAction + public void visitAssignmentExpression(@Nonnull PsiAssignmentExpression expression) { + if (expression.getLExpression() instanceof PsiReferenceExpression lRef + && expression.getRExpression() instanceof PsiReferenceExpression rRef) { + if (lRef.resolve() != rRef.resolve()) { + return; + } + PsiExpression lQualifier = lRef.getQualifierExpression(); + PsiExpression rQualifier = rRef.getQualifierExpression(); + + if ((lQualifier == null && rQualifier == null + || lQualifier instanceof PsiThisExpression && rQualifier instanceof PsiThisExpression + || lQualifier instanceof PsiThisExpression && rQualifier == null + || lQualifier == null && rQualifier instanceof PsiThisExpression) && !isOnTheFly) { + holder.newProblem(InspectionLocalize.inspectionUnusedAssignmentProblemDescriptor6("#ref")) + .range(expression) + .create(); + } + } + } + }); + } + + protected LocalQuickFix createRemoveInitializerFix() { + return null; + } + + @Override + public JComponent createOptionsPanel() { + return new OptionsPanel(); + } + + private class OptionsPanel extends JPanel { + private final JCheckBox myReportPrefix; + private final JCheckBox myReportPostfix; + private final JCheckBox myReportInitializer; + + private OptionsPanel() { + super(new GridBagLayout()); + + GridBagConstraints gc = new GridBagConstraints(); + gc.weighty = 0; + gc.weightx = 1; + gc.fill = GridBagConstraints.HORIZONTAL; + gc.anchor = GridBagConstraints.NORTHWEST; + + myReportInitializer = new JCheckBox(InspectionLocalize.inspectionUnusedAssignmentOption2().get()); + myReportInitializer.setSelected(REPORT_REDUNDANT_INITIALIZER); + myReportInitializer.getModel().addChangeListener(e -> REPORT_REDUNDANT_INITIALIZER = myReportInitializer.isSelected()); + gc.insets = JBUI.insetsBottom(15); + gc.gridy = 0; + add(myReportInitializer, gc); + + myReportPrefix = new JCheckBox(InspectionLocalize.inspectionUnusedAssignmentOption().get()); + myReportPrefix.setSelected(REPORT_PREFIX_EXPRESSIONS); + myReportPrefix.getModel().addChangeListener(e -> REPORT_PREFIX_EXPRESSIONS = myReportPrefix.isSelected()); + gc.insets = JBUI.emptyInsets(); + gc.gridy++; + add(myReportPrefix, gc); + + myReportPostfix = new JCheckBox(InspectionLocalize.inspectionUnusedAssignmentOption1().get()); + myReportPostfix.setSelected(REPORT_POSTFIX_EXPRESSIONS); + myReportPostfix.getModel().addChangeListener(e -> REPORT_POSTFIX_EXPRESSIONS = myReportPostfix.isSelected()); + + gc.weighty = 1; + gc.gridy++; + add(myReportPostfix, gc); + } + } + + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return InspectionLocalize.inspectionUnusedAssignmentDisplayName(); + } + + @Nonnull + @Override + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.groupNamesProbableBugs(); + } + + @Nonnull + @Override + public String getShortName() { + return SHORT_NAME; } - } - - - @Override - @Nonnull - public LocalizeValue getDisplayName() { - return InspectionLocalize.inspectionUnusedAssignmentDisplayName(); - } - - @Override - @Nonnull - public LocalizeValue getGroupDisplayName() { - return InspectionLocalize.groupNamesProbableBugs(); - } - - @Override - @Nonnull - public String getShortName() { - return SHORT_NAME; - } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/duplicateStringLiteral/DuplicateStringLiteralInspection.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/duplicateStringLiteral/DuplicateStringLiteralInspection.java index 6d4eaf1b8..d0d4a4936 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/duplicateStringLiteral/DuplicateStringLiteralInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/duplicateStringLiteral/DuplicateStringLiteralInspection.java @@ -54,7 +54,6 @@ import consulo.util.lang.StringUtil; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import org.jetbrains.annotations.NonNls; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -67,7 +66,7 @@ public class DuplicateStringLiteralInspection extends BaseLocalInspectionTool { public int MIN_STRING_LENGTH = 5; @SuppressWarnings({"WeakerAccess"}) public boolean IGNORE_PROPERTY_KEYS = false; - @NonNls + private static final String BR = "
"; @Override @@ -80,11 +79,12 @@ public PsiElementVisitor buildVisitorImpl( ) { return new JavaElementVisitor() { @Override - public void visitReferenceExpression(@Nonnull final PsiReferenceExpression expression) { + public void visitReferenceExpression(@Nonnull PsiReferenceExpression expression) { visitExpression(expression); } @Override + @RequiredReadAction public void visitLiteralExpression(@Nonnull PsiLiteralExpression expression) { checkStringLiteralExpression(expression, holder, isOnTheFly); } @@ -111,39 +111,37 @@ public String getShortName() { @RequiredReadAction private void checkStringLiteralExpression( - @Nonnull final PsiLiteralExpression originalExpression, + @Nonnull PsiLiteralExpression originalExpression, @Nonnull ProblemsHolder holder, - final boolean isOnTheFly + boolean isOnTheFly ) { - Object value = originalExpression.getValue(); - if (!(value instanceof String)) { + if (!(originalExpression.getValue() instanceof String stringToFind)) { return; } - final Project project = holder.getProject(); + Project project = holder.getProject(); if (!shouldCheck(project, originalExpression)) { return; } - final String stringToFind = (String) value; if (stringToFind.isEmpty()) { return; } - final GlobalSearchScope scope = GlobalSearchScope.projectScope(originalExpression.getProject()); - final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(holder.getFile().getProject()); - final List words = StringUtil.getWordsIn(stringToFind); + GlobalSearchScope scope = GlobalSearchScope.projectScope(originalExpression.getProject()); + PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(holder.getFile().getProject()); + List words = StringUtil.getWordsIn(stringToFind); if (words.isEmpty()) { return; } // put longer strings first Collections.sort(words, (o1, o2) -> o2.length() - o1.length()); - final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); + ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); Set resultFiles = null; for (String word : words) { if (word.length() < MIN_STRING_LENGTH) { continue; } progress.checkCanceled(); - final Set files = new HashSet<>(); + Set files = new HashSet<>(); searchHelper.processAllFilesWithWordInLiterals(word, scope, new CommonProcessors.CollectProcessor<>(files)); if (resultFiles == null) { resultFiles = files; @@ -159,9 +157,9 @@ private void checkStringLiteralExpression( if (resultFiles == null || resultFiles.isEmpty()) { return; } - final List foundExpr = new ArrayList<>(); + List foundExpr = new ArrayList<>(); - for (final PsiFile file : resultFiles) { + for (PsiFile file : resultFiles) { progress.checkCanceled(); FileViewProvider viewProvider = file.getViewProvider(); // important: skip non-java files with given word in literal (IDEA-126201) @@ -171,20 +169,26 @@ private void checkStringLiteralExpression( CharSequence text = viewProvider.getContents(); StringSearcher searcher = new StringSearcher(stringToFind, true, true); - LowLevelSearchUtil.processTextOccurrences(text, 0, text.length(), searcher, progress, offset -> { - PsiElement element = file.findElementAt(offset); - if (element == null || !(element.getParent() instanceof PsiLiteralExpression)) { + LowLevelSearchUtil.processTextOccurrences( + text, + 0, + text.length(), + searcher, + progress, + offset -> { + PsiElement element = file.findElementAt(offset); + if (element == null || !(element.getParent() instanceof PsiLiteralExpression)) { + return true; + } + PsiLiteralExpression expression = (PsiLiteralExpression) element.getParent(); + if (expression != originalExpression + && Comparing.equal(stringToFind, expression.getValue()) + && shouldCheck(project, expression)) { + foundExpr.add(expression); + } return true; } - PsiLiteralExpression expression = (PsiLiteralExpression) element.getParent(); - if (expression != originalExpression && Comparing.equal( - stringToFind, - expression.getValue() - ) && shouldCheck(project, expression)) { - foundExpr.add(expression); - } - return true; - }); + ); } if (foundExpr.isEmpty()) { return; @@ -211,13 +215,16 @@ private void checkStringLiteralExpression( String classList; if (isOnTheFly) { - classList = StringUtil.join(tenClassesMost, aClass -> { - final boolean thisFile = aClass.getContainingFile() == originalExpression.getContainingFile(); - //noinspection HardCodedStringLiteral - return "   '" + aClass.getQualifiedName() + "'" + - (thisFile ? " " + InspectionLocalize.inspectionDuplicatesMessageInThisFile().get() - : ""); - }, ", " + BR); + classList = StringUtil.join( + tenClassesMost, + aClass -> { + boolean thisFile = aClass.getContainingFile() == originalExpression.getContainingFile(); + //noinspection HardCodedStringLiteral + return "   '" + aClass.getQualifiedName() + "'" + + (thisFile ? " " + InspectionLocalize.inspectionDuplicatesMessageInThisFile() : ""); + }, + ", " + BR + ); } else { classList = StringUtil.join(tenClassesMost, aClass -> "'" + aClass.getQualifiedName() + "'", ", "); @@ -227,16 +234,16 @@ private void checkStringLiteralExpression( classList += BR + InspectionLocalize.inspectionDuplicatesMessageMore(classes.size() - 10).get(); } - String msg = InspectionLocalize.inspectionDuplicatesMessage(classList).get(); - Collection fixes = new SmartList<>(); if (isOnTheFly) { - final LocalQuickFix introduceConstFix = createIntroduceConstFix(foundExpr, originalExpression); + LocalQuickFix introduceConstFix = createIntroduceConstFix(foundExpr, originalExpression); fixes.add(introduceConstFix); } createReplaceFixes(foundExpr, originalExpression, fixes); - LocalQuickFix[] array = fixes.toArray(new LocalQuickFix[fixes.size()]); - holder.registerProblem(originalExpression, msg, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, array); + holder.newProblem(InspectionLocalize.inspectionDuplicatesMessage(classList)) + .range(originalExpression) + .withFixes(fixes) + .create(); } private boolean shouldCheck(@Nonnull Project project, @Nonnull PsiLiteralExpression expression) { @@ -245,23 +252,20 @@ private boolean shouldCheck(@Nonnull Project project, @Nonnull PsiLiteralExpress } private static void createReplaceFixes( - final List foundExpr, - final PsiLiteralExpression originalExpression, - final Collection fixes + List foundExpr, + PsiLiteralExpression originalExpression, + Collection fixes ) { Set constants = new HashSet<>(); for (Iterator iterator = foundExpr.iterator(); iterator.hasNext(); ) { PsiExpression expression1 = iterator.next(); - PsiElement parent = expression1.getParent(); - if (parent instanceof PsiField field) { - if (field.getInitializer() == expression1 && field.hasModifierProperty(PsiModifier.STATIC)) { - constants.add(field); - iterator.remove(); - } + if (expression1.getParent() instanceof PsiField field && field.getInitializer() == expression1 && field.isStatic()) { + constants.add(field); + iterator.remove(); } } - for (final PsiField constant : constants) { - final PsiClass containingClass = constant.getContainingClass(); + for (PsiField constant : constants) { + PsiClass containingClass = constant.getContainingClass(); if (containingClass == null) { continue; } @@ -270,16 +274,13 @@ private static void createReplaceFixes( if (!isAccessible && containingClass.getQualifiedName() == null) { continue; } - final LocalQuickFix replaceQuickFix = new ReplaceFix(constant, originalExpression); + LocalQuickFix replaceQuickFix = new ReplaceFix(constant, originalExpression); fixes.add(replaceQuickFix); } } - private static LocalQuickFix createIntroduceConstFix( - final List foundExpr, - final PsiLiteralExpression originalExpression - ) { - final PsiExpression[] expressions = foundExpr.toArray(new PsiExpression[foundExpr.size() + 1]); + private static LocalQuickFix createIntroduceConstFix(List foundExpr, PsiLiteralExpression originalExpression) { + PsiExpression[] expressions = foundExpr.toArray(new PsiExpression[foundExpr.size() + 1]); expressions[foundExpr.size()] = originalExpression; return new IntroduceLiteralConstantFix(expressions); @@ -287,17 +288,15 @@ private static LocalQuickFix createIntroduceConstFix( @Nullable @RequiredWriteAction - private static PsiReferenceExpression createReferenceTo( - final PsiField constant, - final PsiLiteralExpression context - ) throws IncorrectOperationException { + private static PsiReferenceExpression createReferenceTo(PsiField constant, PsiLiteralExpression context) + throws IncorrectOperationException { PsiElementFactory factory = JavaPsiFacade.getInstance(constant.getProject()).getElementFactory(); PsiReferenceExpression reference = (PsiReferenceExpression) factory.createExpressionFromText(constant.getName(), context); if (reference.isReferenceTo(constant)) { return reference; } reference = (PsiReferenceExpression) factory.createExpressionFromText("XXX." + constant.getName(), null); - final PsiReferenceExpression classQualifier = (PsiReferenceExpression) reference.getQualifierExpression(); + PsiReferenceExpression classQualifier = (PsiReferenceExpression) reference.getQualifierExpression(); PsiClass containingClass = constant.getContainingClass(); if (containingClass.getQualifiedName() == null) { return null; @@ -322,7 +321,7 @@ public JComponent createOptionsPanel() { .addActionListener(e -> IGNORE_PROPERTY_KEYS = optionsPanel.myIgnorePropertyKeyExpressions.isSelected()); optionsPanel.myMinStringLengthField.getDocument().addDocumentListener(new DocumentAdapter() { @Override - protected void textChanged(final DocumentEvent e) { + protected void textChanged(DocumentEvent e) { try { MIN_STRING_LENGTH = Integer.parseInt(optionsPanel.myMinStringLengthField.getText()); } @@ -344,7 +343,7 @@ public static class OptionsPanel { private static class IntroduceLiteralConstantFix implements LocalQuickFix { private final SmartPsiElementPointer[] myExpressions; - public IntroduceLiteralConstantFix(final PsiExpression[] expressions) { + public IntroduceLiteralConstantFix(PsiExpression[] expressions) { myExpressions = new SmartPsiElementPointer[expressions.length]; for (int i = 0; i < expressions.length; i++) { PsiExpression expression = expressions[i]; @@ -360,20 +359,20 @@ public LocalizeValue getName() { } @Override - public void applyFix(@Nonnull final Project project, @Nonnull ProblemDescriptor descriptor) { + public void applyFix(@Nonnull Project project, @Nonnull ProblemDescriptor descriptor) { SwingUtilities.invokeLater(() -> { if (project.isDisposed()) { return; } - final List expressions = new ArrayList<>(); + List expressions = new ArrayList<>(); for (SmartPsiElementPointer ptr : myExpressions) { - final PsiElement element = ptr.getElement(); + PsiElement element = ptr.getElement(); if (element != null) { expressions.add((PsiExpression) element); } } final PsiExpression[] expressionArray = expressions.toArray(new PsiExpression[expressions.size()]); - final IntroduceConstantHandlerImpl handler = new IntroduceConstantHandlerImpl() { + IntroduceConstantHandlerImpl handler = new IntroduceConstantHandlerImpl() { @Override protected OccurrenceManager createOccurrenceManager(PsiExpression selectedExpr, PsiClass parentClass) { final OccurrenceFilter filter = occurrence -> true; @@ -425,14 +424,14 @@ public void invoke( @Nonnull PsiElement startElement, @Nonnull PsiElement endElement ) { - final PsiLiteralExpression myOriginalExpression = (PsiLiteralExpression) startElement; - final PsiField myConstant = myConst.getElement(); - if (myConstant == null || !FileModificationService.getInstance() - .prepareFileForWrite(myOriginalExpression.getContainingFile())) { + PsiLiteralExpression myOriginalExpression = (PsiLiteralExpression) startElement; + PsiField myConstant = myConst.getElement(); + if (myConstant == null + || !FileModificationService.getInstance().prepareFileForWrite(myOriginalExpression.getContainingFile())) { return; } try { - final PsiReferenceExpression reference = createReferenceTo(myConstant, myOriginalExpression); + PsiReferenceExpression reference = createReferenceTo(myConstant, myOriginalExpression); if (reference != null) { myOriginalExpression.replace(reference); } diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/duplicateThrows/DuplicateThrowsInspection.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/duplicateThrows/DuplicateThrowsInspection.java index c47b17b70..2017729d9 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/duplicateThrows/DuplicateThrowsInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/duplicateThrows/DuplicateThrowsInspection.java @@ -33,82 +33,86 @@ @ExtensionImpl public class DuplicateThrowsInspection extends BaseLocalInspectionTool { + @SuppressWarnings("PublicField") + public boolean ignoreSubclassing = false; - @SuppressWarnings("PublicField") - public boolean ignoreSubclassing = false; + @Override + @Nonnull + public LocalizeValue getDisplayName() { + return InspectionLocalize.inspectionDuplicateThrowsDisplayName(); + } - @Override - @Nonnull - public LocalizeValue getDisplayName() { - return InspectionLocalize.inspectionDuplicateThrowsDisplayName(); - } + @Override + public boolean isEnabledByDefault() { + return true; + } - @Override - public boolean isEnabledByDefault() { - return true; - } + @Override + @Nonnull + public LocalizeValue getGroupDisplayName() { + return InspectionLocalize.groupNamesDeclarationRedundancy(); + } - @Override - @Nonnull - public LocalizeValue getGroupDisplayName() { - return InspectionLocalize.groupNamesDeclarationRedundancy(); - } + @Override + @Nonnull + public String getShortName() { + return "DuplicateThrows"; + } - @Override - @Nonnull - public String getShortName() { - return "DuplicateThrows"; - } + @Nullable + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel( + InspectionLocalize.inspectionDuplicateThrowsIgnoreSubclassingOption().get(), + this, + "ignoreSubclassing" + ); + } - @Nullable - @Override - public JComponent createOptionsPanel() { - return new SingleCheckboxOptionsPanel( - InspectionLocalize.inspectionDuplicateThrowsIgnoreSubclassingOption().get(), - this, - "ignoreSubclassing" - ); - } + @Override + @Nonnull + public PsiElementVisitor buildVisitorImpl( + @Nonnull final ProblemsHolder holder, + boolean isOnTheFly, + LocalInspectionToolSession session, + Object state + ) { + return new JavaElementVisitor() { - @Override - @Nonnull - public PsiElementVisitor buildVisitorImpl( - @Nonnull final ProblemsHolder holder, - boolean isOnTheFly, - LocalInspectionToolSession session, - Object state - ) { - return new JavaElementVisitor() { - - @Override public void visitMethod(@Nonnull PsiMethod method) { - PsiReferenceList throwsList = method.getThrowsList(); - PsiJavaCodeReferenceElement[] refs = throwsList.getReferenceElements(); - PsiClassType[] types = throwsList.getReferencedTypes(); - for (int i = 0; i < types.length; i++) { - PsiClassType type = types[i]; - for (int j = i+1; j < types.length; j++) { - PsiClassType otherType = types[j]; - LocalizeValue problem = null; - PsiJavaCodeReferenceElement ref = refs[i]; - if (type.equals(otherType)) { - problem = InspectionLocalize.inspectionDuplicateThrowsProblem(); - } - else if (!ignoreSubclassing) { - if (otherType.isAssignableFrom(type)) { - problem = InspectionLocalize.inspectionDuplicateThrowsMoreGeneralProblem(otherType.getCanonicalText()); - } - else if (type.isAssignableFrom(otherType)) { - problem = InspectionLocalize.inspectionDuplicateThrowsMoreGeneralProblem(type.getCanonicalText()); - ref = refs[j]; - type = otherType; - } - } - if (problem != null) { - holder.registerProblem(ref, problem.get(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, new DeleteThrowsFix(method, type)); + @Override + public void visitMethod(@Nonnull PsiMethod method) { + PsiReferenceList throwsList = method.getThrowsList(); + PsiJavaCodeReferenceElement[] refs = throwsList.getReferenceElements(); + PsiClassType[] types = throwsList.getReferencedTypes(); + for (int i = 0; i < types.length; i++) { + PsiClassType type = types[i]; + for (int j = i + 1; j < types.length; j++) { + PsiClassType otherType = types[j]; + LocalizeValue problem = LocalizeValue.empty(); + PsiJavaCodeReferenceElement ref = refs[i]; + if (type.equals(otherType)) { + problem = InspectionLocalize.inspectionDuplicateThrowsProblem(); + } + else if (!ignoreSubclassing) { + if (otherType.isAssignableFrom(type)) { + problem = InspectionLocalize.inspectionDuplicateThrowsMoreGeneralProblem(otherType.getCanonicalText()); + } + else if (type.isAssignableFrom(otherType)) { + problem = InspectionLocalize.inspectionDuplicateThrowsMoreGeneralProblem(type.getCanonicalText()); + ref = refs[j]; + type = otherType; + } + } + if (problem != LocalizeValue.empty()) { + holder.newProblem(problem) + .range(ref) + .withFixes(new DeleteThrowsFix(method, type)) + .highlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL) + .create(); + } + } + } } - } - } - } - }; - } + }; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/codeInspection/miscGenerics/SuspiciousCollectionsMethodCallsInspection.java b/plugin/src/main/java/com/intellij/java/impl/codeInspection/miscGenerics/SuspiciousCollectionsMethodCallsInspection.java index 58ca1b5ca..236c45fae 100644 --- a/plugin/src/main/java/com/intellij/java/impl/codeInspection/miscGenerics/SuspiciousCollectionsMethodCallsInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/codeInspection/miscGenerics/SuspiciousCollectionsMethodCallsInspection.java @@ -8,6 +8,7 @@ import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.MethodSignature; import com.intellij.java.language.psi.util.PsiUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.deadCodeNotWorking.impl.SingleCheckboxOptionsPanel; import consulo.java.analysis.localize.JavaAnalysisLocalize; @@ -58,19 +59,20 @@ public JComponent createOptionsPanel() { ); } - @Override @Nonnull + @Override public PsiElementVisitor buildVisitorImpl( @Nonnull final ProblemsHolder holder, - final boolean isOnTheFly, + boolean isOnTheFly, LocalInspectionToolSession session, Object state ) { final List patternMethods = new ArrayList<>(); return new JavaElementVisitor() { @Override + @RequiredReadAction public void visitMethodCallExpression(@Nonnull PsiMethodCallExpression methodCall) { - final PsiExpression[] args = methodCall.getArgumentList().getExpressions(); + PsiExpression[] args = methodCall.getArgumentList().getExpressions(); if (args.length < 1) { return; } @@ -78,20 +80,23 @@ public void visitMethodCallExpression(@Nonnull PsiMethodCallExpression methodCal String message = getSuspiciousMethodCallMessage(methodCall, REPORT_CONVERTIBLE_METHOD_CALLS, patternMethods, args[idx], idx); if (message != null) { - holder.registerProblem(methodCall.getArgumentList().getExpressions()[idx], message); + holder.newProblem(LocalizeValue.localizeTODO(message)) + .range(methodCall.getArgumentList().getExpressions()[idx]) + .create(); } } } @Override + @RequiredReadAction public void visitMethodReferenceExpression(@Nonnull PsiMethodReferenceExpression expression) { - final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType(); - final PsiClassType.ClassResolveResult functionalInterfaceResolveResult = + PsiType functionalInterfaceType = expression.getFunctionalInterfaceType(); + PsiClassType.ClassResolveResult functionalInterfaceResolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); - final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType); + PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType); if (interfaceMethod != null && interfaceMethod.getParameterList().getParametersCount() == 1) { - final PsiSubstitutor psiSubstitutor = LambdaUtil.getSubstitutor(interfaceMethod, functionalInterfaceResolveResult); - final MethodSignature signature = interfaceMethod.getSignature(psiSubstitutor); + PsiSubstitutor psiSubstitutor = LambdaUtil.getSubstitutor(interfaceMethod, functionalInterfaceResolveResult); + MethodSignature signature = interfaceMethod.getSignature(psiSubstitutor); String message = SuspiciousMethodCallUtil.getSuspiciousMethodCallMessage( expression, signature.getParameterTypes()[0], @@ -100,7 +105,9 @@ public void visitMethodReferenceExpression(@Nonnull PsiMethodReferenceExpression 0 ); if (message != null) { - holder.registerProblem(ObjectUtil.notNull(expression.getReferenceNameElement(), expression), message); + holder.newProblem(LocalizeValue.of(message)) + .range(ObjectUtil.notNull(expression.getReferenceNameElement(), expression)) + .create(); } } } @@ -113,6 +120,7 @@ public String getShortName() { return "SuspiciousMethodCalls"; } + @RequiredReadAction private static String getSuspiciousMethodCallMessage( PsiMethodCallExpression methodCall, boolean reportConvertibleMethodCalls, @@ -122,7 +130,7 @@ private static String getSuspiciousMethodCallMessage( ) { PsiType argType = arg.getType(); boolean exactType = arg instanceof PsiNewExpression; - final String plainMessage = SuspiciousMethodCallUtil + String plainMessage = SuspiciousMethodCallUtil .getSuspiciousMethodCallMessage(methodCall, arg, argType, exactType || reportConvertibleMethodCalls, patternMethods, i); if (plainMessage != null && !exactType) { String methodName = methodCall.getMethodExpression().getReferenceName(); diff --git a/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml b/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml index 538f70a76..5481ced88 100644 --- a/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml +++ b/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml @@ -204,6 +204,10 @@ inline.method.multiline.method.in.ctor.call: text: Inline cannot be applied to multiline method in constructor call inline.method.used.in.javadoc: text: Inlined method is used in javadoc +inline.method.used.in.reflection: + text: Inlined method is used reflectively +inline.method.qualifier.usage.side.effect: + text: Inlined method is used in method reference with side effects in qualifier inline.parameter.cannot.find.initializer.warning.message: text: Cannot find constant initializer for parameter inline.parameter.no.usages.warning.message: