From 8ae49679ad06ab912e910e88242ed11a44b28f95 Mon Sep 17 00:00:00 2001 From: "mohamed-oussama.abidi@outlook.fr" Date: Thu, 6 Apr 2023 10:22:44 +0100 Subject: [PATCH] feat(EC22): Implementing Avoid Method Usage for Only Basic Operations --- .../greencodeinitiative/java/RulesList.java | 23 +-- ...voidMethodUsageForOnlyBasicOperations.java | 52 +++++++ .../l10n/java/rules/java/EC22.html | 13 ++ .../l10n/java/rules/java/EC22.json | 16 ++ ...voidMethodUsageForOnlyBasicOperations.java | 143 ++++++++++++++++++ .../java/JavaCheckRegistrarTest.java | 2 +- ...MethodUsageForOnlyBasicOperationsTest.java | 20 +++ 7 files changed, 248 insertions(+), 21 deletions(-) create mode 100644 java-plugin/src/main/java/fr/greencodeinitiative/java/checks/AvoidMethodUsageForOnlyBasicOperations.java create mode 100644 java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC22.html create mode 100644 java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC22.json create mode 100644 java-plugin/src/test/files/AvoidMethodUsageForOnlyBasicOperations.java create mode 100644 java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidMethodUsageForOnlyBasicOperationsTest.java diff --git a/java-plugin/src/main/java/fr/greencodeinitiative/java/RulesList.java b/java-plugin/src/main/java/fr/greencodeinitiative/java/RulesList.java index d6a5cdbf4..2928583f1 100644 --- a/java-plugin/src/main/java/fr/greencodeinitiative/java/RulesList.java +++ b/java-plugin/src/main/java/fr/greencodeinitiative/java/RulesList.java @@ -24,25 +24,7 @@ import java.util.Collections; import java.util.List; -import fr.greencodeinitiative.java.checks.ArrayCopyCheck; -import fr.greencodeinitiative.java.checks.AvoidConcatenateStringsInLoop; -import fr.greencodeinitiative.java.checks.AvoidFullSQLRequest; -import fr.greencodeinitiative.java.checks.AvoidGettingSizeCollectionInLoop; -import fr.greencodeinitiative.java.checks.AvoidMultipleIfElseStatement; -import fr.greencodeinitiative.java.checks.AvoidRegexPatternNotStatic; -import fr.greencodeinitiative.java.checks.AvoidSQLRequestInLoop; -import fr.greencodeinitiative.java.checks.AvoidSetConstantInBatchUpdate; -import fr.greencodeinitiative.java.checks.AvoidSpringRepositoryCallInLoopCheck; -import fr.greencodeinitiative.java.checks.AvoidStatementForDMLQueries; -import fr.greencodeinitiative.java.checks.AvoidUsageOfStaticCollections; -import fr.greencodeinitiative.java.checks.AvoidUsingGlobalVariablesCheck; -import fr.greencodeinitiative.java.checks.FreeResourcesOfAutoCloseableInterface; -import fr.greencodeinitiative.java.checks.IncrementCheck; -import fr.greencodeinitiative.java.checks.InitializeBufferWithAppropriateSize; -import fr.greencodeinitiative.java.checks.NoFunctionCallWhenDeclaringForLoop; -import fr.greencodeinitiative.java.checks.OptimizeReadFileExceptions; -import fr.greencodeinitiative.java.checks.UnnecessarilyAssignValuesToVariables; -import fr.greencodeinitiative.java.checks.UseCorrectForLoop; +import fr.greencodeinitiative.java.checks.*; import org.sonar.plugins.java.api.JavaCheck; public final class RulesList { @@ -77,7 +59,8 @@ public static List> getJavaChecks() { AvoidUsingGlobalVariablesCheck.class, AvoidSetConstantInBatchUpdate.class, FreeResourcesOfAutoCloseableInterface.class, - AvoidMultipleIfElseStatement.class + AvoidMultipleIfElseStatement.class, + AvoidMethodUsageForOnlyBasicOperations.class )); } diff --git a/java-plugin/src/main/java/fr/greencodeinitiative/java/checks/AvoidMethodUsageForOnlyBasicOperations.java b/java-plugin/src/main/java/fr/greencodeinitiative/java/checks/AvoidMethodUsageForOnlyBasicOperations.java new file mode 100644 index 000000000..08f2307ed --- /dev/null +++ b/java-plugin/src/main/java/fr/greencodeinitiative/java/checks/AvoidMethodUsageForOnlyBasicOperations.java @@ -0,0 +1,52 @@ +package fr.greencodeinitiative.java.checks; + +import org.sonar.check.Rule; +import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.tree.*; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; + +import static fr.greencodeinitiative.java.checks.AvoidMethodUsageForOnlyBasicOperations.RULE_MESSAGE; +import static org.sonar.check.Priority.MINOR; + +/** + * @author Mohamed Oussama A. + * Created on 05/04/2023 + * @version 1.0 + */ + +@Rule(key = "EC22", + name = RULE_MESSAGE, + description = RULE_MESSAGE, + priority = MINOR, + tags = {"smell", "ecocode", "eco-design", "memory", "performance"}) +public class AvoidMethodUsageForOnlyBasicOperations extends IssuableSubscriptionVisitor { + + protected static final String RULE_MESSAGE = "Avoid Method Usage For Only Basic Operations"; + + @Override + public List nodesToVisit() { + return Collections.singletonList(Tree.Kind.METHOD); + } + + + @Override + public void visitNode(Tree tree) { + Optional.ofNullable(((MethodTree) tree).block()) + .map(BlockTree::body) + .filter(list -> list.size() == 1) + .flatMap(list -> list.stream().findFirst()) + .filter(ReturnStatementTree.class::isInstance) + .map(statementTree -> ((ReturnStatementTree) statementTree).expression()) + .filter(this.isBasicOperation) + .ifPresent(expressionTree -> reportIssue(expressionTree, RULE_MESSAGE)); + } + + + private Predicate isBasicOperation = expression -> expression instanceof BinaryExpressionTree + || expression instanceof UnaryExpressionTree + || expression.is(Tree.Kind.CONDITIONAL_EXPRESSION); +} diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC22.html b/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC22.html new file mode 100644 index 000000000..71057a354 --- /dev/null +++ b/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC22.html @@ -0,0 +1,13 @@ +

