Skip to content

Commit 9017297

Browse files
author
Hachemi ATROUNE
committed
Add Rule EC82: Make variable constant
1 parent 716fe9b commit 9017297

File tree

7 files changed

+116
-18
lines changed

7 files changed

+116
-18
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313

1414
### Deleted
1515

16+
17+
## [1.6.2] - 2024-05-30
18+
19+
### Added
20+
21+
- EC82 rule : A variable is never reassigned and can be made constant
22+
1623
## [1.6.1] - 2024-05-15
1724

1825
### Changed

src/main/java/fr/greencodeinitiative/java/JavaCheckRegistrar.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,7 @@
2020
import java.util.Collections;
2121
import java.util.List;
2222

23-
import fr.greencodeinitiative.java.checks.ArrayCopyCheck;
24-
import fr.greencodeinitiative.java.checks.AvoidFullSQLRequest;
25-
import fr.greencodeinitiative.java.checks.AvoidGettingSizeCollectionInLoop;
26-
import fr.greencodeinitiative.java.checks.AvoidMultipleIfElseStatement;
27-
import fr.greencodeinitiative.java.checks.AvoidRegexPatternNotStatic;
28-
import fr.greencodeinitiative.java.checks.AvoidSQLRequestInLoop;
29-
import fr.greencodeinitiative.java.checks.AvoidSetConstantInBatchUpdate;
30-
import fr.greencodeinitiative.java.checks.AvoidSpringRepositoryCallInLoopOrStreamCheck;
31-
import fr.greencodeinitiative.java.checks.AvoidStatementForDMLQueries;
32-
import fr.greencodeinitiative.java.checks.AvoidUsageOfStaticCollections;
33-
import fr.greencodeinitiative.java.checks.FreeResourcesOfAutoCloseableInterface;
34-
import fr.greencodeinitiative.java.checks.IncrementCheck;
35-
import fr.greencodeinitiative.java.checks.InitializeBufferWithAppropriateSize;
36-
import fr.greencodeinitiative.java.checks.NoFunctionCallWhenDeclaringForLoop;
37-
import fr.greencodeinitiative.java.checks.OptimizeReadFileExceptions;
23+
import fr.greencodeinitiative.java.checks.*;
3824
import org.sonar.plugins.java.api.CheckRegistrar;
3925
import org.sonar.plugins.java.api.JavaCheck;
4026
import org.sonarsource.api.sonarlint.SonarLintSide;
@@ -62,7 +48,8 @@ public class JavaCheckRegistrar implements CheckRegistrar {
6248
InitializeBufferWithAppropriateSize.class,
6349
AvoidSetConstantInBatchUpdate.class,
6450
FreeResourcesOfAutoCloseableInterface.class,
65-
AvoidMultipleIfElseStatement.class
51+
AvoidMultipleIfElseStatement.class,
52+
MakeVariableConstant.class
6653
);
6754

6855
/**
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* ecoCode - Java language - Provides rules to reduce the environmental footprint of your Java programs
3+
* Copyright © 2023 Green Code Initiative (https://www.ecocode.io)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package fr.greencodeinitiative.java.checks;
19+
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
import java.util.stream.Collectors;
23+
24+
import org.sonar.check.Rule;
25+
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
26+
import org.sonar.plugins.java.api.semantic.Symbol;
27+
import org.sonar.plugins.java.api.tree.*;
28+
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;
29+
30+
@Rule(key = "EC82")
31+
@DeprecatedRuleKey(repositoryKey = "greencodeinitiative-java", ruleKey = "S82")
32+
public class MakeVariableConstant extends IssuableSubscriptionVisitor {
33+
public static final String ERROR_MESSAGE = "A variable is never reassigned and can be made constant";
34+
35+
@Override
36+
public List<Tree.Kind> nodesToVisit() {
37+
return List.of(Tree.Kind.VARIABLE);
38+
}
39+
40+
@Override
41+
public void visitNode(Tree tree) {
42+
VariableTree variableTree = (VariableTree) tree;
43+
Symbol symbol = variableTree.symbol();
44+
if (symbol.isVariableSymbol() && !symbol.isFinal()) {
45+
boolean reassigned = isReassigned(symbol);
46+
if (!reassigned) {
47+
reportIssue(variableTree.simpleName(), ERROR_MESSAGE);
48+
}
49+
}
50+
}
51+
52+
private boolean isReassigned(Symbol symbol) {
53+
Tree parent = symbol.declaration().parent();
54+
if (parent instanceof BlockTree) {
55+
return isReassignedInBlock(symbol, (BlockTree) parent);
56+
}
57+
return false;
58+
}
59+
60+
private boolean isReassignedInBlock(Symbol symbol, BlockTree blockTree) {
61+
List<AssignmentExpressionTree> assignments = new ArrayList<>();
62+
List<StatementTree> body = blockTree.body();
63+
64+
for (StatementTree statement : body) {
65+
if (statement.is(Tree.Kind.EXPRESSION_STATEMENT)) {
66+
ExpressionTree expression = ((ExpressionStatementTree) statement).expression();
67+
if (expression.is(Tree.Kind.ASSIGNMENT)) {
68+
assignments.add((AssignmentExpressionTree) expression);
69+
}
70+
}
71+
}
72+
73+
for (AssignmentExpressionTree assignment : assignments) {
74+
if (((IdentifierTree) assignment.variable()).symbol().equals(symbol)) {
75+
return true;
76+
}
77+
}
78+
return false;
79+
}
80+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class MakeVariableConstantTest {
2+
3+
public void testEc82() {
4+
String test = "test"; // Noncompliant {{A variable is never reassigned and can be made constant}}
5+
System.out.println("Hello World");
6+
}
7+
}

src/test/java/fr/greencodeinitiative/java/JavaCheckRegistrarTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ void checkNumberRules() {
3131
final JavaCheckRegistrar registrar = new JavaCheckRegistrar();
3232
registrar.register(context);
3333

34-
assertThat(context.checkClasses()).hasSize(15);
34+
assertThat(context.checkClasses()).hasSize(16);
3535
assertThat(context.testCheckClasses()).isEmpty();
3636

3737
}

src/test/java/fr/greencodeinitiative/java/JavaRulesDefinitionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void init() {
4646
RulesDefinition.Context context = new RulesDefinition.Context();
4747
rulesDefinition.define(context);
4848
repository = context.repository(rulesDefinition.repositoryKey());
49-
rulesSize = 15;
49+
rulesSize = 16;
5050
}
5151

5252
@Test
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package fr.greencodeinitiative.java.checks;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.sonar.java.checks.verifier.CheckVerifier;
5+
6+
public class MakeVariableConstantTest {
7+
8+
@Test
9+
void test() {
10+
CheckVerifier.newVerifier()
11+
.onFile("src/test/files/MakeVariableConstantTest.java")
12+
.withCheck(new MakeVariableConstant())
13+
.verifyIssues();
14+
}
15+
}
16+
17+

0 commit comments

Comments
 (0)