[java-inspections] IDEA-355916 Support JEP 477 Update ImplicitToExplicit inspection

- first part. update for implicit static imports

GitOrigin-RevId: 8c0fdf1c8ebd424a80e53b93c707fba02a07448a
This commit is contained in:
Mikhail Pyltsin
2024-07-04 20:25:30 +02:00
committed by intellij-monorepo-bot
parent c437caf780
commit ee1495d613
11 changed files with 79 additions and 29 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInspection;
import com.intellij.java.JavaBundle;
@@ -8,6 +8,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.pom.java.JavaFeature;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
import com.intellij.psi.util.PsiMethodUtil;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.Nls;
@@ -30,7 +33,7 @@ public final class ImplicitToExplicitClassBackwardMigrationInspection extends Ab
return new JavaElementVisitor() {
@Override
public void visitImplicitClass(@NotNull PsiImplicitClass aClass) {
if (!PsiMethodUtil.hasMainMethod(aClass)) {
if (!PsiMethodUtil.hasMainInClass(aClass)) {
return;
}
if (PsiTreeUtil.hasErrorElements(aClass)) {
@@ -93,7 +96,29 @@ public final class ImplicitToExplicitClassBackwardMigrationInspection extends Ab
if (modifierList != null) {
modifierList.setModifierProperty(PsiModifier.PUBLIC, true);
}
implicitClass.replace(newClass);
PsiFile containingFile = implicitClass.getContainingFile();
if (!(containingFile instanceof PsiJavaFile psiJavaFile)) {
return;
}
PsiJavaFile.@NotNull StaticMember[] imports = PsiImplUtil.getImplicitStaticImports(psiJavaFile);
PsiElement replaced = implicitClass.replace(newClass);
PsiJavaFile newPsiJavaFile = PsiTreeUtil.getParentOfType(replaced, PsiJavaFile.class);
if (newPsiJavaFile == null) {
return;
}
PsiImportList importList = newPsiJavaFile.getImportList();
if (importList == null) {
return;
}
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
for (PsiJavaFile.@NotNull StaticMember importMember : imports) {
PsiClass psiClass = psiFacade.findClass(importMember.getContainingClass(), implicitClass.getResolveScope());
if (psiClass == null) {
continue;
}
PsiReferenceExpressionImpl.bindToElementViaStaticImport(psiClass, importMember.getMemberName(), importList);
}
JavaCodeStyleManager.getInstance(project).optimizeImports(newPsiJavaFile);
}
}
}

View File

@@ -248,6 +248,12 @@ public final class PsiMethodUtil {
return findMainMethod(aClass);
}
/**
* Determines if the given class has a main method and can be launched.
*
* @param aClass the class to check for a main method.
* @return true if the class has a main method, false otherwise.
*/
public static boolean hasMainInClass(@NotNull final PsiClass aClass) {
if (!MAIN_CLASS.value(aClass)) return false;
return hasMainMethod(aClass);

View File

@@ -1,8 +1,5 @@
// "Convert implicitly declared class into regular class" "true-preview"
//many comments
public class beforeAdjustComments {
//many comments
private final String field = "field";
//many comments

View File

@@ -1,5 +1,3 @@
// "Convert implicitly declared class into regular class" "true-preview"
public class beforeSimple {
private final String field = "field";

View File

@@ -1,5 +1,3 @@
// "Convert implicitly declared class into regular class" "true-preview"
public class beforeSimple2 {
private final String field = "field";

View File

@@ -0,0 +1,7 @@
import static java.io.IO.println;
public class beforeWit<caret>hPrint {
public static void main() {
println("Hello, world!");
}
}

View File

@@ -1,5 +1,3 @@
// "Convert implicitly declared class into regular class" "true-preview"
//many comments
private final String field = "field";

View File

@@ -1,5 +1,3 @@
// "Convert implicitly declared class into regular class" "true-preview"
private final String field = "field";
public static void main() {

View File

@@ -1,5 +1,3 @@
// "Convert implicitly declared class into regular class" "true-preview"
private final String field = "field";
public static void mai<caret>n() {

View File

@@ -0,0 +1,3 @@
public static void mai<caret>n() {
println("Hello, world!");
}

View File

@@ -1,25 +1,47 @@
// Copyright 2000-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.codeInspection;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.ImplicitToExplicitClassBackwardMigrationInspection;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.java.JavaBundle;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
public class ImplicitToExplicitClassBackwardMigrationInspectionTest extends LightQuickFixParameterizedTestCase {
public class ImplicitToExplicitClassBackwardMigrationInspectionTest extends LightJavaCodeInsightFixtureTestCase {
@NotNull
@Override
protected LocalInspectionTool @NotNull [] configureLocalInspectionTools() {
return new LocalInspectionTool[]{new ImplicitToExplicitClassBackwardMigrationInspection()};
protected LightProjectDescriptor getProjectDescriptor() {
return JAVA_23;
}
@Override
protected String getBasePath() {
return "/inspection/implicitToExplicitClassBackwardMigration/";
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() + "/inspection/implicitToExplicitClassBackwardMigration/";
}
@Override
protected LanguageLevel getLanguageLevel() {
return LanguageLevel.JDK_22_PREVIEW;
private void doTest() {
myFixture.addClass("""
package java.io;
public final class IO {
public static void println(Object obj) {}
}
""");
myFixture.enableInspections(new ImplicitToExplicitClassBackwardMigrationInspection());
myFixture.testHighlighting(true, false, true, "before" + getTestName(false) + ".java");
myFixture.checkPreviewAndLaunchAction(myFixture.findSingleIntention(
JavaBundle.message("inspection.implicit.to.explicit.class.backward.migration.fix.name")));
myFixture.checkResultByFile("after" + getTestName(false) + ".java");
}
public void testSimple() { doTest(); }
public void testSimple2() { doTest(); }
public void testAdjustComments() { doTest(); }
public void testWithPrint() { doTest(); }
}