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

pmd / pmd / 152

11 Sep 2025 09:46AM UTC coverage: 78.65% (+0.05%) from 78.603%
152

push

github

web-flow
[java] New rule: ModifierOrder (#5601)

18160 of 23935 branches covered (75.87%)

Branch coverage included in aggregate %.

175 of 182 new or added lines in 10 files covered. (96.15%)

2 existing lines in 2 files now uncovered.

39628 of 49540 relevant lines covered (79.99%)

0.81 hits per line

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

83.91
/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/AstSymbolicAnnot.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.symbols.internal.ast;
6

7
import static net.sourceforge.pmd.util.CollectionUtil.listOf;
8

9
import java.util.ArrayList;
10
import java.util.List;
11
import java.util.Objects;
12
import java.util.Optional;
13

14
import org.checkerframework.checker.nullness.qual.NonNull;
15
import org.checkerframework.checker.nullness.qual.Nullable;
16

17
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
18
import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr;
19
import net.sourceforge.pmd.lang.java.ast.ASTClassLiteral;
20
import net.sourceforge.pmd.lang.java.ast.ASTMemberValue;
21
import net.sourceforge.pmd.lang.java.ast.ASTMemberValueArrayInitializer;
22
import net.sourceforge.pmd.lang.java.ast.ASTMemberValuePair;
23
import net.sourceforge.pmd.lang.java.symbols.JClassSymbol;
24
import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol;
25
import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol;
26
import net.sourceforge.pmd.lang.java.symbols.SymbolicValue;
27
import net.sourceforge.pmd.lang.java.symbols.SymbolicValue.SymAnnot;
28
import net.sourceforge.pmd.lang.java.symbols.internal.SymbolEquality;
29
import net.sourceforge.pmd.lang.java.symbols.internal.SymbolToStrings;
30
import net.sourceforge.pmd.lang.java.types.JArrayType;
31
import net.sourceforge.pmd.lang.java.types.JClassType;
32
import net.sourceforge.pmd.lang.java.types.JTypeMirror;
33
import net.sourceforge.pmd.lang.java.types.Substitution;
34

35
/**
36
 *
37
 */
38
class AstSymbolicAnnot implements SymAnnot {
39

40
    private final ASTAnnotation node;
41
    private final JClassSymbol sym;
42

43
    AstSymbolicAnnot(@NonNull ASTAnnotation node, @NonNull JClassSymbol sym) {
1✔
44
        this.node = node;
1✔
45
        this.sym = Objects.requireNonNull(sym);
1✔
46
    }
1✔
47

48
    @Override
49
    public @Nullable SymbolicValue getAttribute(String attrName) {
50
        ASTMemberValue explicitAttr = node.getAttribute(attrName);
1✔
51
        if (explicitAttr != null) {
1✔
52
            SymbolicValue valueOfAttr = ofNode(explicitAttr);
1✔
53
            if (shouldWrapInArray(explicitAttr)) {
1✔
54
                return SymArray.forElements(listOf(valueOfAttr));
1✔
55
            }
56
            return valueOfAttr;
1✔
57
        }
58
        return sym.getDefaultAnnotationAttributeValue(attrName);
1✔
59
    }
60

61
    private boolean shouldWrapInArray(@NonNull ASTMemberValue attr) {
62
        ASTMemberValuePair parent = (ASTMemberValuePair) attr.getParent();
1✔
63
        if (!parent.isShorthand() || attr instanceof ASTMemberValueArrayInitializer) {
1✔
64
            // in these syntactic cases there is no implicit conversion to an array
65
            return false;
1✔
66
        }
67
        Optional<JMethodSymbol> first = getAnnotationAttrDeclaration(parent.getName());
1✔
68
        if (first.isPresent()) {
1!
69
            JTypeMirror returnTy = first.get().getReturnType(Substitution.EMPTY);
1✔
70
            return returnTy instanceof JArrayType;
1✔
71
        }
NEW
72
        return false;
×
73
    }
74

75
    private Optional<JMethodSymbol> getAnnotationAttrDeclaration(String attrName) {
76
        return sym.getDeclaredMethods().stream()
1✔
77
                  .filter(it -> it.isAnnotationAttribute()
1!
78
                      && it.getSimpleName().equals(attrName)).findFirst();
1!
79
    }
80

81
    @Override
82
    public @NonNull JClassSymbol getAnnotationSymbol() {
83
        return sym;
1✔
84

85
    }
86

87
    @Override
88
    public String getSimpleName() {
89
        return node.getSimpleName();
1✔
90
    }
91

92
    @Override
93
    public boolean equals(Object o) {
94
        return SymbolEquality.ANNOTATION.equals(this, o);
1✔
95
    }
96

97
    @Override
98
    public int hashCode() {
99
        return SymbolEquality.ANNOTATION.hash(this);
1✔
100
    }
101

102
    @Override
103
    public String toString() {
104
        return SymbolToStrings.AST.toString(this);
×
105
    }
106

107
    static SymbolicValue ofNode(ASTMemberValue valueNode) {
108
        if (valueNode == null) {
1!
109
            return null;
×
110
        }
111

112
        { // note: this returns null for enums, annotations, and classes
113
            Object constValue = valueNode.getConstValue();
1✔
114
            if (constValue != null) {
1✔
115
                return SymbolicValue.of(valueNode.getTypeSystem(), constValue);
1✔
116
            }
117
        }
118

119
        if (valueNode instanceof ASTMemberValueArrayInitializer) {
1✔
120
            // array
121
            List<SymbolicValue> elements = new ArrayList<>(valueNode.getNumChildren());
1✔
122
            for (ASTMemberValue elt : (ASTMemberValueArrayInitializer) valueNode) {
1✔
123
                SymbolicValue symElt = ofNode(elt);
1✔
124
                if (symElt == null) {
1!
125
                    return null;
×
126
                }
127
                elements.add(symElt);
1✔
128
            }
1✔
129
            return SymArray.forElements(elements);
1✔
130
        } else if (valueNode instanceof ASTClassLiteral) {
1✔
131
            // class
132
            JTypeDeclSymbol symbol = ((ASTClassLiteral) valueNode).getTypeNode().getTypeMirror().getSymbol();
1✔
133
            if (symbol instanceof JClassSymbol) {
1!
134
                return SymClass.ofBinaryName(symbol.getTypeSystem(), ((JClassSymbol) symbol).getBinaryName());
1✔
135
            }
136
        } else if (valueNode instanceof ASTNamedReferenceExpr) {
1!
137
            // enum constants
138
            ASTNamedReferenceExpr refExpr = (ASTNamedReferenceExpr) valueNode;
1✔
139
            JTypeMirror t = refExpr.getTypeMirror();
1✔
140
            if (t instanceof JClassType && ((JClassType) t).getSymbol().isEnum()) {
1!
141
                return SymEnum.fromBinaryName(t.getTypeSystem(),
1✔
142
                                              ((JClassType) t).getSymbol().getBinaryName(),
1✔
143
                                              refExpr.getName());
1✔
144
            }
145
        }
146
        return null;
×
147
    }
148
}
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