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

pmd / pmd / 111

08 Aug 2025 10:20AM UTC coverage: 78.459% (-0.002%) from 78.461%
111

push

github

adangel
chore: CI improvements (#5970)

Merge pull request #5970 from adangel:chore/ci-improvements

17886 of 23639 branches covered (75.66%)

Branch coverage included in aggregate %.

39179 of 49093 relevant lines covered (79.81%)

0.81 hits per line

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

85.86
/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.ASTVariableAccess;
18
import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
19
import net.sourceforge.pmd.lang.java.ast.JavaNode;
20
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
21
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
22
import net.sourceforge.pmd.properties.PropertyDescriptor;
23
import net.sourceforge.pmd.properties.PropertySource;
24
import net.sourceforge.pmd.reporting.RuleContext;
25

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

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

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

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

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

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

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

61

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

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

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

86
    private void checkAssignment(ASTExpression impureExpr, RuleContext ctx) {
87
        ASTExpression toplevel = JavaAstUtils.getTopLevelExpr(impureExpr);
1✔
88
        JavaNode parent = toplevel.getParent();
1✔
89
        if (parent instanceof ASTExpressionStatement) {
1✔
90
            // that's ok
91
            return;
1✔
92
        }
93
        if (parent instanceof ASTIfStatement && !getProperty(ALLOW_IF_DESCRIPTOR)
1✔
94
            || parent instanceof ASTWhileStatement && !getProperty(ALLOW_WHILE_DESCRIPTOR)
1✔
95
            || parent instanceof ASTDoStatement && !getProperty(ALLOW_DO_WHILE_DESCRIPTOR)
1✔
96
            || parent instanceof ASTSwitchStatement && !getProperty(ALLOW_SWITCH_DESCRIPTOR)
1✔
97
            || parent instanceof ASTForStatement && ((ASTForStatement) parent).getCondition() == toplevel && !getProperty(ALLOW_FOR_DESCRIPTOR)) {
1!
98
            JavaNode firstChild = impureExpr.getChild(0);
1✔
99
            if (firstChild instanceof ASTVariableAccess) {
1!
100
                ctx.addViolation(impureExpr, ((ASTVariableAccess) firstChild).getName());
1✔
101
            } else {
102
                ctx.addViolationWithMessage(impureExpr, "Avoid assignments in operands");
×
103
            }
104
        }
105
    }
1✔
106

107
    public boolean allowsAllAssignments() {
108
        return getProperty(ALLOW_IF_DESCRIPTOR) && getProperty(ALLOW_FOR_DESCRIPTOR)
1!
109
                && getProperty(ALLOW_WHILE_DESCRIPTOR) && getProperty(ALLOW_INCREMENT_DECREMENT_DESCRIPTOR)
×
110
                && getProperty(ALLOW_DO_WHILE_DESCRIPTOR) && getProperty(ALLOW_SWITCH_DESCRIPTOR);
1!
111
    }
112

113
    /**
114
     * @see PropertySource#dysfunctionReason()
115
     */
116
    @Override
117
    public String dysfunctionReason() {
118
        return allowsAllAssignments() ? "All assignment types allowed, no checks performed" : null;
1!
119
    }
120
}
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