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

pmd / pmd / 277

27 Nov 2025 01:37PM UTC coverage: 78.778% (+0.03%) from 78.749%
277

push

github

adangel
[java] UseArraysAsList: skip when if-statements (#6228)

18419 of 24233 branches covered (76.01%)

Branch coverage included in aggregate %.

40090 of 50038 relevant lines covered (80.12%)

0.81 hits per line

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

83.78
/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.ASTLambdaExpression;
16
import net.sourceforge.pmd.lang.java.ast.ASTStatementExpressionList;
17
import net.sourceforge.pmd.lang.java.ast.ASTSwitchArrowBranch;
18
import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
19
import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression;
20
import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess;
21
import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
22
import net.sourceforge.pmd.lang.java.ast.JavaNode;
23
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
24
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
25
import net.sourceforge.pmd.properties.PropertyDescriptor;
26
import net.sourceforge.pmd.reporting.RuleContext;
27

28
/**
29
 *
30
 */
31
public class AssignmentInOperandRule extends AbstractJavaRulechainRule {
32

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

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

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

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

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

58
    private static final PropertyDescriptor<Boolean> ALLOW_INCREMENT_DECREMENT_DESCRIPTOR =
1✔
59
            booleanProperty("allowIncrementDecrement")
1✔
60
                    .desc("Allow increment or decrement operators in any context")
1✔
61
                    .defaultValue(false).build();
1✔
62

63

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

74
    @Override
75
    public Object visit(ASTAssignmentExpression node, Object data) {
76
        checkAssignment(node, (RuleContext) data);
1✔
77
        return null;
1✔
78
    }
79

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

88
    private void checkAssignment(ASTExpression impureExpr, RuleContext ctx) {
89
        ASTExpression toplevel = JavaAstUtils.getTopLevelExpr(impureExpr);
1✔
90
        JavaNode parent = toplevel.getParent();
1✔
91

92
        if (toplevel == impureExpr) {
1✔
93
            if (parent instanceof ASTExpressionStatement
1✔
94
                    || parent instanceof ASTStatementExpressionList
95
                    || parent instanceof ASTLambdaExpression) {
96
                // that's ok
97
                return;
1✔
98
            }
99
            if (parent instanceof ASTSwitchArrowBranch
1✔
100
                    && parent.getParent() instanceof ASTSwitchStatement) {
1✔
101
                // assignments in modern (->) switch statements are ok
102
                return;
1✔
103
            }
104
        }
105
        if (parent instanceof ASTIfStatement && getProperty(ALLOW_IF_DESCRIPTOR)
1✔
106
            || parent instanceof ASTWhileStatement && getProperty(ALLOW_WHILE_DESCRIPTOR)
1✔
107
            || parent instanceof ASTDoStatement && getProperty(ALLOW_DO_WHILE_DESCRIPTOR)
1✔
108
            || parent instanceof ASTSwitchStatement && getProperty(ALLOW_SWITCH_DESCRIPTOR)
1✔
109
            || parent instanceof ASTForStatement && ((ASTForStatement) parent).getCondition() == toplevel && getProperty(ALLOW_FOR_DESCRIPTOR)
1!
110
        ) {
111
            return;
1✔
112
        }
113
        JavaNode firstChild = impureExpr.getChild(0);
1✔
114
        if (firstChild instanceof ASTVariableAccess) {
1!
115
            ctx.addViolation(impureExpr, ((ASTVariableAccess) firstChild).getName());
1✔
116
        } else {
117
            ctx.addViolationWithMessage(impureExpr, "Avoid assignments in operands");
×
118
        }
119
    }
1✔
120

121
    /**
122
     * @deprecated Since 7.17.0. This method is an implementation detail and will be internalized.
123
     */
124
    @Deprecated
125
    public boolean allowsAllAssignments() {
126
        return getProperty(ALLOW_IF_DESCRIPTOR) && getProperty(ALLOW_FOR_DESCRIPTOR)
×
127
                && getProperty(ALLOW_WHILE_DESCRIPTOR) && getProperty(ALLOW_INCREMENT_DECREMENT_DESCRIPTOR)
×
128
                && getProperty(ALLOW_DO_WHILE_DESCRIPTOR) && getProperty(ALLOW_SWITCH_DESCRIPTOR);
×
129
    }
130

131
}
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