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

pmd / pmd / 317

19 Dec 2025 11:16AM UTC coverage: 78.975% (+0.01%) from 78.963%
317

push

github

adangel
[core] Fix #6330: Cannot access Chars attribute from XPath (#6342)

18510 of 24316 branches covered (76.12%)

Branch coverage included in aggregate %.

11 of 11 new or added lines in 2 files covered. (100.0%)

5 existing lines in 3 files now uncovered.

40302 of 50153 relevant lines covered (80.36%)

0.81 hits per line

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

88.89
/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/NullAssignmentRule.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 org.checkerframework.checker.nullness.qual.NonNull;
8
import org.checkerframework.checker.nullness.qual.Nullable;
9

10
import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr;
11
import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr;
12
import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression;
13
import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
14
import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral;
15
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
16
import net.sourceforge.pmd.lang.java.ast.JavaNode;
17
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
18
import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol;
19

20
public class NullAssignmentRule extends AbstractJavaRulechainRule {
21

22
    public NullAssignmentRule() {
23
        super(ASTNullLiteral.class);
1✔
24
    }
1✔
25

26
    @Override
27
    public Object visit(ASTNullLiteral node, Object data) {
28
        if (node.getParent() instanceof ASTAssignmentExpression) {
1✔
29
            ASTAssignmentExpression assignment = (ASTAssignmentExpression) node.getParent();
1✔
30
            if (isAssignmentToFinal(assignment)) {
1✔
31
                return data;
1✔
32
            }
33
            if (assignment.getRightOperand() == node) {
1!
34
                asCtx(data).addViolation(node);
1✔
35
            }
36
        } else if (node.getParent() instanceof ASTConditionalExpression) {
1✔
37
            if (isBadTernary((ASTConditionalExpression) node.getParent(), node)) {
1✔
38
                asCtx(data).addViolation(node);
1✔
39
            }
40
        }
41

42
        return data;
1✔
43
    }
44

45
    private boolean isAssignmentToFinal(ASTAssignmentExpression n) {
46
        @Nullable
47
        JVariableSymbol symbol = tryGetLeftOperandSymbol(n);
1✔
48
        return symbol != null && symbol.isFinal();
1!
49
    }
50

51
    private boolean isBadTernary(ASTConditionalExpression ternary, ASTNullLiteral nullLiteral) {
52
        boolean isInitializer;
53

54
        ASTVariableDeclarator variableDeclarator = ternary.ancestors(ASTVariableDeclarator.class).first();
1✔
55
        isInitializer = variableDeclarator != null && variableDeclarator.getInitializer() == ternary;
1✔
56

57
        boolean isThenOrElse = ternary.getThenBranch() == nullLiteral || ternary.getElseBranch() == nullLiteral;
1!
58

59
        // check for nested ternaries...
60
        ASTConditionalExpression currentTernary = ternary;
1✔
61
        while (currentTernary.getParent() instanceof ASTConditionalExpression) {
1✔
62
            ASTConditionalExpression parentTernary = (ASTConditionalExpression) currentTernary.getParent();
1✔
63
            isThenOrElse &= parentTernary.getThenBranch() == currentTernary || parentTernary.getElseBranch() == currentTernary;
1!
64
            currentTernary = parentTernary;
1✔
65
        }
1✔
66

67
        final JavaNode parent = currentTernary.getParent();
1✔
68
        boolean isAssignment = parent instanceof ASTAssignmentExpression;
1✔
69
        if (isAssignment && isFinalField((ASTAssignmentExpression) parent)) {
1✔
70
            isInitializer = true;
1✔
71
        }
72

73
        return isThenOrElse
1!
74
                && isAssignment
75
                && !isInitializer;
76
    }
77

78
    private @Nullable JVariableSymbol tryGetLeftOperandSymbol(ASTAssignmentExpression expression) {
79
        @NonNull
80
        ASTAssignableExpr leftOperand = expression.getLeftOperand();
1✔
81
        if (leftOperand instanceof ASTNamedReferenceExpr) {
1!
82
            @Nullable
83
            JVariableSymbol symbol = ((ASTNamedReferenceExpr) leftOperand).getReferencedSym();
1✔
84
            return symbol;
1✔
85
        }
UNCOV
86
        return null;
×
87
    }
88

89
    private boolean isFinalField(ASTAssignmentExpression expression) {
90
        @Nullable
91
        JVariableSymbol symbol = tryGetLeftOperandSymbol(expression);
1✔
92
        return symbol != null && symbol.isField() && symbol.isFinal();
1!
93
    }
94
}
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