From 029b379fe0b1db9f1ba4a2a1e690604ae199793c Mon Sep 17 00:00:00 2001 From: "Samuel MARTIN [aa6a131a-f6b6-40af-9503-007c1ae129a9]" Date: Thu, 6 Apr 2023 11:26:43 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20D=C3=A9tection=20des=20annotations=20Ma?= =?UTF-8?q?nyToOne,=20OneToMany=20et=20ManyToMany=20dans=20l'entit=C3=A9?= =?UTF-8?q?=20li=C3=A9e=20au=20Repository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AvoidNPlusOneQueryProblemCheck.java | 41 ++++++++++++++++++- .../files/AvoidNPlusOneQueryProblemBad.java | 27 ++++++++++++ ...ava => AvoidNPlusOneQueryProblemTest.java} | 2 +- 3 files changed, 68 insertions(+), 2 deletions(-) rename java-plugin/src/test/java/fr/greencodeinitiative/java/checks/{AvoidOnePlusOneQueryProblemTest.java => AvoidNPlusOneQueryProblemTest.java} (96%) diff --git a/java-plugin/src/main/java/fr/greencodeinitiative/java/checks/AvoidNPlusOneQueryProblemCheck.java b/java-plugin/src/main/java/fr/greencodeinitiative/java/checks/AvoidNPlusOneQueryProblemCheck.java index 71c2b1b29..70e51f052 100644 --- a/java-plugin/src/main/java/fr/greencodeinitiative/java/checks/AvoidNPlusOneQueryProblemCheck.java +++ b/java-plugin/src/main/java/fr/greencodeinitiative/java/checks/AvoidNPlusOneQueryProblemCheck.java @@ -2,10 +2,15 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; +import java.util.Optional; + import org.sonar.check.Priority; import org.sonar.check.Rule; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.semantic.Type; +import org.sonar.plugins.java.api.semantic.Type; import org.sonar.plugins.java.api.tree.*; @Rule(key = "EC206", @@ -23,6 +28,12 @@ public class AvoidNPlusOneQueryProblemCheck extends IssuableSubscriptionVisitor private static final String LEFT_JOIN = "LEFT JOIN"; private static final String VALUE = "value"; + private static final List SPRING_PROBLEMATIC_ANNOTATIONS = List.of( + "javax.persistence.OneToMany", + "javax.persistence.ManyToOne", + "javax.persistence.ManyToMany" + ); + private final AvoidNPlusOneQueryProblemCheckVisitor visitorInFile = new AvoidNPlusOneQueryProblemCheckVisitor(); @Override @@ -32,11 +43,39 @@ public List nodesToVisit() { @Override public void visitNode(Tree tree) { - if (((ClassTree) tree).symbol().type().isSubtypeOf(SPRING_REPOSITORY)) { + ClassTree classTree = (ClassTree) tree; + + if (isSpringRepository(classTree) && hasManyToOneAnnotations(classTree)) { tree.accept(visitorInFile); } } + private boolean hasManyToOneAnnotations(ClassTree classTree) { + Optional crudRepositoryInterface = classTree.symbol().interfaces().stream() + .filter(t -> t.isSubtypeOf(SPRING_REPOSITORY)) + .findFirst(); + + return crudRepositoryInterface.map(type -> type + .typeArguments() + .get(0) + .symbol() + .declaration() + .members() + .stream() + .filter(t -> t.is(Tree.Kind.VARIABLE)) + .anyMatch(t -> ((VariableTree) t).modifiers() + .annotations() + .stream() + .anyMatch(a -> + SPRING_PROBLEMATIC_ANNOTATIONS.stream().anyMatch(a.symbolType()::isSubtypeOf) + ))) + .orElse(false); + } + + private static boolean isSpringRepository(ClassTree classTree) { + return classTree.symbol().type().isSubtypeOf(SPRING_REPOSITORY); + } + private class AvoidNPlusOneQueryProblemCheckVisitor extends BaseTreeVisitor { @Override diff --git a/java-plugin/src/test/files/AvoidNPlusOneQueryProblemBad.java b/java-plugin/src/test/files/AvoidNPlusOneQueryProblemBad.java index 61e55d89f..3302aa957 100644 --- a/java-plugin/src/test/files/AvoidNPlusOneQueryProblemBad.java +++ b/java-plugin/src/test/files/AvoidNPlusOneQueryProblemBad.java @@ -1,5 +1,7 @@ import org.springframework.data.repository.CrudRepository; import java.util.List; +import javax.persistence.Entity; +import javax.persistence.OneToMany; public interface UserRepository extends CrudRepository { @@ -12,6 +14,31 @@ public interface UserRepository extends CrudRepository { List findAllWithRoles(); } +@Entity public class User { + @OneToMany + private List roles; + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } +} + +@Entity +public class Role { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } diff --git a/java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidOnePlusOneQueryProblemTest.java b/java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidNPlusOneQueryProblemTest.java similarity index 96% rename from java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidOnePlusOneQueryProblemTest.java rename to java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidNPlusOneQueryProblemTest.java index 85400b201..e8374783d 100644 --- a/java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidOnePlusOneQueryProblemTest.java +++ b/java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidNPlusOneQueryProblemTest.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test; import org.sonar.java.checks.verifier.CheckVerifier; -class AvoidOnePlusOneQueryProblemTest { +class AvoidNPlusOneQueryProblemTest { /** * @formatter:off