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

pmd / pmd / 196

16 Oct 2025 08:33AM UTC coverage: 78.642% (-0.02%) from 78.661%
196

push

github

web-flow
chore: fix dogfood issues from new rules (#6056)

18180 of 23973 branches covered (75.84%)

Branch coverage included in aggregate %.

2 of 27 new or added lines in 14 files covered. (7.41%)

2 existing lines in 1 file now uncovered.

39693 of 49617 relevant lines covered (80.0%)

0.81 hits per line

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

78.57
/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/BinaryOp.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.ast;
6

7
import java.util.Comparator;
8
import java.util.EnumSet;
9
import java.util.Set;
10

11
import org.checkerframework.checker.nullness.qual.NonNull;
12
import org.checkerframework.checker.nullness.qual.Nullable;
13

14
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
15
import net.sourceforge.pmd.util.AssertionUtil;
16
import net.sourceforge.pmd.util.CollectionUtil;
17

18
/**
19
 * Represents the operator of an {@linkplain ASTInfixExpression infix expression}.
20
 * Constants are roughly ordered by precedence, except some of them have the same
21
 * precedence.
22
 *
23
 * <p>All of those operators are left-associative.
24
 *
25
 * @see UnaryOp
26
 * @see AssignmentOp
27
 */
28
public enum BinaryOp implements InternalInterfaces.OperatorLike {
1✔
29

30
    // shortcut boolean ops
31

32
    /** Conditional (shortcut) OR {@code "||"} operator. */
33
    CONDITIONAL_OR("||"),
1✔
34
    /** Conditional (shortcut) AND {@code "&&"} operator. */
35
    CONDITIONAL_AND("&&"),
1✔
36

37
    // non-shortcut (also bitwise)
38

39
    /** OR {@code "|"} operator. Either logical or bitwise depending on the type of the operands. */
40
    OR("|"),
1✔
41
    /** XOR {@code "^"} operator. Either logical or bitwise depending on the type of the operands. */
42
    XOR("^"),
1✔
43
    /** AND {@code "&"} operator. Either logical or bitwise depending on the type of the operands. */
44
    AND("&"),
1✔
45

46
    // equality
47

48
    /** Equals {@code "=="} operator. */
49
    EQ("=="),
1✔
50
    /** Not-equals {@code "!="} operator. */
51
    NE("!="),
1✔
52

53
    // relational
54

55
    /** Lower-or-equal {@code "<="} operator. */
56
    LE("<="),
1✔
57
    /** Greater-or-equal {@code ">="} operator. */
58
    GE(">="),
1✔
59
    /** Greater-than {@code ">"} operator. */
60
    GT(">"),
1✔
61
    /** Lower-than {@code "<"} operator. */
62
    LT("<"),
1✔
63
    /** Type test {@code "instanceof"} operator. */
64
    INSTANCEOF("instanceof"),
1✔
65

66
    // shift
67

68
    /** Left shift {@code "<<"} operator. */
69
    LEFT_SHIFT("<<"),
1✔
70
    /** Right shift {@code ">>"} operator. */
71
    RIGHT_SHIFT(">>"),
1✔
72
    /** Unsigned right shift {@code ">>>"} operator. */
73
    UNSIGNED_RIGHT_SHIFT(">>>"),
1✔
74

75
    // additive
76

77
    /** Addition {@code "+"} operator, or string concatenation. */
78
    ADD("+"),
1✔
79
    /** Subtraction {@code "-"} operator. */
80
    SUB("-"),
1✔
81

82
    // multiplicative
83

84
    /** Multiplication {@code "*"} operator. */
85
    MUL("*"),
1✔
86
    /** Division {@code "/"} operator. */
87
    DIV("/"),
1✔
88
    /** Modulo {@code "%"} operator. */
89
    MOD("%");
1✔
90

91
    /** Set of {@code &&} and {@code ||}. Use with {@link JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */
92
    public static final Set<BinaryOp> CONDITIONAL_OPS =
1✔
93
        CollectionUtil.immutableEnumSet(CONDITIONAL_AND, CONDITIONAL_OR);
1✔
94
    /** Set of {@code <}, {@code <=}, {@code >=} and {@code >}. Use with {@link JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */
95
    public static final Set<BinaryOp> COMPARISON_OPS = CollectionUtil.immutableEnumSet(LE, GE, GT, LT);
1✔
96
    /** Set of {@code ==} and {@code !=}. Use with {@link JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */
97
    public static final Set<BinaryOp> EQUALITY_OPS = CollectionUtil.immutableEnumSet(EQ, NE);
1✔
98
    /** Set of {@code <<}, {@code >>} and {@code >>>}. Use with {@link JavaAstUtils#isInfixExprWithOperator(JavaNode, Set)}. */
99
    public static final Set<BinaryOp> SHIFT_OPS = CollectionUtil.immutableEnumSet(LEFT_SHIFT, RIGHT_SHIFT, UNSIGNED_RIGHT_SHIFT);
1✔
100

101
    private final String code;
102

103

104
    BinaryOp(String code) {
1✔
105
        this.code = code;
1✔
106
    }
1✔
107

108

109
    @Override
110
    public String getToken() {
111
        return code;
1✔
112
    }
113

114

115
    @Override
116
    public String toString() {
117
        return this.code;
1✔
118
    }
119

120
    /**
121
     * Compare the precedence of this operator with that of the other,
122
     * as if with a {@link Comparator}. Returns a positive integer if
123
     * this operator has a higher precedence as the argument, zero if
124
     * they have the same precedence, etc.
125
     *
126
     * @throws NullPointerException If the argument is null
127
     */
128
    public int comparePrecedence(@NonNull BinaryOp other) {
129
        // arguments are flipped because precedence class decreases
130
        return Integer.compare(other.precedenceClass(), this.precedenceClass());
1✔
131
    }
132

133
    /**
134
     * Returns true if this operator has the same relative precedence
135
     * as the argument. For example, {@link #ADD} and {@link #SUB} have
136
     * the same precedence.
137
     *
138
     * @throws NullPointerException If the argument is null
139
     */
140
    public boolean hasSamePrecedenceAs(@NonNull BinaryOp other) {
141
        return comparePrecedence(other) == 0;
1✔
142
    }
143

144

145
    /**
146
     * Returns the ops with strictly greater precedence than the given op.
147
     * This may return an empty set.
148
     */
149
    public static Set<BinaryOp> opsWithGreaterPrecedence(BinaryOp op) {
150
        Set<BinaryOp> range = EnumSet.range(op, MOD);
1✔
151
        range.remove(op);
1✔
152
        return range;
1✔
153
    }
154

155
    private int precedenceClass() {
156
        switch (this) {
1!
157
        case CONDITIONAL_OR:
158
            return 9;
1✔
159
        case CONDITIONAL_AND:
160
            return 8;
1✔
161
        case OR:
162
            return 7;
1✔
163
        case XOR:
164
            return 6;
1✔
165
        case AND:
166
            return 5;
1✔
167
        case EQ:
168
        case NE:
169
            return 4;
1✔
170
        case LE:
171
        case GE:
172
        case GT:
173
        case LT:
174
        case INSTANCEOF:
175
            return 3;
1✔
176
        case LEFT_SHIFT:
177
        case RIGHT_SHIFT:
178
        case UNSIGNED_RIGHT_SHIFT:
179
            return 2;
1✔
180
        case ADD:
181
        case SUB:
182
            return 1;
1✔
183
        case MUL:
184
        case DIV:
185
        case MOD:
186
            return 0;
1✔
187
        }
NEW
188
        throw AssertionUtil.shouldNotReachHere("Invalid binary op " + this);
×
189
    }
190

191

192
    /**
193
     * Complement, for boolean operators. Eg for {@code ==}, return {@code !=},
194
     * for {@code <=}, returns {@code >}. Returns null if this is another kind
195
     * of operator.
196
     */
197
    public @Nullable BinaryOp getComplement() {
198
        switch (this) {
1!
199
        case CONDITIONAL_OR: return CONDITIONAL_AND;
×
200
        case CONDITIONAL_AND: return CONDITIONAL_OR;
1✔
201
        case OR: return AND;
×
202
        case AND: return OR;
×
203

204
        case EQ: return NE;
1✔
205
        case NE: return EQ;
1✔
206
        case LE: return GT;
×
207
        case GE: return LT;
×
208
        case GT: return LE;
×
209
        case LT: return GE;
×
210

211
        default: return null;
×
212
        }
213
    }
214

215

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