Skip to content

Commit 1dead4d

Browse files
authored
Merge pull request #110 from max-208/82-java
GCI82 [Team STEP][2025] correct false positives
2 parents 4a7435a + 17e2739 commit 1dead4d

File tree

5 files changed

+194
-4
lines changed

5 files changed

+194
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
### Changed
13-
13+
- [#110](https://github.com/green-code-initiative/creedengo-java/pull/110) GCI82 - remove false positives with reassignment using this and with passing a variable to a function it can be reassigned in
1414
- compatibility updates for SonarQube 25.5.0
1515
- upgrade libraries versions
1616
- correction of technical problem with Integration tests (because of Maven format in technical answer to "sonar-orchestrator-junit5" library)

src/it/java/org/greencodeinitiative/creedengo/java/integration/tests/GCIRulesIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,8 @@ void testGCI82() {
440440
String filePath = "src/main/java/org/greencodeinitiative/creedengo/java/checks/MakeNonReassignedVariablesConstants.java";
441441
String ruleId = "creedengo-java:GCI82";
442442
String ruleMsg = "The variable is never reassigned and can be 'final'";
443-
int[] startLines = new int[]{7, 12, 13, 45};
444-
int[] endLines = new int[]{7, 12, 13, 45};
443+
int[] startLines = new int[]{7, 12, 13, 18, 24, 27, 46, 73, 106, 119};
444+
int[] endLines = new int[]{7, 12, 13, 18, 24, 27, 46, 73, 106, 119};
445445

446446
checkIssuesForFile(filePath, ruleId, ruleMsg, startLines, endLines);
447447
}

src/it/test-projects/creedengo-java-plugin-test-project/src/main/java/org/greencodeinitiative/creedengo/java/checks/MakeNonReassignedVariablesConstants.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,37 @@ public class MakeNonReassignedVariablesConstants {
1414
private String varDefinedInClassReassigned = "0"; // Compliant
1515
private String varDefinedInConstructorReassigned = "1"; // Compliant
1616

17+
// using "this"
18+
private String varDefinedInClassNotReassignedByThis = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
19+
private String varDefinedInClassReassignedByThis = "0"; // Compliant
20+
private String varDefinedInConstructorReassignedByThis = "1"; // Compliant
21+
22+
// passing through a method
23+
private String varDefinedInClassReassignedInMethod = "0"; // Compliant
24+
private String varDefinedInClassInFinalMethod = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
25+
private String varDefinedInClassNotReassignedInMethod = "0"; // Compliant (the String was passed as a non-final parameter to the method)
26+
private String varDefinedInClassReassignedInConstructor = "0"; // Compliant
27+
private String varDefinedInClassInFinalConstructor = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
28+
private String varDefinedInClassNotReassignedInConstructor = "0"; // Compliant (the String was passed as a non-final parameter to the constructor)
29+
1730
public MakeNonReassignedVariablesConstants() {
1831
varDefinedInConstructorReassigned = "3";
32+
this.varDefinedInConstructorReassignedByThis = "3";
1933
logger.info(varDefinedInConstructorReassigned);
34+
logger.info(this.varDefinedInConstructorReassignedByThis);
35+
}
36+
37+
public void parameterReassigned(String reassigned) {
38+
reassigned = "10";
39+
logger.info(reassigned);
40+
}
41+
42+
public void parameterNotReassigned(final String notReassigned) {
43+
logger.info(notReassigned);
44+
}
45+
46+
public void parameterNotReassignedNotFinal(String notReassigned) { // Noncompliant {{The variable is never reassigned and can be 'final'}}
47+
logger.info(notReassigned);
2048
}
2149

2250
void localVariableReassigned() {
@@ -66,4 +94,54 @@ void classVariableReassignedBis() {
6694
logger.info(myFinalAndNotReassignedObject.toString());
6795
}
6896

97+
void classVariableReassignedByThis() {
98+
this.varDefinedInClassReassignedByThis = "1";
99+
100+
logger.info(this.varDefinedInClassReassignedByThis);
101+
logger.info(this.varDefinedInClassNotReassignedByThis);
102+
}
103+
104+
void reassignedInMethod() {
105+
String varDefinedInMethodReassignedInMethod = "0"; // Compliant
106+
String varDefinedInMethodInFinalMethod = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
107+
String varDefinedInMethodNotReassignedInMethod = "0"; // Compliant (the String was passed as a non-final parameter to the method)
108+
109+
this.parameterReassigned(varDefinedInMethodReassignedInMethod);
110+
this.parameterReassigned(this.varDefinedInClassReassignedInMethod);
111+
this.parameterNotReassigned(varDefinedInMethodInFinalMethod);
112+
this.parameterNotReassigned(this.varDefinedInClassInFinalMethod);
113+
this.parameterNotReassignedNotFinal(varDefinedInMethodNotReassignedInMethod);
114+
this.parameterNotReassignedNotFinal(this.varDefinedInClassNotReassignedInMethod);
115+
}
116+
117+
void reassignedInConstructor(){
118+
String varDefinedInMethodReassignedInConstructor = "0"; // Compliant
119+
String varDefinedInMethodInFinalConstructor = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
120+
String varDefinedInMethodNotReassignedInConstructor = "0"; // Compliant (the String was passed as a non-final parameter to the constructor)
121+
Object o = null;
122+
o = new reassignedInConstructor(varDefinedInMethodReassignedInConstructor);
123+
o = new reassignedInConstructor(this.varDefinedInClassReassignedInConstructor);
124+
o = new notReassignedInConstructor(varDefinedInMethodInFinalConstructor);
125+
o = new notReassignedInConstructor(this.varDefinedInClassInFinalConstructor);
126+
o = new notReassignedInConstructorNotFinal(varDefinedInMethodNotReassignedInConstructor);
127+
o = new notReassignedInConstructorNotFinal(this.varDefinedInClassNotReassignedInConstructor);
128+
}
129+
130+
}
131+
132+
class reassignedInConstructor{
133+
reassignedInConstructor(String reassignedInConstructor) {
134+
reassignedInConstructor = "10";
135+
System.out.println(reassignedInConstructor);
136+
}
137+
}
138+
class notReassignedInConstructor{
139+
notReassignedInConstructor(final String notReassignedInConstructor) {
140+
System.out.println(notReassignedInConstructor);
141+
}
142+
}
143+
class notReassignedInConstructorNotFinal{
144+
notReassignedInConstructorNotFinal(String notReassignedInConstructorNotFinal) { // Noncompliant {{The variable is never reassigned and can be 'final'}}
145+
System.out.println(notReassignedInConstructorNotFinal);
146+
}
69147
}

src/main/java/org/greencodeinitiative/creedengo/java/checks/MakeNonReassignedVariablesConstants.java

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public void visitNode(@Nonnull Tree tree) {
2929
LOGGER.debug(" => isNotFinalAndNotStatic(variableTree) = " + isNotFinalAndNotStatic(variableTree));
3030
LOGGER.debug(" => usages = " + variableTree.symbol().usages().size());
3131
LOGGER.debug(" => isNotReassigned = " + isNotReassigned(variableTree));
32+
LOGGER.debug(" => isPassedAsNonFinalParameter = " + isPassedAsNonFinalParameter(variableTree));
3233

3334
if (isNotFinalAndNotStatic(variableTree) && isNotReassigned(variableTree)) {
3435
reportIssue(tree, MESSAGE_RULE);
@@ -41,10 +42,43 @@ private static boolean isNotReassigned(VariableTree variableTree) {
4142
return variableTree.symbol()
4243
.usages()
4344
.stream()
44-
.noneMatch(MakeNonReassignedVariablesConstants::parentIsAssignment);
45+
.noneMatch(MakeNonReassignedVariablesConstants::parentIsAssignment)
46+
&& !isPassedAsNonFinalParameter(variableTree); // if a variable is passed into a method as a non-final parameter, it may have been reassigned
47+
}
48+
49+
private static boolean isPassedAsNonFinalParameter(VariableTree variableTree) {
50+
return variableTree.symbol()
51+
.usages()
52+
.stream()
53+
.anyMatch(MakeNonReassignedVariablesConstants::parentIsNonFinalParameter);
54+
}
55+
56+
private static boolean parentIsNonFinalParameter(Tree tree) {
57+
// Skip the parent if it is a member select (e.g. "this.myVar")
58+
while (tree.parent().is(Kind.MEMBER_SELECT)) {
59+
tree = tree.parent();
60+
}
61+
if(!parentIsKind(tree, Kind.ARGUMENTS))
62+
return false;
63+
if(tree.parent() == null)
64+
return false;
65+
Arguments arguments = (Arguments) tree.parent();
66+
if (parentIsKind(arguments, Kind.METHOD_INVOCATION, Kind.NEW_CLASS)) {
67+
MethodTree methodTree = arguments.parent().is(Kind.METHOD_INVOCATION)
68+
? ((MethodInvocationTree) arguments.parent()).methodSymbol().declaration()
69+
: ((NewClassTree) arguments.parent()).methodSymbol().declaration();
70+
int argument_idx = arguments.indexOf(tree);
71+
return methodTree != null && !hasModifier(methodTree.parameters().get(argument_idx).modifiers(), Modifier.FINAL);
72+
}
73+
return false;
74+
4575
}
4676

4777
private static boolean parentIsAssignment(Tree tree) {
78+
// Skip the parent if it is a member select (e.g. "this.myVar")
79+
while (tree.parent().is(Kind.MEMBER_SELECT)) {
80+
tree = tree.parent();
81+
}
4882
return parentIsKind(tree,
4983
Kind.ASSIGNMENT,
5084
Kind.MULTIPLY_ASSIGNMENT,

src/test/files/MakeNonReassignedVariablesConstants.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,37 @@ public class MakeNonReassignedVariablesConstants {
1414
private String varDefinedInClassReassigned = "0"; // Compliant
1515
private String varDefinedInConstructorReassigned = "1"; // Compliant
1616

17+
// using "this"
18+
private String varDefinedInClassNotReassignedByThis = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
19+
private String varDefinedInClassReassignedByThis = "0"; // Compliant
20+
private String varDefinedInConstructorReassignedByThis = "1"; // Compliant
21+
22+
// passing through a method
23+
private String varDefinedInClassReassignedInMethod = "0"; // Compliant
24+
private String varDefinedInClassInFinalMethod = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
25+
private String varDefinedInClassNotReassignedInMethod = "0"; // Compliant (the String was passed as a non-final parameter to the method)
26+
private String varDefinedInClassReassignedInConstructor = "0"; // Compliant
27+
private String varDefinedInClassInFinalConstructor = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
28+
private String varDefinedInClassNotReassignedInConstructor = "0"; // Compliant (the String was passed as a non-final parameter to the constructor)
29+
1730
public MakeNonReassignedVariablesConstants() {
1831
varDefinedInConstructorReassigned = "3";
32+
this.varDefinedInConstructorReassignedByThis = "3";
1933
logger.info(varDefinedInConstructorReassigned);
34+
logger.info(this.varDefinedInConstructorReassignedByThis);
35+
}
36+
37+
public void parameterReassigned(String reassigned) {
38+
reassigned = "10";
39+
logger.info(reassigned);
40+
}
41+
42+
public void parameterNotReassigned(final String notReassigned) {
43+
logger.info(notReassigned);
44+
}
45+
46+
public void parameterNotReassignedNotFinal(String notReassigned) { // Noncompliant {{The variable is never reassigned and can be 'final'}}
47+
logger.info(notReassigned);
2048
}
2149

2250
void localVariableReassigned() {
@@ -66,4 +94,54 @@ void classVariableReassignedBis() {
6694
logger.info(myFinalAndNotReassignedObject.toString());
6795
}
6896

97+
void classVariableReassignedByThis() {
98+
this.varDefinedInClassReassignedByThis = "1";
99+
100+
logger.info(this.varDefinedInClassReassignedByThis);
101+
logger.info(this.varDefinedInClassNotReassignedByThis);
102+
}
103+
104+
void reassignedInMethod() {
105+
String varDefinedInMethodReassignedInMethod = "0"; // Compliant
106+
String varDefinedInMethodInFinalMethod = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
107+
String varDefinedInMethodNotReassignedInMethod = "0"; // Compliant (the String was passed as a non-final parameter to the method)
108+
109+
this.parameterReassigned(varDefinedInMethodReassignedInMethod);
110+
this.parameterReassigned(this.varDefinedInClassReassignedInMethod);
111+
this.parameterNotReassigned(varDefinedInMethodInFinalMethod);
112+
this.parameterNotReassigned(this.varDefinedInClassInFinalMethod);
113+
this.parameterNotReassignedNotFinal(varDefinedInMethodNotReassignedInMethod);
114+
this.parameterNotReassignedNotFinal(this.varDefinedInClassNotReassignedInMethod);
115+
}
116+
117+
void reassignedInConstructor(){
118+
String varDefinedInMethodReassignedInConstructor = "0"; // Compliant
119+
String varDefinedInMethodInFinalConstructor = "0"; // Noncompliant {{The variable is never reassigned and can be 'final'}}
120+
String varDefinedInMethodNotReassignedInConstructor = "0"; // Compliant (the String was passed as a non-final parameter to the constructor)
121+
Object o = null;
122+
o = new reassignedInConstructor(varDefinedInMethodReassignedInConstructor);
123+
o = new reassignedInConstructor(this.varDefinedInClassReassignedInConstructor);
124+
o = new notReassignedInConstructor(varDefinedInMethodInFinalConstructor);
125+
o = new notReassignedInConstructor(this.varDefinedInClassInFinalConstructor);
126+
o = new notReassignedInConstructorNotFinal(varDefinedInMethodNotReassignedInConstructor);
127+
o = new notReassignedInConstructorNotFinal(this.varDefinedInClassNotReassignedInConstructor);
128+
}
129+
130+
}
131+
132+
class reassignedInConstructor{
133+
reassignedInConstructor(String reassignedInConstructor) {
134+
reassignedInConstructor = "10";
135+
System.out.println(reassignedInConstructor);
136+
}
137+
}
138+
class notReassignedInConstructor{
139+
notReassignedInConstructor(final String notReassignedInConstructor) {
140+
System.out.println(notReassignedInConstructor);
141+
}
142+
}
143+
class notReassignedInConstructorNotFinal{
144+
notReassignedInConstructorNotFinal(String notReassignedInConstructorNotFinal) { // Noncompliant {{The variable is never reassigned and can be 'final'}}
145+
System.out.println(notReassignedInConstructorNotFinal);
146+
}
69147
}

0 commit comments

Comments
 (0)