Skip to content

Commit

Permalink
Fix pmd#1619 - LocalVariableCouldBeFinal FP with loops
Browse files Browse the repository at this point in the history
  • Loading branch information
oowekyala committed May 11, 2024
1 parent e5f55c0 commit 02cb570
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -802,4 +802,13 @@ public static boolean isInStaticCtx(JavaNode node) {
|| it instanceof ASTExplicitConstructorInvocation
);
}

public static boolean isEffectivelyFinal(ASTVariableId var) {
for (ASTNamedReferenceExpr usage : var.getLocalUsages()) {
if (usage.getAccessType() == AccessType.WRITE) {
return false;
}
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

import net.sourceforge.pmd.lang.java.ast.ASTForeachStatement;
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTVariableId;
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
import net.sourceforge.pmd.properties.PropertyDescriptor;
import net.sourceforge.pmd.reporting.RuleContext;

public class LocalVariableCouldBeFinalRule extends AbstractJavaRulechainRule {

Expand All @@ -30,7 +31,16 @@ public Object visit(ASTLocalVariableDeclaration node, Object data) {
if (getProperty(IGNORE_FOR_EACH) && node.getParent() instanceof ASTForeachStatement) {
return data;
}
MethodArgumentCouldBeFinalRule.checkForFinal((RuleContext) data, node.getVarIds());
if (node.getVarIds().all(JavaAstUtils::isEffectivelyFinal)) {
// All variables declared in this ASTLocalVariableDeclaration need to be
// effectively final, otherwise we cannot just add a final modifier.
for (ASTVariableId vid : node.getVarIds()) {
if (!vid.getLocalUsages().isEmpty()) {
// filter out unused variables
asCtx(data).addViolation(vid, vid.getName());
}
}
}
return data;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@

package net.sourceforge.pmd.lang.java.rule.codestyle;

import net.sourceforge.pmd.lang.ast.NodeStream;
import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr;
import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.AccessType;
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTExecutableDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTVariableId;
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
import net.sourceforge.pmd.reporting.RuleContext;

public class MethodArgumentCouldBeFinalRule extends AbstractJavaRulechainRule {

Expand All @@ -37,24 +34,10 @@ public Object visit(ASTConstructorDeclaration constructor, Object data) {
}

private void lookForViolation(ASTExecutableDeclaration node, Object data) {
checkForFinal((RuleContext) data, node.getFormalParameters().toStream().map(ASTFormalParameter::getVarId));
}

static void checkForFinal(RuleContext ruleContext, NodeStream<ASTVariableId> variables) {
outer:
for (ASTVariableId var : variables) {
if (var.isFinal()) {
continue;
}
boolean used = false;
for (ASTNamedReferenceExpr usage : var.getLocalUsages()) {
used = true;
if (usage.getAccessType() == AccessType.WRITE) {
continue outer;
}
}
if (used) {
ruleContext.addViolation(var, var.getName());
for (ASTFormalParameter param : node.getFormalParameters()) {
ASTVariableId varId = param.getVarId();
if (!param.isFinal() && !varId.getLocalUsages().isEmpty() && JavaAstUtils.isEffectivelyFinal(varId)) {
asCtx(data).addViolation(varId, varId.getName());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,17 @@ public class ClassWithLambda {
System.out.println(a);
};
}
}
]]></code>
</test-code>
<test-code>
<description>#1619 FP with loop variable</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class ClassWithLambda {
void method() {
for (int i = 0, size = loaders.size(); i < size; ++i);
}
}
]]></code>
</test-code>
Expand Down

0 comments on commit 02cb570

Please sign in to comment.