From c10f0372124bcbbd3b9bdfa197255b1ac985a5bd Mon Sep 17 00:00:00 2001 From: jberque Date: Thu, 9 Mar 2023 15:48:05 +0100 Subject: [PATCH 1/3] Add Dockerfile build context preventing docker error : "ERROR: The Compose file is invalid because: Service sonar has neither an image nor a build context specified. At least one must be provided." --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index e1a3abcc..924b4dbf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ services: sonar: build: dockerfile: Dockerfile + context: . container_name: sonar_ecocode-mobile ports: - "9000:9000" From 23c15afb7b35f5b4f08ca4b12954f903f1647e33 Mon Sep 17 00:00:00 2001 From: jberque Date: Thu, 9 Mar 2023 15:51:00 +0100 Subject: [PATCH 2/3] Updating rule EREA001 SupportedVersionRange adding short targetSdk / minSdk coverage --- .../org/sonar/plugins/groovy/rules.xml | 2 +- .../groovy/GroovySonarWayProfileTest.java | 94 +++++++++++-------- .../CodeNarc/docs/codenarc-rules-ecocode.md | 2 +- .../ecocode/SupportedVersionRangeRule.groovy | 12 ++- .../SupportedVersionRangeRuleTest.groovy | 35 +++++++ 5 files changed, 103 insertions(+), 42 deletions(-) diff --git a/android-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml b/android-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml index acbdffb8..3c75be05 100644 --- a/android-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml +++ b/android-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml @@ -50,7 +50,7 @@ MINOR - When looking at the minSdkVersion and targetSdkVersion attributes for the in the AndroidManifest.xml file, the amplitude of supported platform versions should not be too wide, at the risk of making the app too heavy to handle all cases.

+ When looking at the minSdkVersion and targetSdkVersion (or minSdk, targetSdk) attributes for the in the AndroidManifest.xml file, the amplitude of supported platform versions should not be too wide, at the risk of making the app too heavy to handle all cases.

Example of violations:

