• 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

87.37
/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ImplicitMemberSymbols.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 static java.util.Collections.emptyList;
8
import static java.util.Collections.singletonList;
9

10
import java.lang.reflect.Modifier;
11
import java.util.List;
12
import java.util.function.BiFunction;
13
import java.util.function.Function;
14

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

18
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
19
import net.sourceforge.pmd.lang.java.symbols.JClassSymbol;
20
import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol;
21
import net.sourceforge.pmd.lang.java.symbols.JExecutableSymbol;
22
import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol;
23
import net.sourceforge.pmd.lang.java.symbols.JFormalParamSymbol;
24
import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol;
25
import net.sourceforge.pmd.lang.java.types.JTypeMirror;
26
import net.sourceforge.pmd.lang.java.types.JTypeVar;
27
import net.sourceforge.pmd.lang.java.types.Substitution;
28
import net.sourceforge.pmd.lang.java.types.TypeSystem;
29
import net.sourceforge.pmd.util.CollectionUtil;
30

31
/**
32
 * Members inserted by the compiler, eg default constructor, etc. They
33
 * would be absent from the source, but are reflected by the {@link Class}.
34
 */
35
public final class ImplicitMemberSymbols {
1✔
36

37
    private static final int VISIBILITY_MASK = Modifier.PRIVATE | Modifier.PUBLIC | Modifier.PROTECTED;
38
    /** This is the private access flag for varargs modifiers. */
39
    private static final int VARARGS_MOD = 0x00000080;
40

41
    private ImplicitMemberSymbols() {
42

43
    }
44

45
    public static JMethodSymbol enumValueOf(JClassSymbol enumSym) {
46
        assert enumSym.isEnum() : "Not an enum symbol " + enumSym;
1✔
47

48
        return new FakeMethodSym(
1✔
49
            enumSym,
50
            "valueOf",
51
            Modifier.PUBLIC | Modifier.STATIC,
52
            TypeSystem::declaration,
53
            singletonList(t -> new FakeFormalParamSym(t, "name", (ts, s) -> ts.declaration(ts.getClassSymbol(String.class))))
1✔
54
        );
55
    }
56

57
    public static JMethodSymbol enumValues(JClassSymbol enumSym) {
58
        assert enumSym.isEnum() : "Not an enum symbol " + enumSym;
1✔
59

60
        return new FakeMethodSym(
1✔
61
            enumSym,
62
            "values",
63
            Modifier.PUBLIC | Modifier.STATIC,
64
            (ts, c) -> ts.arrayType(ts.declaration(c)),
1✔
65
            emptyList()
1✔
66
        );
67
    }
68

69

70
    public static JConstructorSymbol defaultCtor(JClassSymbol sym) {
71
        assert sym != null;
1✔
72

73
        // Enum constructors have 2 additional implicit parameters, for the name and ordinal
74
        // Inner classes have 1 additional implicit param, for the outer instance
75
        // They are not reflected by the symbol
76

77
        int modifiers = sym.isEnum() ? Modifier.PRIVATE
1✔
78
                                     : sym.getModifiers() & VISIBILITY_MASK;
1✔
79

80
        return new FakeCtorSym(sym, modifiers, emptyList());
1✔
81
    }
82

83

84
    public static JMethodSymbol arrayClone(JClassSymbol arraySym) {
85
        assert arraySym.isArray() : "Not an array symbol " + arraySym;
1✔
86

87
        return new FakeMethodSym(
1✔
88
            arraySym,
89
            "clone",
90
            Modifier.PUBLIC | Modifier.FINAL,
91
            TypeSystem::declaration,
92
            emptyList()
1✔
93
        );
94
    }
95

96
    public static JConstructorSymbol arrayConstructor(JClassSymbol arraySym) {
97
        assert arraySym.isArray() : "Not an array symbol " + arraySym;
1✔
98

99
        return new FakeCtorSym(
1✔
100
            arraySym,
101
            Modifier.PUBLIC | Modifier.FINAL,
102
            singletonList(c -> new FakeFormalParamSym(c, "arg0", (ts, sym) -> ts.INT))
1✔
103
        );
104
    }
105

106
    /** Symbol for the canonical record constructor. */
107
    public static JConstructorSymbol recordConstructor(JClassSymbol recordSym,
108
                                                       List<JFieldSymbol> recordComponents,
109
                                                       boolean isVarargs) {
110
        assert recordSym.isRecord() : "Not a record symbol " + recordSym;
1✔
111

112
        int modifiers = isVarargs ? Modifier.PUBLIC | VARARGS_MOD
1✔
113
                                  : Modifier.PUBLIC;
1✔
114

115
        return new FakeCtorSym(
1✔
116
            recordSym,
117
            modifiers,
118
            CollectionUtil.map(
1✔
119
                recordComponents,
120
                f -> c -> new FakeFormalParamSym(c, f.getSimpleName(), f.tryGetNode(), (ts, sym) -> f.getTypeMirror(Substitution.EMPTY))
1✔
121
            )
122
        );
123
    }
124

125
    /**
126
     * Symbol for a record component accessor.
127
     * Only synthesized if it is not explicitly declared.
128
     */
129
    public static JMethodSymbol recordAccessor(JClassSymbol recordSym, JFieldSymbol recordComponent) {
130
        // See https://cr.openjdk.java.net/~gbierman/jep359/jep359-20200115/specs/records-jls.html#jls-8.10.3
131

132
        assert recordSym.isRecord() : "Not a record symbol " + recordSym;
1✔
133

134
        return new FakeMethodSym(
1✔
135
            recordSym,
136
            recordComponent.getSimpleName(),
1✔
137
            Modifier.PUBLIC,
138
            (ts, encl) -> recordComponent.getTypeMirror(Substitution.EMPTY),
1✔
139
            emptyList()
1✔
140
        );
141
    }
142

143
    public static JFieldSymbol arrayLengthField(JClassSymbol arraySym) {
144
        assert arraySym.isArray() : "Not an array symbol " + arraySym;
1✔
145

146
        return new FakeFieldSym(
1✔
147
            arraySym,
148
            "length",
149
            Modifier.PUBLIC | Modifier.FINAL,
150
            (ts, s) -> ts.INT
1✔
151
        );
152
    }
153

154
    private abstract static class FakeExecutableSymBase<T extends JExecutableSymbol> implements JExecutableSymbol {
155

156
        private final JClassSymbol owner;
157
        private final String name;
158
        private final int modifiers;
159
        private final List<JFormalParamSymbol> formals;
160

161

162
        FakeExecutableSymBase(JClassSymbol owner,
163
                              String name,
164
                              int modifiers,
165
                              List<Function<T, JFormalParamSymbol>> formals) {
1✔
166
            this.owner = owner;
1✔
167
            this.name = name;
1✔
168
            this.modifiers = modifiers;
1✔
169
            this.formals = CollectionUtil.map(formals, f -> f.apply((T) this));
1✔
170
        }
1✔
171

172
        @Override
173
        public TypeSystem getTypeSystem() {
174
            return owner.getTypeSystem();
1✔
175
        }
176

177
        @Override
178
        public List<JTypeMirror> getFormalParameterTypes(Substitution subst) {
179
            return CollectionUtil.map(formals, p -> p.getTypeMirror(subst));
1✔
180
        }
181

182
        @Override
183
        public List<JTypeMirror> getThrownExceptionTypes(Substitution subst) {
184
            return emptyList();
1✔
185
        }
186

187
        @Override
188
        public List<JTypeVar> getTypeParameters() {
189
            return emptyList();
1✔
190
        }
191

192
        @Override
193
        public String getSimpleName() {
194
            return name;
1✔
195
        }
196

197
        @Override
198
        public List<JFormalParamSymbol> getFormalParameters() {
199
            return formals;
1✔
200
        }
201

202
        @Override
203
        public boolean isVarargs() {
204
            return (modifiers & VARARGS_MOD) != 0;
1✔
205
        }
206

207
        @Override
208
        public int getArity() {
209
            return formals.size();
1✔
210
        }
211

212
        @Override
213
        public @Nullable JTypeMirror getAnnotatedReceiverType(Substitution subst) {
214
            if (!this.hasReceiver()) {
×
215
                return null;
×
216
            }
217
            return getTypeSystem().declaration(owner).subst(subst);
×
218
        }
219

220
        @Override
221
        public int getModifiers() {
222
            return modifiers;
1✔
223
        }
224

225
        @Override
226
        public @NonNull JClassSymbol getEnclosingClass() {
227
            return owner;
1✔
228
        }
229

230
        @Override
231
        public String toString() {
232
            return SymbolToStrings.FAKE.toString(this);
×
233
        }
234
    }
235

236
    private static final class FakeMethodSym extends FakeExecutableSymBase<JMethodSymbol> implements JMethodSymbol {
237

238
        private final BiFunction<? super TypeSystem, ? super JClassSymbol, ? extends JTypeMirror> returnType;
239

240
        FakeMethodSym(JClassSymbol owner,
241
                      String name,
242
                      int modifiers,
243
                      BiFunction<? super TypeSystem, ? super JClassSymbol, ? extends JTypeMirror> returnType,
244
                      List<Function<JMethodSymbol, JFormalParamSymbol>> formals) {
245
            super(owner, name, modifiers, formals);
1✔
246
            this.returnType = returnType;
1✔
247
        }
1✔
248

249
        @Override
250
        public boolean isBridge() {
251
            return false;
×
252
        }
253

254
        @Override
255
        public JTypeMirror getReturnType(Substitution subst) {
256
            return returnType.apply(getTypeSystem(), getEnclosingClass());
1✔
257
        }
258

259
        @Override
260
        public boolean equals(Object o) {
261
            return SymbolEquality.METHOD.equals(this, o);
1✔
262
        }
263

264
        @Override
265
        public int hashCode() {
266
            return SymbolEquality.METHOD.hash(this);
×
267
        }
268
    }
269

270
    private static final class FakeCtorSym extends FakeExecutableSymBase<JConstructorSymbol> implements JConstructorSymbol {
271

272
        FakeCtorSym(JClassSymbol owner,
273
                    int modifiers,
274
                    List<Function<JConstructorSymbol, JFormalParamSymbol>> formals) {
275
            super(owner, JConstructorSymbol.CTOR_NAME, modifiers, formals);
1✔
276
        }
1✔
277

278
        @Override
279
        public boolean equals(Object o) {
280
            return SymbolEquality.CONSTRUCTOR.equals(this, o);
1✔
281
        }
282

283
        @Override
284
        public int hashCode() {
285
            return SymbolEquality.CONSTRUCTOR.hash(this);
×
286
        }
287
    }
288

289
    private static final class FakeFormalParamSym implements JFormalParamSymbol {
290

291
        private final JExecutableSymbol owner;
292
        private final String name;
293
        private final ASTVariableDeclaratorId node;
294
        private final BiFunction<? super TypeSystem, ? super JFormalParamSymbol, ? extends JTypeMirror> type;
295

296
        private FakeFormalParamSym(JExecutableSymbol owner, String name, BiFunction<? super TypeSystem, ? super JFormalParamSymbol, ? extends JTypeMirror> type) {
297
            this(owner, name, null, type);
1✔
298
        }
1✔
299

300
        private FakeFormalParamSym(JExecutableSymbol owner, String name, @Nullable ASTVariableDeclaratorId node, BiFunction<? super TypeSystem, ? super JFormalParamSymbol, ? extends JTypeMirror> type) {
1✔
301
            this.owner = owner;
1✔
302
            this.name = name;
1✔
303
            this.node = node;
1✔
304
            this.type = type;
1✔
305
        }
1✔
306

307
        @Override
308
        public @Nullable ASTVariableDeclaratorId tryGetNode() {
309
            return node;
1✔
310
        }
311

312
        @Override
313
        public TypeSystem getTypeSystem() {
314
            return owner.getTypeSystem();
1✔
315
        }
316

317
        @Override
318
        public JTypeMirror getTypeMirror(Substitution subst) {
319
            return type.apply(getTypeSystem(), this).subst(subst);
1✔
320
        }
321

322
        @Override
323
        public JExecutableSymbol getDeclaringSymbol() {
324
            return owner;
1✔
325
        }
326

327
        @Override
328
        public boolean isFinal() {
329
            return false;
×
330
        }
331

332
        @Override
333
        public String getSimpleName() {
334
            return name;
1✔
335
        }
336

337
        @Override
338
        public String toString() {
339
            return SymbolToStrings.FAKE.toString(this);
×
340
        }
341

342
        @Override
343
        public boolean equals(Object o) {
344
            return SymbolEquality.FORMAL_PARAM.equals(this, o);
1✔
345
        }
346

347
        @Override
348
        public int hashCode() {
349
            return SymbolEquality.FORMAL_PARAM.hash(this);
×
350
        }
351
    }
352

353

354
    private static final class FakeFieldSym implements JFieldSymbol {
355

356
        private final JClassSymbol owner;
357
        private final String name;
358
        private final int modifiers;
359
        private final BiFunction<? super TypeSystem, ? super JClassSymbol, ? extends JTypeMirror> type;
360

361
        FakeFieldSym(JClassSymbol owner, String name, int modifiers, BiFunction<? super TypeSystem, ? super JClassSymbol, ? extends JTypeMirror> type) {
1✔
362
            this.owner = owner;
1✔
363
            this.name = name;
1✔
364
            this.modifiers = modifiers;
1✔
365
            this.type = type;
1✔
366
        }
1✔
367

368
        @Override
369
        public TypeSystem getTypeSystem() {
370
            return owner.getTypeSystem();
1✔
371
        }
372

373
        @Override
374
        public JTypeMirror getTypeMirror(Substitution subst) {
375
            return type.apply(getTypeSystem(), owner).subst(subst);
1✔
376
        }
377

378
        @Override
379
        public String getSimpleName() {
380
            return name;
1✔
381
        }
382

383
        @Override
384
        public int getModifiers() {
385
            return modifiers;
1✔
386
        }
387

388
        @Override
389
        public boolean isEnumConstant() {
390
            return false;
×
391
        }
392

393
        @Override
394
        public @NonNull JClassSymbol getEnclosingClass() {
395
            return owner;
1✔
396
        }
397

398
        @Override
399
        public String toString() {
400
            return SymbolToStrings.FAKE.toString(this);
1✔
401
        }
402

403
        @Override
404
        public boolean equals(Object o) {
405
            return SymbolEquality.FIELD.equals(this, o);
1✔
406
        }
407

408
        @Override
409
        public int hashCode() {
410
            return SymbolEquality.FIELD.hash(this);
×
411
        }
412
    }
413

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