1 |
/* Class.java -- Representation of a Java class. |
/* GenericSignatureParser.java |
2 |
Copyright (C) 2005 |
Copyright (C) 2005 |
3 |
Free Software Foundation |
Free Software Foundation |
4 |
|
|
40 |
|
|
41 |
import java.lang.reflect.*; |
import java.lang.reflect.*; |
42 |
import java.util.ArrayList; |
import java.util.ArrayList; |
43 |
|
import java.util.Arrays; |
44 |
|
|
45 |
class TypeImpl implements Type |
abstract class TypeImpl implements Type |
46 |
{ |
{ |
47 |
Type resolve() |
abstract Type resolve(); |
48 |
|
|
49 |
|
static void resolve(Type[] types) |
50 |
{ |
{ |
51 |
return this; |
for (int i = 0; i < types.length; i++) |
52 |
|
{ |
53 |
|
types[i] = resolve(types[i]); |
54 |
|
} |
55 |
|
} |
56 |
|
|
57 |
|
static Type resolve(Type type) |
58 |
|
{ |
59 |
|
if (type instanceof TypeImpl) |
60 |
|
{ |
61 |
|
type = ((TypeImpl) type).resolve(); |
62 |
|
} |
63 |
|
return type; |
64 |
} |
} |
65 |
} |
} |
66 |
|
|
67 |
class TypeVariableImpl extends TypeImpl implements TypeVariable |
final class TypeVariableImpl extends TypeImpl implements TypeVariable |
68 |
{ |
{ |
69 |
private GenericDeclaration decl; |
private GenericDeclaration decl; |
70 |
private Type[] bounds; |
private Type[] bounds; |
77 |
this.name = name; |
this.name = name; |
78 |
} |
} |
79 |
|
|
80 |
|
Type resolve() |
81 |
|
{ |
82 |
|
return this; |
83 |
|
} |
84 |
|
|
85 |
public Type[] getBounds() |
public Type[] getBounds() |
86 |
{ |
{ |
87 |
|
resolve(bounds); |
88 |
return bounds.clone(); |
return bounds.clone(); |
89 |
} |
} |
90 |
|
|
98 |
return name; |
return name; |
99 |
} |
} |
100 |
|
|
101 |
// TODO implement equals/hashCode |
public boolean equals(Object obj) |
102 |
|
{ |
103 |
|
if (obj instanceof TypeVariableImpl) |
104 |
|
{ |
105 |
|
TypeVariableImpl other = (TypeVariableImpl)obj; |
106 |
|
return decl.equals(other.decl) && name.equals(other.name); |
107 |
|
} |
108 |
|
return false; |
109 |
|
} |
110 |
|
|
111 |
|
public int hashCode() |
112 |
|
{ |
113 |
|
return 0x5f4d5156 ^ decl.hashCode() ^ name.hashCode(); |
114 |
|
} |
115 |
|
|
116 |
|
public String toString() |
117 |
|
{ |
118 |
|
return name; |
119 |
|
} |
120 |
} |
} |
121 |
|
|
122 |
class ParameterizedTypeImpl extends TypeImpl implements ParameterizedType |
final class ParameterizedTypeImpl extends TypeImpl implements ParameterizedType |
123 |
{ |
{ |
124 |
private Type rawType; |
private String rawTypeName; |
125 |
|
private ClassLoader loader; |
126 |
|
private Class rawType; |
127 |
private Type owner; |
private Type owner; |
128 |
private Type[] typeArgs; |
private Type[] typeArgs; |
129 |
|
|
130 |
ParameterizedTypeImpl(Type rawType, Type owner, Type[] typeArgs) |
ParameterizedTypeImpl(String rawTypeName, ClassLoader loader, Type owner, |
131 |
|
Type[] typeArgs) |
132 |
{ |
{ |
133 |
this.rawType = rawType; |
this.rawTypeName = rawTypeName; |
134 |
|
this.loader = loader; |
135 |
this.owner = owner; |
this.owner = owner; |
136 |
this.typeArgs = typeArgs; |
this.typeArgs = typeArgs; |
137 |
} |
} |
138 |
|
|
139 |
public Type[] getActualTypeArguments() |
Type resolve() |
140 |
{ |
{ |
141 |
for (int i = 0; i < typeArgs.length; i++) |
if (rawType == null) |
142 |
|
{ |
143 |
|
try |
144 |
|
{ |
145 |
|
rawType = Class.forName(rawTypeName, false, loader); |
146 |
|
} |
147 |
|
catch (ClassNotFoundException x) |
148 |
|
{ |
149 |
|
throw new TypeNotPresentException(rawTypeName, x); |
150 |
|
} |
151 |
|
} |
152 |
|
if (typeArgs == null) |
153 |
{ |
{ |
154 |
if (typeArgs[i] instanceof TypeImpl) |
if (owner == null) |
155 |
{ |
{ |
156 |
typeArgs[i] = ((TypeImpl)typeArgs[i]).resolve(); |
return rawType; |
157 |
} |
} |
158 |
|
typeArgs = new Type[0]; |
159 |
} |
} |
160 |
|
resolve(typeArgs); |
161 |
|
owner = resolve(owner); |
162 |
|
return this; |
163 |
|
} |
164 |
|
|
165 |
|
public Type[] getActualTypeArguments() |
166 |
|
{ |
167 |
return typeArgs.clone(); |
return typeArgs.clone(); |
168 |
} |
} |
169 |
|
|
177 |
return owner; |
return owner; |
178 |
} |
} |
179 |
|
|
180 |
// TODO implement equals/hashCode |
public boolean equals(Object obj) |
181 |
|
{ |
182 |
|
if (obj instanceof ParameterizedTypeImpl) |
183 |
|
{ |
184 |
|
ParameterizedTypeImpl other = (ParameterizedTypeImpl)obj; |
185 |
|
return rawType.equals(other.rawType) |
186 |
|
&& ((owner == null && other.owner == null) |
187 |
|
|| owner.equals(other.owner)) |
188 |
|
&& Arrays.deepEquals(typeArgs, other.typeArgs); |
189 |
|
} |
190 |
|
return false; |
191 |
|
} |
192 |
|
|
193 |
|
public int hashCode() |
194 |
|
{ |
195 |
|
int h = 0x58158970 ^ rawType.hashCode(); |
196 |
|
if (owner != null) |
197 |
|
{ |
198 |
|
h ^= Integer.reverse(owner.hashCode()); |
199 |
|
} |
200 |
|
for (int i = 0; i < typeArgs.length; i++) |
201 |
|
{ |
202 |
|
h ^= Integer.rotateLeft(typeArgs[i].hashCode(), i); |
203 |
|
} |
204 |
|
return h; |
205 |
|
} |
206 |
|
|
207 |
|
public String toString() |
208 |
|
{ |
209 |
|
StringBuilder sb = new StringBuilder(); |
210 |
|
if (owner != null) |
211 |
|
{ |
212 |
|
sb.append(owner); |
213 |
|
sb.append('.'); |
214 |
|
sb.append(rawType.getSimpleName()); |
215 |
|
} |
216 |
|
else |
217 |
|
{ |
218 |
|
sb.append(rawTypeName); |
219 |
|
} |
220 |
|
if (typeArgs.length > 0) |
221 |
|
{ |
222 |
|
sb.append('<'); |
223 |
|
for (int i = 0; i < typeArgs.length; i++) |
224 |
|
{ |
225 |
|
if (i > 0) |
226 |
|
sb.append(", "); |
227 |
|
if (typeArgs[i] instanceof Class) |
228 |
|
{ |
229 |
|
sb.append(((Class)typeArgs[i]).getName()); |
230 |
|
} |
231 |
|
else |
232 |
|
{ |
233 |
|
sb.append(typeArgs[i]); |
234 |
|
} |
235 |
|
} |
236 |
|
sb.append('>'); |
237 |
|
} |
238 |
|
return sb.toString(); |
239 |
|
} |
240 |
} |
} |
241 |
|
|
242 |
class GenericArrayTypeImpl extends TypeImpl implements GenericArrayType |
final class GenericArrayTypeImpl extends TypeImpl implements GenericArrayType |
243 |
{ |
{ |
244 |
private Type componentType; |
private Type componentType; |
245 |
|
|
248 |
this.componentType = componentType; |
this.componentType = componentType; |
249 |
} |
} |
250 |
|
|
251 |
|
Type resolve() |
252 |
|
{ |
253 |
|
componentType = resolve(componentType); |
254 |
|
return this; |
255 |
|
} |
256 |
|
|
257 |
public Type getGenericComponentType() |
public Type getGenericComponentType() |
258 |
{ |
{ |
259 |
return componentType; |
return componentType; |
260 |
} |
} |
261 |
|
|
262 |
// TODO implement equals/hashCode |
public boolean equals(Object obj) |
263 |
|
{ |
264 |
|
if (obj instanceof GenericArrayTypeImpl) |
265 |
|
{ |
266 |
|
GenericArrayTypeImpl other = (GenericArrayTypeImpl)obj; |
267 |
|
return componentType.equals(other.componentType); |
268 |
|
} |
269 |
|
return false; |
270 |
|
} |
271 |
|
|
272 |
|
public int hashCode() |
273 |
|
{ |
274 |
|
return 0x4be37a7f ^ componentType.hashCode(); |
275 |
|
} |
276 |
|
|
277 |
|
public String toString() |
278 |
|
{ |
279 |
|
return componentType + "[]"; |
280 |
|
} |
281 |
} |
} |
282 |
|
|
283 |
class UnresolvedTypeVariable extends TypeImpl implements Type |
final class UnresolvedTypeVariable extends TypeImpl implements Type |
284 |
{ |
{ |
285 |
private GenericDeclaration decl; |
private GenericDeclaration decl; |
286 |
private String name; |
private String name; |
340 |
} |
} |
341 |
} |
} |
342 |
|
|
343 |
|
final class WildcardTypeImpl extends TypeImpl implements WildcardType |
344 |
|
{ |
345 |
|
private Type lower; |
346 |
|
private Type upper; |
347 |
|
|
348 |
|
WildcardTypeImpl(Type lower, Type upper) |
349 |
|
{ |
350 |
|
this.lower = lower; |
351 |
|
this.upper = upper; |
352 |
|
} |
353 |
|
|
354 |
|
Type resolve() |
355 |
|
{ |
356 |
|
upper = resolve(upper); |
357 |
|
lower = resolve(lower); |
358 |
|
return this; |
359 |
|
} |
360 |
|
|
361 |
|
public Type[] getUpperBounds() |
362 |
|
{ |
363 |
|
if (upper == null) |
364 |
|
{ |
365 |
|
return new Type[0]; |
366 |
|
} |
367 |
|
return new Type[] { upper }; |
368 |
|
} |
369 |
|
|
370 |
|
public Type[] getLowerBounds() |
371 |
|
{ |
372 |
|
if (lower == null) |
373 |
|
{ |
374 |
|
return new Type[0]; |
375 |
|
} |
376 |
|
return new Type[] { lower }; |
377 |
|
} |
378 |
|
|
379 |
|
public boolean equals(Object obj) |
380 |
|
{ |
381 |
|
if (obj instanceof WildcardTypeImpl) |
382 |
|
{ |
383 |
|
WildcardTypeImpl other = (WildcardTypeImpl)obj; |
384 |
|
return Arrays.deepEquals(getUpperBounds(), other.getUpperBounds()) |
385 |
|
&& Arrays.deepEquals(getLowerBounds(), other.getLowerBounds()); |
386 |
|
} |
387 |
|
return false; |
388 |
|
} |
389 |
|
|
390 |
|
public int hashCode() |
391 |
|
{ |
392 |
|
int h = 0x75d074fd; |
393 |
|
if (upper != null) |
394 |
|
{ |
395 |
|
h ^= upper.hashCode(); |
396 |
|
} |
397 |
|
if (lower != null) |
398 |
|
{ |
399 |
|
h ^= lower.hashCode(); |
400 |
|
} |
401 |
|
return h; |
402 |
|
} |
403 |
|
|
404 |
|
public String toString() |
405 |
|
{ |
406 |
|
if (lower != null) |
407 |
|
{ |
408 |
|
return "? super " + lower; |
409 |
|
} |
410 |
|
if (upper == java.lang.Object.class) |
411 |
|
{ |
412 |
|
return "?"; |
413 |
|
} |
414 |
|
return "? extends " + upper; |
415 |
|
} |
416 |
|
} |
417 |
|
|
418 |
class GenericSignatureParser |
class GenericSignatureParser |
419 |
{ |
{ |
420 |
private ClassLoader loader; |
private ClassLoader loader; |
422 |
private String signature; |
private String signature; |
423 |
private int pos; |
private int pos; |
424 |
|
|
425 |
GenericSignatureParser(GenericDeclaration container, ClassLoader loader, String signature) |
GenericSignatureParser(GenericDeclaration container, ClassLoader loader, |
426 |
|
String signature) |
427 |
{ |
{ |
428 |
this.container = container; |
this.container = container; |
429 |
this.loader = loader; |
this.loader = loader; |
454 |
{ |
{ |
455 |
bounds.add(readFieldTypeSignature()); |
bounds.add(readFieldTypeSignature()); |
456 |
} |
} |
|
else |
|
|
{ |
|
|
bounds.add(java.lang.Object.class); |
|
|
} |
|
457 |
while (peekChar() == ':') |
while (peekChar() == ':') |
458 |
{ |
{ |
459 |
consume(':'); |
consume(':'); |
460 |
bounds.add(readFieldTypeSignature()); |
bounds.add(readFieldTypeSignature()); |
461 |
} |
} |
462 |
return new TypeVariableImpl(container, bounds.toArray(new Type[bounds.size()]), identifier); |
Type[] b = new Type[bounds.size()]; |
463 |
|
bounds.toArray(b); |
464 |
|
return new TypeVariableImpl(container, b, identifier); |
465 |
} |
} |
466 |
|
|
467 |
Type readFieldTypeSignature() |
Type readFieldTypeSignature() |
479 |
} |
} |
480 |
} |
} |
481 |
|
|
|
private Class resolveClass(String className) |
|
|
{ |
|
|
try |
|
|
{ |
|
|
return Class.forName(className, false, loader); |
|
|
} |
|
|
catch (ClassNotFoundException x) |
|
|
{ |
|
|
throw new TypeNotPresentException(className, x); |
|
|
} |
|
|
} |
|
|
|
|
482 |
Type readClassTypeSignature() |
Type readClassTypeSignature() |
483 |
{ |
{ |
484 |
consume('L'); |
consume('L'); |
499 |
{ |
{ |
500 |
typeArguments = readTypeArguments(); |
typeArguments = readTypeArguments(); |
501 |
} |
} |
502 |
|
Type type = new ParameterizedTypeImpl(className, loader, null, |
503 |
|
typeArguments); |
504 |
while (peekChar() == '.') |
while (peekChar() == '.') |
505 |
{ |
{ |
506 |
consume('.'); |
consume('.'); |
507 |
// TODO |
className += "$" + readIdentifier(); |
508 |
readIdentifier(); |
typeArguments = null; |
509 |
if (peekChar() == '<') |
if (peekChar() == '<') |
510 |
{ |
{ |
511 |
// TODO |
typeArguments = readTypeArguments(); |
|
readTypeArguments(); |
|
512 |
} |
} |
513 |
|
type = new ParameterizedTypeImpl(className, loader, type, |
514 |
|
typeArguments); |
515 |
} |
} |
516 |
consume(';'); |
consume(';'); |
517 |
if (typeArguments == null || typeArguments.length == 0) |
return type; |
|
{ |
|
|
return resolveClass(className); |
|
|
} |
|
|
// TODO get the owner |
|
|
return new ParameterizedTypeImpl(resolveClass(className), null, typeArguments); |
|
518 |
} |
} |
519 |
|
|
520 |
private Type[] readTypeArguments() |
private Type[] readTypeArguments() |
534 |
private Type readTypeArgument() |
private Type readTypeArgument() |
535 |
{ |
{ |
536 |
char c = peekChar(); |
char c = peekChar(); |
537 |
if (c == '+' || c == '-') |
if (c == '+') |
538 |
{ |
{ |
539 |
readChar(); |
consume('+'); |
540 |
// FIXME add wildcard indicator |
return new WildcardTypeImpl(null, readFieldTypeSignature()); |
541 |
return readFieldTypeSignature(); |
} |
542 |
|
else if (c == '-') |
543 |
|
{ |
544 |
|
consume('-'); |
545 |
|
return new WildcardTypeImpl(readFieldTypeSignature(), |
546 |
|
java.lang.Object.class); |
547 |
} |
} |
548 |
else if (c == '*') |
else if (c == '*') |
549 |
{ |
{ |
|
// FIXME what does this mean? |
|
550 |
consume('*'); |
consume('*'); |
551 |
return java.lang.Object.class; |
return new WildcardTypeImpl(null, java.lang.Object.class); |
552 |
} |
} |
553 |
else |
else |
554 |
{ |
{ |
566 |
case 'T': |
case 'T': |
567 |
return new GenericArrayTypeImpl(readFieldTypeSignature()); |
return new GenericArrayTypeImpl(readFieldTypeSignature()); |
568 |
case 'Z': |
case 'Z': |
569 |
|
consume('Z'); |
570 |
return boolean[].class; |
return boolean[].class; |
571 |
case 'B': |
case 'B': |
572 |
|
consume('B'); |
573 |
return byte[].class; |
return byte[].class; |
574 |
case 'S': |
case 'S': |
575 |
|
consume('S'); |
576 |
return short[].class; |
return short[].class; |
577 |
case 'C': |
case 'C': |
578 |
|
consume('C'); |
579 |
return char[].class; |
return char[].class; |
580 |
case 'I': |
case 'I': |
581 |
|
consume('I'); |
582 |
return int[].class; |
return int[].class; |
583 |
case 'F': |
case 'F': |
584 |
|
consume('F'); |
585 |
return float[].class; |
return float[].class; |
586 |
case 'J': |
case 'J': |
587 |
|
consume('J'); |
588 |
return long[].class; |
return long[].class; |
589 |
case 'D': |
case 'D': |
590 |
|
consume('D'); |
591 |
return double[].class; |
return double[].class; |
592 |
default: |
default: |
593 |
throw new GenericSignatureFormatError(); |
throw new GenericSignatureFormatError(); |
632 |
if (readChar() != c) |
if (readChar() != c) |
633 |
throw new GenericSignatureFormatError(); |
throw new GenericSignatureFormatError(); |
634 |
} |
} |
635 |
|
|
636 |
|
final void end() |
637 |
|
{ |
638 |
|
if (pos != signature.length()) |
639 |
|
throw new GenericSignatureFormatError(); |
640 |
|
} |
641 |
} |
} |