android {
     compileSdk 32
diff --git a/android-plugin/src/test/java/org/sonar/plugins/groovy/GroovySonarWayProfileTest.java b/android-plugin/src/test/java/org/sonar/plugins/groovy/GroovySonarWayProfileTest.java
index 19cafd91..1638640a 100644
--- a/android-plugin/src/test/java/org/sonar/plugins/groovy/GroovySonarWayProfileTest.java
+++ b/android-plugin/src/test/java/org/sonar/plugins/groovy/GroovySonarWayProfileTest.java
@@ -18,11 +18,6 @@
  */
 package org.sonar.plugins.groovy;
 
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
 import org.junit.Test;
 import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
 import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInActiveRule;
@@ -30,45 +25,68 @@
 import org.sonar.api.utils.ValidationMessages;
 import org.sonar.plugins.groovy.codenarc.CodeNarcRulesDefinition;
 import org.sonar.plugins.groovy.foundation.Groovy;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
 
 public class GroovySonarWayProfileTest {
 
-  @Test
-  public void shouldCreateSonarWayProfile() {
-    ValidationMessages messages = ValidationMessages.create();
+    @Test
+    public void shouldCreateSonarWayProfile() {
+        ValidationMessages messages = ValidationMessages.create();
 
-    GroovySonarWayProfile profileDef = new GroovySonarWayProfile();
-    BuiltInQualityProfilesDefinition.Context profileContext =
-        new BuiltInQualityProfilesDefinition.Context();
-    profileDef.define(profileContext);
-    BuiltInQualityProfilesDefinition.BuiltInQualityProfile profile =
-        profileContext.profile(Groovy.KEY, Groovy.PROFILE_NAME);
-    assertThat(profile.language()).isEqualTo(Groovy.KEY);
-    List activeRules = profile.rules();
-    // TODO The Number of Custom profile rules are set here,
-    //  we need to change this to get the size dynamically
-    assertThat(activeRules).as("Expected number of rules in profile").hasSize(3);
-    assertThat(profile.name()).isEqualTo(Groovy.PROFILE_NAME);
+        GroovySonarWayProfile profileDef = new GroovySonarWayProfile();
+        BuiltInQualityProfilesDefinition.Context profileContext = new BuiltInQualityProfilesDefinition.Context();
+        profileDef.define(profileContext);
+        BuiltInQualityProfilesDefinition.BuiltInQualityProfile profile = profileContext.profile(Groovy.KEY, Groovy.PROFILE_NAME);
+        assertThat(profile.language()).isEqualTo(Groovy.KEY);
+        List activeRules = profile.rules();
 
-    // Check that we use severity from the read rule and not default one.
-    assertThat(activeRules.get(0).overriddenSeverity()).isNull();
-    assertThat(messages.hasErrors()).isFalse();
+        // Here we check the rules.xml file to get the number of rules in it
+        File profile_default = new File("src/main/resources/org/sonar/plugins/groovy/rules.xml");
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        DocumentBuilder db;
+        try {
+            db = dbf.newDocumentBuilder();
+            Document doc = db.parse(profile_default);
+            doc.getDocumentElement().normalize();
+            NodeList rule = doc.getElementsByTagName("rule");
+            assertThat(activeRules).as("Expected number of rules in profile").hasSize(rule.getLength());
+        } catch (ParserConfigurationException | SAXException | IOException e) {
+            e.printStackTrace();
+        }
+        assertThat(profile.name()).isEqualTo(Groovy.PROFILE_NAME);
 
-    // Check that all rules in "Sonar way" actually exist
-    CodeNarcRulesDefinition definition = new CodeNarcRulesDefinition();
-    RulesDefinition.Context rulesContext = new RulesDefinition.Context();
-    definition.define(rulesContext);
-    RulesDefinition.Repository repository =
-        rulesContext.repository(CodeNarcRulesDefinition.REPOSITORY_KEY);
+        // Check that we use severity from the read rule and not default one.
+        assertThat(activeRules.get(0).overriddenSeverity()).isNull();
+        assertThat(messages.hasErrors()).isFalse();
 
-    Set rules = new HashSet<>();
-    for (RulesDefinition.Rule rule : repository.rules()) {
-      rules.add(rule.key());
-    }
-    for (BuiltInActiveRule activeRule : profile.rules()) {
-      assertThat(rules.contains(activeRule.ruleKey()))
-          .as("No such rule: " + activeRule.ruleKey())
-          .isTrue();
+        // Check that all rules in "Sonar way" actually exist
+        CodeNarcRulesDefinition definition = new CodeNarcRulesDefinition();
+        RulesDefinition.Context rulesContext = new RulesDefinition.Context();
+        definition.define(rulesContext);
+        RulesDefinition.Repository repository =
+                rulesContext.repository(CodeNarcRulesDefinition.REPOSITORY_KEY);
+
+        Set rules = new HashSet<>();
+        for (RulesDefinition.Rule rule : repository.rules()) {
+            rules.add(rule.key());
+        }
+        for (BuiltInActiveRule activeRule : profile.rules()) {
+            assertThat(rules.contains(activeRule.ruleKey()))
+                    .as("No such rule: " + activeRule.ruleKey())
+                    .isTrue();
+        }
     }
-  }
 }
diff --git a/codenarc-converter/CodeNarc/docs/codenarc-rules-ecocode.md b/codenarc-converter/CodeNarc/docs/codenarc-rules-ecocode.md
index 516dcf8b..ea059f96 100644
--- a/codenarc-converter/CodeNarc/docs/codenarc-rules-ecocode.md
+++ b/codenarc-converter/CodeNarc/docs/codenarc-rules-ecocode.md
@@ -49,7 +49,7 @@ Example of violations:
 
 *Since CodeNarc 2.2.1*
 
-When looking at the minSdkVersion and targetSdkVersion attributes for the  in the AndroidManifest.xml file, the amplitude of supported platform versions should not be too wide, at the risk of making the app too heavy to handle all cases.
+When looking at the minSdkVersion and targetSdkVersion (or minSdk, targetSdk) attributes for the  in the AndroidManifest.xml file, the amplitude of supported platform versions should not be too wide, at the risk of making the app too heavy to handle all cases.
 
 Example of violations:
 
diff --git a/codenarc-converter/CodeNarc/src/main/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRule.groovy b/codenarc-converter/CodeNarc/src/main/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRule.groovy
index 3985da55..d9df0334 100644
--- a/codenarc-converter/CodeNarc/src/main/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRule.groovy
+++ b/codenarc-converter/CodeNarc/src/main/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRule.groovy
@@ -22,7 +22,7 @@ import org.codenarc.rule.AbstractAstVisitorRule
 import org.codenarc.util.AstUtil
 
 /**
- * When looking at the minSdkVersion and targetSdkVersion attributes for the  in the AndroidManifest.xml file, the amplitude of supported platform versions should not be too wide, at the risk of making the app too heavy to handle all cases.
+ * When looking at the minSdkVersion and targetSdkVersion or minSdk and targetSdk attributes for the  in the AndroidManifest.xml file, the amplitude of supported platform versions should not be too wide, at the risk of making the app too heavy to handle all cases.
  *
  * @author Leboulanger Mickael
  */
@@ -31,7 +31,9 @@ class SupportedVersionRangeRule extends AbstractAstVisitorRule {
     String name = 'SupportedVersionRange'
     int priority = 2
     int minSdkVersion = 0
+    int minSdk = 0
     int targetSdkVersion = 0
+    int targetSdk = 0
     int threshold = 4 // Value used to compare minSdkVersion and targetSdkVersion
     Class astVisitorClass = SupportedVersionRangeAstVisitor
 }
@@ -41,14 +43,20 @@ class SupportedVersionRangeAstVisitor extends AbstractAstVisitor {
     @Override
     void visitMethodCallExpression(MethodCallExpression methodCallExpression) {
         def methodName = ((ConstantExpression) methodCallExpression.getMethod()).getValue()
-        if (methodName == 'minSdkVersion' || methodName == 'targetSdkVersion') {
+        if (methodName == 'minSdkVersion' || methodName == 'targetSdkVersion' || methodName == 'minSdk' || methodName == 'targetSdk') {
             def arguments = AstUtil.getArgumentsValue(methodCallExpression.getArguments())
+
             if (arguments.size() == 1) {
                 rule[methodName] = arguments.get(0)
             }
+
             if ((rule.minSdkVersion && rule.targetSdkVersion) && rule.targetSdkVersion - rule.minSdkVersion > rule.threshold) {
                 addViolation(methodCallExpression, getViolationMessage())
             }
+
+            if ((rule.minSdk && rule.targetSdk) && rule.targetSdk - rule.minSdk > rule.threshold) {
+                addViolation(methodCallExpression, getViolationMessage())
+            }
         }
         super.visitMethodCallExpression(methodCallExpression)
     }
diff --git a/codenarc-converter/CodeNarc/src/test/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRuleTest.groovy b/codenarc-converter/CodeNarc/src/test/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRuleTest.groovy
index 6c5968ed..df1bf4b2 100644
--- a/codenarc-converter/CodeNarc/src/test/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRuleTest.groovy
+++ b/codenarc-converter/CodeNarc/src/test/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRuleTest.groovy
@@ -99,6 +99,41 @@ class SupportedVersionRangeRuleTest extends AbstractRuleTestCase
Date: Thu, 9 Mar 2023 16:34:44 +0100
Subject: [PATCH 3/3] make the test method throws exceptions , if the file is
 not found in the project, the test will fail showing the 
 FileNotFoundException

---
 .../groovy/GroovySonarWayProfileTest.java        | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/android-plugin/src/test/java/org/sonar/plugins/groovy/GroovySonarWayProfileTest.java b/android-plugin/src/test/java/org/sonar/plugins/groovy/GroovySonarWayProfileTest.java
index 1638640a..046b367a 100644
--- a/android-plugin/src/test/java/org/sonar/plugins/groovy/GroovySonarWayProfileTest.java
+++ b/android-plugin/src/test/java/org/sonar/plugins/groovy/GroovySonarWayProfileTest.java
@@ -43,7 +43,7 @@
 public class GroovySonarWayProfileTest {
 
     @Test
-    public void shouldCreateSonarWayProfile() {
+    public void shouldCreateSonarWayProfile() throws ParserConfigurationException, IOException, SAXException {
         ValidationMessages messages = ValidationMessages.create();
 
         GroovySonarWayProfile profileDef = new GroovySonarWayProfile();
@@ -57,15 +57,11 @@ public void shouldCreateSonarWayProfile() {
         File profile_default = new File("src/main/resources/org/sonar/plugins/groovy/rules.xml");
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder db;
-        try {
-            db = dbf.newDocumentBuilder();
-            Document doc = db.parse(profile_default);
-            doc.getDocumentElement().normalize();
-            NodeList rule = doc.getElementsByTagName("rule");
-            assertThat(activeRules).as("Expected number of rules in profile").hasSize(rule.getLength());
-        } catch (ParserConfigurationException | SAXException | IOException e) {
-            e.printStackTrace();
-        }
+        db = dbf.newDocumentBuilder();
+        Document doc = db.parse(profile_default);
+        doc.getDocumentElement().normalize();
+        NodeList ruleList = doc.getElementsByTagName("rule");
+        assertThat(activeRules).as("Expected number of rules in profile").hasSize(ruleList.getLength());
         assertThat(profile.name()).isEqualTo(Groovy.PROFILE_NAME);
 
         // Check that we use severity from the read rule and not default one.