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