• 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

88.46
/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeVarImpl.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.types;
6

7
import java.util.Objects;
8
import java.util.function.Function;
9

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

14
import net.sourceforge.pmd.internal.util.AssertionUtil;
15
import net.sourceforge.pmd.lang.java.symbols.JTypeParameterSymbol;
16
import net.sourceforge.pmd.lang.java.symbols.SymbolicValue.SymAnnot;
17

18
@SuppressWarnings("PMD.CompareObjectsWithEquals")
19
abstract class TypeVarImpl implements JTypeVar {
20

21

22
    final TypeSystem ts;
23
    JTypeMirror upperBound;
24

25
    /**
26
     * These are only the type annotations on a usage of the variable.
27
     * Annotations on the declaration of the tparam are not considered.
28
     */
29
    final PSet<SymAnnot> typeAnnots;
30

31
    // constructor only for the captured version.
32
    private TypeVarImpl(TypeSystem ts, PSet<SymAnnot> typeAnnots) {
1✔
33
        this.ts = ts;
1✔
34
        this.typeAnnots = Objects.requireNonNull(typeAnnots);
1✔
35
    }
1✔
36

37
    @Override
38
    public PSet<SymAnnot> getTypeAnnotations() {
39
        return typeAnnots;
1✔
40
    }
41

42
    @Override
43
    public TypeSystem getTypeSystem() {
44
        return ts;
1✔
45
    }
46

47
    @Override
48
    public JTypeMirror getErasure() {
49
        return getUpperBound().getErasure();
1✔
50
    }
51

52
    @Override
53
    public String toString() {
54
        return TypePrettyPrint.prettyPrint(this);
1✔
55
    }
56

57
    /**
58
     * Returns a fresh type variable, whose bounds will be initialised by
59
     * the capture conversion algo in {@link TypeConversion#capture(JTypeMirror)}.
60
     * Captured variables use reference identity as equality relation.
61
     */
62
    static TypeVarImpl.CapturedTypeVar freshCapture(JWildcardType wildcard) {
63
        return new CapturedTypeVar(wildcard, wildcard.getTypeAnnotations());
1✔
64
    }
65

66
    static final class RegularTypeVar extends TypeVarImpl {
67

68
        private final @NonNull JTypeParameterSymbol symbol;
69

70
        RegularTypeVar(TypeSystem ts, @NonNull JTypeParameterSymbol symbol, PSet<SymAnnot> typeAnnots) {
71
            super(ts, typeAnnots);
1✔
72
            this.symbol = symbol;
1✔
73
        }
1✔
74

75
        private RegularTypeVar(RegularTypeVar base, PSet<SymAnnot> typeAnnots) {
76
            this(base.ts, base.symbol, typeAnnots);
1✔
77
            this.upperBound = base.upperBound;
1✔
78
        }
1✔
79

80
        @Override
81
        public boolean isCaptured() {
82
            return false;
1✔
83
        }
84

85
        @Override
86
        public @NonNull JTypeMirror getLowerBound() {
87
            return ts.NULL_TYPE;
1✔
88
        }
89

90
        @Override
91
        public @NonNull JTypeParameterSymbol getSymbol() {
92
            return symbol;
1✔
93
        }
94

95
        @Override
96
        public @NonNull String getName() {
97
            return symbol.getSimpleName();
1✔
98
        }
99

100
        @Override
101
        public @NonNull JTypeMirror getUpperBound() {
102
            if (upperBound == null) {
1✔
103
                upperBound = symbol.computeUpperBound();
1✔
104
            }
105
            return upperBound;
1✔
106
        }
107

108
        @Override
109
        public JTypeVar withUpperBound(@NonNull JTypeMirror newUB) {
110
            RegularTypeVar tv = new RegularTypeVar(this, this.typeAnnots);
1✔
111
            tv.upperBound = newUB;
1✔
112
            return tv;
1✔
113
        }
114

115

116
        @Override
117
        public JTypeVar withAnnotations(PSet<SymAnnot> newTypeAnnots) {
118
            if (newTypeAnnots.isEmpty() && this.typeAnnots.isEmpty()) {
1✔
119
                return this;
1✔
120
            }
121
            return new RegularTypeVar(this, newTypeAnnots);
1✔
122
        }
123

124
        @Override
125
        public JTypeVar substInBounds(Function<? super SubstVar, ? extends @NonNull JTypeMirror> substitution) {
126
            if (Substitution.isEmptySubst(substitution)) {
1✔
127
                return this;
×
128
            }
129
            JTypeMirror newBound = getUpperBound().subst(substitution);
1✔
130
            if (newBound == upperBound) {
1✔
131
                return this;
1✔
132
            }
133
            RegularTypeVar newTVar = new RegularTypeVar(this.ts, this.symbol, this.getTypeAnnotations());
1✔
134
            newTVar.upperBound = newBound;
1✔
135
            return newTVar;
1✔
136
        }
137

138
        @Override
139
        public JTypeVar cloneWithBounds(JTypeMirror lower, JTypeMirror upper) {
140
            throw new UnsupportedOperationException("Not a capture variable");
×
141
        }
142

143
        @Override
144
        public boolean isCaptureOf(JWildcardType wildcard) {
145
            return false;
1✔
146
        }
147

148
        @Override
149
        public @Nullable JWildcardType getCapturedOrigin() {
150
            return null;
×
151
        }
152

153
        // we only compare the symbol
154
        // the point is to make tvars whose bound was substed equal to the original
155
        // tvar, for substs to work repeatedly. Maybe improving how JMethodSig works
156
        // would remove the need for that
157
        // Eg it would be nice to conceptualize JMethodSig as just a method symbol +
158
        // a substitution mapping type params in scope at that point to actual types
159
        // The problem is that we may want to subst it with type vars, and then use
160
        // those
161

162
        @Override
163
        public boolean equals(Object o) {
164
            if (this == o) {
1✔
165
                return true;
1✔
166
            }
167
            if (o == null || getClass() != o.getClass()) {
1✔
168
                return false;
1✔
169
            }
170
            RegularTypeVar that = (RegularTypeVar) o;
1✔
171
            return symbol.equals(that.symbol);
1✔
172
        }
173

174
        @Override
175
        public int hashCode() {
176
            return Objects.hash(symbol);
1✔
177
        }
178
    }
179

180
    static final class CapturedTypeVar extends TypeVarImpl {
181

182
        private static final int PRIME = 997;  // largest prime less than 1000
183

184
        private final @NonNull JWildcardType wildcard;
185

186
        private JTypeMirror upperBound;
187
        private JTypeMirror lowerBound;
188

189
        private CapturedTypeVar(JWildcardType wild, PSet<SymAnnot> typeAnnots) {
190
            this(wild, wild.asLowerBound(), wild.asUpperBound(), typeAnnots);
1✔
191
        }
1✔
192

193
        private CapturedTypeVar(JWildcardType wild, @NonNull JTypeMirror lower, @NonNull JTypeMirror upper, PSet<SymAnnot> typeAnnots) {
194
            super(wild.getTypeSystem(), typeAnnots);
1✔
195
            this.upperBound = upper;
1✔
196
            this.lowerBound = lower;
1✔
197
            this.wildcard = wild;
1✔
198
        }
1✔
199

200
        void setUpperBound(@NonNull JTypeMirror upperBound) {
201
            this.upperBound = upperBound;
1✔
202
        }
1✔
203

204

205
        void setLowerBound(@NonNull JTypeMirror lowerBound) {
206
            this.lowerBound = lowerBound;
1✔
207
        }
1✔
208

209
        @Override
210
        public boolean equals(Object o) {
211
            return this == o || o instanceof CaptureMatcher && o.equals(this);
1✔
212
        }
213

214
        @Override
215
        public int hashCode() { // NOPMD UselessOverridingMethod
216
            return super.hashCode();
1✔
217
        }
218

219
        @Override
220
        public boolean isCaptured() {
221
            return true;
1✔
222
        }
223

224
        @Override
225
        public boolean isCaptureOf(JWildcardType wildcard) {
226
            return this.wildcard.equals(wildcard);
1✔
227
        }
228

229
        @Override
230
        public JWildcardType getCapturedOrigin() {
231
            return wildcard;
1✔
232
        }
233

234
        @Override
235
        public JTypeVar substInBounds(Function<? super SubstVar, ? extends @NonNull JTypeMirror> substitution) {
236
            JWildcardType wild = this.wildcard.subst(substitution);
1✔
237
            JTypeMirror lower = getLowerBound().subst(substitution);
1✔
238
            JTypeMirror upper = getUpperBound().subst(substitution);
1✔
239
            if (wild == this.wildcard && lower == this.lowerBound && upper == this.lowerBound) {
1✔
240
                return this;
×
241
            }
242
            return new CapturedTypeVar(wild, lower, upper, getTypeAnnotations());
1✔
243
        }
244

245
        @Override
246
        public JTypeVar cloneWithBounds(JTypeMirror lower, JTypeMirror upper) {
247
            return new CapturedTypeVar(wildcard, lower, upper, getTypeAnnotations());
1✔
248
        }
249

250

251
        @Override
252
        public JTypeVar withAnnotations(PSet<SymAnnot> newTypeAnnots) {
253
            if (newTypeAnnots.isEmpty() && typeAnnots.isEmpty()) {
×
254
                return this;
×
255
            }
256
            return new CapturedTypeVar(wildcard, lowerBound, upperBound, newTypeAnnots);
×
257
        }
258

259
        @Override
260
        public JTypeVar withUpperBound(@NonNull JTypeMirror newUB) {
261
            AssertionUtil.requireParamNotNull("upper bound", newUB);
×
262
            return new CapturedTypeVar(wildcard, lowerBound, newUB, getTypeAnnotations());
×
263
        }
264

265
        @Override
266
        public @NonNull JTypeMirror getUpperBound() {
267
            return upperBound;
1✔
268
        }
269

270
        @Override
271
        public @NonNull JTypeMirror getLowerBound() {
272
            return lowerBound;
1✔
273
        }
274

275
        @Override
276
        public @Nullable JTypeParameterSymbol getSymbol() {
277
            return null;
1✔
278
        }
279

280
        @Override
281
        public @NonNull String getName() {
282
            return "capture#" + hashCode() % PRIME + " of " + wildcard;
1✔
283
        }
284
    }
285
}
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