Merge from mainline.
[official-gcc.git] / libjava / classpath / gnu / java / lang / reflect / GenericSignatureParser.java
blob399f1bdc46ff920489a16452fbc1370188da6145
1 /* GenericSignatureParser.java
2 Copyright (C) 2005
3 Free Software Foundation
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
39 package gnu.java.lang.reflect;
41 import java.lang.reflect.*;
42 import java.util.ArrayList;
43 import java.util.Arrays;
45 final class TypeVariableImpl extends TypeImpl implements TypeVariable
47 private GenericDeclaration decl;
48 private Type[] bounds;
49 private String name;
51 TypeVariableImpl(GenericDeclaration decl, Type[] bounds, String name)
53 this.decl = decl;
54 this.bounds = bounds;
55 this.name = name;
58 Type resolve()
60 return this;
63 /* FIXME[GENERICS]: Remove cast */
64 public Type[] getBounds()
66 resolve(bounds);
67 return (Type[]) bounds.clone();
70 public GenericDeclaration getGenericDeclaration()
72 return decl;
75 public String getName()
77 return name;
80 public boolean equals(Object obj)
82 if (obj instanceof TypeVariableImpl)
84 TypeVariableImpl other = (TypeVariableImpl)obj;
85 return decl.equals(other.decl) && name.equals(other.name);
87 return false;
90 public int hashCode()
92 return 0x5f4d5156 ^ decl.hashCode() ^ name.hashCode();
95 public String toString()
97 return name;
101 final class ParameterizedTypeImpl extends TypeImpl implements ParameterizedType
103 private String rawTypeName;
104 private ClassLoader loader;
105 private Class rawType;
106 private Type owner;
107 private Type[] typeArgs;
109 ParameterizedTypeImpl(String rawTypeName, ClassLoader loader, Type owner,
110 Type[] typeArgs)
112 this.rawTypeName = rawTypeName;
113 this.loader = loader;
114 this.owner = owner;
115 this.typeArgs = typeArgs;
118 Type resolve()
120 if (rawType == null)
124 rawType = Class.forName(rawTypeName, false, loader);
126 catch (ClassNotFoundException x)
128 throw new TypeNotPresentException(rawTypeName, x);
131 if (typeArgs == null)
133 if (owner == null)
135 return rawType;
137 typeArgs = new Type[0];
139 resolve(typeArgs);
140 owner = resolve(owner);
141 return this;
144 /* FIXME[GENERICS]: Remove cast */
145 public Type[] getActualTypeArguments()
147 return (Type[]) typeArgs.clone();
150 public Type getRawType()
152 return rawType;
155 public Type getOwnerType()
157 return owner;
160 public boolean equals(Object obj)
162 if (obj instanceof ParameterizedTypeImpl)
164 ParameterizedTypeImpl other = (ParameterizedTypeImpl)obj;
165 return rawType.equals(other.rawType)
166 && ((owner == null && other.owner == null)
167 || owner.equals(other.owner))
168 && Arrays.deepEquals(typeArgs, other.typeArgs);
170 return false;
173 public int hashCode()
175 int h = 0x58158970 ^ rawType.hashCode();
176 if (owner != null)
178 h ^= Integer.reverse(owner.hashCode());
180 for (int i = 0; i < typeArgs.length; i++)
182 h ^= Integer.rotateLeft(typeArgs[i].hashCode(), i);
184 return h;
187 public String toString()
189 StringBuilder sb = new StringBuilder();
190 if (owner != null)
192 sb.append(owner);
193 sb.append('.');
194 sb.append(rawType.getSimpleName());
196 else
198 sb.append(rawTypeName);
200 if (typeArgs.length > 0)
202 sb.append('<');
203 for (int i = 0; i < typeArgs.length; i++)
205 if (i > 0)
206 sb.append(", ");
207 if (typeArgs[i] instanceof Class)
209 sb.append(((Class)typeArgs[i]).getName());
211 else
213 sb.append(typeArgs[i]);
216 sb.append('>');
218 return sb.toString();
222 final class GenericArrayTypeImpl extends TypeImpl implements GenericArrayType
224 private Type componentType;
226 GenericArrayTypeImpl(Type componentType)
228 this.componentType = componentType;
231 Type resolve()
233 componentType = resolve(componentType);
234 return this;
237 public Type getGenericComponentType()
239 return componentType;
242 public boolean equals(Object obj)
244 if (obj instanceof GenericArrayTypeImpl)
246 GenericArrayTypeImpl other = (GenericArrayTypeImpl)obj;
247 return componentType.equals(other.componentType);
249 return false;
252 public int hashCode()
254 return 0x4be37a7f ^ componentType.hashCode();
257 public String toString()
259 return componentType + "[]";
263 final class UnresolvedTypeVariable extends TypeImpl implements Type
265 private GenericDeclaration decl;
266 private String name;
268 UnresolvedTypeVariable(GenericDeclaration decl, String name)
270 this.decl = decl;
271 this.name = name;
274 Type resolve()
276 GenericDeclaration d = decl;
277 while (d != null)
279 TypeVariable[] vars = d.getTypeParameters();
280 for (int a = 0; a < vars.length ; ++a)
282 if (vars[a].getName().equals(name))
284 return vars[a];
287 d = getParent(d);
289 throw new MalformedParameterizedTypeException();
292 private static GenericDeclaration getParent(GenericDeclaration d)
294 if (d instanceof Class)
296 Method m = ((Class)d).getEnclosingMethod();
297 if (m != null)
299 return m;
301 Constructor c = ((Class)d).getEnclosingConstructor();
302 if (c != null)
304 return c;
306 return ((Class)d).getEnclosingClass();
308 else if (d instanceof Method)
310 return ((Method)d).getDeclaringClass();
312 else if (d instanceof Constructor)
314 return ((Constructor)d).getDeclaringClass();
316 else
318 // TODO figure out what this represents
319 throw new Error();
324 final class WildcardTypeImpl extends TypeImpl implements WildcardType
326 private Type lower;
327 private Type upper;
329 WildcardTypeImpl(Type lower, Type upper)
331 this.lower = lower;
332 this.upper = upper;
335 Type resolve()
337 upper = resolve(upper);
338 lower = resolve(lower);
339 return this;
342 public Type[] getUpperBounds()
344 if (upper == null)
346 return new Type[0];
348 return new Type[] { upper };
351 public Type[] getLowerBounds()
353 if (lower == null)
355 return new Type[0];
357 return new Type[] { lower };
360 public boolean equals(Object obj)
362 if (obj instanceof WildcardTypeImpl)
364 WildcardTypeImpl other = (WildcardTypeImpl)obj;
365 return Arrays.deepEquals(getUpperBounds(), other.getUpperBounds())
366 && Arrays.deepEquals(getLowerBounds(), other.getLowerBounds());
368 return false;
371 public int hashCode()
373 int h = 0x75d074fd;
374 if (upper != null)
376 h ^= upper.hashCode();
378 if (lower != null)
380 h ^= lower.hashCode();
382 return h;
385 public String toString()
387 if (lower != null)
389 return "? super " + lower;
391 if (upper == java.lang.Object.class)
393 return "?";
395 return "? extends " + upper;
399 class GenericSignatureParser
401 private ClassLoader loader;
402 private GenericDeclaration container;
403 private String signature;
404 private int pos;
406 GenericSignatureParser(GenericDeclaration container, ClassLoader loader,
407 String signature)
409 this.container = container;
410 this.loader = loader;
411 this.signature = signature;
414 TypeVariable[] readFormalTypeParameters()
416 consume('<');
417 ArrayList params = new ArrayList();
420 // TODO should we handle name clashes?
421 params.add(readFormalTypeParameter());
422 } while (peekChar() != '>');
423 consume('>');
424 TypeVariable[] list = new TypeVariable[params.size()];
425 params.toArray(list);
426 return list;
429 private TypeVariable readFormalTypeParameter()
431 String identifier = readIdentifier();
432 consume(':');
433 ArrayList bounds = new ArrayList();
434 if (peekChar() != ':')
436 bounds.add(readFieldTypeSignature());
438 while (peekChar() == ':')
440 consume(':');
441 bounds.add(readFieldTypeSignature());
443 Type[] b = new Type[bounds.size()];
444 bounds.toArray(b);
445 return new TypeVariableImpl(container, b, identifier);
448 Type readFieldTypeSignature()
450 switch (peekChar())
452 case 'L':
453 return readClassTypeSignature();
454 case '[':
455 return readArrayTypeSignature();
456 case 'T':
457 return readTypeVariableSignature();
458 default:
459 throw new GenericSignatureFormatError();
463 Type readClassTypeSignature()
465 consume('L');
466 String className = "";
467 for (;;)
469 String part = readIdentifier();
470 if (peekChar() != '/')
472 className += part;
473 break;
475 consume('/');
476 className += part + ".";
478 Type[] typeArguments = null;
479 if (peekChar() == '<')
481 typeArguments = readTypeArguments();
483 Type type = new ParameterizedTypeImpl(className, loader, null,
484 typeArguments);
485 while (peekChar() == '.')
487 consume('.');
488 className += "$" + readIdentifier();
489 typeArguments = null;
490 if (peekChar() == '<')
492 typeArguments = readTypeArguments();
494 type = new ParameterizedTypeImpl(className, loader, type,
495 typeArguments);
497 consume(';');
498 return type;
501 private Type[] readTypeArguments()
503 consume('<');
504 ArrayList list = new ArrayList();
507 list.add(readTypeArgument());
508 } while ((peekChar() != '>'));
509 consume('>');
510 Type[] arr = new Type[list.size()];
511 list.toArray(arr);
512 return arr;
515 private Type readTypeArgument()
517 char c = peekChar();
518 if (c == '+')
520 consume('+');
521 return new WildcardTypeImpl(null, readFieldTypeSignature());
523 else if (c == '-')
525 consume('-');
526 return new WildcardTypeImpl(readFieldTypeSignature(),
527 java.lang.Object.class);
529 else if (c == '*')
531 consume('*');
532 return new WildcardTypeImpl(null, java.lang.Object.class);
534 else
536 return readFieldTypeSignature();
540 Type readArrayTypeSignature()
542 consume('[');
543 switch (peekChar())
545 case 'L':
546 case '[':
547 case 'T':
548 return new GenericArrayTypeImpl(readFieldTypeSignature());
549 case 'Z':
550 consume('Z');
551 return boolean[].class;
552 case 'B':
553 consume('B');
554 return byte[].class;
555 case 'S':
556 consume('S');
557 return short[].class;
558 case 'C':
559 consume('C');
560 return char[].class;
561 case 'I':
562 consume('I');
563 return int[].class;
564 case 'F':
565 consume('F');
566 return float[].class;
567 case 'J':
568 consume('J');
569 return long[].class;
570 case 'D':
571 consume('D');
572 return double[].class;
573 default:
574 throw new GenericSignatureFormatError();
578 Type readTypeVariableSignature()
580 consume('T');
581 String identifier = readIdentifier();
582 consume(';');
583 return new UnresolvedTypeVariable(container, identifier);
586 private String readIdentifier()
588 int start = pos;
589 char c;
592 readChar();
593 c = peekChar();
594 } while (";:./<>-+*".indexOf(c) == -1);
595 return signature.substring(start, pos);
598 final char peekChar()
600 if (pos == signature.length())
601 return '\u0000';
602 else
603 return signature.charAt(pos);
606 final char readChar()
608 return signature.charAt(pos++);
611 final void consume(char c)
613 if (readChar() != c)
614 throw new GenericSignatureFormatError();
617 final void end()
619 if (pos != signature.length())
620 throw new GenericSignatureFormatError();