• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
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 
17 package org.apache.harmony.luni.lang.reflect;
18 
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.GenericDeclaration;
21 import java.lang.reflect.GenericSignatureFormatError;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.Type;
24 import java.lang.reflect.TypeVariable;
25 
26 /**
27  * Implements a parser for the generics signature attribute.
28  * Uses a top-down, resursive descent parsing approach for the following grammar:
29  * <pre>
30  * ClassSignature ::=
31  *     OptFormalTypeParams SuperclassSignature {SuperinterfaceSignature}.
32  * SuperclassSignature ::= ClassTypeSignature.
33  * SuperinterfaceSignature ::= ClassTypeSignature.
34  *
35  * OptFormalTypeParams ::=
36  *     ["<" FormalTypeParameter {FormalTypeParameter} ">"].
37  *
38  * FormalTypeParameter ::= Ident ClassBound {InterfaceBound}.
39  * ClassBound ::= ":" [FieldTypeSignature].
40  * InterfaceBound ::= ":" FieldTypeSignature.
41  *
42  * FieldTypeSignature ::=
43  *     ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature.
44  * ArrayTypeSignature ::= "[" TypSignature.
45  *
46  * ClassTypeSignature ::=
47  *     "L" {Ident "/"} Ident OptTypeArguments {"." Ident OptTypeArguments} ";".
48  *
49  * OptTypeArguments ::= "<" TypeArgument {TypeArgument} ">".
50  *
51  * TypeArgument ::= ([WildcardIndicator] FieldTypeSignature) | "*".
52  * WildcardIndicator ::= "+" | "-".
53  *
54  * TypeVariableSignature ::= "T" Ident ";".
55  *
56  * TypSignature ::= FieldTypeSignature | BaseType.
57  * BaseType ::= "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z".
58  *
59  * MethodTypeSignature ::=
60  *     OptFormalTypeParams "(" {TypeSignature} ")" ReturnType {ThrowsSignature}.
61  * ThrowsSignature ::= ("^" ClassTypeSignature) | ("^" TypeVariableSignature).
62  *
63  * ReturnType ::= TypSignature | VoidDescriptor.
64  * VoidDescriptor ::= "V".
65  * </pre>
66  */
67 public class GenericSignatureParser {
68 
69     public ListOfTypes exceptionTypes;
70     public ListOfTypes parameterTypes;
71     public TypeVariable[] formalTypeParameters;
72     public Type returnType;
73     public Type fieldType;
74     public ListOfTypes interfaceTypes;
75     public Type superclassType;
76     public ClassLoader loader;
77 
78     GenericDeclaration genericDecl;
79 
80     /*
81      * Parser:
82      */
83     char symbol; // 0: eof; else valid term symbol or first char of identifier.
84     String identifier;
85 
86 
87     /*
88      * Scanner:
89      * eof is private to the scan methods
90      * and it's set only when a scan is issued at the end of the buffer.
91      */
92     private boolean eof;
93 
94     char[] buffer;
95     int pos;
96 
GenericSignatureParser(ClassLoader loader)97     public GenericSignatureParser(ClassLoader loader) {
98         this.loader = loader;
99     }
100 
setInput(GenericDeclaration genericDecl, String input)101     void setInput(GenericDeclaration genericDecl, String input) {
102         if (input != null) {
103             this.genericDecl = genericDecl;
104             this.buffer = input.toCharArray();
105             this.eof = false;
106             scanSymbol();
107         }
108         else {
109             this.eof = true;
110         }
111     }
112 
113     /**
114      * Parses the generic signature of a class and creates the data structure
115      * representing the signature.
116      *
117      * @param genericDecl the GenericDeclaration calling this method
118      * @param signature the generic signature of the class
119      */
parseForClass(GenericDeclaration genericDecl, String signature)120     public void parseForClass(GenericDeclaration genericDecl,
121             String signature) {
122         setInput(genericDecl, signature);
123         if (!eof) {
124             parseClassSignature();
125         } else {
126             if(genericDecl instanceof Class) {
127                 Class c = (Class) genericDecl;
128                 this.formalTypeParameters = ListOfVariables.empty;
129                 this.superclassType = c.getSuperclass();
130                 this.interfaceTypes = new ListOfTypes(c.getInterfaces());
131             } else {
132                 this.formalTypeParameters = ListOfVariables.empty;
133                 this.superclassType = Object.class;
134                 this.interfaceTypes = ListOfTypes.empty;
135             }
136         }
137     }
138 
139     /**
140      * Parses the generic signature of a method and creates the data structure
141      * representing the signature.
142      *
143      * @param genericDecl the GenericDeclaration calling this method
144      * @param signature the generic signature of the class
145      */
parseForMethod(GenericDeclaration genericDecl, String signature)146     public void parseForMethod(GenericDeclaration genericDecl,
147             String signature) {
148         setInput(genericDecl, signature);
149         if (!eof) {
150             parseMethodTypeSignature();
151         } else {
152             if(genericDecl instanceof Method) {
153                 Method m = (Method) genericDecl;
154                 this.formalTypeParameters = ListOfVariables.empty;
155                 this.parameterTypes = new ListOfTypes(m.getParameterTypes());
156                 this.exceptionTypes = new ListOfTypes(m.getExceptionTypes());
157                 this.returnType = m.getReturnType();
158             } else {
159                 this.formalTypeParameters = ListOfVariables.empty;
160                 this.parameterTypes = ListOfTypes.empty;
161                 this.exceptionTypes = ListOfTypes.empty;
162                 this.returnType = void.class;
163             }
164         }
165     }
166 
167     /**
168      * Parses the generic signature of a constructor and creates the data
169      * structure representing the signature.
170      *
171      * @param genericDecl the GenericDeclaration calling this method
172      * @param signature the generic signature of the class
173      */
parseForConstructor(GenericDeclaration genericDecl, String signature)174     public void parseForConstructor(GenericDeclaration genericDecl,
175             String signature) {
176         setInput(genericDecl, signature);
177         if (!eof) {
178             parseMethodTypeSignature();
179         } else {
180             if(genericDecl instanceof Constructor) {
181                 Constructor c = (Constructor) genericDecl;
182                 this.formalTypeParameters = ListOfVariables.empty;
183                 this.parameterTypes = new ListOfTypes(c.getParameterTypes());
184                 this.exceptionTypes = new ListOfTypes(c.getExceptionTypes());
185             } else {
186                 this.formalTypeParameters = ListOfVariables.empty;
187                 this.parameterTypes = ListOfTypes.empty;
188                 this.exceptionTypes = ListOfTypes.empty;
189             }
190         }
191     }
192 
193     /**
194      * Parses the generic signature of a field and creates the data structure
195      * representing the signature.
196      *
197      * @param genericDecl the GenericDeclaration calling this method
198      * @param signature the generic signature of the class
199      */
parseForField(GenericDeclaration genericDecl, String signature)200     public void parseForField(GenericDeclaration genericDecl,
201             String signature) {
202         setInput(genericDecl, signature);
203         if (!eof) {
204             this.fieldType = parseFieldTypeSignature();
205         }
206     }
207 
208 
209     //
210     // Parser:
211     //
212 
parseClassSignature()213     void parseClassSignature() {
214         // ClassSignature ::=
215         // OptFormalTypeParameters SuperclassSignature {SuperinterfaceSignature}.
216 
217         parseOptFormalTypeParameters();
218 
219         // SuperclassSignature ::= ClassTypeSignature.
220         this.superclassType = parseClassTypeSignature();
221 
222         interfaceTypes = new ListOfTypes(16);
223         while (symbol > 0) {
224             // SuperinterfaceSignature ::= ClassTypeSignature.
225             interfaceTypes.add(parseClassTypeSignature());
226         }
227     }
228 
parseOptFormalTypeParameters()229     void parseOptFormalTypeParameters() {
230         // OptFormalTypeParameters ::=
231         // ["<" FormalTypeParameter {FormalTypeParameter} ">"].
232 
233         ListOfVariables typeParams = new ListOfVariables();
234 
235         if (symbol == '<') {
236             scanSymbol();
237             typeParams.add(parseFormalTypeParameter());
238             while ((symbol != '>') && (symbol > 0)) {
239                 typeParams.add(parseFormalTypeParameter());
240             }
241             expect('>');
242         }
243         this.formalTypeParameters = typeParams.getArray();
244     }
245 
parseFormalTypeParameter()246     ImplForVariable<GenericDeclaration> parseFormalTypeParameter() {
247         // FormalTypeParameter ::= Ident ClassBound {InterfaceBound}.
248 
249         scanIdentifier();
250         String name = identifier.intern(); // FIXME: is this o.k.?
251 
252         ListOfTypes bounds = new ListOfTypes(8);
253 
254         // ClassBound ::= ":" [FieldTypeSignature].
255         expect(':');
256         if (symbol == 'L' || symbol == '[' || symbol == 'T') {
257             bounds.add(parseFieldTypeSignature());
258         }
259 
260         while (symbol == ':') {
261             // InterfaceBound ::= ":" FieldTypeSignature.
262             scanSymbol();
263             bounds.add(parseFieldTypeSignature());
264         }
265 
266         return new ImplForVariable<GenericDeclaration>(genericDecl, name, bounds);
267     }
268 
parseFieldTypeSignature()269     Type parseFieldTypeSignature() {
270         // FieldTypeSignature ::= ClassTypeSignature | ArrayTypeSignature
271         //         | TypeVariableSignature.
272 
273         switch (symbol) {
274         case 'L':
275             return parseClassTypeSignature();
276         case '[':
277             // ArrayTypeSignature ::= "[" TypSignature.
278             scanSymbol();
279             return new ImplForArray(parseTypeSignature());
280         case 'T':
281             return parseTypeVariableSignature();
282         default:
283             throw new GenericSignatureFormatError();
284         }
285     }
286 
parseClassTypeSignature()287     Type parseClassTypeSignature() {
288         // ClassTypeSignature ::= "L" {Ident "/"} Ident
289         //         OptTypeArguments {"." Ident OptTypeArguments} ";".
290 
291         expect('L');
292 
293         StringBuilder qualIdent = new StringBuilder();
294         scanIdentifier();
295         while (symbol == '/') {
296             scanSymbol();
297             qualIdent.append(identifier).append(".");
298             scanIdentifier();
299         }
300 
301         qualIdent.append(this.identifier);
302 
303         ListOfTypes typeArgs = parseOptTypeArguments();
304         ImplForType parentType =
305                 new ImplForType(null, qualIdent.toString(), typeArgs, loader);
306         ImplForType type = parentType;
307 
308         while (symbol == '.') {
309             // Deal with Member Classes:
310             scanSymbol();
311             scanIdentifier();
312             qualIdent.append("$").append(identifier); // FIXME: is "$" correct?
313             typeArgs = parseOptTypeArguments();
314             type = new ImplForType(parentType, qualIdent.toString(), typeArgs,
315                     loader);
316         }
317 
318         expect(';');
319 
320         return type;
321     }
322 
parseOptTypeArguments()323     ListOfTypes parseOptTypeArguments() {
324         // OptTypeArguments ::= "<" TypeArgument {TypeArgument} ">".
325 
326         ListOfTypes typeArgs = new ListOfTypes(8);
327         if (symbol == '<') {
328             scanSymbol();
329 
330             typeArgs.add(parseTypeArgument());
331             while ((symbol != '>') && (symbol > 0)) {
332                 typeArgs.add(parseTypeArgument());
333             }
334             expect('>');
335         }
336         return typeArgs;
337     }
338 
parseTypeArgument()339     Type parseTypeArgument() {
340         // TypeArgument ::= (["+" | "-"] FieldTypeSignature) | "*".
341         ListOfTypes extendsBound = new ListOfTypes(1);
342         ListOfTypes superBound = new ListOfTypes(1);
343         if (symbol == '*') {
344             scanSymbol();
345             extendsBound.add(Object.class);
346             return new ImplForWildcard(extendsBound, superBound);
347         }
348         else if (symbol == '+') {
349             scanSymbol();
350             extendsBound.add(parseFieldTypeSignature());
351             return new ImplForWildcard(extendsBound, superBound);
352         }
353         else if (symbol == '-') {
354             scanSymbol();
355             superBound.add(parseFieldTypeSignature());
356             extendsBound.add(Object.class);
357             return new ImplForWildcard(extendsBound, superBound);
358         }
359         else {
360             return parseFieldTypeSignature();
361         }
362     }
363 
parseTypeVariableSignature()364     ImplForVariable<GenericDeclaration> parseTypeVariableSignature() {
365         // TypeVariableSignature ::= "T" Ident ";".
366         expect('T');
367         scanIdentifier();
368         expect(';');
369         // Reference to type variable:
370         // Note: we don't know the declaring GenericDeclaration yet.
371         return new ImplForVariable<GenericDeclaration>(genericDecl, identifier);
372     }
373 
parseTypeSignature()374     Type parseTypeSignature() {
375         switch (symbol) {
376         case 'B': scanSymbol(); return byte.class;
377         case 'C': scanSymbol(); return char.class;
378         case 'D': scanSymbol(); return double.class;
379         case 'F': scanSymbol(); return float.class;
380         case 'I': scanSymbol(); return int.class;
381         case 'J': scanSymbol(); return long.class;
382         case 'S': scanSymbol(); return short.class;
383         case 'Z': scanSymbol(); return boolean.class;
384         default:
385             // Not an elementary type, but a FieldTypeSignature.
386             return parseFieldTypeSignature();
387         }
388     }
389 
parseMethodTypeSignature()390     void parseMethodTypeSignature() {
391         // MethodTypeSignature ::= [FormalTypeParameters]
392         //         "(" {TypeSignature} ")" ReturnType {ThrowsSignature}.
393 
394         parseOptFormalTypeParameters();
395 
396         parameterTypes = new ListOfTypes(16);
397         expect('(');
398         while (symbol != ')' && (symbol > 0)) {
399             parameterTypes.add(parseTypeSignature());
400         }
401         expect(')');
402 
403         returnType = parseReturnType();
404 
405         exceptionTypes = new ListOfTypes(8);
406         while (symbol == '^') {
407             scanSymbol();
408 
409             // ThrowsSignature ::= ("^" ClassTypeSignature) |
410             //     ("^" TypeVariableSignature).
411             if (symbol == 'T') {
412                 exceptionTypes.add(parseTypeVariableSignature());
413             } else {
414                 exceptionTypes.add(parseClassTypeSignature());
415             }
416         }
417     }
418 
parseReturnType()419     Type parseReturnType() {
420         // ReturnType ::= TypeSignature | "V".
421         if (symbol != 'V') { return parseTypeSignature(); }
422         else { scanSymbol(); return void.class; }
423     }
424 
425 
426     //
427     // Scanner:
428     //
429 
scanSymbol()430     void scanSymbol() {
431         if (!eof) {
432             if (pos < buffer.length) {
433                 symbol = buffer[pos];
434                 pos++;
435             } else {
436                 symbol = 0;
437                 eof = true;
438             }
439         } else {
440             throw new GenericSignatureFormatError();
441         }
442     }
443 
expect(char c)444     void expect(char c) {
445         if (symbol == c) {
446             scanSymbol();
447         } else {
448             throw new GenericSignatureFormatError();
449         }
450     }
451 
isStopSymbol(char ch)452     boolean isStopSymbol(char ch) {
453         switch (ch) {
454         case ':':
455         case '/':
456         case ';':
457         case '<':
458         case '.':
459             return true;
460         }
461         return false;
462     }
463 
464     // PRE: symbol is the first char of the identifier.
465     // POST: symbol = the next symbol AFTER the identifier.
scanIdentifier()466     void scanIdentifier() {
467         if (!eof) {
468             StringBuilder identBuf = new StringBuilder(32);
469             if (!isStopSymbol(symbol)) {
470                 identBuf.append(symbol);
471                 do {
472                     char ch = buffer[pos];
473                     if ((ch >= 'a') && (ch <= 'z') || (ch >= 'A') && (ch <= 'Z')
474                             || !isStopSymbol(ch)) {
475                         identBuf.append(buffer[pos]);
476                         pos++;
477                     } else {
478                         identifier = identBuf.toString();
479                         scanSymbol();
480                         return;
481                     }
482                 } while (pos != buffer.length);
483                 identifier = identBuf.toString();
484                 symbol = 0;
485                 eof = true;
486             } else {
487                 // Ident starts with incorrect char.
488                 symbol = 0;
489                 eof = true;
490                 throw new GenericSignatureFormatError();
491             }
492         } else {
493             throw new GenericSignatureFormatError();
494         }
495     }
496 
497 }
498