OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / lang / reflect / GenericSignatureParser.java
1 /* GenericSignatureParser.java
2    Copyright (C) 2005
3    Free Software Foundation
4
5 This file is part of GNU Classpath.
6
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.
11
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.
16
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.
21
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.
26
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. */
38
39 package gnu.java.lang.reflect;
40
41 import java.lang.reflect.*;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44
45 final class TypeVariableImpl extends TypeImpl implements TypeVariable
46 {
47     private GenericDeclaration decl;
48     private Type[] bounds;
49     private String name;
50
51     TypeVariableImpl(GenericDeclaration decl, Type[] bounds, String name)
52     {
53         this.decl = decl;
54         this.bounds = bounds;
55         this.name = name;
56     }
57
58     Type resolve()
59     {
60         return this;
61     }
62
63     public Type[] getBounds()
64     {
65         resolve(bounds);
66         return (Type[]) bounds.clone();
67     }
68
69     public GenericDeclaration getGenericDeclaration()
70     {
71         return decl;
72     }
73
74     public String getName()
75     {
76         return name;
77     }
78
79     public boolean equals(Object obj)
80     {
81         if (obj instanceof TypeVariableImpl)
82         {
83             TypeVariableImpl other = (TypeVariableImpl)obj;
84             return decl.equals(other.decl) && name.equals(other.name);
85         }
86         return false;
87     }
88
89     public int hashCode()
90     {
91         return 0x5f4d5156 ^ decl.hashCode() ^ name.hashCode();
92     }
93
94     public String toString()
95     {
96         return name;
97     }
98 }
99
100 final class ParameterizedTypeImpl extends TypeImpl implements ParameterizedType
101 {
102     private String rawTypeName;
103     private ClassLoader loader;
104     private Class rawType;
105     private Type owner;
106     private Type[] typeArgs;
107
108     ParameterizedTypeImpl(String rawTypeName, ClassLoader loader, Type owner,
109         Type[] typeArgs)
110     {
111         this.rawTypeName = rawTypeName;
112         this.loader = loader;
113         this.owner = owner;
114         this.typeArgs = typeArgs;
115     }
116
117     Type resolve()
118     {
119         if (rawType == null)
120         {
121             try
122             {
123                 rawType = Class.forName(rawTypeName, false, loader);
124             }
125             catch (ClassNotFoundException x)
126             {
127                 throw new TypeNotPresentException(rawTypeName, x);
128             }
129         }
130         if (typeArgs == null)
131         {
132             if (owner == null)
133             {
134                 return rawType;
135             }
136             typeArgs = new Type[0];
137         }
138         resolve(typeArgs);
139         owner = resolve(owner);
140         return this;
141     }
142
143     public Type[] getActualTypeArguments()
144     {
145       return (Type[]) typeArgs.clone();
146     }
147
148     public Type getRawType()
149     {
150         return rawType;
151     }
152
153     public Type getOwnerType()
154     {
155         return owner;
156     }
157
158     public boolean equals(Object obj)
159     {
160         if (obj instanceof ParameterizedTypeImpl)
161         {
162             ParameterizedTypeImpl other = (ParameterizedTypeImpl)obj;
163             return rawType.equals(other.rawType)
164                 && ((owner == null && other.owner == null)
165                     || owner.equals(other.owner))
166                 && Arrays.deepEquals(typeArgs, other.typeArgs);
167         }
168         return false;
169     }
170
171     public int hashCode()
172     {
173         int h = 0x58158970 ^ rawType.hashCode();
174         if (owner != null)
175         {
176             h ^= Integer.reverse(owner.hashCode());
177         }
178         for (int i = 0; i < typeArgs.length; i++)
179         {
180             h ^= Integer.rotateLeft(typeArgs[i].hashCode(), i);
181         }
182         return h;
183     }
184
185     public String toString()
186     {
187         StringBuilder sb = new StringBuilder();
188         if (owner != null)
189         {
190             sb.append(owner);
191             sb.append('.');
192             sb.append(rawType.getSimpleName());
193         }
194         else
195         {
196             sb.append(rawTypeName);
197         }
198         if (typeArgs.length > 0)
199         {
200             sb.append('<');
201             for (int i = 0; i < typeArgs.length; i++)
202             {
203                 if (i > 0)
204                     sb.append(", ");
205                 if (typeArgs[i] instanceof Class)
206                 {
207                     sb.append(((Class)typeArgs[i]).getName());
208                 }
209                 else
210                 {
211                     sb.append(typeArgs[i]);
212                 }
213             }
214             sb.append('>');
215         }
216         return sb.toString();
217     }
218 }
219
220 final class GenericArrayTypeImpl extends TypeImpl implements GenericArrayType
221 {
222     private Type componentType;
223
224     GenericArrayTypeImpl(Type componentType)
225     {
226         this.componentType = componentType;
227     }
228
229     Type resolve()
230     {
231         componentType = resolve(componentType);
232         return this;
233     }
234
235     public Type getGenericComponentType()
236     {
237         return componentType;
238     }
239
240     public boolean equals(Object obj)
241     {
242         if (obj instanceof GenericArrayTypeImpl)
243         {
244             GenericArrayTypeImpl other = (GenericArrayTypeImpl)obj;
245             return componentType.equals(other.componentType);
246         }
247         return false;
248     }
249
250     public int hashCode()
251     {
252         return 0x4be37a7f ^ componentType.hashCode();
253     }
254
255     public String toString()
256     {
257         return componentType + "[]";
258     }
259 }
260
261 final class UnresolvedTypeVariable extends TypeImpl implements Type
262 {
263     private GenericDeclaration decl;
264     private String name;
265
266     UnresolvedTypeVariable(GenericDeclaration decl, String name)
267     {
268         this.decl = decl;
269         this.name = name;
270     }
271
272     Type resolve()
273     {
274         GenericDeclaration d = decl;
275         while (d != null)
276         {
277             for (TypeVariable t : d.getTypeParameters())
278             {
279                 if (t.getName().equals(name))
280                 {
281                     return t;
282                 }
283             }
284             d = getParent(d);
285         }
286         throw new MalformedParameterizedTypeException();
287     }
288
289     private static GenericDeclaration getParent(GenericDeclaration d)
290     {
291         if (d instanceof Class)
292         {
293             Method m = ((Class)d).getEnclosingMethod();
294             if (m != null)
295             {
296                 return m;
297             }
298             Constructor c = ((Class)d).getEnclosingConstructor();
299             if (c != null)
300             {
301                 return c;
302             }
303             return ((Class)d).getEnclosingClass();
304         }
305         else if (d instanceof Method)
306         {
307             return ((Method)d).getDeclaringClass();
308         }
309         else if (d instanceof Constructor)
310         {
311             return ((Constructor)d).getDeclaringClass();
312         }
313         else
314         {
315             // TODO figure out what this represents
316             throw new Error();
317         }
318     }
319 }
320
321 final class WildcardTypeImpl extends TypeImpl implements WildcardType
322 {
323     private Type lower;
324     private Type upper;
325
326     WildcardTypeImpl(Type lower, Type upper)
327     {
328         this.lower = lower;
329         this.upper = upper;
330     }
331
332     Type resolve()
333     {
334         upper = resolve(upper);
335         lower = resolve(lower);
336         return this;
337     }
338
339     public Type[] getUpperBounds()
340     {
341         if (upper == null)
342         {
343             return new Type[0];
344         }
345         return new Type[] { upper };
346     }
347
348     public Type[] getLowerBounds()
349     {
350         if (lower == null)
351         {
352             return new Type[0];
353         }
354         return new Type[] { lower };
355     }
356
357     public boolean equals(Object obj)
358     {
359         if (obj instanceof WildcardTypeImpl)
360         {
361             WildcardTypeImpl other = (WildcardTypeImpl)obj;
362             return Arrays.deepEquals(getUpperBounds(), other.getUpperBounds())
363                 && Arrays.deepEquals(getLowerBounds(), other.getLowerBounds());
364         }
365         return false;
366     }
367
368     public int hashCode()
369     {
370         int h = 0x75d074fd;
371         if (upper != null)
372         {
373             h ^= upper.hashCode();
374         }
375         if (lower != null)
376         {
377             h ^= lower.hashCode();
378         }
379         return h;
380     }
381
382     public String toString()
383     {
384         if (lower != null)
385         {
386             return "? super " + lower;
387         }
388         if (upper == java.lang.Object.class)
389         {
390             return "?";
391         }
392         return "? extends " + upper;
393     }
394 }
395
396 class GenericSignatureParser
397 {
398     private ClassLoader loader;
399     private GenericDeclaration container;
400     private String signature;
401     private int pos;
402
403     GenericSignatureParser(GenericDeclaration container, ClassLoader loader,
404         String signature)
405     {
406         this.container = container;
407         this.loader = loader;
408         this.signature = signature;
409     }
410
411     TypeVariable[] readFormalTypeParameters()
412     {
413         consume('<');
414         ArrayList<TypeVariable> params = new ArrayList<TypeVariable>();
415         do
416         {
417             // TODO should we handle name clashes?
418             params.add(readFormalTypeParameter());
419         } while (peekChar() != '>');
420         consume('>');
421         TypeVariable[] list = new TypeVariable[params.size()];
422         params.toArray(list);
423         return list;
424     }
425
426     private TypeVariable readFormalTypeParameter()
427     {
428         String identifier = readIdentifier();
429         consume(':');
430         ArrayList<Type> bounds = new ArrayList<Type>();
431         if (peekChar() != ':')
432         {
433             bounds.add(readFieldTypeSignature());
434         }
435         while (peekChar() == ':')
436         {
437             consume(':');
438             bounds.add(readFieldTypeSignature());
439         }
440         Type[] b = new Type[bounds.size()];
441         bounds.toArray(b);
442         return new TypeVariableImpl(container, b, identifier);
443     }
444
445     Type readFieldTypeSignature()
446     {
447         switch (peekChar())
448         {
449             case 'L':
450                 return readClassTypeSignature();
451             case '[':
452                 return readArrayTypeSignature();
453             case 'T':
454                 return readTypeVariableSignature();
455             default:
456                 throw new GenericSignatureFormatError();
457         }
458     }
459
460     Type readClassTypeSignature()
461     {
462         consume('L');
463         String className = "";
464         for (;;)
465         {
466             String part = readIdentifier();
467             if (peekChar() != '/')
468             {
469                 className += part;
470                 break;
471             }
472             consume('/');
473             className += part + ".";
474         }
475         Type[] typeArguments = null;
476         if (peekChar() == '<')
477         {
478             typeArguments = readTypeArguments();
479         }
480         Type type = new ParameterizedTypeImpl(className, loader, null,
481                                               typeArguments);
482         while (peekChar() == '.')
483         {
484             consume('.');
485             className += "$" + readIdentifier();
486             typeArguments = null;
487             if (peekChar() == '<')
488             {
489                 typeArguments = readTypeArguments();
490             }
491             type = new ParameterizedTypeImpl(className, loader, type,
492                                              typeArguments);
493         }
494         consume(';');
495         return type;
496     }
497
498     private Type[] readTypeArguments()
499     {
500         consume('<');
501         ArrayList<Type> list = new ArrayList<Type>();
502         do
503         {
504             list.add(readTypeArgument());
505         } while ((peekChar() != '>'));
506         consume('>');
507         Type[] arr = new Type[list.size()];
508         list.toArray(arr);
509         return arr;
510     }
511
512     private Type readTypeArgument()
513     {
514         char c = peekChar();
515         if (c == '+')
516         {
517             consume('+');
518             return new WildcardTypeImpl(null, readFieldTypeSignature());
519         }
520         else if (c == '-')
521         {
522             consume('-');
523             return new WildcardTypeImpl(readFieldTypeSignature(),
524                 java.lang.Object.class);
525         }
526         else if (c == '*')
527         {
528             consume('*');
529             return new WildcardTypeImpl(null, java.lang.Object.class);
530         }
531         else
532         {
533             return readFieldTypeSignature();
534         }
535     }
536
537     Type readArrayTypeSignature()
538     {
539         consume('[');
540         switch (peekChar())
541         {
542             case 'L':
543             case '[':
544             case 'T':
545                 return new GenericArrayTypeImpl(readFieldTypeSignature());
546             case 'Z':
547                 consume('Z');
548                 return boolean[].class;
549             case 'B':
550                 consume('B');
551                 return byte[].class;
552             case 'S':
553                 consume('S');
554                 return short[].class;
555             case 'C':
556                 consume('C');
557                 return char[].class;
558             case 'I':
559                 consume('I');
560                 return int[].class;
561             case 'F':
562                 consume('F');
563                 return float[].class;
564             case 'J':
565                 consume('J');
566                 return long[].class;
567             case 'D':
568                 consume('D');
569                 return double[].class;
570             default:
571                 throw new GenericSignatureFormatError();
572         }
573     }
574
575     Type readTypeVariableSignature()
576     {
577         consume('T');
578         String identifier = readIdentifier();
579         consume(';');
580         return new UnresolvedTypeVariable(container, identifier);
581     }
582
583     private String readIdentifier()
584     {
585         int start = pos;
586         char c;
587         do
588         {
589             readChar();
590             c = peekChar();
591         } while (";:./<>-+*".indexOf(c) == -1);
592         return signature.substring(start, pos);
593     }
594
595     final char peekChar()
596     {
597         if (pos == signature.length())
598             return '\u0000';
599         else
600             return signature.charAt(pos);
601     }
602
603     final char readChar()
604     {
605         return signature.charAt(pos++);
606     }
607
608     final void consume(char c)
609     {
610         if (readChar() != c)
611             throw new GenericSignatureFormatError();
612     }
613
614     final void end()
615     {
616         if (pos != signature.length())
617             throw new GenericSignatureFormatError();
618     }
619 }