diff --git a/java-checks-test-sources/default/src/main/java/checks/S3252_StaticMemberAccessCheckSample/StaticMemberAccessCheckSample.java b/java-checks-test-sources/default/src/main/java/checks/S3252_StaticMemberAccessCheckSample/StaticMemberAccessCheckSample.java index e72ba532427..fa769567b4f 100644 --- a/java-checks-test-sources/default/src/main/java/checks/S3252_StaticMemberAccessCheckSample/StaticMemberAccessCheckSample.java +++ b/java-checks-test-sources/default/src/main/java/checks/S3252_StaticMemberAccessCheckSample/StaticMemberAccessCheckSample.java @@ -34,6 +34,21 @@ void test() { } } +// Quarkus Panache: static methods are bytecode-generated in subclasses, so accessing them via the subclass is intended +class MeetingType extends io.quarkus.hibernate.orm.panache.PanacheEntityBase { + void doSomething() { + MeetingType.listAll(); // Compliant - Panache generates static methods in subclasses + MeetingType.count(); // Compliant + } +} + +class MongoMeetingType extends io.quarkus.mongodb.panache.PanacheMongoEntityBase { + void doSomething() { + MongoMeetingType.listAll(); // Compliant - Panache generates static methods in subclasses + MongoMeetingType.count(); // Compliant + } +} + class GuavaFP { // method is incorrectly resolved as Set.of, specifically excluded in implementation to avoid // see SONARJAVA-3095 diff --git a/java-checks-test-sources/default/src/main/java/io/quarkus/hibernate/orm/panache/PanacheEntityBase.java b/java-checks-test-sources/default/src/main/java/io/quarkus/hibernate/orm/panache/PanacheEntityBase.java index 38b78403cb7..0f77ef7652f 100644 --- a/java-checks-test-sources/default/src/main/java/io/quarkus/hibernate/orm/panache/PanacheEntityBase.java +++ b/java-checks-test-sources/default/src/main/java/io/quarkus/hibernate/orm/panache/PanacheEntityBase.java @@ -1,4 +1,13 @@ package io.quarkus.hibernate.orm.panache; +import java.util.List; + public abstract class PanacheEntityBase { + public static List listAll() { + return null; + } + + public static long count() { + return 0; + } } diff --git a/java-checks-test-sources/default/src/main/java/io/quarkus/mongodb/panache/PanacheMongoEntityBase.java b/java-checks-test-sources/default/src/main/java/io/quarkus/mongodb/panache/PanacheMongoEntityBase.java index 03824cd350d..949de41cdad 100644 --- a/java-checks-test-sources/default/src/main/java/io/quarkus/mongodb/panache/PanacheMongoEntityBase.java +++ b/java-checks-test-sources/default/src/main/java/io/quarkus/mongodb/panache/PanacheMongoEntityBase.java @@ -1,4 +1,13 @@ package io.quarkus.mongodb.panache; +import java.util.List; + public abstract class PanacheMongoEntityBase { + public static List listAll() { + return null; + } + + public static long count() { + return 0; + } } diff --git a/java-checks/src/main/java/org/sonar/java/checks/StaticMemberAccessCheck.java b/java-checks/src/main/java/org/sonar/java/checks/StaticMemberAccessCheck.java index e9cbe1bad81..2536eca3be3 100644 --- a/java-checks/src/main/java/org/sonar/java/checks/StaticMemberAccessCheck.java +++ b/java-checks/src/main/java/org/sonar/java/checks/StaticMemberAccessCheck.java @@ -71,6 +71,7 @@ public void visitNode(Tree tree) { if (!staticType.isUnknown() && !expressionType.isUnknown() && !expressionType.erasure().equals(staticType.erasure()) && (memberOwnerIsInCurrentPackage || owner.isPublic()) + && !isPanacheEntityBase(staticType) ) { QuickFixHelper.newIssue(context) .forRule(this) @@ -87,6 +88,11 @@ private static String classPackage(Type classType) { return endPackage == -1 ? "" : classType.fullyQualifiedName().substring(0, endPackage); } + private static boolean isPanacheEntityBase(Type type) { + return type.isSubtypeOf("io.quarkus.hibernate.orm.panache.PanacheEntityBase") + || type.isSubtypeOf("io.quarkus.mongodb.panache.PanacheMongoEntityBase"); + } + private static boolean isListOrSetOf(MemberSelectExpressionTree mse) { // this is necessary because we incorrectly resolve to Set#of List#of methods on JDK11 // see SONARJAVA-3095