From 5b348c7df387af2969a3ce49ab4b190808205966 Mon Sep 17 00:00:00 2001 From: Luc Fouin Date: Thu, 30 May 2024 14:09:08 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20EC24=20in=20Java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementing rule EC24 in Java: - Adding the rule, the example code and the tests - Registering the rule using SNAPSHOT of ecocode-rules-specifications, and updating registrar tests Fixes green-code-initiative/ecoCode#308 --- pom.xml | 2 +- .../java/JavaCheckRegistrar.java | 4 +- .../java/checks/LimitDbQueryResults.java | 52 +++++++++++++++++++ src/test/files/LimitDbQueryResults.java | 39 ++++++++++++++ .../java/JavaCheckRegistrarTest.java | 2 +- .../java/JavaRulesDefinitionTest.java | 2 +- .../java/checks/LimitDbQueryResultsTest.java | 33 ++++++++++++ 7 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 src/main/java/fr/greencodeinitiative/java/checks/LimitDbQueryResults.java create mode 100644 src/test/files/LimitDbQueryResults.java create mode 100644 src/test/java/fr/greencodeinitiative/java/checks/LimitDbQueryResultsTest.java diff --git a/pom.xml b/pom.xml index fa0c7e9..d788256 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ 1.7 - 1.5.1 + 1.5.5-SNAPSHOT diff --git a/src/main/java/fr/greencodeinitiative/java/JavaCheckRegistrar.java b/src/main/java/fr/greencodeinitiative/java/JavaCheckRegistrar.java index f4ef343..697c246 100644 --- a/src/main/java/fr/greencodeinitiative/java/JavaCheckRegistrar.java +++ b/src/main/java/fr/greencodeinitiative/java/JavaCheckRegistrar.java @@ -33,6 +33,7 @@ import fr.greencodeinitiative.java.checks.FreeResourcesOfAutoCloseableInterface; import fr.greencodeinitiative.java.checks.IncrementCheck; import fr.greencodeinitiative.java.checks.InitializeBufferWithAppropriateSize; +import fr.greencodeinitiative.java.checks.LimitDbQueryResults; import fr.greencodeinitiative.java.checks.NoFunctionCallWhenDeclaringForLoop; import fr.greencodeinitiative.java.checks.OptimizeReadFileExceptions; import org.sonar.plugins.java.api.CheckRegistrar; @@ -62,7 +63,8 @@ public class JavaCheckRegistrar implements CheckRegistrar { InitializeBufferWithAppropriateSize.class, AvoidSetConstantInBatchUpdate.class, FreeResourcesOfAutoCloseableInterface.class, - AvoidMultipleIfElseStatement.class + AvoidMultipleIfElseStatement.class, + LimitDbQueryResults.class ); /** diff --git a/src/main/java/fr/greencodeinitiative/java/checks/LimitDbQueryResults.java b/src/main/java/fr/greencodeinitiative/java/checks/LimitDbQueryResults.java new file mode 100644 index 0000000..0de7382 --- /dev/null +++ b/src/main/java/fr/greencodeinitiative/java/checks/LimitDbQueryResults.java @@ -0,0 +1,52 @@ +/* + * ecoCode - Java language - Provides rules to reduce the environmental footprint of your Java programs + * Copyright © 2023 Green Code Initiative (https://www.ecocode.io) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package fr.greencodeinitiative.java.checks; + +import java.util.Collections; +import java.util.List; + +import org.sonar.check.Rule; +import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.tree.LiteralTree; +import org.sonar.plugins.java.api.tree.Tree; +import org.sonar.plugins.java.api.tree.Tree.Kind; + +import com.google.re2j.Pattern; + +@Rule(key = "EC24") +public class LimitDbQueryResults extends IssuableSubscriptionVisitor { + + protected static final String MESSAGERULE = "Try and limit the number of data returned for a single query (by using the LIMIT keyword for example)"; + + private static final Pattern PATTERN = Pattern.compile("(LIMIT|TOP|ROW_NUMBER|FETCH FIRST|WHERE)", Pattern.CASE_INSENSITIVE); + + @Override + public List nodesToVisit() { + return Collections.singletonList(Tree.Kind.STRING_LITERAL); + } + + @Override + public void visitNode(Tree tree) { + String value = ((LiteralTree) tree).value().toUpperCase(); + if (value.contains("SELECT") && value.contains("FROM") && !PATTERN.matcher(value).find()) { + reportIssue(tree, MESSAGERULE); + } + } + + +} diff --git a/src/test/files/LimitDbQueryResults.java b/src/test/files/LimitDbQueryResults.java new file mode 100644 index 0000000..49f3633 --- /dev/null +++ b/src/test/files/LimitDbQueryResults.java @@ -0,0 +1,39 @@ +/* + * ecoCode - Java language - Provides rules to reduce the environmental footprint of your Java programs + * Copyright © 2023 Green Code Initiative (https://www.ecocode.io) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package fr.greencodeinitiative.java.checks; + +class LimitDbQueryResults { + LimitDbQueryResults(LimitDbQueryResults mc) { + } + + public void literalSQLrequest() { + dummyCall("SELECT id, name, email FROM customers LIMIT 10;"); + dummyCall("SELECT TOP 5 * FROM products;"); + dummyCall("SELECT id, name, email FROM customers WHERE id = 1;"); + dummyCall("SELECT * FROM orders FETCH FIRST 20 ROWS ONLY;"); + dummyCall("WITH numbered_customers AS (SELECT *, ROW_NUMBER() OVER (ORDER BY customer_id) AS row_num FROM customers) SELECT * FROM numbered_customers WHERE row_num <= 50;"); + + dummyCall("SELECT * FROM bikes;"); // Noncompliant {{Try and limit the number of data returned for a single query (by using the LIMIT keyword for example)}} + dummyCall("SELECT id FROM customers;"); // Noncompliant {{Try and limit the number of data returned for a single query (by using the LIMIT keyword for example)}} + } + + private String dummyCall(String request) { + return request; + } + +} \ No newline at end of file diff --git a/src/test/java/fr/greencodeinitiative/java/JavaCheckRegistrarTest.java b/src/test/java/fr/greencodeinitiative/java/JavaCheckRegistrarTest.java index 02270ca..5933a93 100644 --- a/src/test/java/fr/greencodeinitiative/java/JavaCheckRegistrarTest.java +++ b/src/test/java/fr/greencodeinitiative/java/JavaCheckRegistrarTest.java @@ -31,7 +31,7 @@ void checkNumberRules() { final JavaCheckRegistrar registrar = new JavaCheckRegistrar(); registrar.register(context); - assertThat(context.checkClasses()).hasSize(15); + assertThat(context.checkClasses()).hasSize(16); assertThat(context.testCheckClasses()).isEmpty(); } diff --git a/src/test/java/fr/greencodeinitiative/java/JavaRulesDefinitionTest.java b/src/test/java/fr/greencodeinitiative/java/JavaRulesDefinitionTest.java index ad1b536..4eb941c 100644 --- a/src/test/java/fr/greencodeinitiative/java/JavaRulesDefinitionTest.java +++ b/src/test/java/fr/greencodeinitiative/java/JavaRulesDefinitionTest.java @@ -46,7 +46,7 @@ void init() { RulesDefinition.Context context = new RulesDefinition.Context(); rulesDefinition.define(context); repository = context.repository(rulesDefinition.repositoryKey()); - rulesSize = 15; + rulesSize = 16; } @Test diff --git a/src/test/java/fr/greencodeinitiative/java/checks/LimitDbQueryResultsTest.java b/src/test/java/fr/greencodeinitiative/java/checks/LimitDbQueryResultsTest.java new file mode 100644 index 0000000..cf9fe19 --- /dev/null +++ b/src/test/java/fr/greencodeinitiative/java/checks/LimitDbQueryResultsTest.java @@ -0,0 +1,33 @@ +/* + * ecoCode - Java language - Provides rules to reduce the environmental footprint of your Java programs + * Copyright © 2023 Green Code Initiative (https://www.ecocode.io) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package fr.greencodeinitiative.java.checks; + +import org.junit.jupiter.api.Test; +import org.sonar.java.checks.verifier.CheckVerifier; + +class LimitDbQueryResultsTest { + + @Test + void test() { + CheckVerifier.newVerifier() + .onFile("src/test/files/LimitDbQueryResults.java") + .withCheck(new LimitDbQueryResults()) + .verifyIssues(); + } + +} \ No newline at end of file