we should not use methods for only basic operations

+

Non compliant Code Example

+
+    public int sum(int a, int b) {
+        return a + b; // Noncompliant
+    }
+
+    x = sum(5, 4); // Noncompliant
+
+

Compliant Solution

+
+    x = a + b;
+
\ No newline at end of file diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC22.json b/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC22.json new file mode 100644 index 000000000..93e63fada --- /dev/null +++ b/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC22.json @@ -0,0 +1,16 @@ +{ + "title": "we should not use methods for only basic operations", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "eco-design", + "memory", + "performance", + "ecocode" + ], + "defaultSeverity": "Minor" +} \ No newline at end of file diff --git a/java-plugin/src/test/files/AvoidMethodUsageForOnlyBasicOperations.java b/java-plugin/src/test/files/AvoidMethodUsageForOnlyBasicOperations.java new file mode 100644 index 000000000..bc9bee0e4 --- /dev/null +++ b/java-plugin/src/test/files/AvoidMethodUsageForOnlyBasicOperations.java @@ -0,0 +1,143 @@ +/** + * @author Mohamed Oussama A. + * Created on 05/04/2023 + * @version 1.0 + */ +public class AvoidBasicOperationsUsageMethods { + + private int x =0; + + /* + * Below method must be reported by an other Rule of unnecessarily assignment of variable + * (but not with this rule - SRP - SOLID ) + * */ + + public static int getMin(int a, int b) { + int c = a < b ? a : b; // Compliant + return c; + } + + public int getX() { + return x; // Compliant + } + + /* + * Conditional expressions using ternanry operator + */ + public static int getMin(int a, int b) { + return a < b ? a : b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int calculateFormuleX(int a, int b) { + return a / a * b < b ? a - b : b + a; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + /* + * Binary Operations + */ + + //Using Arithmetic Operators + + public static int add(int a, int b) { + return a + b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int substract(int a, int b) { + return a - b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int multiply(int a, int b) { + return a * b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int divide(int a, int b) { + return a / b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int modulus(int a, int b) { + return a % b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + //Using Logical Operators + + public static boolean compareAnd(int a, int b) { + return (a > b) && (b > 0); // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static boolean compareOr(int a, int b) { + return (a > b) || (b > 0); // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static boolean equalsTo(int a, int b) { + return a == b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static boolean notEqualsTo(int a, int b) { + return !(a == b); // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static boolean compare1(int a, int b) { + return (a > b) && (b > 0); // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + // Using Bitwise operators + + public static boolean andBitwise(int a, int b) { + return a & b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static boolean orBitwise(int a, int b) { + return a | b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static boolean xorBitwise(int a, int b) { + return a ^ b; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + /* + * Unary Operations + */ + + public static int negate(int a) { + return -a; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int preIncrement(int a) { + return ++a; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int postDecrement(int a) { + return a--; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int notBitwise(int a) { + return ~a; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + // Using Bitwise operators + + public static int negate(int a) { + return -a; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int preIncrement(int a) { + return ++a; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int postDecrement(int a) { + return a--; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int leftShift(int a) { + return a << 1; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int rightShift(int a) { + return a >> 1; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + + public static int zeroFillRightShift(int a) { + return a >>> 1; // Noncompliant {{Avoid Method Usage For Only Basic Operations}} + } + +} \ No newline at end of file diff --git a/java-plugin/src/test/java/fr/greencodeinitiative/java/JavaCheckRegistrarTest.java b/java-plugin/src/test/java/fr/greencodeinitiative/java/JavaCheckRegistrarTest.java index 3225b1a56..fe7f03adf 100644 --- a/java-plugin/src/test/java/fr/greencodeinitiative/java/JavaCheckRegistrarTest.java +++ b/java-plugin/src/test/java/fr/greencodeinitiative/java/JavaCheckRegistrarTest.java @@ -32,7 +32,7 @@ void checkNumberRules() { final JavaCheckRegistrar registrar = new JavaCheckRegistrar(); registrar.register(context); - assertThat(context.checkClasses()).hasSize(19); + assertThat(context.checkClasses()).hasSize(20); assertThat(context.testCheckClasses()).isEmpty(); } } diff --git a/java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidMethodUsageForOnlyBasicOperationsTest.java b/java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidMethodUsageForOnlyBasicOperationsTest.java new file mode 100644 index 000000000..7bd20ab3b --- /dev/null +++ b/java-plugin/src/test/java/fr/greencodeinitiative/java/checks/AvoidMethodUsageForOnlyBasicOperationsTest.java @@ -0,0 +1,20 @@ +package fr.greencodeinitiative.java.checks; + +import org.junit.jupiter.api.Test; +import org.sonar.java.checks.verifier.CheckVerifier; + +/** + * @author Mohamed Oussama ABIDI. + * Created on 05/04/2023 + * @version 1.0 + */ +class AvoidMethodUsageForOnlyBasicOperationsTest { + + @Test + void it_should_verify_non_compliant_basic_operations_usage_in_methods() { + CheckVerifier.newVerifier() + .onFile("src/test/files/AvoidMethodUsageForOnlyBasicOperations.java") + .withCheck(new AvoidMethodUsageForOnlyBasicOperations()) + .verifyIssues(); + } +}