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

pmd / pmd / 119

15 Aug 2025 10:06AM UTC coverage: 78.488% (+0.01%) from 78.476%
119

push

github

adangel
[java] ShortVariable - improve detection of unnamed variables

Refs #5914

Co-authored-by: Juan Martín Sotuyo Dodero <juan.sotuyo@pedidosya.com>

17911 of 23661 branches covered (75.7%)

Branch coverage included in aggregate %.

39213 of 49120 relevant lines covered (79.83%)

0.81 hits per line

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

82.18
/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.ASTStatementExpressionList;
16
import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
17
import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression;
18
import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess;
19
import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
20
import net.sourceforge.pmd.lang.java.ast.JavaNode;
21
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
22
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
23
import net.sourceforge.pmd.properties.PropertyDescriptor;
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

90
        if (toplevel == impureExpr
1✔
91
            && (parent instanceof ASTExpressionStatement
92
            || parent instanceof ASTStatementExpressionList)
93
        ) {
94
            // that's ok
95
            return;
1✔
96
        }
97
        if (parent instanceof ASTIfStatement && getProperty(ALLOW_IF_DESCRIPTOR)
1✔
98
            || parent instanceof ASTWhileStatement && getProperty(ALLOW_WHILE_DESCRIPTOR)
1✔
99
            || parent instanceof ASTDoStatement && getProperty(ALLOW_DO_WHILE_DESCRIPTOR)
1✔
100
            || parent instanceof ASTSwitchStatement && getProperty(ALLOW_SWITCH_DESCRIPTOR)
1✔
101
            || parent instanceof ASTForStatement && ((ASTForStatement) parent).getCondition() == toplevel && getProperty(ALLOW_FOR_DESCRIPTOR)
1!
102
        ) {
103
            return;
1✔
104
        }
105
        JavaNode firstChild = impureExpr.getChild(0);
1✔
106
        if (firstChild instanceof ASTVariableAccess) {
1!
107
            ctx.addViolation(impureExpr, ((ASTVariableAccess) firstChild).getName());
1✔
108
        } else {
109
            ctx.addViolationWithMessage(impureExpr, "Avoid assignments in operands");
×
110
        }
111
    }
1✔
112

113
    /**
114
     * @deprecated Since 7.17.0. This method is an implementation detail and will be internalized.
115
     */
116
    @Deprecated
117
    public boolean allowsAllAssignments() {
118
        return getProperty(ALLOW_IF_DESCRIPTOR) && getProperty(ALLOW_FOR_DESCRIPTOR)
×
119
                && getProperty(ALLOW_WHILE_DESCRIPTOR) && getProperty(ALLOW_INCREMENT_DECREMENT_DESCRIPTOR)
×
120
                && getProperty(ALLOW_DO_WHILE_DESCRIPTOR) && getProperty(ALLOW_SWITCH_DESCRIPTOR);
×
121
    }
122

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