[java-inspections] IDEA-374922 Highlight the second main method as unused (part of IDEA-372969 WIP)

GitOrigin-RevId: 11bc0dcd62d29f94270781ea5a79f4665575d0a9
This commit is contained in:
Mikhail Pyltsin
2025-06-24 23:04:26 +00:00
committed by intellij-monorepo-bot
parent 105b2eac5d
commit 7a31ef1f7d
9 changed files with 66 additions and 6 deletions
@@ -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;
@@ -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);
@@ -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);");
@@ -0,0 +1,3 @@
interface A{
default void main(){}
}
@@ -0,0 +1,8 @@
void main(String[] <warning descr="Parameter 'args' is never used">args</warning>){
}
void <warning descr="Method 'main()' is never used">main</warning>(){
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>Test.java</file>
<line>6</line>
<highlighted_element>t3</highlighted_element>
<problem_class id="unused" severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">unused declaration</problem_class>
<description>Method is never used.</description>
</problem>
</problems>
@@ -0,0 +1,8 @@
void main(String[] args){
}
void main(){
}
@@ -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";
@@ -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());
}