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

pmd / pmd / 4476

27 Feb 2025 08:31AM UTC coverage: 77.717% (+0.02%) from 77.694%
4476

push

github

adangel
[apex] New Rule: Avoid Stateful Database Results (#5425)

Merge pull request #5425 from mitchspano:stateful

17395 of 23322 branches covered (74.59%)

Branch coverage included in aggregate %.

22 of 22 new or added lines in 1 file covered. (100.0%)

99 existing lines in 9 files now uncovered.

38180 of 48187 relevant lines covered (79.23%)

0.8 hits per line

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

81.89
/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.lang.java.symbols.JTypeParameterSymbol;
15
import net.sourceforge.pmd.lang.java.symbols.SymbolicValue.SymAnnot;
16

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

20

21
    final TypeSystem ts;
22
    JTypeMirror upperBound;
23

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

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

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

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

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

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

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

65
    static final class RegularTypeVar extends TypeVarImpl {
66

67
        private final @NonNull JTypeParameterSymbol symbol;
68

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

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

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

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

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

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

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

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

114

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

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

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

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

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

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

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

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

179
    static final class CapturedTypeVar extends TypeVarImpl {
180

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

183
        private final @Nullable JWildcardType wildcard;
184
        private final @Nullable JTypeVar tvar;
185

186
        private JTypeMirror upperBound;
187
        private JTypeMirror lowerBound;
188

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

193
        private CapturedTypeVar(@Nullable JWildcardType wild, @NonNull JTypeMirror lower, @NonNull JTypeMirror upper, PSet<SymAnnot> typeAnnots) {
194
            this(null, wild, lower, upper, typeAnnots);
1✔
195
        }
1✔
196

197
        private CapturedTypeVar(@Nullable JTypeVar tvar, @Nullable JWildcardType wild, @NonNull JTypeMirror lower, @NonNull JTypeMirror upper, PSet<SymAnnot> typeAnnots) {
198
            super(lower.getTypeSystem(), typeAnnots);
1✔
199
            this.upperBound = upper;
1✔
200
            this.lowerBound = lower;
1✔
201
            this.tvar = tvar;
1✔
202
            this.wildcard = wild;
1✔
203
        }
1✔
204

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

209

210
        void setLowerBound(@NonNull JTypeMirror lowerBound) {
211
            this.lowerBound = lowerBound;
1✔
212
        }
1✔
213

214
        @Override
215
        public boolean equals(Object o) {
216
            return this == o || o instanceof CaptureMatcher && o.equals(this);
1✔
217
        }
218

219
        @Override
220
        public int hashCode() { // NOPMD UselessOverridingMethod
221
            return super.hashCode();
1✔
222
        }
223

224
        @Override
225
        public boolean isCaptured() {
226
            return true;
1✔
227
        }
228

229
        @Override
230
        public boolean isCaptureOf(JWildcardType wildcard) {
231
            return this.wildcard != null && this.wildcard.equals(wildcard);
1!
232
        }
233

234
        @Override
235
        public JWildcardType getCapturedOrigin() {
236
            return wildcard;
1✔
237
        }
238

239
        @Override
240
        public JTypeVar substInBounds(Function<? super SubstVar, ? extends @NonNull JTypeMirror> substitution) {
241
            JWildcardType wild = this.wildcard == null ? null : this.wildcard.subst(substitution);
1!
242
            JTypeMirror lower = getLowerBound().subst(substitution);
1✔
243
            JTypeMirror upper = getUpperBound().subst(substitution);
1✔
244
            if (wild == this.wildcard && lower == this.lowerBound && upper == this.lowerBound) {
1!
UNCOV
245
                return this;
×
246
            } else if (wild == null) {
1!
UNCOV
247
                return new CapturedTypeVar(tvar, null, lower, upper, typeAnnots);
×
248
            }
249
            return new CapturedTypeVar(wild, lower, upper, getTypeAnnotations());
1✔
250
        }
251

252
        @Override
253
        public JTypeVar cloneWithBounds(JTypeMirror lower, JTypeMirror upper) {
254
            return new CapturedTypeVar(wildcard, lower, upper, getTypeAnnotations());
1✔
255
        }
256

257

258
        @Override
259
        public JTypeVar withAnnotations(PSet<SymAnnot> newTypeAnnots) {
UNCOV
260
            if (newTypeAnnots.isEmpty() && typeAnnots.isEmpty()) {
×
UNCOV
261
                return this;
×
262
            }
UNCOV
263
            return new CapturedTypeVar(tvar, wildcard, lowerBound, upperBound, newTypeAnnots);
×
264
        }
265

266
        @Override
267
        public JTypeVar withUpperBound(@NonNull JTypeMirror newUB) {
268
            return cloneWithBounds(upperBound, newUB);
×
269
        }
270

271
        @Override
272
        public @NonNull JTypeMirror getUpperBound() {
273
            return upperBound;
1✔
274
        }
275

276
        @Override
277
        public @NonNull JTypeMirror getLowerBound() {
278
            return lowerBound;
1✔
279
        }
280

281
        @Override
282
        public @Nullable JTypeParameterSymbol getSymbol() {
283
            return tvar == null ? null : tvar.getSymbol();
1!
284
        }
285

286
        @Override
287
        public @NonNull String getName() {
288
            Object captureOrigin = wildcard == null ? tvar : wildcard;
1!
289
            return "capture#" + hashCode() % PRIME + " of " + captureOrigin;
1✔
290
            // + "[" + lowerBound + ".." + upperBound + "]";
291
        }
292
    }
293
}
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