1 /*
2 * Copyright 2014 - 2020 Rafael Winterhalter
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.bytebuddy.description.type;
17
18 import net.bytebuddy.description.ModifierReviewable;
19 import net.bytebuddy.description.NamedElement;
20 import net.bytebuddy.description.field.FieldList;
21 import net.bytebuddy.description.method.MethodList;
22 import net.bytebuddy.implementation.bytecode.StackSize;
23
24 import java.lang.reflect.*;
25 import java.util.Iterator;
26 import java.util.NoSuchElementException;
27
28 /**
29 * Implementations define a type, either as a {@link TypeDescription} or as a {@link TypeDescription.Generic}.
30 */
31 public interface TypeDefinition extends NamedElement, ModifierReviewable.ForTypeDefinition, Iterable<TypeDefinition> {
32
33 /**
34 * <p>
35 * If this property is set to {@code true}, non-generic {@link TypeDefinition}s do no longer resolve their referenced
36 * generic types when traversing type hierarchies. Setting this property can cause unexpected side effects such as
37 * {@link ClassCastException}s from overridden methods as type variables are resolved to their erasures where a method
38 * might return that is unexpected by the callee. Setting this property also makes type annotations unavailable using
39 * such type navigation.
40 * </p>
41 * <p>
42 * Setting this property can be useful if generic type information is not required in order to avoid bugs in
43 * implementations of the JVM where processing generic types can cause segmentation faults. Byte Buddy will undertake
44 * a best effort to retain the generic type information and information about type annotations within the redefined
45 * types' class files. Typically, this property can be meaningful in combination with a Java agent that only changes
46 * byte code without changing a class type's structure.
47 * </p>
48 */
49 String RAW_TYPES_PROPERTY = "net.bytebuddy.raw";
50
51 /**
52 * Returns this type definition as a generic type.
53 *
54 * @return This type definition represented as a generic type.
55 */
56 TypeDescription.Generic asGenericType();
57
58 /**
59 * Returns the erasure of this type. Wildcard types ({@link TypeDescription.Generic.Sort#WILDCARD})
60 * do not have a well-defined erasure and cause an {@link IllegalStateException} to be thrown.
61 *
62 * @return The erasure of this type.
63 */
64 TypeDescription asErasure();
65
66 /**
67 * Returns the super class of this type. A super type is only defined for non-generic types ({@link Sort#NON_GENERIC}),
68 * parameterized types ({@link Sort#PARAMETERIZED}) or generic array types ({@link Sort#GENERIC_ARRAY}) types. Interface types
69 * and the {@link Object} class do not define a super class where {@code null} is returned. Array types define {@link Object}
70 * as their direct super class.
71 *
72 * @return The super class of this type or {@code null} if no super class exists for this type.
73 */
74 TypeDescription.Generic getSuperClass();
75
76 /**
77 * Returns the interfaces that this type implements. A super type is only defined for non-generic types ({@link Sort#NON_GENERIC}),
78 * parameterized types ({@link Sort#PARAMETERIZED}) or generic array types ({@link Sort#GENERIC_ARRAY}) types.
79 *
80 * @return The interfaces that this type implements.
81 */
82 TypeList.Generic getInterfaces();
83
84 /**
85 * Returns the fields that this type declares. A super type is only defined for non-generic types ({@link Sort#NON_GENERIC}),
86 * parameterized types ({@link Sort#PARAMETERIZED}) or generic array types ({@link Sort#GENERIC_ARRAY}) types. Generic array
87 * types never define fields and the returned list is always empty for such types.
88 *
89 * @return The fields that this type declares. A super type is only defined for non-generic types ({@link Sort#NON_GENERIC}),
90 * parameterized types ({@link Sort#PARAMETERIZED}) or generic array types ({@link Sort#GENERIC_ARRAY}) types. Generic array
91 * types never define methods and the returned list is always empty for such types.
92 */
93 FieldList<?> getDeclaredFields();
94
95 /**
96 * Returns the methods that this type declares.
97 *
98 * @return The methods that this type declares.
99 */
100 MethodList<?> getDeclaredMethods();
101
102 /**
103 * <p>
104 * Returns the component type of this type.
105 * </p>
106 * <p>
107 * Only non-generic types ({@link TypeDescription.Generic.Sort#NON_GENERIC}) and generic array types
108 * {@link TypeDescription.Generic.Sort#GENERIC_ARRAY}) define a component type. For other
109 * types, an {@link IllegalStateException} is thrown.
110 * </p>
111 *
112 * @return The component type of this type or {@code null} if this type does not represent an array type.
113 */
114 TypeDefinition getComponentType();
115
116 /**
117 * Returns the list of record components that are declared by this type. If this type is not
118 * a record, the returned list is empty.
119 *
120 * @return A list of record components that this type declares.
121 */
122 RecordComponentList<?> getRecordComponents();
123
124 /**
125 * Returns the sort of the generic type this instance represents.
126 *
127 * @return The sort of the generic type.
128 */
129 Sort getSort();
130
131 /**
132 * Returns the name of the type. For generic types, this name is their {@link Object#toString()} representations. For a non-generic
133 * type, it is the fully qualified binary name of the type.
134 *
135 * @return The name of this type.
136 */
137 String getTypeName();
138
139 /**
140 * Returns the size of the type described by this instance. Wildcard types
141 * ({@link TypeDescription.Generic.Sort#WILDCARD} do not have a well-defined a stack size and
142 * cause an {@link IllegalStateException} to be thrown.
143 *
144 * @return The size of the type described by this instance.
145 */
146 StackSize getStackSize();
147
148 /**
149 * Checks if the type described by this entity is an array.
150 *
151 * @return {@code true} if this type description represents an array.
152 */
153 boolean isArray();
154
155 /**
156 * Checks if this type is a Java record.
157 *
158 * @return {@code true} if this type is a Java record.
159 */
160 boolean isRecord();
161
162 /**
163 * Checks if the type described by this entity is a primitive type.
164 *
165 * @return {@code true} if this type description represents a primitive type.
166 */
167 boolean isPrimitive();
168
169 /**
170 * Checks if the type described by this instance represents {@code type}.
171 *
172 * @param type The type of interest.
173 * @return {@code true} if the type described by this instance represents {@code type}.
174 */
175 boolean represents(Type type);
176
177 /**
178 * Represents a {@link TypeDescription.Generic}'s form.
179 */
180 enum Sort {
181
182 /**
183 * Represents a non-generic type.
184 */
185 NON_GENERIC,
186
187 /**
188 * Represents a generic array type.
189 */
190 GENERIC_ARRAY,
191
192 /**
193 * Represents a parameterized type.
194 */
195 PARAMETERIZED,
196
197 /**
198 * Represents a wildcard type.
199 */
200 WILDCARD,
201
202 /**
203 * Represents a type variable that is attached to a {@link net.bytebuddy.description.TypeVariableSource}.
204 */
205 VARIABLE,
206
207 /**
208 * Represents a type variable that is merely symbolic and is not attached to a {@link net.bytebuddy.description.TypeVariableSource}
209 * and does not defined bounds.
210 */
211 VARIABLE_SYMBOLIC;
212
213 /**
214 * Describes a loaded generic type as a {@link TypeDescription.Generic}.
215 *
216 * @param type The type to describe.
217 * @return A description of the provided generic type.
218 */
219 public static TypeDescription.Generic describe(Type type) {
220 return describe(type, TypeDescription.Generic.AnnotationReader.NoOp.INSTANCE);
221 }
222
223 /**
224 * Describes the generic type while using the supplied annotation reader for resolving type annotations if this
225 * language feature is available on the current JVM.
226 *
227 * @param type The type to describe.
228 * @param annotationReader The annotation reader for extracting type annotations.
229 * @return A description of the provided generic annotated type.
230 */
231 protected static TypeDescription.Generic describe(Type type, TypeDescription.Generic.AnnotationReader annotationReader) {
232 if (type instanceof Class<?>) {
233 return new TypeDescription.Generic.OfNonGenericType.ForLoadedType((Class<?>) type, annotationReader);
234 } else if (type instanceof GenericArrayType) {
235 return new TypeDescription.Generic.OfGenericArray.ForLoadedType((GenericArrayType) type, annotationReader);
236 } else if (type instanceof ParameterizedType) {
237 return new TypeDescription.Generic.OfParameterizedType.ForLoadedType((ParameterizedType) type, annotationReader);
238 } else if (type instanceof TypeVariable) {
239 return new TypeDescription.Generic.OfTypeVariable.ForLoadedType((TypeVariable<?>) type, annotationReader);
240 } else if (type instanceof WildcardType) {
241 return new TypeDescription.Generic.OfWildcardType.ForLoadedType((WildcardType) type, annotationReader);
242 } else {
243 throw new IllegalArgumentException("Unknown type: " + type);
244 }
245 }
246
247 /**
248 * Checks if this type sort represents a non-generic type.
249 *
250 * @return {@code true} if this sort form represents a non-generic.
251 */
252 public boolean isNonGeneric() {
253 return this == NON_GENERIC;
254 }
255
256 /**
257 * Checks if this type sort represents a parameterized type.
258 *
259 * @return {@code true} if this sort form represents a parameterized type.
260 */
261 public boolean isParameterized() {
262 return this == PARAMETERIZED;
263 }
264
265 /**
266 * Checks if this type sort represents a generic array.
267 *
268 * @return {@code true} if this type sort represents a generic array.
269 */
270 public boolean isGenericArray() {
271 return this == GENERIC_ARRAY;
272 }
273
274 /**
275 * Checks if this type sort represents a wildcard.
276 *
277 * @return {@code true} if this type sort represents a wildcard.
278 */
279 public boolean isWildcard() {
280 return this == WILDCARD;
281 }
282
283 /**
284 * Checks if this type sort represents a type variable of any form.
285 *
286 * @return {@code true} if this type sort represents an attached type variable.
287 */
288 public boolean isTypeVariable() {
289 return this == VARIABLE || this == VARIABLE_SYMBOLIC;
290 }
291 }
292
293 /**
294 * An iterator that iterates over a type's class hierarchy.
295 */
296 class SuperClassIterator implements Iterator<TypeDefinition> {
297
298 /**
299 * The next class to represent.
300 */
301 private TypeDefinition nextClass;
302
303 /**
304 * Creates a new iterator.
305 *
306 * @param initialType The initial type of this iterator.
307 */
308 public SuperClassIterator(TypeDefinition initialType) {
309 nextClass = initialType;
310 }
311
312 /**
313 * {@inheritDoc}
314 */
315 public boolean hasNext() {
316 return nextClass != null;
317 }
318
319 /**
320 * {@inheritDoc}
321 */
322 public TypeDefinition next() {
323 if (!hasNext()) {
324 throw new NoSuchElementException("End of type hierarchy");
325 }
326 try {
327 return nextClass;
328 } finally {
329 nextClass = nextClass.getSuperClass();
330 }
331 }
332
333 /**
334 * {@inheritDoc}
335 */
336 public void remove() {
337 throw new UnsupportedOperationException("remove");
338 }
339 }
340 }
341