diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java index a1469b66855a..c97b842ca357 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java @@ -7,6 +7,7 @@ import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.util.Predicates; import com.intellij.openapi.util.text.Strings; import com.intellij.psi.*; +import com.intellij.psi.impl.PsiClassImplUtil; import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.*; @@ -134,7 +135,9 @@ public sealed class RefMethodImpl extends RefJavaElementImpl implements RefMetho } private static boolean isAppMain(PsiMethod psiMethod, RefMethod refMethod) { - if ("main".equals(psiMethod.getName()) && PsiMethodUtil.isMainMethod(psiMethod)) return true; + if ("main".equals(psiMethod.getName()) && PsiClassImplUtil.isMainOrPremainMethod(psiMethod)) { + return true; + } if (!refMethod.isStatic()) return false; if (!PsiTypes.voidType().equals(psiMethod.getReturnType())) return false; diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java index cd02e4e9a32b..5fe12423b9b5 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java @@ -55,7 +55,7 @@ public final class PsiMethodUtil { private PsiMethodUtil() { } - public static @Nullable PsiMethod findMainMethod(final PsiClass aClass) { + public static @Nullable PsiMethod findMainMethod(@NotNull final PsiClass aClass) { JavaMainMethodProvider mainMethodProvider = getApplicableMainMethodProvider(aClass); if (mainMethodProvider != null) { return mainMethodProvider.findMainInClass(aClass); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index e9ffefe0079d..65b4fe16268b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -328,17 +328,22 @@ public final class PsiClassImplUtil { public static boolean isMainOrPremainMethod(@NotNull PsiMethod method) { if ("main".equals(method.getName()) && PsiMethodUtil.isMainMethod(method)) { - return true; + PsiClass psiClass = method.getContainingClass(); + PsiManager manager = method.getManager(); + if (psiClass != null && manager != null) { + PsiMethod otherMethod = PsiMethodUtil.findMainMethod(psiClass); + //can be used not from this class + if (otherMethod == null) return true; + return manager.areElementsEquivalent(method, otherMethod); + } } String name = method.getName(); - if (!("main".equals(name) || "premain".equals(name) || "agentmain".equals(name))) return false; + if (!("premain".equals(name) || "agentmain".equals(name))) return false; if (!PsiTypes.voidType().equals(method.getReturnType())) return false; PsiElementFactory factory = JavaPsiFacade.getElementFactory(method.getProject()); MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY); try { - MethodSignature main = createSignatureFromText(factory, "void main(String[] args);"); - if (MethodSignatureUtil.areSignaturesEqual(signature, main)) return true; MethodSignature premain = createSignatureFromText(factory, "void premain(String args, java.lang.instrument.Instrumentation i);"); if (MethodSignatureUtil.areSignaturesEqual(signature, premain)) return true; MethodSignature agentmain = createSignatureFromText(factory, "void agentmain(String args, java.lang.instrument.Instrumentation i);"); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advFixture/MainMethodInInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advFixture/MainMethodInInterface.java new file mode 100644 index 000000000000..67815a1d3bee --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advFixture/MainMethodInInterface.java @@ -0,0 +1,3 @@ +interface A{ + default void main(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advFixture/SeveralMainMethods.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advFixture/SeveralMainMethods.java new file mode 100644 index 000000000000..7c5fdc106d51 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advFixture/SeveralMainMethods.java @@ -0,0 +1,8 @@ +void main(String[] args){ + +} + + +void main(){ + +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/deadCode/severalMainMethods/expected.xml b/java/java-tests/testData/inspection/deadCode/severalMainMethods/expected.xml new file mode 100644 index 000000000000..c8df10cafb41 --- /dev/null +++ b/java/java-tests/testData/inspection/deadCode/severalMainMethods/expected.xml @@ -0,0 +1,11 @@ + + + + Test.java + 6 + t3 + unused declaration + Method is never used. + + + diff --git a/java/java-tests/testData/inspection/deadCode/severalMainMethods/src/Test.java b/java/java-tests/testData/inspection/deadCode/severalMainMethods/src/Test.java new file mode 100644 index 000000000000..abcfc6cde5cf --- /dev/null +++ b/java/java-tests/testData/inspection/deadCode/severalMainMethods/src/Test.java @@ -0,0 +1,8 @@ +void main(String[] args){ + +} + + +void main(){ + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightUnusedHighlightingFixtureTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightUnusedHighlightingFixtureTest.java index 928f699f66a1..739133d3bbd2 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightUnusedHighlightingFixtureTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightUnusedHighlightingFixtureTest.java @@ -7,6 +7,7 @@ import com.intellij.codeInsight.daemon.ImplicitUsageProvider; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.pom.java.JavaFeature; +import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiField; import com.intellij.psi.PsiNamedElement; @@ -65,6 +66,20 @@ public class LightUnusedHighlightingFixtureTest extends LightJavaCodeInsightFixt }); } + public void testSeveralMainMethods() { + IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_25, ()->{ + myFixture.configureByFile(getTestName(false) + ".java"); + myFixture.checkHighlighting(); + }); + } + + public void testMainMethodInInterface() { + IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_25, ()->{ + myFixture.configureByFile(getTestName(false) + ".java"); + myFixture.checkHighlighting(); + }); + } + @Override protected String getBasePath() { return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/daemonCodeAnalyzer/advFixture"; diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java index 5de2d8e90e87..031f881bf78d 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java @@ -300,6 +300,13 @@ public class UnusedDeclarationInspectionTest extends AbstractUnusedDeclarationTe }); } + public void testSeveralMainMethods() { + IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_25, () -> { + myTool.ADD_MAINS_TO_ENTRIES = true; + doTest(); + }); + } + private void doTest5() { IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_1_5, () -> doTest()); }