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

hazendaz / jmockit1 / 496

15 Nov 2025 05:33PM UTC coverage: 72.192% (-0.008%) from 72.2%
496

push

github

web-flow
Merge pull request #412 from hazendaz/renovate/major-spring-core

Update spring core to v7 (major)

5677 of 8360 branches covered (67.91%)

Branch coverage included in aggregate %.

11922 of 16018 relevant lines covered (74.43%)

0.74 hits per line

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

99.22
/main/src/main/java/mockit/asm/types/JavaType.java
1
/*
2
 * MIT License
3
 * Copyright (c) 2006-2025 JMockit developers
4
 * See LICENSE file for full license text.
5
 */
6
package mockit.asm.types;
7

8
import edu.umd.cs.findbugs.annotations.NonNull;
9

10
import java.lang.reflect.Constructor;
11
import java.lang.reflect.Method;
12

13
import org.checkerframework.checker.index.qual.NonNegative;
14

15
/**
16
 * A Java field or method type. This class can be used to make it easier to manipulate type and method descriptors.
17
 */
18
@SuppressWarnings("ClassReferencesSubclass")
19
public abstract class JavaType {
20
    private static final JavaType[] NO_ARGS = {};
1✔
21

22
    /**
23
     * The length of the internal name of this Java type.
24
     */
25
    @NonNegative
26
    final int len;
27

28
    /**
29
     * Constructs a Java type.
30
     *
31
     * @param len
32
     *            the length of this descriptor.
33
     */
34
    JavaType(@NonNegative int len) {
1✔
35
        this.len = len;
1✔
36
    }
1✔
37

38
    /**
39
     * Returns the Java type corresponding to the given type descriptor.
40
     *
41
     * @param typeDescriptor
42
     *            a field or method type descriptor.
43
     */
44
    @NonNull
45
    public static JavaType getType(@NonNull String typeDescriptor) {
46
        return getType(typeDescriptor.toCharArray(), 0);
1✔
47
    }
48

49
    /**
50
     * Returns the Java types corresponding to the argument types of the given method descriptor.
51
     */
52
    @NonNull
53
    public static JavaType[] getArgumentTypes(@NonNull String methodDescriptor) {
54
        char[] buf = methodDescriptor.toCharArray();
1✔
55
        int off = 1;
1✔
56
        int size = 0;
1✔
57

58
        while (true) {
59
            char c = buf[off];
1✔
60
            off++;
1✔
61

62
            if (c == ')') {
1✔
63
                break;
1✔
64
            }
65
            if (c == 'L') {
1✔
66
                off = findNextTypeTerminatorCharacter(buf, off);
1✔
67
                size++;
1✔
68
            } else if (c != '[') {
1✔
69
                size++;
1✔
70
            }
71
        }
1✔
72

73
        return getArgumentTypes(buf, size);
1✔
74
    }
75

76
    @NonNegative
77
    private static int findNextTypeTerminatorCharacter(@NonNull char[] desc, @NonNegative int i) {
78
        while (desc[i++] != ';') {
1✔
79
        }
80
        return i;
1✔
81
    }
82

83
    @NonNull
84
    private static JavaType[] getArgumentTypes(@NonNull char[] buf, @NonNegative int argCount) {
85
        if (argCount == 0) {
1✔
86
            return NO_ARGS;
1✔
87
        }
88

89
        JavaType[] argTypes = new JavaType[argCount];
1✔
90
        int off = 1;
1✔
91

92
        for (int i = 0; buf[off] != ')'; i++) {
1✔
93
            JavaType argType = getType(buf, off);
1✔
94
            argTypes[i] = argType;
1✔
95
            off += argType.len + (argType instanceof ObjectType ? 2 : 0);
1✔
96
        }
97

98
        return argTypes;
1✔
99
    }
100

101
    /**
102
     * Returns the Java type corresponding to the return type of the given method descriptor.
103
     */
104
    @NonNull
105
    public static JavaType getReturnType(@NonNull String methodDescriptor) {
106
        char[] buf = methodDescriptor.toCharArray();
1✔
107
        return getType(buf, methodDescriptor.indexOf(')') + 1);
1✔
108
    }
109

110
    /**
111
     * Computes the size of the arguments and of the return value of a method.
112
     *
113
     * @param desc
114
     *            the descriptor of a method.
115
     *
116
     * @return the size of the arguments of the method (plus one for the implicit <code>this</code> argument),
117
     *         <code>argSize</code>, and the size of its return value, <code>retSize</code>, packed into a single
118
     *
119
     *         <pre>{@code int i = (argSize << 2) | retSize }</pre>
120
     *
121
     *         (<code>argSize</code> is therefore equal to
122
     *
123
     *         <pre>{@code i >> 2 }</pre>
124
     *
125
     *         , and
126
     *
127
     *         <pre>{@code retSize }</pre>
128
     *
129
     *         to
130
     *
131
     *         <pre>
132
     * &#64;{code i &amp; 0x03 }
133
     *         </pre>
134
     *
135
     *         ).
136
     */
137
    public static int getArgumentsAndReturnSizes(@NonNull String desc) {
138
        int argSize = 1;
1✔
139
        int i = 1;
1✔
140

141
        while (true) {
142
            char currentChar = desc.charAt(i);
1✔
143
            i++;
1✔
144

145
            switch (currentChar) {
1✔
146
                case ')': {
147
                    char nextChar = desc.charAt(i);
1✔
148
                    return argSize << 2 | (nextChar == 'V' ? 0 : isDoubleSizePrimitiveType(nextChar) ? 2 : 1);
1✔
149
                }
150
                case 'L':
151
                    i = findNextTypeTerminatorCharacter(desc, i);
1✔
152
                    argSize++;
1✔
153
                    break;
1✔
154
                case '[': {
155
                    i = findStartOfArrayElementType(desc, i);
1✔
156
                    char arrayElementType = desc.charAt(i);
1✔
157
                    if (isDoubleSizePrimitiveType(arrayElementType)) {
1✔
158
                        argSize--;
1✔
159
                    }
160
                    break;
161
                }
162
                default:
163
                    if (isDoubleSizePrimitiveType(currentChar)) {
1✔
164
                        argSize += 2;
1✔
165
                    } else {
166
                        argSize++;
1✔
167
                    }
168
                    break;
169
            }
170
        }
1✔
171
    }
172

173
    private static boolean isDoubleSizePrimitiveType(char typeCode) {
174
        return typeCode == 'D' || typeCode == 'J';
1✔
175
    }
176

177
    @NonNegative
178
    private static int findNextTypeTerminatorCharacter(@NonNull String desc, @NonNegative int i) {
179
        while (desc.charAt(i++) != ';') {
1✔
180
        }
181
        return i;
1✔
182
    }
183

184
    @NonNegative
185
    private static int findStartOfArrayElementType(@NonNull String desc, @NonNegative int i) {
186
        while (desc.charAt(i) == '[') {
1✔
187
            i++;
1✔
188
        }
189
        return i;
1✔
190
    }
191

192
    /**
193
     * Returns the Java type corresponding to the given type descriptor. For method descriptors, <code>buf</code> is
194
     * supposed to contain nothing more than the descriptor itself.
195
     *
196
     * @param buf
197
     *            a buffer containing a type descriptor.
198
     * @param off
199
     *            the offset of this descriptor in the previous buffer.
200
     */
201
    @NonNull
202
    static JavaType getType(@NonNull char[] buf, @NonNegative int off) {
203
        PrimitiveType primitiveType = PrimitiveType.getPrimitiveType(buf[off]);
1✔
204

205
        if (primitiveType != null) {
1✔
206
            return primitiveType;
1✔
207
        }
208

209
        return ReferenceType.getReferenceType(buf, off);
1✔
210
    }
211

212
    /**
213
     * Returns the binary name of the class corresponding to this type. This method must not be used on method types.
214
     */
215
    @NonNull
216
    public abstract String getClassName();
217

218
    // ------------------------------------------------------------------------
219
    // Conversion to type descriptors
220
    // ------------------------------------------------------------------------
221

222
    /**
223
     * Returns the descriptor corresponding to this Java type.
224
     */
225
    @NonNull
226
    public final String getDescriptor() {
227
        StringBuilder buf = new StringBuilder();
1✔
228
        getDescriptor(buf);
1✔
229
        return buf.toString();
1✔
230
    }
231

232
    /**
233
     * Appends the descriptor corresponding to this Java type to the given string buffer.
234
     *
235
     * @param typeDesc
236
     *            the string builder to which the descriptor must be appended
237
     */
238
    abstract void getDescriptor(@NonNull StringBuilder typeDesc);
239

240
    // -------------------------------------------------------------------------------------------------------
241
    // Direct conversion from classes to type descriptors, and vice-versa, without intermediate JavaType objects
242
    // -------------------------------------------------------------------------------------------------------
243

244
    /**
245
     * Returns the internal name of the given class. The internal name of a class is its fully qualified name, as
246
     * returned by Class.getName(), where '.' are replaced by '/'.
247
     *
248
     * @param aClass
249
     *            an object or array class
250
     */
251
    @NonNull
252
    public static String getInternalName(@NonNull Class<?> aClass) {
253
        return aClass.getName().replace('.', '/');
1✔
254
    }
255

256
    /**
257
     * Returns the descriptor corresponding to the given constructor.
258
     */
259
    @NonNull
260
    public static String getConstructorDescriptor(@NonNull Constructor<?> constructor) {
261
        StringBuilder buf = getMemberDescriptor(constructor.getParameterTypes());
1✔
262
        buf.append('V');
1✔
263
        return buf.toString();
1✔
264
    }
265

266
    @NonNull
267
    private static StringBuilder getMemberDescriptor(@NonNull Class<?>[] parameterTypes) {
268
        StringBuilder buf = new StringBuilder();
1✔
269
        buf.append('(');
1✔
270

271
        for (Class<?> parameterType : parameterTypes) {
1✔
272
            getDescriptor(buf, parameterType);
1✔
273
        }
274

275
        buf.append(')');
1✔
276
        return buf;
1✔
277
    }
278

279
    /**
280
     * Returns the descriptor corresponding to the given method.
281
     */
282
    @NonNull
283
    public static String getMethodDescriptor(@NonNull Method method) {
284
        StringBuilder buf = getMemberDescriptor(method.getParameterTypes());
1✔
285
        getDescriptor(buf, method.getReturnType());
1✔
286
        return buf.toString();
1✔
287
    }
288

289
    /**
290
     * Appends the descriptor of the given class to the given string builder.
291
     */
292
    private static void getDescriptor(@NonNull StringBuilder buf, @NonNull Class<?> aClass) {
293
        Class<?> d = aClass;
1✔
294

295
        while (true) {
296
            if (d.isPrimitive()) {
1✔
297
                char typeCode = PrimitiveType.getPrimitiveType(d).getTypeCode();
1✔
298
                buf.append(typeCode);
1✔
299
                return;
1✔
300
            }
301
            if (!d.isArray()) {
1✔
302
                ReferenceType.getDescriptor(buf, d);
1✔
303
                return;
1✔
304
            }
305
            buf.append('[');
1✔
306
            d = d.getComponentType();
1✔
307
        }
308
    }
309

310
    // ------------------------------------------------------------------------
311
    // Corresponding size and opcodes
312
    // ------------------------------------------------------------------------
313

314
    /**
315
     * Returns the size of values of this type. This method must not be used for method types.
316
     *
317
     * @return the size of values of this type, i.e., 2 for <code>long</code> and <code>double</code>, 0 for
318
     *         <code>void</code> and 1 otherwise.
319
     */
320
    @NonNegative
321
    public abstract int getSize();
322

323
    /**
324
     * Returns a JVM instruction opcode adapted to this Java type. This method must not be used for method types.
325
     *
326
     * @param opcode
327
     *            a JVM instruction opcode. This opcode must be one of ILOAD, ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL,
328
     *            IDIV, IREM, INEG, ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
329
     *
330
     * @return an opcode that is similar to the given opcode, but adapted to this Java type. For example, if this type
331
     *         is <code>float</code> and <code>opcode</code> is IRETURN, this method returns FRETURN.
332
     */
333
    public abstract int getOpcode(int opcode);
334

335
    public abstract int getLoadOpcode();
336

337
    public abstract int getConstOpcode();
338

339
    /**
340
     * Returns a string representation of this type.
341
     *
342
     * @return the descriptor of this type.
343
     */
344
    @Override
345
    public final String toString() {
346
        return getDescriptor();
×
347
    }
348
}
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