[java-inspections] IDEA-357009 new option to configure custom classes for IncorrectMessageFormatInspection

GitOrigin-RevId: ab026ee405f78ff29519afb0db62449a682b5bd3
This commit is contained in:
Mikhail Pyltsin
2024-09-18 18:48:51 +02:00
committed by intellij-monorepo-bot
parent b1e1776977
commit abb1899900
4 changed files with 83 additions and 5 deletions

View File

@@ -2328,6 +2328,10 @@ inspection.incorrect.message.format.incorrect.quotes.number=Probably incorrect n
inspection.incorrect.message.format.not.found.argument=No argument for index ''{0}''
inspection.incorrect.message.format.not.found.arguments=No arguments for indexes: {0}
inspection.incorrect.message.format.not.used.argument=Argument with index ''{0}'' is not used in the pattern
inspection.incorrect.message.custom.classes.methods=Custom classes and methods:
inspection.incorrect.message.custom.classes=Classes
inspection.incorrect.message.custom.methods=Methods
inspection.incorrect.message.custom.classes.methods.description=Use this inspection setting to mark additional classes and methods as related to string formatting.
# {0} is one of the inspection.incorrect.message.format messages above
inspection.incorrect.message.format.pattern={0} in message format pattern ''{1}''

View File

@@ -1,10 +1,12 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.siyeh.ig.bugs;
import com.intellij.codeInsight.options.JavaClassValidator;
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.dataFlow.CommonDataflow;
import com.intellij.codeInspection.options.OptPane;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.java.PsiEmptyExpressionImpl;
@@ -21,6 +23,54 @@ import java.util.*;
public final class IncorrectMessageFormatInspection extends AbstractBaseJavaLocalInspectionTool {
public List<String> customClasses = new ArrayList<>();
public List<String> customMethods = new ArrayList<>();
@Override
public @NotNull OptPane getOptionsPane() {
return OptPane.pane(
OptPane.table(
InspectionGadgetsBundle.message("inspection.incorrect.message.custom.classes.methods"),
OptPane.column("customClasses", InspectionGadgetsBundle.message("inspection.incorrect.message.custom.classes"),
new JavaClassValidator()),
OptPane.column("customMethods", InspectionGadgetsBundle.message("inspection.incorrect.message.custom.methods"))
).description(InspectionGadgetsBundle.message("inspection.incorrect.message.custom.classes.methods.description"))
);
}
private boolean isCustomPatternMethodCall(@NotNull PsiMethodCallExpression call) {
PsiReferenceExpression methodExpression = call.getMethodExpression();
String methodName = methodExpression.getReferenceName();
if (methodName == null || !customMethods.contains(methodName)) {
return false;
}
PsiMethod method = call.resolveMethod();
if (method == null) return false;
PsiClass containingClass = method.getContainingClass();
if (containingClass == null || !customClasses.contains(containingClass.getQualifiedName())) {
return false;
}
PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != 2) {
return false;
}
PsiType firstArgType = parameters[0].getType();
if (!CommonClassNames.JAVA_LANG_STRING.equals(firstArgType.getCanonicalText())) {
return false;
}
PsiParameter secondParameter = parameters[1];
if (!secondParameter.isVarArgs()) {
return false;
}
return true;
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
@@ -56,7 +106,8 @@ public final class IncorrectMessageFormatInspection extends AbstractBaseJavaLoca
@Override
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
if (MessageFormatUtil.PATTERN_METHODS.test(call)) {
if (MessageFormatUtil.PATTERN_METHODS.test(call) ||
isCustomPatternMethodCall(call)) {
List<MessageFormatUtil.MessageFormatPlaceholder> indexes =
checkStringFormatAndGetIndexes(call.getArgumentList().getExpressions()[0]);
if (indexes != null) {
@@ -257,4 +308,4 @@ public final class IncorrectMessageFormatInspection extends AbstractBaseJavaLoca
case INCORRECT_ORDER_CHOICE_SELECTOR -> InspectionGadgetsBundle.message("inspection.incorrect.message.format.incorrect.order.choice");
};
}
}
}

View File

@@ -0,0 +1,14 @@
package org.example.util;
import java.text.MessageFormat;
class Formatter {
public static String formatNew(String pattern, Object... arguments) {
return MessageFormat.format(pattern, arguments);
}
public static void main(String[] args)
{
final String format2 = formatNew("Hello {0}", "Alice", <warning descr="Argument with index '1' is not used in the pattern">"Bob"</warning>);
}
}

View File

@@ -6,6 +6,8 @@ import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import com.siyeh.ig.LightJavaInspectionTestCase;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class IncorrectMessageFormatInspectionTest extends LightJavaCodeInsightFixtureTestCase {
@Override
protected String getBasePath() {
@@ -18,12 +20,19 @@ public class IncorrectMessageFormatInspectionTest extends LightJavaCodeInsightFi
return JAVA_21;
}
private void doTest() {
myFixture.enableInspections(new IncorrectMessageFormatInspection());
private void doTest(List<String> classes, List<String> methods) {
IncorrectMessageFormatInspection inspection = new IncorrectMessageFormatInspection();
inspection.customClasses.addAll(classes);
inspection.customMethods.addAll(methods);
myFixture.enableInspections(inspection);
myFixture.testHighlighting(getTestName(false) + ".java");
}
public void testIncorrectMessageFormat() {
doTest();
doTest(List.of(), List.of());
}
public void testIncorrectMessageFormatWithCustomMethods() {
doTest(List.of("org.example.util.Formatter"), List.of("formatNew"));
}
}