From 09d46b2382681ccd27fe2d2db3171307eb23d7cc Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Fri, 4 Jul 2025 17:10:14 +0200 Subject: [PATCH] [java] IDEA-371865 Inspection to convert 'System.out'<->'IO' - fixes for comments - simplified replacement - support char[] - support ImplicitArrayToStringInspection GitOrigin-RevId: 49f9f829821a498259aa53ebb12cd0b0007f1238 --- .../com/siyeh/ig/callMatcher/CallMatcher.java | 86 +++++++++++++++++++ .../siyeh/ig/psiutils/ExpressionUtils.java | 9 +- ...citToImplicitClassMigrationInspection.java | 12 +-- .../MigrateFromJavaLangIoInspection.java | 43 +++------- .../MigrateToJavaLangIoInspection.java | 32 ++++--- .../ImplicitArrayToStringIO.java | 18 ++++ .../afterWithSeveralNestedIO.java | 4 + .../beforeWithSeveralNestedIO.java | 6 ++ .../afterPrintUnresolved.java | 3 +- .../beforePrintArrayChar.java | 3 + .../beforePrintUnresolved.java | 2 +- .../afterPrintRegularClass.java | 3 +- .../beforePrintArrayChar.java | 5 ++ .../beforePrintRegularClass.java | 2 +- ...lassMigrationInspectionInspectionTest.java | 1 + .../MigrateFromJavaLangIoInspectionTest.java | 17 ++++ .../MigrateToJavaLangIoInspectionTest.java | 6 +- .../ImplicitArrayToStringInspectionTest.java | 10 +++ 18 files changed, 200 insertions(+), 62 deletions(-) create mode 100644 java/java-tests/testData/ig/com/siyeh/igtest/bugs/implicit_array_to_string/ImplicitArrayToStringIO.java create mode 100644 java/java-tests/testData/inspection/explicitToImplicitClassMigration/afterWithSeveralNestedIO.java create mode 100644 java/java-tests/testData/inspection/explicitToImplicitClassMigration/beforeWithSeveralNestedIO.java create mode 100644 java/java-tests/testData/inspection/migrateFromJavaLangIo/beforePrintArrayChar.java create mode 100644 java/java-tests/testData/inspection/migrateToJavaLangIo/beforePrintArrayChar.java diff --git a/java/java-analysis-impl/src/com/siyeh/ig/callMatcher/CallMatcher.java b/java/java-analysis-impl/src/com/siyeh/ig/callMatcher/CallMatcher.java index 5ce87351658b..075ca42a5ff4 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/callMatcher/CallMatcher.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/callMatcher/CallMatcher.java @@ -304,6 +304,71 @@ public interface CallMatcher extends Predicate { myCallType = callType; } + /** + * Creates a new matcher based on the current matcher, allowing unresolved method calls to be matched. + * This matcher supports verifying unresolved method calls and their context, such as method names, + * qualifier expressions, and class names. + *

+ * The resulting matcher enforces the following criteria for unresolved calls: + * - Method name must match the specified names. + * - The argument list must match certain conditions based on parameter types. + * - Class name must end with qualifier expressions. Qualifier expression should be unresolved. + * - Call type (for example, static/instance) is not checked + *

+ * This matcher supports only {@link #test(PsiMethodCallExpression)} method. + * + * @return a new CallMatcher instance that allows unresolved method calls to be matched + */ + public CallMatcher allowUnresolved() { + return new CallMatcher() { + @Override + public Stream names() { + return Simple.this.names(); + } + + @Override + public boolean methodReferenceMatches(PsiMethodReferenceExpression methodRef) { + throw new UnsupportedOperationException("PsiMethodReferenceExpression is not supported"); + } + + @Override + public boolean test(@Nullable PsiMethodCallExpression call) { + if (Simple.this.test(call)) return true; + if (call == null) return false; + String name = call.getMethodExpression().getReferenceName(); + if (name == null || !myNames.contains(name)) return false; + if (!unresolvedArgumentListMatch(call.getArgumentList())) return false; + PsiMethod method = call.resolveMethod(); + if (method != null) return false; + PsiExpression qualifierExpression = call.getMethodExpression().getQualifierExpression(); + if (!(qualifierExpression instanceof PsiReferenceExpression qualifierRefExpression)) return false; + if (qualifierRefExpression.getQualifierExpression() != null) return false; + String referenceName = qualifierRefExpression.getReferenceName(); + if (referenceName == null && myClassName.isEmpty()) return true; + if (referenceName == null) return false; + if (!myClassName.endsWith(referenceName)) return false; + PsiElement resolvedQualifier = qualifierRefExpression.resolve(); + if (resolvedQualifier != null) return false; + return true; + } + + @Override + public boolean methodMatches(@Nullable PsiMethod method) { + throw new UnsupportedOperationException("PsiMethod is not supported"); + } + + @Override + public boolean uCallMatches(@Nullable UCallExpression call) { + throw new UnsupportedOperationException("UCallExpression is not supported"); + } + + @Override + public boolean uCallableReferenceMatches(@Nullable UCallableReferenceExpression reference) { + throw new UnsupportedOperationException("UCallableReferenceExpression is not supported"); + } + }; + } + @Override public Stream names() { return myNames.stream(); @@ -346,6 +411,13 @@ public interface CallMatcher extends Predicate { return psiType.equalsToText(type) || PsiTypesUtil.classNameEquals(psiType, type); } + private static boolean expressionTypeMatches(@Nullable String type, @NotNull PsiExpression argument) { + if (type == null) return true; + PsiType psiType = argument.getType(); + if (psiType == null) return false; + return psiType.equalsToText(type) || PsiTypesUtil.classNameEquals(psiType, type); + } + @Contract(pure = true) @Override public boolean methodReferenceMatches(PsiMethodReferenceExpression methodRef) { @@ -383,6 +455,20 @@ public interface CallMatcher extends Predicate { Simple::parameterTypeMatches).allMatch(Boolean.TRUE::equals); } + private boolean unresolvedArgumentListMatch(@NotNull PsiExpressionList expressionList) { + if (myParameters == null) return true; + PsiExpression[] args = expressionList.getExpressions(); + if (myParameters.length > 0) { + if (args.length < myParameters.length - 1) return false; + } + for (int i = 0; i < Math.min(myParameters.length, args.length); i++) { + PsiExpression arg = args[i]; + String parameter = myParameters[i]; + if (!expressionTypeMatches(parameter, arg)) return false; + } + return true; + } + @Override @Contract(value = "null -> false", pure = true) public boolean methodMatches(@Nullable PsiMethod method) { diff --git a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/ExpressionUtils.java b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/ExpressionUtils.java index 61b0c49d952f..51e53776af42 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/ExpressionUtils.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/ExpressionUtils.java @@ -1479,10 +1479,11 @@ public final class ExpressionUtils { yield !hasCharArrayParameter(method); } case "print", "println" -> { - if (arguments.length != 1 || hasCharArrayParameter(method)) yield false; - yield JAVA_UTIL_FORMATTER.equals(className) || - InheritanceUtil.isInheritor(containingClass, JAVA_IO_PRINT_STREAM) || - InheritanceUtil.isInheritor(containingClass, JAVA_IO_PRINT_WRITER); + if (arguments.length != 1) yield false; + yield (!hasCharArrayParameter(method) && (JAVA_UTIL_FORMATTER.equals(className) || + InheritanceUtil.isInheritor(containingClass, JAVA_IO_PRINT_STREAM) || + InheritanceUtil.isInheritor(containingClass, JAVA_IO_PRINT_WRITER))) || + "java.lang.IO".equals(className); } case "printf", "format" -> { if (arguments.length < 1) yield false; diff --git a/java/java-impl-inspections/src/com/intellij/codeInspection/ExplicitToImplicitClassMigrationInspection.java b/java/java-impl-inspections/src/com/intellij/codeInspection/ExplicitToImplicitClassMigrationInspection.java index c95bee259ada..62bd3b1ec7f1 100644 --- a/java/java-impl-inspections/src/com/intellij/codeInspection/ExplicitToImplicitClassMigrationInspection.java +++ b/java/java-impl-inspections/src/com/intellij/codeInspection/ExplicitToImplicitClassMigrationInspection.java @@ -328,19 +328,21 @@ public final class ExplicitToImplicitClassMigrationInspection extends AbstractBa if (!(file instanceof PsiJavaFile javaFile)) { return; } - List systemOutPrints = new ArrayList<>(); + List> systemOutPrints = new ArrayList<>(); + SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(file.getProject()); javaFile.accept(new JavaRecursiveElementWalkingVisitor() { @Override public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { if (MigrateToJavaLangIoInspection.isSystemOutPrintln(expression)) { - systemOutPrints.add(expression); - return; + systemOutPrints.add(smartPointerManager.createSmartPsiElementPointer(expression)); } super.visitMethodCallExpression(expression); } }); - for (PsiMethodCallExpression print : systemOutPrints) { - MigrateToJavaLangIoInspection.replaceToIO(print); + for (SmartPsiElementPointer print : systemOutPrints) { + PsiMethodCallExpression element = print.getElement(); + if (element == null) continue; + MigrateToJavaLangIoInspection.replaceToIO(element); } } diff --git a/java/java-impl-inspections/src/com/intellij/codeInspection/MigrateFromJavaLangIoInspection.java b/java/java-impl-inspections/src/com/intellij/codeInspection/MigrateFromJavaLangIoInspection.java index 3690c8ad0494..eef82d5fc474 100644 --- a/java/java-impl-inspections/src/com/intellij/codeInspection/MigrateFromJavaLangIoInspection.java +++ b/java/java-impl-inspections/src/com/intellij/codeInspection/MigrateFromJavaLangIoInspection.java @@ -6,23 +6,23 @@ import com.intellij.modcommand.ModPsiUpdater; import com.intellij.modcommand.PsiUpdateModCommandQuickFix; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.siyeh.ig.callMatcher.CallMatcher; import com.siyeh.ig.psiutils.CommentTracker; import org.jetbrains.annotations.NotNull; -import java.util.Set; -import java.util.stream.Collectors; - public final class MigrateFromJavaLangIoInspection extends AbstractBaseJavaLocalInspectionTool { private static final CallMatcher IO_PRINT = CallMatcher.anyOf( - CallMatcher.staticCall("java.lang.IO", "println").parameterCount(0), - CallMatcher.staticCall("java.lang.IO", "println", "print").parameterCount(1) + CallMatcher.staticCall("java.lang.IO", "println") + .parameterCount(0) + .allowUnresolved(), + CallMatcher.staticCall("java.lang.IO", "println", "print") + .parameterCount(1) + .allowUnresolved() ); - private static final Set IO_PRINT_NAMES = IO_PRINT.names().collect(Collectors.toSet()); - @Override public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { return new JavaElementVisitor() { @@ -72,33 +72,14 @@ public final class MigrateFromJavaLangIoInspection extends AbstractBaseJavaLocal PsiReferenceExpression methodExpr = methodCall.getMethodExpression(); String methodName = methodExpr.getReferenceName(); if (methodName == null) return; - PsiExpression[] arguments = methodCall.getArgumentList().getExpressions(); - StringBuilder replacement = new StringBuilder("System.out.").append(methodName).append("("); - if (arguments.length == 1) { - replacement.append(arguments[0].getText()); + PsiElement replaced = new CommentTracker().replaceAndRestoreComments(methodExpr, "java.lang.System.out." + methodName); + if (replaced instanceof PsiReferenceExpression replacedReferenceExpression) { + JavaCodeStyleManager.getInstance(replacedReferenceExpression.getProject()).shortenClassReferences(replacedReferenceExpression); } - replacement.append(')'); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(methodCall.getProject()); - PsiExpression expr = factory.createExpressionFromText(replacement.toString(), methodCall); - new CommentTracker().replace(methodCall, expr); } private static boolean isIOPrint(@NotNull PsiMethodCallExpression expression) { - boolean isResolvedIO = IO_PRINT.test(expression); - if (isResolvedIO) return true; - String name = expression.getMethodExpression().getReferenceName(); - if (!IO_PRINT_NAMES.contains(name)) return false; - PsiExpression[] args = expression.getArgumentList().getExpressions(); - if (!(args.length == 0 || args.length == 1)) return false; - PsiMethod method = expression.resolveMethod(); - if (method != null) return false; - PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression(); - if (!(qualifierExpression instanceof PsiReferenceExpression qualifierRefExpression)) return false; - if (qualifierRefExpression.getQualifierExpression() != null) return false; - String referenceName = qualifierRefExpression.getReferenceName(); - if (!"IO".equals(referenceName)) return false; - PsiElement resolvedQualifier = qualifierRefExpression.resolve(); - if (resolvedQualifier != null) return false; - return true; + if (!IO_PRINT.test(expression)) return false; + return MigrateToJavaLangIoInspection.callIOAndSystemIdentical(expression.getArgumentList()); } } diff --git a/java/java-impl-inspections/src/com/intellij/codeInspection/MigrateToJavaLangIoInspection.java b/java/java-impl-inspections/src/com/intellij/codeInspection/MigrateToJavaLangIoInspection.java index d369e233ba7b..0b65fc70ca22 100644 --- a/java/java-impl-inspections/src/com/intellij/codeInspection/MigrateToJavaLangIoInspection.java +++ b/java/java-impl-inspections/src/com/intellij/codeInspection/MigrateToJavaLangIoInspection.java @@ -8,6 +8,7 @@ import com.intellij.modcommand.PsiUpdateModCommandQuickFix; import com.intellij.openapi.project.Project; import com.intellij.pom.java.JavaFeature; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import com.siyeh.ig.callMatcher.CallMatcher; import com.siyeh.ig.psiutils.CommentTracker; @@ -116,28 +117,25 @@ public final class MigrateToJavaLangIoInspection extends AbstractBaseJavaLocalIn PsiReferenceExpression methodExpr = methodCall.getMethodExpression(); String methodName = methodExpr.getReferenceName(); if (methodName == null) return; - PsiExpression[] arguments = methodCall.getArgumentList().getExpressions(); - StringBuilder replacement = new StringBuilder("IO.").append(methodName).append("("); - if (arguments.length == 1) { - replacement.append(arguments[0].getText()); + PsiElement replaced = new CommentTracker().replaceAndRestoreComments(methodExpr, "java.lang.IO." + methodName); + if (replaced instanceof PsiReferenceExpression replacedReferenceExpression) { + JavaCodeStyleManager.getInstance(replacedReferenceExpression.getProject()).shortenClassReferences(replacedReferenceExpression); } - replacement.append(')'); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(methodCall.getProject()); - PsiExpression expr = factory.createExpressionFromText(replacement.toString(), methodCall); - new CommentTracker().replace(methodCall, expr); } static boolean isSystemOutPrintln(@NotNull PsiMethodCallExpression expression) { if (!PRINT_STREAM_PRINT.test(expression)) return false; - PsiReferenceExpression methodExpression = expression.getMethodExpression(); - PsiExpression qualifier = methodExpression.getQualifierExpression(); - if (!(qualifier instanceof PsiReferenceExpression ref)) return false; - PsiElement resolved = ref.resolve(); - if (!(resolved instanceof PsiField field)) return false; - if (!field.getName().equals("out")) return false; - PsiClass containingClass = field.getContainingClass(); - if (containingClass == null) return false; - if (!CommonClassNames.JAVA_LANG_SYSTEM.equals(containingClass.getQualifiedName())) return false; + return callIOAndSystemIdentical(expression.getArgumentList()); + } + + static boolean callIOAndSystemIdentical(@NotNull PsiExpressionList list) { + PsiExpression[] expressions = list.getExpressions(); + if (expressions.length == 0) return true; + if (expressions.length == 1) { + PsiType type = expressions[0].getType(); + if (type == null) return false; + if (type instanceof PsiArrayType arrayType && PsiTypes.charType().equals(arrayType.getComponentType())) return false; + } return true; } } diff --git a/java/java-tests/testData/ig/com/siyeh/igtest/bugs/implicit_array_to_string/ImplicitArrayToStringIO.java b/java/java-tests/testData/ig/com/siyeh/igtest/bugs/implicit_array_to_string/ImplicitArrayToStringIO.java new file mode 100644 index 000000000000..ece395faffe7 --- /dev/null +++ b/java/java-tests/testData/ig/com/siyeh/igtest/bugs/implicit_array_to_string/ImplicitArrayToStringIO.java @@ -0,0 +1,18 @@ +package com.siyeh.igtest.bugs.implicit_array_to_string; + +import java.io.PrintWriter; +import java.util.Formatter; + +public class ImplicitArrayToStringIO { + + void foo() { + IO.println("T"); + IO.print("T"); + + IO.println(new char[]{'1', '2'}); + IO.print(new char[]{'1', '2'}); + + IO.println(new byte[]{'1', '2'}); + IO.print(new byte[]{'1', '2'}); + } +} diff --git a/java/java-tests/testData/inspection/explicitToImplicitClassMigration/afterWithSeveralNestedIO.java b/java/java-tests/testData/inspection/explicitToImplicitClassMigration/afterWithSeveralNestedIO.java new file mode 100644 index 000000000000..7336af747cf8 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitToImplicitClassMigration/afterWithSeveralNestedIO.java @@ -0,0 +1,4 @@ + +void main() { + IO.println((Runnable) () -> IO.println("Hello")); +} diff --git a/java/java-tests/testData/inspection/explicitToImplicitClassMigration/beforeWithSeveralNestedIO.java b/java/java-tests/testData/inspection/explicitToImplicitClassMigration/beforeWithSeveralNestedIO.java new file mode 100644 index 000000000000..d0ee647d58d8 --- /dev/null +++ b/java/java-tests/testData/inspection/explicitToImplicitClassMigration/beforeWithSeveralNestedIO.java @@ -0,0 +1,6 @@ + +public class beforeWithSeveralNestedIO { + public static void main(String[] args) { + System.out.println((Runnable) () -> System.out.println("Hello")); + } +} diff --git a/java/java-tests/testData/inspection/migrateFromJavaLangIo/afterPrintUnresolved.java b/java/java-tests/testData/inspection/migrateFromJavaLangIo/afterPrintUnresolved.java index e61fd3871c94..0f5ed3feb43f 100644 --- a/java/java-tests/testData/inspection/migrateFromJavaLangIo/afterPrintUnresolved.java +++ b/java/java-tests/testData/inspection/migrateFromJavaLangIo/afterPrintUnresolved.java @@ -1,3 +1,4 @@ void main() { -System.out.print("Hello"); + /*some*/ + System.out.print(/*some2*/"Hello"); } diff --git a/java/java-tests/testData/inspection/migrateFromJavaLangIo/beforePrintArrayChar.java b/java/java-tests/testData/inspection/migrateFromJavaLangIo/beforePrintArrayChar.java new file mode 100644 index 000000000000..e7eec4aeb34f --- /dev/null +++ b/java/java-tests/testData/inspection/migrateFromJavaLangIo/beforePrintArrayChar.java @@ -0,0 +1,3 @@ +void main() { + IO.print(new char[]{'a', 'b'}); +} diff --git a/java/java-tests/testData/inspection/migrateFromJavaLangIo/beforePrintUnresolved.java b/java/java-tests/testData/inspection/migrateFromJavaLangIo/beforePrintUnresolved.java index 01dddcd81bce..b41559566b04 100644 --- a/java/java-tests/testData/inspection/migrateFromJavaLangIo/beforePrintUnresolved.java +++ b/java/java-tests/testData/inspection/migrateFromJavaLangIo/beforePrintUnresolved.java @@ -1,3 +1,3 @@ void main() { -IO/*some*/.print("Hello"); +IO/*some*/.print(/*some2*/"Hello"); } diff --git a/java/java-tests/testData/inspection/migrateToJavaLangIo/afterPrintRegularClass.java b/java/java-tests/testData/inspection/migrateToJavaLangIo/afterPrintRegularClass.java index 78d4da2bfeec..a85fd096c01d 100644 --- a/java/java-tests/testData/inspection/migrateToJavaLangIo/afterPrintRegularClass.java +++ b/java/java-tests/testData/inspection/migrateToJavaLangIo/afterPrintRegularClass.java @@ -1,5 +1,6 @@ class Test { public static void main(String[] args) { - IO.print("Hello"); + /*some comment*/ + IO.print(/*some2*/"Hello"); } } diff --git a/java/java-tests/testData/inspection/migrateToJavaLangIo/beforePrintArrayChar.java b/java/java-tests/testData/inspection/migrateToJavaLangIo/beforePrintArrayChar.java new file mode 100644 index 000000000000..a3f87bd991a0 --- /dev/null +++ b/java/java-tests/testData/inspection/migrateToJavaLangIo/beforePrintArrayChar.java @@ -0,0 +1,5 @@ +class Test { + public static void main(String[] args) { + System.out.print(new char[]{'1', '2'}); + } +} diff --git a/java/java-tests/testData/inspection/migrateToJavaLangIo/beforePrintRegularClass.java b/java/java-tests/testData/inspection/migrateToJavaLangIo/beforePrintRegularClass.java index 99bc4b4a3990..3952038c2e6b 100644 --- a/java/java-tests/testData/inspection/migrateToJavaLangIo/beforePrintRegularClass.java +++ b/java/java-tests/testData/inspection/migrateToJavaLangIo/beforePrintRegularClass.java @@ -1,5 +1,5 @@ class Test { public static void main(String[] args) { - System./*some comment*/out.print("Hello"); + System./*some comment*/out.print(/*some2*/"Hello"); } } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/ExplicitToImplicitClassMigrationInspectionInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/ExplicitToImplicitClassMigrationInspectionInspectionTest.java index fd06cb93b4d3..602062dc8332 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/ExplicitToImplicitClassMigrationInspectionInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/ExplicitToImplicitClassMigrationInspectionInspectionTest.java @@ -95,6 +95,7 @@ public class ExplicitToImplicitClassMigrationInspectionInspectionTest extends Li } public void testWithSeveralIO() { doTest(); } + public void testWithSeveralNestedIO() { doTest(); } private void doNotFind() { myFixture.enableInspections(new ExplicitToImplicitClassMigrationInspection()); diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/MigrateFromJavaLangIoInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/MigrateFromJavaLangIoInspectionTest.java index 441abfa0d134..c58971bdd0e1 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/MigrateFromJavaLangIoInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/MigrateFromJavaLangIoInspectionTest.java @@ -2,7 +2,10 @@ package com.intellij.java.codeInspection; import com.intellij.JavaTestUtil; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.MigrateFromJavaLangIoInspection; +import com.intellij.java.JavaBundle; import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; @@ -27,6 +30,20 @@ public class MigrateFromJavaLangIoInspectionTest extends LightJavaCodeInsightFix public void testPrintUnresolved() { doTest("Replace with 'System.out.print()'"); } + public void testPrintArrayChar() { + doNotFind( + InspectionsBundle.message("fix.all.inspection.problems.in.file", JavaBundle.message("inspection.migrate.to.java.lang.io.name"))); + } + + private void doNotFind(String message) { + MigrateToJavaLangIoInspectionTest.addIOClass(myFixture); + MigrateFromJavaLangIoInspection inspection = new MigrateFromJavaLangIoInspection(); + myFixture.enableInspections(inspection); + myFixture.testHighlighting(true, true, true, "before" + getTestName(false) + ".java"); + IntentionAction intention = myFixture.getAvailableIntention(message); + assertNull(intention); + } + private void doTest(String message) { myFixture.enableInspections(new MigrateFromJavaLangIoInspection()); myFixture.testHighlighting(true, true, true, "before" + getTestName(false) + ".java"); diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/MigrateToJavaLangIoInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/MigrateToJavaLangIoInspectionTest.java index a4f197df01d9..2937f5b9cd4b 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/MigrateToJavaLangIoInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/MigrateToJavaLangIoInspectionTest.java @@ -28,6 +28,10 @@ public class MigrateToJavaLangIoInspectionTest extends LightJavaCodeInsightFixtu public void testPrintRegularClass() { doTest("Replace with 'IO.print()'"); } + public void testPrintArrayChar() { + doNotFind(InspectionsBundle.message("fix.all.inspection.problems.in.file", JavaBundle.message("inspection.migrate.to.java.lang.io.name"))); + } + public void testPrintf() { doNotFind(InspectionsBundle.message("fix.all.inspection.problems.in.file", JavaBundle.message("inspection.migrate.to.java.lang.io.name"))); } @@ -49,7 +53,7 @@ public class MigrateToJavaLangIoInspectionTest extends LightJavaCodeInsightFixtu myFixture.checkResultByFile("after" + getTestName(false) + ".java"); } - static void addIOClass(@NotNull JavaCodeInsightTestFixture fixture) { + public static void addIOClass(@NotNull JavaCodeInsightTestFixture fixture) { fixture.addClass(""" package java.lang; public final class IO { diff --git a/java/java-tests/testSrc/com/siyeh/ig/bugs/ImplicitArrayToStringInspectionTest.java b/java/java-tests/testSrc/com/siyeh/ig/bugs/ImplicitArrayToStringInspectionTest.java index 1637d3d17d25..f79699920658 100644 --- a/java/java-tests/testSrc/com/siyeh/ig/bugs/ImplicitArrayToStringInspectionTest.java +++ b/java/java-tests/testSrc/com/siyeh/ig/bugs/ImplicitArrayToStringInspectionTest.java @@ -2,6 +2,9 @@ package com.siyeh.ig.bugs; import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.java.codeInspection.MigrateToJavaLangIoInspectionTest; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.LightProjectDescriptor; import com.siyeh.ig.LightJavaInspectionTestCase; import org.jetbrains.annotations.NotNull; @@ -13,6 +16,13 @@ public class ImplicitArrayToStringInspectionTest extends LightJavaInspectionTest doTest(); } + public void testImplicitArrayToStringIO() { + IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_25, () -> { + MigrateToJavaLangIoInspectionTest.addIOClass(myFixture); + doTest(); + }); + } + @NotNull @Override protected LightProjectDescriptor getProjectDescriptor() {