Skip to content

Commit bb54bb0

Browse files
authored
Merge pull request #28 from green-code-initiative/rule/EREA001_supported_version_range
Rule/erea001 supported version range
2 parents 5a4cb76 + 00618ca commit bb54bb0

File tree

6 files changed

+100
-42
lines changed

6 files changed

+100
-42
lines changed

android-plugin/src/main/resources/org/sonar/plugins/groovy/rules.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
<severity>MINOR</severity>
5151
<name><![CDATA[Supported Version Range]]></name>
5252
<internalKey><![CDATA[SupportedVersionRange]]></internalKey>
53-
<description><![CDATA[<p>When looking at the minSdkVersion and targetSdkVersion attributes for the <uses-sdk> 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.</p>
53+
<description><![CDATA[<p>When looking at the minSdkVersion and targetSdkVersion (or minSdk, targetSdk) attributes for the <uses-sdk> 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.</p>
5454
<p>Example of violations:</p>
5555
<pre><code>android {
5656
compileSdk 32

android-plugin/src/test/java/org/sonar/plugins/groovy/GroovySonarWayProfileTest.java

+52-38
Original file line numberDiff line numberDiff line change
@@ -18,57 +18,71 @@
1818
*/
1919
package org.sonar.plugins.groovy;
2020

21-
import static org.assertj.core.api.Assertions.assertThat;
22-
23-
import java.util.HashSet;
24-
import java.util.List;
25-
import java.util.Set;
2621
import org.junit.Test;
2722
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
2823
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.BuiltInActiveRule;
2924
import org.sonar.api.server.rule.RulesDefinition;
3025
import org.sonar.api.utils.ValidationMessages;
3126
import org.sonar.plugins.groovy.codenarc.CodeNarcRulesDefinition;
3227
import org.sonar.plugins.groovy.foundation.Groovy;
28+
import org.w3c.dom.Document;
29+
import org.w3c.dom.NodeList;
30+
import org.xml.sax.SAXException;
31+
32+
import javax.xml.parsers.DocumentBuilder;
33+
import javax.xml.parsers.DocumentBuilderFactory;
34+
import javax.xml.parsers.ParserConfigurationException;
35+
import java.io.File;
36+
import java.io.IOException;
37+
import java.util.HashSet;
38+
import java.util.List;
39+
import java.util.Set;
40+
41+
import static org.assertj.core.api.Assertions.assertThat;
3342

3443
public class GroovySonarWayProfileTest {
3544

36-
@Test
37-
public void shouldCreateSonarWayProfile() {
38-
ValidationMessages messages = ValidationMessages.create();
45+
@Test
46+
public void shouldCreateSonarWayProfile() throws ParserConfigurationException, IOException, SAXException {
47+
ValidationMessages messages = ValidationMessages.create();
3948

40-
GroovySonarWayProfile profileDef = new GroovySonarWayProfile();
41-
BuiltInQualityProfilesDefinition.Context profileContext =
42-
new BuiltInQualityProfilesDefinition.Context();
43-
profileDef.define(profileContext);
44-
BuiltInQualityProfilesDefinition.BuiltInQualityProfile profile =
45-
profileContext.profile(Groovy.KEY, Groovy.PROFILE_NAME);
46-
assertThat(profile.language()).isEqualTo(Groovy.KEY);
47-
List<BuiltInActiveRule> activeRules = profile.rules();
48-
// TODO The Number of Custom profile rules are set here,
49-
// we need to change this to get the size dynamically
50-
assertThat(activeRules).as("Expected number of rules in profile").hasSize(3);
51-
assertThat(profile.name()).isEqualTo(Groovy.PROFILE_NAME);
49+
GroovySonarWayProfile profileDef = new GroovySonarWayProfile();
50+
BuiltInQualityProfilesDefinition.Context profileContext = new BuiltInQualityProfilesDefinition.Context();
51+
profileDef.define(profileContext);
52+
BuiltInQualityProfilesDefinition.BuiltInQualityProfile profile = profileContext.profile(Groovy.KEY, Groovy.PROFILE_NAME);
53+
assertThat(profile.language()).isEqualTo(Groovy.KEY);
54+
List<BuiltInActiveRule> activeRules = profile.rules();
5255

53-
// Check that we use severity from the read rule and not default one.
54-
assertThat(activeRules.get(0).overriddenSeverity()).isNull();
55-
assertThat(messages.hasErrors()).isFalse();
56+
// Here we check the rules.xml file to get the number of rules in it
57+
File profile_default = new File("src/main/resources/org/sonar/plugins/groovy/rules.xml");
58+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
59+
DocumentBuilder db;
60+
db = dbf.newDocumentBuilder();
61+
Document doc = db.parse(profile_default);
62+
doc.getDocumentElement().normalize();
63+
NodeList ruleList = doc.getElementsByTagName("rule");
64+
assertThat(activeRules).as("Expected number of rules in profile").hasSize(ruleList.getLength());
65+
assertThat(profile.name()).isEqualTo(Groovy.PROFILE_NAME);
5666

57-
// Check that all rules in "Sonar way" actually exist
58-
CodeNarcRulesDefinition definition = new CodeNarcRulesDefinition();
59-
RulesDefinition.Context rulesContext = new RulesDefinition.Context();
60-
definition.define(rulesContext);
61-
RulesDefinition.Repository repository =
62-
rulesContext.repository(CodeNarcRulesDefinition.REPOSITORY_KEY);
67+
// Check that we use severity from the read rule and not default one.
68+
assertThat(activeRules.get(0).overriddenSeverity()).isNull();
69+
assertThat(messages.hasErrors()).isFalse();
6370

64-
Set<String> rules = new HashSet<>();
65-
for (RulesDefinition.Rule rule : repository.rules()) {
66-
rules.add(rule.key());
67-
}
68-
for (BuiltInActiveRule activeRule : profile.rules()) {
69-
assertThat(rules.contains(activeRule.ruleKey()))
70-
.as("No such rule: " + activeRule.ruleKey())
71-
.isTrue();
71+
// Check that all rules in "Sonar way" actually exist
72+
CodeNarcRulesDefinition definition = new CodeNarcRulesDefinition();
73+
RulesDefinition.Context rulesContext = new RulesDefinition.Context();
74+
definition.define(rulesContext);
75+
RulesDefinition.Repository repository =
76+
rulesContext.repository(CodeNarcRulesDefinition.REPOSITORY_KEY);
77+
78+
Set<String> rules = new HashSet<>();
79+
for (RulesDefinition.Rule rule : repository.rules()) {
80+
rules.add(rule.key());
81+
}
82+
for (BuiltInActiveRule activeRule : profile.rules()) {
83+
assertThat(rules.contains(activeRule.ruleKey()))
84+
.as("No such rule: " + activeRule.ruleKey())
85+
.isTrue();
86+
}
7287
}
73-
}
7488
}

codenarc-converter/CodeNarc/docs/codenarc-rules-ecocode.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Example of violations:
4949

5050
*Since CodeNarc 2.2.1*
5151

52-
When looking at the minSdkVersion and targetSdkVersion attributes for the <uses-sdk> 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.
52+
When looking at the minSdkVersion and targetSdkVersion (or minSdk, targetSdk) attributes for the <uses-sdk> 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.
5353

5454
Example of violations:
5555

codenarc-converter/CodeNarc/src/main/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRule.groovy

+10-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import org.codenarc.rule.AbstractAstVisitorRule
2222
import org.codenarc.util.AstUtil
2323

2424
/**
25-
* When looking at the minSdkVersion and targetSdkVersion attributes for the <uses-sdk> 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.
25+
* When looking at the minSdkVersion and targetSdkVersion or minSdk and targetSdk attributes for the <uses-sdk> 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.
2626
*
2727
* @author Leboulanger Mickael
2828
*/
@@ -31,7 +31,9 @@ class SupportedVersionRangeRule extends AbstractAstVisitorRule {
3131
String name = 'SupportedVersionRange'
3232
int priority = 2
3333
int minSdkVersion = 0
34+
int minSdk = 0
3435
int targetSdkVersion = 0
36+
int targetSdk = 0
3537
int threshold = 4 // Value used to compare minSdkVersion and targetSdkVersion
3638
Class astVisitorClass = SupportedVersionRangeAstVisitor
3739
}
@@ -41,14 +43,20 @@ class SupportedVersionRangeAstVisitor extends AbstractAstVisitor {
4143
@Override
4244
void visitMethodCallExpression(MethodCallExpression methodCallExpression) {
4345
def methodName = ((ConstantExpression) methodCallExpression.getMethod()).getValue()
44-
if (methodName == 'minSdkVersion' || methodName == 'targetSdkVersion') {
46+
if (methodName == 'minSdkVersion' || methodName == 'targetSdkVersion' || methodName == 'minSdk' || methodName == 'targetSdk') {
4547
def arguments = AstUtil.getArgumentsValue(methodCallExpression.getArguments())
48+
4649
if (arguments.size() == 1) {
4750
rule[methodName] = arguments.get(0)
4851
}
52+
4953
if ((rule.minSdkVersion && rule.targetSdkVersion) && rule.targetSdkVersion - rule.minSdkVersion > rule.threshold) {
5054
addViolation(methodCallExpression, getViolationMessage())
5155
}
56+
57+
if ((rule.minSdk && rule.targetSdk) && rule.targetSdk - rule.minSdk > rule.threshold) {
58+
addViolation(methodCallExpression, getViolationMessage())
59+
}
5260
}
5361
super.visitMethodCallExpression(methodCallExpression)
5462
}

codenarc-converter/CodeNarc/src/test/groovy/org/codenarc/rule/ecocode/SupportedVersionRangeRuleTest.groovy

+35
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,41 @@ class SupportedVersionRangeRuleTest extends AbstractRuleTestCase<SupportedVersio
9999
assertSingleViolation(SOURCE,8, 'targetSdkVersion')
100100
}
101101

102+
103+
@Test
104+
void test_SdkRange_Short_SingleViolation() {
105+
final SOURCE = '''
106+
android {
107+
compileSdk 32
108+
109+
defaultConfig {
110+
applicationId "com.example.sampleForSonar"
111+
minSdk 26
112+
targetSdk 31
113+
versionCode 1
114+
versionName "1.0"
115+
116+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
117+
}
118+
119+
buildTypes {
120+
release {
121+
minifyEnabled false
122+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro\'
123+
}
124+
}
125+
compileOptions {
126+
sourceCompatibility JavaVersion.VERSION_1_8
127+
targetCompatibility JavaVersion.VERSION_1_8
128+
}
129+
buildFeatures {
130+
viewBinding true
131+
}
132+
}
133+
'''
134+
assertSingleViolation(SOURCE,8, 'targetSdk')
135+
}
136+
102137
@Override
103138
protected SupportedVersionRangeRule createRule() {
104139
new SupportedVersionRangeRule()

docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ services:
33
sonar:
44
build:
55
dockerfile: Dockerfile
6+
context: .
67
container_name: sonar_ecocode-mobile
78
ports:
89
- "9000:9000"

0 commit comments

Comments
 (0)