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