diff --git a/src/it/test-projects/creedengo-java-plugin-test-project/src/main/java/org/greencodeinitiative/creedengo/java/checks/GCI82/MakeNonReassignedVariablesConstants.java b/src/it/test-projects/creedengo-java-plugin-test-project/src/main/java/org/greencodeinitiative/creedengo/java/checks/GCI82/MakeNonReassignedVariablesConstants.java index dc192cdd..51c5493d 100644 --- a/src/it/test-projects/creedengo-java-plugin-test-project/src/main/java/org/greencodeinitiative/creedengo/java/checks/GCI82/MakeNonReassignedVariablesConstants.java +++ b/src/it/test-projects/creedengo-java-plugin-test-project/src/main/java/org/greencodeinitiative/creedengo/java/checks/GCI82/MakeNonReassignedVariablesConstants.java @@ -45,7 +45,7 @@ public void parameterNotReassigned(final String notReassigned) { logger.info(notReassigned); } - public void parameterNotReassignedNotFinal(String notReassigned) { // Noncompliant {{The variable is never reassigned and can be 'final'}} + public void parameterNotReassignedNotFinal(String notReassigned) { // Compliant logger.info(notReassigned); } @@ -129,6 +129,13 @@ void reassignedInConstructor(){ o = new notReassignedInConstructorNotFinal(this.varDefinedInClassNotReassignedInConstructor); } + void tryCatch(){ + try{ + logger.info(CONSTANT); + }catch (Exception e) { // Compliant + logger.error(e); + } + } } class reassignedInConstructor{ @@ -143,7 +150,76 @@ class notReassignedInConstructor{ } } class notReassignedInConstructorNotFinal{ - notReassignedInConstructorNotFinal(String notReassignedInConstructorNotFinal) { // Noncompliant {{The variable is never reassigned and can be 'final'}} + notReassignedInConstructorNotFinal(String notReassignedInConstructorNotFinal) { // Compliant System.out.println(notReassignedInConstructorNotFinal); } +} + +class AssignedVarFromMethod{ + AssignedVarFromMethod(){ + + } + final String constVar = "Toto"; + + getConstVar(){ + return this.constVar; + } + + static format(String s){ + return s.toUpperCase(); + } + + assignedVarFromMethod(){ + String var = this.getConstVar(); // Compliant + String var2 = AssignedVarFromMethod.format(var); // Compliant + } +} + +class ParentClass { + protected String parentAttribute = "parent"; + ParentClass(){ + parentAttribute = "parent2"; + } + ParentClass(String attribute){ + this.parentAttribute = attribute; + } +} + +class ChildClass extends ParentClass { + void methodWithParentAttribute(){ + String local1 = parentAttribute; // Noncompliant {{The variable is never reassigned and can be 'final'}} + } + void methodThisWithParentAttribute(){ + String local2 = this.parentAttribute; // Compliant + } + void methodWithSuperAttribute(){ + String local3 = super.parentAttribute; // Compliant + } + + String getAttribute(){ + return this.parentAttribute; + } +} + +class AssignedFromMethodvar { + private int bufferSize; + + AssignedFromMethodvar(int bufferSize){ + this.bufferSize = bufferSize; + } + + AssignedFromMethodvar(){ + final org.greencodeinitiative.creedengo.java.checks.ChildClass childClass = new ParentClass("child"); // Compliant + String childAttribute = childClass.getAttribute(); // Compliant + } + void assignedArray(){ + byte[] buffer = new byte[1024]; // Compliant + int[] values = new int[this.bufferSize]; // Compliant + String[] fixedArray = {"a","b","c"}; // Noncompliant {{The variable is never reassigned and can be 'final'}} + String[] strArray = new String[fixedArray.length]; // Compliant + } +} + +enum classEnum { // Compliant + un,deux,trois,quatre; } \ No newline at end of file diff --git a/src/main/java/org/greencodeinitiative/creedengo/java/checks/MakeNonReassignedVariablesConstants.java b/src/main/java/org/greencodeinitiative/creedengo/java/checks/MakeNonReassignedVariablesConstants.java index 495bc4e2..70c1b83e 100644 --- a/src/main/java/org/greencodeinitiative/creedengo/java/checks/MakeNonReassignedVariablesConstants.java +++ b/src/main/java/org/greencodeinitiative/creedengo/java/checks/MakeNonReassignedVariablesConstants.java @@ -3,7 +3,9 @@ import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.check.Rule; +import org.sonar.java.model.expression.NewArrayTreeImpl; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.semantic.Symbol; import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.Tree.Kind; @@ -32,6 +34,15 @@ public void visitNode(@Nonnull Tree tree) { LOGGER.debug(" => isNotReassigned = {}", isNotReassigned(variableTree)); LOGGER.debug(" => isPassedAsNonFinalParameter = {}", isPassedAsNonFinalParameter(variableTree)); } + + Tree parent = variableTree.parent(); + + if(isInitializedFromMethod(variableTree) || isInitializedFromField(variableTree) || variableTree.symbol().isParameter() + || isInitializedFromArray(variableTree)|| (parent != null && parent.is(Kind.CATCH))) { + super.visitNode(tree); + return; + } + if (isNotFinalAndNotStatic(variableTree) && isNotReassigned(variableTree)) { reportIssue(tree, MESSAGE_RULE); } else { @@ -39,6 +50,32 @@ public void visitNode(@Nonnull Tree tree) { } } + private static boolean isInitializedFromMethod(VariableTree variableTree) { + ExpressionTree initializer = variableTree.initializer(); + return initializer != null && initializer.is(Kind.METHOD_INVOCATION); + } + + private static boolean isInitializedFromArray(VariableTree variableTree) { + if(variableTree.initializer() instanceof NewArrayTreeImpl) { + NewArrayTreeImpl initializer = (NewArrayTreeImpl) variableTree.initializer(); + return initializer != null && initializer.is(Kind.NEW_ARRAY) && initializer.initializers().isEmpty(); + } + return false; + } + + private static boolean isInitializedFromField(VariableTree variableTree) { + ExpressionTree initializer = variableTree.initializer(); + if(initializer == null) return false; + if(initializer.is(Kind.MEMBER_SELECT)) return true; + + if(initializer.is(Kind.IDENTIFIER)){ + Symbol symbol = variableTree.symbol(); + Symbol owner = symbol.owner(); + return owner != null && variableTree.symbol().isVariableSymbol() && owner.isTypeSymbol(); + } + return false; + } + private static boolean isNotReassigned(VariableTree variableTree) { return variableTree.symbol() .usages() @@ -72,7 +109,7 @@ private static boolean parentIsNonFinalParameter(Tree tree) { return methodTree != null && !hasModifier(methodTree.parameters().get(argument_idx).modifiers(), Modifier.FINAL); } return false; - + } private static boolean parentIsAssignment(Tree tree) {