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

pmd / pmd / #3722

pending completion
#3722

push

github actions

adangel
Suppress MissingOverride for Chars::isEmpty (#4291)

67270 of 127658 relevant lines covered (52.7%)

0.53 hits per line

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

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

7
import java.util.Objects;
8

9
import net.sourceforge.pmd.lang.java.symbols.JClassSymbol;
10
import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol;
11
import net.sourceforge.pmd.lang.java.symbols.JElementSymbol;
12
import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol;
13
import net.sourceforge.pmd.lang.java.symbols.JFormalParamSymbol;
14
import net.sourceforge.pmd.lang.java.symbols.JLocalVariableSymbol;
15
import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol;
16
import net.sourceforge.pmd.lang.java.symbols.JTypeParameterSymbol;
17
import net.sourceforge.pmd.lang.java.symbols.SymbolVisitor;
18
import net.sourceforge.pmd.lang.java.symbols.SymbolicValue.SymAnnot;
19

20
/**
21
 * Routines to share logic for equality, respecting the contract of
22
 * {@link JElementSymbol#equals(Object)}.
23
 *
24
 * <p>Despite this two equal symbols may not hold the same amount of
25
 * information... Reflection symbols are nice, but they also add some
26
 * synthetic stuff (eg implicit formal parameters, bridge methods),
27
 * which we must either filter-out or replicate in AST symbols. This is TODO
28
 */
29
@SuppressWarnings("PMD.CompareObjectsWithEquals")
30
public final class SymbolEquality {
31

32
    private SymbolEquality() {
33
        // util class
34
    }
35

36
    public static final EqAndHash<JTypeParameterSymbol> TYPE_PARAM = new EqAndHash<JTypeParameterSymbol>() {
1✔
37
        @Override
38
        public int hash(JTypeParameterSymbol t1) {
39
            return Objects.hash(t1.getDeclaringSymbol(), t1.getSimpleName());
1✔
40
        }
41

42
        @Override
43
        public boolean equals(JTypeParameterSymbol m1, Object o) {
44
            if (m1 == o) {
1✔
45
                return true;
1✔
46
            }
47
            if (!(o instanceof JTypeParameterSymbol)) {
1✔
48
                return false;
×
49
            }
50
            JTypeParameterSymbol m2 = (JTypeParameterSymbol) o;
1✔
51

52
            return m1.nameEquals(m2.getSimpleName())
1✔
53
                && m1.getDeclaringSymbol().equals(m2.getDeclaringSymbol());
1✔
54
        }
55
    };
56

57
    public static final EqAndHash<JMethodSymbol> METHOD = new EqAndHash<JMethodSymbol>() {
1✔
58
        @Override
59
        public int hash(JMethodSymbol t1) {
60
            return 0;
1✔
61
        }
62

63
        @Override
64
        public boolean equals(JMethodSymbol m1, Object o) {
65
            if (m1 == o) {
1✔
66
                return true;
1✔
67
            }
68
            if (!(o instanceof JMethodSymbol)) {
1✔
69
                return false;
1✔
70
            }
71
            JMethodSymbol m2 = (JMethodSymbol) o;
1✔
72

73
            // FIXME arity check is not enough for overloads
74
            return m1.getModifiers() == m2.getModifiers()
1✔
75
                && m1.getArity() == m2.getArity()
1✔
76
                && Objects.equals(m1.getSimpleName(), m2.getSimpleName())
1✔
77
                && m1.getEnclosingClass().equals(m2.getEnclosingClass());
1✔
78
        }
79
    };
80

81
    public static final EqAndHash<JConstructorSymbol> CONSTRUCTOR = new EqAndHash<JConstructorSymbol>() {
1✔
82
        @Override
83
        public int hash(JConstructorSymbol t1) {
84
            return 0;
1✔
85
        }
86

87
        @Override
88
        public boolean equals(JConstructorSymbol m1, Object o) {
89
            if (m1 == o) {
1✔
90
                return true;
1✔
91
            }
92
            if (!(o instanceof JConstructorSymbol)) {
1✔
93
                return false;
1✔
94
            }
95
            JConstructorSymbol m2 = (JConstructorSymbol) o;
1✔
96

97
            // FIXME arity check is not enough for overloads
98
            return m1.getModifiers() == m2.getModifiers()
1✔
99
                && m1.getArity() == m2.getArity()
1✔
100
                && Objects.equals(m1.getSimpleName(), m2.getSimpleName())
×
101
                && m1.getEnclosingClass().equals(m2.getEnclosingClass());
1✔
102
        }
103
    };
104

105

106
    public static final EqAndHash<JClassSymbol> CLASS = new EqAndHash<JClassSymbol>() {
1✔
107
        @Override
108
        public int hash(JClassSymbol t1) {
109
            return t1.getBinaryName().hashCode();
1✔
110
        }
111

112
        @Override
113
        public boolean equals(JClassSymbol m1, Object o) {
114
            if (m1 == o) {
1✔
115
                return true;
1✔
116
            }
117
            if (!(o instanceof JClassSymbol)) {
1✔
118
                return false;
1✔
119
            }
120
            JClassSymbol m2 = (JClassSymbol) o;
1✔
121

122
            return m1.getBinaryName().equals(m2.getBinaryName());
1✔
123
        }
124
    };
125

126
    public static final EqAndHash<JFieldSymbol> FIELD = new EqAndHash<JFieldSymbol>() {
1✔
127
        @Override
128
        public int hash(JFieldSymbol t1) {
129
            return Objects.hash(t1.getEnclosingClass(), t1.getSimpleName());
1✔
130
        }
131

132
        @Override
133
        public boolean equals(JFieldSymbol f1, Object o) {
134
            if (!(o instanceof JFieldSymbol)) {
1✔
135
                return false;
1✔
136
            }
137
            JFieldSymbol f2 = (JFieldSymbol) o;
1✔
138
            return f1.nameEquals(f2.getSimpleName())
1✔
139
                && f1.getEnclosingClass().equals(f2.getEnclosingClass());
1✔
140

141
        }
142
    };
143

144
    public static final EqAndHash<SymAnnot> ANNOTATION = new EqAndHash<SymAnnot>() {
1✔
145
        @Override
146
        public int hash(SymAnnot t1) {
147
            return Objects.hash(t1.getBinaryName());
1✔
148
        }
149

150
        @Override
151
        public boolean equals(SymAnnot f1, Object o) {
152
            if (!(o instanceof SymAnnot)) {
1✔
153
                return false;
×
154
            }
155
            SymAnnot f2 = (SymAnnot) o;
1✔
156
            return f1.getBinaryName().equals(f2.getBinaryName());
1✔
157

158
        }
159
    };
160

161
    public static final EqAndHash<JFormalParamSymbol> FORMAL_PARAM = new EqAndHash<JFormalParamSymbol>() {
1✔
162
        @Override
163
        public int hash(JFormalParamSymbol t1) {
164
            return Objects.hash(t1.getDeclaringSymbol(), t1.getSimpleName());
1✔
165
        }
166

167
        @Override
168
        public boolean equals(JFormalParamSymbol f1, Object o) {
169
            if (!(o instanceof JFormalParamSymbol)) {
1✔
170
                return false;
1✔
171
            }
172
            JFormalParamSymbol f2 = (JFormalParamSymbol) o;
1✔
173
            return f1.nameEquals(f2.getSimpleName())
1✔
174
                && f1.getDeclaringSymbol().equals(f2.getDeclaringSymbol());
1✔
175

176
        }
177
    };
178

179
    private static final EqAndHash<Object> IDENTITY = new EqAndHash<Object>() {
1✔
180
        @Override
181
        public int hash(Object t1) {
182
            return System.identityHashCode(t1);
×
183
        }
184

185
        @Override
186
        public boolean equals(Object t1, Object t2) {
187
            return t1 == t2;
×
188
        }
189
    };
190

191
    /**
192
     * Strategy to perform equals/hashcode for a type T. There are libraries
193
     * for that, whatever.
194
     */
195
    public abstract static class EqAndHash<T> {
1✔
196

197
        public abstract int hash(T t1);
198

199

200
        public abstract boolean equals(T t1, Object t2);
201

202
    }
203

204
    public static <T extends JElementSymbol> boolean equals(T e1, Object e2) {
205
        if (e1 == e2) {
1✔
206
            return true;
1✔
207
        } else if (e2 == null) {
1✔
208
            return false;
×
209
        }
210
        @SuppressWarnings("unchecked")
211
        EqAndHash<T> eqAndHash = (EqAndHash<T>) e1.acceptVisitor(EqAndHashVisitor.INSTANCE, null);
1✔
212
        return eqAndHash.equals(e1, e2);
1✔
213
    }
214

215
    public static <T extends JElementSymbol> int hash(T e1) {
216
        @SuppressWarnings("unchecked")
217
        EqAndHash<T> eqAndHash = (EqAndHash<T>) e1.acceptVisitor(EqAndHashVisitor.INSTANCE, null);
1✔
218
        return eqAndHash.hash(e1);
1✔
219
    }
220

221

222
    private static final class EqAndHashVisitor implements SymbolVisitor<EqAndHash<?>, Void> {
223

224
        static final EqAndHashVisitor INSTANCE = new EqAndHashVisitor();
1✔
225

226
        @Override
227
        public EqAndHash<?> visitSymbol(JElementSymbol sym, Void aVoid) {
228
            throw new IllegalStateException("Unknown symbol " + sym.getClass());
×
229
        }
230

231
        @Override
232
        public EqAndHash<?> visitClass(JClassSymbol sym, Void param) {
233
            return CLASS;
1✔
234
        }
235

236
        @Override
237
        public EqAndHash<?> visitTypeParam(JTypeParameterSymbol sym, Void param) {
238
            return TYPE_PARAM;
1✔
239
        }
240

241
        @Override
242
        public EqAndHash<?> visitCtor(JConstructorSymbol sym, Void param) {
243
            return CONSTRUCTOR;
1✔
244
        }
245

246
        @Override
247
        public EqAndHash<?> visitMethod(JMethodSymbol sym, Void param) {
248
            return METHOD;
1✔
249
        }
250

251
        @Override
252
        public EqAndHash<?> visitField(JFieldSymbol sym, Void param) {
253
            return FIELD;
1✔
254
        }
255

256
        @Override
257
        public EqAndHash<?> visitLocal(JLocalVariableSymbol sym, Void param) {
258
            return IDENTITY;
×
259
        }
260

261
        @Override
262
        public EqAndHash<?> visitFormal(JFormalParamSymbol sym, Void param) {
263
            return FORMAL_PARAM;
1✔
264
        }
265
    }
266

267

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