From 13481745c39c27b9e3d03add53426ac08a3053e4 Mon Sep 17 00:00:00 2001 From: Tomasz Tylenda Date: Mon, 2 Feb 2026 17:31:21 +0100 Subject: [PATCH] S2325 Do not report on instance main. --- .../checks/StaticMethodCheckCompactSample.java | 3 +++ .../java/checks/StaticMethodCheckSample.java | 16 ++++++++++++++++ .../org/sonar/java/checks/StaticMethodCheck.java | 10 +++++++++- .../sonar/java/checks/StaticMethodCheckTest.java | 8 ++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 java-checks-test-sources/default/src/main/java/checks/StaticMethodCheckCompactSample.java diff --git a/java-checks-test-sources/default/src/main/java/checks/StaticMethodCheckCompactSample.java b/java-checks-test-sources/default/src/main/java/checks/StaticMethodCheckCompactSample.java new file mode 100644 index 00000000000..e94a191a5d2 --- /dev/null +++ b/java-checks-test-sources/default/src/main/java/checks/StaticMethodCheckCompactSample.java @@ -0,0 +1,3 @@ +void main() { + System.out.println("Hello, World!"); +} diff --git a/java-checks-test-sources/default/src/main/java/checks/StaticMethodCheckSample.java b/java-checks-test-sources/default/src/main/java/checks/StaticMethodCheckSample.java index 3068dfeb518..6470ceec593 100644 --- a/java-checks-test-sources/default/src/main/java/checks/StaticMethodCheckSample.java +++ b/java-checks-test-sources/default/src/main/java/checks/StaticMethodCheckSample.java @@ -426,3 +426,19 @@ private List> requiresNestedTypeVar() { // Compliant } } } + +// Note `final` on the class indicating that main methods will not be overridden. +// Without it, the check would apply only to private methods. +final public class StaticMethodCheckSample { + void main() { // Compliant + System.out.println("StaticMethodCheckSample no arg main"); + } + + void main(String[] args) { // Compliant + System.out.println("StaticMethodCheckSample main with args"); + } + + void main(int i) { // Noncompliant + System.out.println("i = " + i); + } +} diff --git a/java-checks/src/main/java/org/sonar/java/checks/StaticMethodCheck.java b/java-checks/src/main/java/org/sonar/java/checks/StaticMethodCheck.java index 6997a8e438b..268969ed5e3 100644 --- a/java-checks/src/main/java/org/sonar/java/checks/StaticMethodCheck.java +++ b/java-checks/src/main/java/org/sonar/java/checks/StaticMethodCheck.java @@ -64,6 +64,14 @@ public class StaticMethodCheck extends BaseTreeVisitor implements JavaFileScanne .addWithoutParametersMatcher() .build()); + private static final MethodMatchers MAIN_METHOD = + MethodMatchers.create() + .ofAnyType() + .names("main") + .addParametersMatcher(params -> + params.isEmpty() || (params.size() == 1 && params.get(0).isSubtypeOf("java.lang.String[]"))) + .build(); + private JavaFileScannerContext context; private Deque methodReferences = new LinkedList<>(); @@ -160,7 +168,7 @@ private static boolean shouldBePlacedAfterStatic(Modifier modifier) { } private static boolean isExcluded(MethodTree tree) { - return tree.is(Tree.Kind.CONSTRUCTOR) || EXCLUDED_SERIALIZABLE_METHODS.matches(tree) || hasEmptyBody(tree); + return tree.is(Tree.Kind.CONSTRUCTOR) || EXCLUDED_SERIALIZABLE_METHODS.matches(tree) || hasEmptyBody(tree) || MAIN_METHOD.matches(tree); } private static boolean hasEmptyBody(MethodTree tree) { diff --git a/java-checks/src/test/java/org/sonar/java/checks/StaticMethodCheckTest.java b/java-checks/src/test/java/org/sonar/java/checks/StaticMethodCheckTest.java index 5b5deec3983..66b8e78df90 100644 --- a/java-checks/src/test/java/org/sonar/java/checks/StaticMethodCheckTest.java +++ b/java-checks/src/test/java/org/sonar/java/checks/StaticMethodCheckTest.java @@ -32,6 +32,14 @@ void test() { .verifyIssues(); } + @Test + void test_compact_source() { + CheckVerifier.newVerifier() + .onFile(mainCodeSourcesPath("checks/StaticMethodCheckCompactSample.java")) + .withCheck(new StaticMethodCheck()) + .verifyNoIssues(); + } + @Test void test_non_compiling() { CheckVerifier.newVerifier()