• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pmd / pmd / 110

07 Aug 2025 01:45PM UTC coverage: 78.461% (+0.04%) from 78.421%
110

push

github

adangel
Fix #4500: [java] Fix AvoidReassigningLoopVariablesRule to allow only simple assignments in the forReassign=skip case (#5930)

Merge pull request #5930 from UncleOwen:issue-4500

17854 of 23593 branches covered (75.67%)

Branch coverage included in aggregate %.

29 of 33 new or added lines in 1 file covered. (87.88%)

5 existing lines in 2 files now uncovered.

39140 of 49047 relevant lines covered (79.8%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.23
/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/AssignmentInOperandRule.java
1
/*
2
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3
 */
4

5
package net.sourceforge.pmd.lang.java.rule.errorprone;
6

7
import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty;
8

9
import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression;
10
import net.sourceforge.pmd.lang.java.ast.ASTDoStatement;
11
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
12
import net.sourceforge.pmd.lang.java.ast.ASTExpressionStatement;
13
import net.sourceforge.pmd.lang.java.ast.ASTForStatement;
14
import net.sourceforge.pmd.lang.java.ast.ASTIfStatement;
15
import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
16
import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression;
17
import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
18
import net.sourceforge.pmd.lang.java.ast.JavaNode;
19
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
20
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
21
import net.sourceforge.pmd.properties.PropertyDescriptor;
22
import net.sourceforge.pmd.properties.PropertySource;
23
import net.sourceforge.pmd.reporting.RuleContext;
24

25
/**
26
 *
27
 */
28
public class AssignmentInOperandRule extends AbstractJavaRulechainRule {
29

30
    private static final PropertyDescriptor<Boolean> ALLOW_IF_DESCRIPTOR =
1✔
31
        booleanProperty("allowIf")
1✔
32
            .desc("Allow assignment within the conditional expression of an if statement")
1✔
33
            .defaultValue(false).build();
1✔
34

35
    private static final PropertyDescriptor<Boolean> ALLOW_SWITCH_DESCRIPTOR =
1✔
36
            booleanProperty("allowSwitch")
1✔
37
                    .desc("Allow assignment within the conditional expression of a switch statement")
1✔
38
                    .defaultValue(false).build();
1✔
39

40
    private static final PropertyDescriptor<Boolean> ALLOW_FOR_DESCRIPTOR =
1✔
41
        booleanProperty("allowFor")
1✔
42
            .desc("Allow assignment within the conditional expression of a for statement")
1✔
43
            .defaultValue(false).build();
1✔
44

45
    private static final PropertyDescriptor<Boolean> ALLOW_WHILE_DESCRIPTOR =
1✔
46
            booleanProperty("allowWhile")
1✔
47
                    .desc("Allow assignment within the conditional expression of a while statement")
1✔
48
                    .defaultValue(false).build();
1✔
49

50
    private static final PropertyDescriptor<Boolean> ALLOW_DO_WHILE_DESCRIPTOR =
1✔
51
            booleanProperty("allowDoWhile")
1✔
52
                    .desc("Allow assignment within the conditional expression of a do-while statement")
1✔
53
                    .defaultValue(false).build();
1✔
54

55
    private static final PropertyDescriptor<Boolean> ALLOW_INCREMENT_DECREMENT_DESCRIPTOR =
1✔
56
            booleanProperty("allowIncrementDecrement")
1✔
57
                    .desc("Allow increment or decrement operators within the conditional expression of an if, for, or while statement")
1✔
58
                    .defaultValue(false).build();
1✔
59

60

61
    public AssignmentInOperandRule() {
62
        super(ASTAssignmentExpression.class, ASTUnaryExpression.class);
1✔
63
        definePropertyDescriptor(ALLOW_IF_DESCRIPTOR);
1✔
64
        definePropertyDescriptor(ALLOW_FOR_DESCRIPTOR);
1✔
65
        definePropertyDescriptor(ALLOW_WHILE_DESCRIPTOR);
1✔
66
        definePropertyDescriptor(ALLOW_INCREMENT_DECREMENT_DESCRIPTOR);
1✔
67
        definePropertyDescriptor(ALLOW_DO_WHILE_DESCRIPTOR);
1✔
68
        definePropertyDescriptor(ALLOW_SWITCH_DESCRIPTOR);
1✔
69
    }
1✔
70

71
    @Override
72
    public Object visit(ASTAssignmentExpression node, Object data) {
73
        checkAssignment(node, (RuleContext) data);
1✔
74
        return null;
1✔
75
    }
76

77
    @Override
78
    public Object visit(ASTUnaryExpression node, Object data) {
79
        if (!getProperty(ALLOW_INCREMENT_DECREMENT_DESCRIPTOR) && !node.getOperator().isPure()) {
1✔
80
            checkAssignment(node, (RuleContext) data);
1✔
81
        }
82
        return null;
1✔
83
    }
84

85
    private void checkAssignment(ASTExpression impureExpr, RuleContext ctx) {
86
        ASTExpression toplevel = JavaAstUtils.getTopLevelExpr(impureExpr);
1✔
87
        JavaNode parent = toplevel.getParent();
1✔
88
        if (parent instanceof ASTExpressionStatement) {
1✔
89
            // that's ok
90
            return;
1✔
91
        }
92
        if (parent instanceof ASTIfStatement && !getProperty(ALLOW_IF_DESCRIPTOR)
1✔
93
            || parent instanceof ASTWhileStatement && !getProperty(ALLOW_WHILE_DESCRIPTOR)
1✔
94
            || parent instanceof ASTDoStatement && !getProperty(ALLOW_DO_WHILE_DESCRIPTOR)
1✔
95
            || parent instanceof ASTSwitchStatement && !getProperty(ALLOW_SWITCH_DESCRIPTOR)
1✔
96
            || parent instanceof ASTForStatement && ((ASTForStatement) parent).getCondition() == toplevel && !getProperty(ALLOW_FOR_DESCRIPTOR)) {
1!
97

98
            ctx.addViolation(impureExpr);
1✔
99
        }
100
    }
1✔
101

102
    public boolean allowsAllAssignments() {
103
        return getProperty(ALLOW_IF_DESCRIPTOR) && getProperty(ALLOW_FOR_DESCRIPTOR)
1!
UNCOV
104
                && getProperty(ALLOW_WHILE_DESCRIPTOR) && getProperty(ALLOW_INCREMENT_DECREMENT_DESCRIPTOR)
×
105
                && getProperty(ALLOW_DO_WHILE_DESCRIPTOR) && getProperty(ALLOW_SWITCH_DESCRIPTOR);
1!
106
    }
107

108
    /**
109
     * @see PropertySource#dysfunctionReason()
110
     */
111
    @Override
112
    public String dysfunctionReason() {
113
        return allowsAllAssignments() ? "All assignment types allowed, no checks performed" : null;
1!
114
    }
115
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc