1 11 package org.eclipse.jdt.internal.compiler.parser; 12 13 25 26 import java.util.ArrayList ; 27 import java.util.HashMap ; 28 29 import org.eclipse.jdt.core.IImportDeclaration; 30 import org.eclipse.jdt.core.IJavaElement; 31 import org.eclipse.jdt.core.JavaModelException; 32 import org.eclipse.jdt.core.Signature; 33 import org.eclipse.jdt.core.compiler.CharOperation; 34 import org.eclipse.jdt.internal.compiler.CompilationResult; 35 import org.eclipse.jdt.internal.compiler.ast.*; 36 import org.eclipse.jdt.internal.compiler.ast.TypeParameter; 37 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 38 import org.eclipse.jdt.internal.compiler.env.*; 39 40 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; 41 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 42 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; 43 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; 44 import org.eclipse.jdt.internal.core.*; 45 import org.eclipse.jdt.internal.core.util.Util; 46 47 public class SourceTypeConverter { 48 49 54 static class AnonymousMemberFound extends RuntimeException { 55 private static final long serialVersionUID = 1L; 56 } 57 58 public static final int FIELD = 0x01; 59 public static final int CONSTRUCTOR = 0x02; 60 public static final int METHOD = 0x04; 61 public static final int MEMBER_TYPE = 0x08; 62 public static final int FIELD_INITIALIZATION = 0x10; 63 public static final int FIELD_AND_METHOD = FIELD | CONSTRUCTOR | METHOD; 64 public static final int LOCAL_TYPE = 0x20; 65 public static final int NONE = 0; 66 67 private int flags; 68 private CompilationUnitDeclaration unit; 69 private Parser parser; 70 private ProblemReporter problemReporter; 71 private ICompilationUnit cu; 72 private char[] source; 73 private HashMap annotationPositions; 74 private boolean has1_5Compliance; 75 76 int namePos; 77 78 private SourceTypeConverter(int flags, ProblemReporter problemReporter) { 79 this.flags = flags; 80 this.problemReporter = problemReporter; 81 this.has1_5Compliance = problemReporter.options.complianceLevel >= ClassFileConstants.JDK1_5; 82 } 83 84 90 public static CompilationUnitDeclaration buildCompilationUnit( 91 ISourceType[] sourceTypes, 92 int flags, 93 ProblemReporter problemReporter, 94 CompilationResult compilationResult) { 95 96 SourceTypeConverter converter = new SourceTypeConverter(flags, problemReporter); 98 try { 99 return converter.convert(sourceTypes, compilationResult); 100 } catch (JavaModelException e) { 101 return null; 102 } 105 } 106 107 112 private CompilationUnitDeclaration convert(ISourceType[] sourceTypes, CompilationResult compilationResult) throws JavaModelException { 113 this.unit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0); 114 116 if (sourceTypes.length == 0) return this.unit; 117 SourceTypeElementInfo topLevelTypeInfo = (SourceTypeElementInfo) sourceTypes[0]; 118 org.eclipse.jdt.core.ICompilationUnit cuHandle = topLevelTypeInfo.getHandle().getCompilationUnit(); 119 this.cu = (ICompilationUnit) cuHandle; 120 this.annotationPositions = ((CompilationUnitElementInfo) ((JavaElement) this.cu).getElementInfo()).annotationPositions; 121 122 if (this.has1_5Compliance && this.annotationPositions != null && this.annotationPositions.size() > 10) { return new Parser(this.problemReporter, true).dietParse(this.cu, compilationResult); 125 } 126 127 128 int start = topLevelTypeInfo.getNameSourceStart(); 129 int end = topLevelTypeInfo.getNameSourceEnd(); 130 131 132 String [] packageName = ((PackageFragment) cuHandle.getParent()).names; 133 if (packageName.length > 0) 134 this.unit.currentPackage = 136 createImportReference(packageName, start, end, false, ClassFileConstants.AccDefault); 137 IImportDeclaration[] importDeclarations = topLevelTypeInfo.getHandle().getCompilationUnit().getImports(); 138 int importCount = importDeclarations.length; 139 this.unit.imports = new ImportReference[importCount]; 140 for (int i = 0; i < importCount; i++) { 141 ImportDeclaration importDeclaration = (ImportDeclaration) importDeclarations[i]; 142 ISourceImport sourceImport = (ISourceImport) importDeclaration.getElementInfo(); 143 String nameWithoutStar = importDeclaration.getNameWithoutStar(); 144 this.unit.imports[i] = createImportReference( 145 Util.splitOn('.', nameWithoutStar, 0, nameWithoutStar.length()), 146 sourceImport.getDeclarationSourceStart(), 147 sourceImport.getDeclarationSourceEnd(), 148 importDeclaration.isOnDemand(), 149 sourceImport.getModifiers()); 150 } 151 152 try { 153 int typeCount = sourceTypes.length; 154 final TypeDeclaration[] types = new TypeDeclaration[typeCount]; 155 160 for (int i = 0; i < typeCount; i++) { 161 SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) sourceTypes[i]; 162 types[i] = convert((SourceType) typeInfo.getHandle(), compilationResult); 163 } 164 this.unit.types = types; 165 return this.unit; 166 } catch (AnonymousMemberFound e) { 167 return new Parser(this.problemReporter, true).parse(this.cu, compilationResult); 168 } 169 } 170 171 private void addIdentifiers(String typeSignature, int start, int endExclusive, int identCount, ArrayList fragments) { 172 if (identCount == 1) { 173 char[] identifier; 174 typeSignature.getChars(start, endExclusive, identifier = new char[endExclusive-start], 0); 175 fragments.add(identifier); 176 } else 177 fragments.add(extractIdentifiers(typeSignature, start, endExclusive-1, identCount)); 178 } 179 180 183 private Initializer convert(InitializerElementInfo initializerInfo, CompilationResult compilationResult) throws JavaModelException { 184 185 Block block = new Block(0); 186 Initializer initializer = new Initializer(block, ClassFileConstants.AccDefault); 187 188 int start = initializerInfo.getDeclarationSourceStart(); 189 int end = initializerInfo.getDeclarationSourceEnd(); 190 191 initializer.sourceStart = initializer.declarationSourceStart = start; 192 initializer.sourceEnd = initializer.declarationSourceEnd = end; 193 initializer.modifiers = initializerInfo.getModifiers(); 194 195 196 IJavaElement[] children = initializerInfo.getChildren(); 197 int typesLength = children.length; 198 if (typesLength > 0) { 199 Statement[] statements = new Statement[typesLength]; 200 for (int i = 0; i < typesLength; i++) { 201 SourceType type = (SourceType) children[i]; 202 TypeDeclaration localType = convert(type, compilationResult); 203 if ((localType.bits & ASTNode.IsAnonymousType) != 0) { 204 QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType); 205 expression.type = localType.superclass; 206 localType.superclass = null; 207 localType.superInterfaces = null; 208 localType.allocation = expression; 209 statements[i] = expression; 210 } else { 211 statements[i] = localType; 212 } 213 } 214 block.statements = statements; 215 } 216 217 return initializer; 218 } 219 220 223 private FieldDeclaration convert(SourceField fieldHandle, TypeDeclaration type, CompilationResult compilationResult) throws JavaModelException { 224 225 SourceFieldElementInfo fieldInfo = (SourceFieldElementInfo) fieldHandle.getElementInfo(); 226 FieldDeclaration field = new FieldDeclaration(); 227 228 int start = fieldInfo.getNameSourceStart(); 229 int end = fieldInfo.getNameSourceEnd(); 230 231 field.name = fieldHandle.getElementName().toCharArray(); 232 field.sourceStart = start; 233 field.sourceEnd = end; 234 field.declarationSourceStart = fieldInfo.getDeclarationSourceStart(); 235 field.declarationSourceEnd = fieldInfo.getDeclarationSourceEnd(); 236 int modifiers = fieldInfo.getModifiers(); 237 boolean isEnumConstant = (modifiers & ClassFileConstants.AccEnum) != 0; 238 if (isEnumConstant) { 239 field.modifiers = modifiers & ~ClassFileConstants.AccEnum; } else { 241 field.modifiers = modifiers; 242 field.type = createTypeReference(fieldInfo.getTypeName(), start, end); 243 } 244 245 if (this.has1_5Compliance) { 247 248 field.annotations = convertAnnotations(fieldHandle); 249 } 250 251 252 if ((this.flags & FIELD_INITIALIZATION) != 0) { 253 char[] initializationSource = fieldInfo.getInitializationSource(); 254 if (initializationSource != null) { 255 if (this.parser == null) { 256 this.parser = new Parser(this.problemReporter, true); 257 } 258 this.parser.parse(field, type, this.unit, initializationSource); 259 } 260 } 261 262 263 if ((this.flags & LOCAL_TYPE) != 0) { 264 IJavaElement[] children = fieldInfo.getChildren(); 265 int childrenLength = children.length; 266 if (childrenLength == 1) { 267 field.initialization = convert(children[0], isEnumConstant ? field : null, compilationResult); 268 } else if (childrenLength > 1) { 269 ArrayInitializer initializer = new ArrayInitializer(); 270 field.initialization = initializer; 271 Expression[] expressions = new Expression[childrenLength]; 272 initializer.expressions = expressions; 273 for (int i = 0; i < childrenLength; i++) { 274 expressions[i] = convert(children[i], isEnumConstant ? field : null, compilationResult); 275 } 276 } 277 } 278 return field; 279 } 280 281 private QualifiedAllocationExpression convert(IJavaElement localType, FieldDeclaration enumConstant, CompilationResult compilationResult) throws JavaModelException { 282 TypeDeclaration anonymousLocalTypeDeclaration = convert((SourceType) localType, compilationResult); 283 QualifiedAllocationExpression expression = new QualifiedAllocationExpression(anonymousLocalTypeDeclaration); 284 expression.type = anonymousLocalTypeDeclaration.superclass; 285 anonymousLocalTypeDeclaration.superclass = null; 286 anonymousLocalTypeDeclaration.superInterfaces = null; 287 anonymousLocalTypeDeclaration.allocation = expression; 288 if (enumConstant != null) { 289 anonymousLocalTypeDeclaration.modifiers &= ~ClassFileConstants.AccEnum; 290 expression.enumConstant = enumConstant; 291 expression.type = null; 292 } 293 return expression; 294 } 295 296 299 private AbstractMethodDeclaration convert(SourceMethod methodHandle, SourceMethodElementInfo methodInfo, CompilationResult compilationResult) throws JavaModelException { 300 AbstractMethodDeclaration method; 301 302 303 int start = methodInfo.getNameSourceStart(); 304 int end = methodInfo.getNameSourceEnd(); 305 306 TypeParameter[] typeParams = null; 308 if (this.has1_5Compliance) { 309 310 char[][] typeParameterNames = methodInfo.getTypeParameterNames(); 311 if (typeParameterNames != null) { 312 int parameterCount = typeParameterNames.length; 313 if (parameterCount > 0) { char[][][] typeParameterBounds = methodInfo.getTypeParameterBounds(); 315 typeParams = new TypeParameter[parameterCount]; 316 for (int i = 0; i < parameterCount; i++) { 317 typeParams[i] = createTypeParameter(typeParameterNames[i], typeParameterBounds[i], start, end); 318 } 319 } 320 } 321 } 322 323 int modifiers = methodInfo.getModifiers(); 324 if (methodInfo.isConstructor()) { 325 ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult); 326 decl.bits &= ~ASTNode.IsDefaultConstructor; 327 method = decl; 328 decl.typeParameters = typeParams; 329 } else { 330 MethodDeclaration decl; 331 if (methodInfo.isAnnotationMethod()) { 332 AnnotationMethodDeclaration annotationMethodDeclaration = new AnnotationMethodDeclaration(compilationResult); 333 334 335 SourceAnnotationMethodInfo annotationMethodInfo = (SourceAnnotationMethodInfo) methodInfo; 336 boolean hasDefaultValue = annotationMethodInfo.defaultValueStart != -1 || annotationMethodInfo.defaultValueEnd != -1; 337 if ((this.flags & FIELD_INITIALIZATION) != 0) { 338 if (hasDefaultValue) { 339 char[] defaultValueSource = CharOperation.subarray(getSource(), annotationMethodInfo.defaultValueStart, annotationMethodInfo.defaultValueEnd+1); 340 if (defaultValueSource != null) { 341 Expression expression = parseMemberValue(defaultValueSource); 342 if (expression != null) { 343 annotationMethodDeclaration.defaultValue = expression; 344 } 345 } else { 346 hasDefaultValue = false; 348 } 349 } 350 } 351 if (hasDefaultValue) 352 modifiers |= ClassFileConstants.AccAnnotationDefault; 353 decl = annotationMethodDeclaration; 354 } else { 355 decl = new MethodDeclaration(compilationResult); 356 } 357 358 decl.returnType = createTypeReference(methodInfo.getReturnTypeName(), start, end); 360 361 decl.typeParameters = typeParams; 363 364 method = decl; 365 } 366 method.selector = methodHandle.getElementName().toCharArray(); 367 boolean isVarargs = (modifiers & ClassFileConstants.AccVarargs) != 0; 368 method.modifiers = modifiers & ~ClassFileConstants.AccVarargs; 369 method.sourceStart = start; 370 method.sourceEnd = end; 371 method.declarationSourceStart = methodInfo.getDeclarationSourceStart(); 372 method.declarationSourceEnd = methodInfo.getDeclarationSourceEnd(); 373 374 if (this.has1_5Compliance) { 376 377 method.annotations = convertAnnotations(methodHandle); 378 } 379 380 381 String [] argumentTypeSignatures = methodHandle.getParameterTypes(); 382 char[][] argumentNames = methodInfo.getArgumentNames(); 383 int argumentCount = argumentTypeSignatures == null ? 0 : argumentTypeSignatures.length; 384 if (argumentCount > 0) { 385 long position = ((long) start << 32) + end; 386 method.arguments = new Argument[argumentCount]; 387 for (int i = 0; i < argumentCount; i++) { 388 TypeReference typeReference = createTypeReference(argumentTypeSignatures[i], start, end); 389 if (isVarargs && i == argumentCount-1) { 390 typeReference.bits |= ASTNode.IsVarArgs; 391 } 392 method.arguments[i] = 393 new Argument( 394 argumentNames[i], 395 position, 396 typeReference, 397 ClassFileConstants.AccDefault); 398 } 400 } 401 402 403 char[][] exceptionTypeNames = methodInfo.getExceptionTypeNames(); 404 int exceptionCount = exceptionTypeNames == null ? 0 : exceptionTypeNames.length; 405 if (exceptionCount > 0) { 406 method.thrownExceptions = new TypeReference[exceptionCount]; 407 for (int i = 0; i < exceptionCount; i++) { 408 method.thrownExceptions[i] = 409 createTypeReference(exceptionTypeNames[i], start, end); 410 } 411 } 412 413 414 if ((this.flags & LOCAL_TYPE) != 0) { 415 IJavaElement[] children = methodInfo.getChildren(); 416 int typesLength = children.length; 417 if (typesLength != 0) { 418 Statement[] statements = new Statement[typesLength]; 419 for (int i = 0; i < typesLength; i++) { 420 SourceType type = (SourceType) children[i]; 421 TypeDeclaration localType = convert(type, compilationResult); 422 if ((localType.bits & ASTNode.IsAnonymousType) != 0) { 423 QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType); 424 expression.type = localType.superclass; 425 localType.superclass = null; 426 localType.superInterfaces = null; 427 localType.allocation = expression; 428 statements[i] = expression; 429 } else { 430 statements[i] = localType; 431 } 432 } 433 method.statements = statements; 434 } 435 } 436 437 return method; 438 } 439 440 443 private TypeDeclaration convert(SourceType typeHandle, CompilationResult compilationResult) throws JavaModelException { 444 SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) typeHandle.getElementInfo(); 445 if (typeInfo.isAnonymousMember()) 446 throw new AnonymousMemberFound(); 447 448 TypeDeclaration type = new TypeDeclaration(compilationResult); 449 if (typeInfo.getEnclosingType() == null) { 450 if (typeHandle.isAnonymous()) { 451 type.name = CharOperation.NO_CHAR; 452 type.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType); 453 } else { 454 if (typeHandle.isLocal()) { 455 type.bits |= ASTNode.IsLocalType; 456 } 457 } 458 } else { 459 type.bits |= ASTNode.IsMemberType; 460 } 461 if ((type.bits & ASTNode.IsAnonymousType) == 0) { 462 type.name = typeInfo.getName(); 463 } 464 type.name = typeInfo.getName(); 465 int start, end; type.sourceStart = start = typeInfo.getNameSourceStart(); 467 type.sourceEnd = end = typeInfo.getNameSourceEnd(); 468 type.modifiers = typeInfo.getModifiers(); 469 type.declarationSourceStart = typeInfo.getDeclarationSourceStart(); 470 type.declarationSourceEnd = typeInfo.getDeclarationSourceEnd(); 471 type.bodyEnd = type.declarationSourceEnd; 472 473 if (this.has1_5Compliance) { 475 476 type.annotations = convertAnnotations(typeHandle); 477 478 479 char[][] typeParameterNames = typeInfo.getTypeParameterNames(); 480 if (typeParameterNames.length > 0) { 481 int parameterCount = typeParameterNames.length; 482 char[][][] typeParameterBounds = typeInfo.getTypeParameterBounds(); 483 type.typeParameters = new TypeParameter[parameterCount]; 484 for (int i = 0; i < parameterCount; i++) { 485 type.typeParameters[i] = createTypeParameter(typeParameterNames[i], typeParameterBounds[i], start, end); 486 } 487 } 488 } 489 490 491 if (typeInfo.getSuperclassName() != null) { 492 type.superclass = createTypeReference(typeInfo.getSuperclassName(), start, end); 493 type.superclass.bits |= ASTNode.IsSuperType; 494 } 495 char[][] interfaceNames = typeInfo.getInterfaceNames(); 496 int interfaceCount = interfaceNames == null ? 0 : interfaceNames.length; 497 if (interfaceCount > 0) { 498 type.superInterfaces = new TypeReference[interfaceCount]; 499 for (int i = 0; i < interfaceCount; i++) { 500 type.superInterfaces[i] = createTypeReference(interfaceNames[i], start, end); 501 type.superInterfaces[i].bits |= ASTNode.IsSuperType; 502 } 503 } 504 505 if ((this.flags & MEMBER_TYPE) != 0) { 506 SourceType[] sourceMemberTypes = typeInfo.getMemberTypeHandles(); 507 int sourceMemberTypeCount = sourceMemberTypes.length; 508 type.memberTypes = new TypeDeclaration[sourceMemberTypeCount]; 509 for (int i = 0; i < sourceMemberTypeCount; i++) { 510 type.memberTypes[i] = convert(sourceMemberTypes[i], compilationResult); 511 } 512 } 513 514 515 InitializerElementInfo[] initializers = null; 516 int initializerCount = 0; 517 if ((this.flags & LOCAL_TYPE) != 0) { 518 initializers = typeInfo.getInitializers(); 519 initializerCount = initializers.length; 520 } 521 SourceField[] sourceFields = null; 522 int sourceFieldCount = 0; 523 if ((this.flags & FIELD) != 0) { 524 sourceFields = typeInfo.getFieldHandles(); 525 sourceFieldCount = sourceFields.length; 526 } 527 int length = initializerCount + sourceFieldCount; 528 if (length > 0) { 529 type.fields = new FieldDeclaration[length]; 530 for (int i = 0; i < initializerCount; i++) { 531 type.fields[i] = convert(initializers[i], compilationResult); 532 } 533 int index = 0; 534 for (int i = initializerCount; i < length; i++) { 535 type.fields[i] = convert(sourceFields[index++], type, compilationResult); 536 } 537 } 538 539 540 boolean needConstructor = (this.flags & CONSTRUCTOR) != 0; 541 boolean needMethod = (this.flags & METHOD) != 0; 542 if (needConstructor || needMethod) { 543 544 SourceMethod[] sourceMethods = typeInfo.getMethodHandles(); 545 int sourceMethodCount = sourceMethods.length; 546 547 548 549 int extraConstructor = 0; 550 int methodCount = 0; 551 int kind = TypeDeclaration.kind(type.modifiers); 552 boolean isAbstract = kind == TypeDeclaration.INTERFACE_DECL || kind == TypeDeclaration.ANNOTATION_TYPE_DECL; 553 if (!isAbstract) { 554 extraConstructor = needConstructor ? 1 : 0; 555 for (int i = 0; i < sourceMethodCount; i++) { 556 if (sourceMethods[i].isConstructor()) { 557 if (needConstructor) { 558 extraConstructor = 0; methodCount++; 560 } 561 } else if (needMethod) { 562 methodCount++; 563 } 564 } 565 } else { 566 methodCount = needMethod ? sourceMethodCount : 0; 567 } 568 type.methods = new AbstractMethodDeclaration[methodCount + extraConstructor]; 569 if (extraConstructor != 0) { type.methods[0] = type.createDefaultConstructor(false, false); 571 } 572 int index = 0; 573 boolean hasAbstractMethods = false; 574 for (int i = 0; i < sourceMethodCount; i++) { 575 SourceMethod sourceMethod = sourceMethods[i]; 576 SourceMethodElementInfo methodInfo = (SourceMethodElementInfo)sourceMethod.getElementInfo(); 577 boolean isConstructor = methodInfo.isConstructor(); 578 if ((methodInfo.getModifiers() & ClassFileConstants.AccAbstract) != 0) { 579 hasAbstractMethods = true; 580 } 581 if ((isConstructor && needConstructor) || (!isConstructor && needMethod)) { 582 AbstractMethodDeclaration method = convert(sourceMethod, methodInfo, compilationResult); 583 if (isAbstract || method.isAbstract()) { method.modifiers |= ExtraCompilerModifiers.AccSemicolonBody; 585 } 586 type.methods[extraConstructor + index++] = method; 587 } 588 } 589 if (hasAbstractMethods) type.bits |= ASTNode.HasAbstractMethods; 590 } 591 592 return type; 593 } 594 595 private Annotation[] convertAnnotations(JavaElement element) { 596 if (this.annotationPositions == null) return null; 597 char[] cuSource = getSource(); 598 long[] positions = (long[]) this.annotationPositions.get(element); 599 if (positions == null) return null; 600 int length = positions.length; 601 Annotation[] annotations = new Annotation[length]; 602 int recordedAnnotations = 0; 603 for (int i = 0; i < length; i++) { 604 long position = positions[i]; 605 int start = (int) (position >>> 32); 606 int end = (int) position; 607 char[] annotationSource = CharOperation.subarray(cuSource, start, end+1); 608 if (annotationSource != null) { 609 Expression expression = parseMemberValue(annotationSource); 610 616 if (expression instanceof Annotation) { 617 annotations[recordedAnnotations++] = (Annotation) expression; 618 } 619 } 620 } 621 if (length != recordedAnnotations) { 622 System.arraycopy(annotations, 0, (annotations = new Annotation[recordedAnnotations]), 0, recordedAnnotations); 624 } 625 return annotations; 626 } 627 628 631 private ImportReference createImportReference( 632 String [] importName, 633 int start, 634 int end, 635 boolean onDemand, 636 int modifiers) { 637 638 int length = importName.length; 639 long[] positions = new long[length]; 640 long position = ((long) start << 32) + end; 641 char[][] qImportName = new char[length][]; 642 for (int i = 0; i < length; i++) { 643 qImportName[i] = importName[i].toCharArray(); 644 positions[i] = position; } 646 return new ImportReference( 647 qImportName, 648 positions, 649 onDemand, 650 modifiers); 651 } 652 653 private TypeParameter createTypeParameter(char[] typeParameterName, char[][] typeParameterBounds, int start, int end) { 654 655 TypeParameter parameter = new TypeParameter(); 656 parameter.name = typeParameterName; 657 parameter.sourceStart = start; 658 parameter.sourceEnd = end; 659 if (typeParameterBounds != null) { 660 int length = typeParameterBounds.length; 661 if (length > 0) { 662 parameter.type = createTypeReference(typeParameterBounds[0], start, end); 663 if (length > 1) { 664 parameter.bounds = new TypeReference[length-1]; 665 for (int i = 1; i < length; i++) { 666 TypeReference bound = createTypeReference(typeParameterBounds[i], start, end); 667 bound.bits |= ASTNode.IsSuperType; 668 parameter.bounds[i-1] = bound; 669 } 670 } 671 } 672 } 673 return parameter; 674 } 675 676 679 private TypeReference createTypeReference( 680 char[] typeName, 681 int start, 682 int end) { 683 684 int length = typeName.length; 685 this.namePos = 0; 686 return decodeType(typeName, length, start, end); 687 } 688 689 692 private TypeReference createTypeReference( 693 String typeSignature, 694 int start, 695 int end) { 696 697 int length = typeSignature.length(); 698 this.namePos = 0; 699 return decodeType(typeSignature, length, start, end); 700 } 701 702 private TypeReference decodeType(String typeSignature, int length, int start, int end) { 703 int identCount = 1; 704 int dim = 0; 705 int nameFragmentStart = this.namePos, nameFragmentEnd = -1; 706 boolean nameStarted = false; 707 ArrayList fragments = null; 708 typeLoop: while (this.namePos < length) { 709 char currentChar = typeSignature.charAt(this.namePos); 710 switch (currentChar) { 711 case Signature.C_BOOLEAN : 712 if (!nameStarted) { 713 this.namePos++; 714 if (dim == 0) 715 return new SingleTypeReference(TypeBinding.BOOLEAN.simpleName, ((long) start << 32) + end); 716 else 717 return new ArrayTypeReference(TypeBinding.BOOLEAN.simpleName, dim, ((long) start << 32) + end); 718 } 719 break; 720 case Signature.C_BYTE : 721 if (!nameStarted) { 722 this.namePos++; 723 if (dim == 0) 724 return new SingleTypeReference(TypeBinding.BYTE.simpleName, ((long) start << 32) + end); 725 else 726 return new ArrayTypeReference(TypeBinding.BYTE.simpleName, dim, ((long) start << 32) + end); 727 } 728 break; 729 case Signature.C_CHAR : 730 if (!nameStarted) { 731 this.namePos++; 732 if (dim == 0) 733 return new SingleTypeReference(TypeBinding.CHAR.simpleName, ((long) start << 32) + end); 734 else 735 return new ArrayTypeReference(TypeBinding.CHAR.simpleName, dim, ((long) start << 32) + end); 736 } 737 break; 738 case Signature.C_DOUBLE : 739 if (!nameStarted) { 740 this.namePos++; 741 if (dim == 0) 742 return new SingleTypeReference(TypeBinding.DOUBLE.simpleName, ((long) start << 32) + end); 743 else 744 return new ArrayTypeReference(TypeBinding.DOUBLE.simpleName, dim, ((long) start << 32) + end); 745 } 746 break; 747 case Signature.C_FLOAT : 748 if (!nameStarted) { 749 this.namePos++; 750 if (dim == 0) 751 return new SingleTypeReference(TypeBinding.FLOAT.simpleName, ((long) start << 32) + end); 752 else 753 return new ArrayTypeReference(TypeBinding.FLOAT.simpleName, dim, ((long) start << 32) + end); 754 } 755 break; 756 case Signature.C_INT : 757 if (!nameStarted) { 758 this.namePos++; 759 if (dim == 0) 760 return new SingleTypeReference(TypeBinding.INT.simpleName, ((long) start << 32) + end); 761 else 762 return new ArrayTypeReference(TypeBinding.INT.simpleName, dim, ((long) start << 32) + end); 763 } 764 break; 765 case Signature.C_LONG : 766 if (!nameStarted) { 767 this.namePos++; 768 if (dim == 0) 769 return new SingleTypeReference(TypeBinding.LONG.simpleName, ((long) start << 32) + end); 770 else 771 return new ArrayTypeReference(TypeBinding.LONG.simpleName, dim, ((long) start << 32) + end); 772 } 773 break; 774 case Signature.C_SHORT : 775 if (!nameStarted) { 776 this.namePos++; 777 if (dim == 0) 778 return new SingleTypeReference(TypeBinding.SHORT.simpleName, ((long) start << 32) + end); 779 else 780 return new ArrayTypeReference(TypeBinding.SHORT.simpleName, dim, ((long) start << 32) + end); 781 } 782 break; 783 case Signature.C_VOID : 784 if (!nameStarted) { 785 this.namePos++; 786 new SingleTypeReference(TypeBinding.VOID.simpleName, ((long) start << 32) + end); 787 } 788 break; 789 case Signature.C_RESOLVED : 790 case Signature.C_UNRESOLVED : 791 if (!nameStarted) { 792 nameFragmentStart = this.namePos+1; 793 nameStarted = true; 794 } 795 break; 796 case Signature.C_STAR: 797 this.namePos++; 798 Wildcard result = new Wildcard(Wildcard.UNBOUND); 799 result.sourceStart = start; 800 result.sourceEnd = end; 801 return result; 802 case Signature.C_EXTENDS: 803 this.namePos++; 804 result = new Wildcard(Wildcard.EXTENDS); 805 result.bound = decodeType(typeSignature, length, start, end); 806 result.sourceStart = start; 807 result.sourceEnd = end; 808 return result; 809 case Signature.C_SUPER: 810 this.namePos++; 811 result = new Wildcard(Wildcard.SUPER); 812 result.bound = decodeType(typeSignature, length, start, end); 813 result.sourceStart = start; 814 result.sourceEnd = end; 815 return result; 816 case Signature.C_ARRAY : 817 dim++; 818 break; 819 case Signature.C_GENERIC_END : 820 case Signature.C_SEMICOLON : 821 nameFragmentEnd = this.namePos-1; 822 this.namePos++; 823 break typeLoop; 824 case Signature.C_DOT : 825 case Signature.C_DOLLAR: 826 if (!nameStarted) { 827 nameFragmentStart = this.namePos+1; 828 nameStarted = true; 829 } else if (this.namePos > nameFragmentStart) identCount ++; 831 break; 832 case Signature.C_GENERIC_START : 833 nameFragmentEnd = this.namePos-1; 834 if (!this.has1_5Compliance) 836 break typeLoop; 837 if (fragments == null) fragments = new ArrayList (2); 838 addIdentifiers(typeSignature, nameFragmentStart, nameFragmentEnd + 1, identCount, fragments); 839 this.namePos++; TypeReference[] arguments = decodeTypeArguments(typeSignature, length, start, end); fragments.add(arguments); 842 identCount = 1; 843 nameStarted = false; 844 break; 846 } 847 this.namePos++; 848 } 849 if (fragments == null) { 851 if (identCount == 1) { if (dim == 0) { 853 char[] nameFragment = new char[nameFragmentEnd - nameFragmentStart + 1]; 854 typeSignature.getChars(nameFragmentStart, nameFragmentEnd +1, nameFragment, 0); 855 return new SingleTypeReference(nameFragment, ((long) start << 32) + end); 856 } else { 857 char[] nameFragment = new char[nameFragmentEnd - nameFragmentStart + 1]; 858 typeSignature.getChars(nameFragmentStart, nameFragmentEnd +1, nameFragment, 0); 859 return new ArrayTypeReference(nameFragment, dim, ((long) start << 32) + end); 860 } 861 } else { long[] positions = new long[identCount]; 863 long pos = ((long) start << 32) + end; 864 for (int i = 0; i < identCount; i++) { 865 positions[i] = pos; 866 } 867 char[][] identifiers = extractIdentifiers(typeSignature, nameFragmentStart, nameFragmentEnd, identCount); 868 if (dim == 0) { 869 return new QualifiedTypeReference(identifiers, positions); 870 } else { 871 return new ArrayQualifiedTypeReference(identifiers, dim, positions); 872 } 873 } 874 } else { if (nameStarted) { 878 addIdentifiers(typeSignature, nameFragmentStart, nameFragmentEnd + 1, identCount, fragments); 879 } 880 int fragmentLength = fragments.size(); 881 if (fragmentLength == 2) { 882 Object firstFragment = fragments.get(0); 883 if (firstFragment instanceof char[]) { 884 return new ParameterizedSingleTypeReference((char[]) firstFragment, (TypeReference[]) fragments.get(1), dim, ((long) start << 32) + end); 886 } 887 } 888 identCount = 0; 890 for (int i = 0; i < fragmentLength; i ++) { 891 Object element = fragments.get(i); 892 if (element instanceof char[][]) { 893 identCount += ((char[][])element).length; 894 } else if (element instanceof char[]) 895 identCount++; 896 } 897 char[][] tokens = new char[identCount][]; 898 TypeReference[][] arguments = new TypeReference[identCount][]; 899 int index = 0; 900 for (int i = 0; i < fragmentLength; i ++) { 901 Object element = fragments.get(i); 902 if (element instanceof char[][]) { 903 char[][] fragmentTokens = (char[][]) element; 904 int fragmentTokenLength = fragmentTokens.length; 905 System.arraycopy(fragmentTokens, 0, tokens, index, fragmentTokenLength); 906 index += fragmentTokenLength; 907 } else if (element instanceof char[]) { 908 tokens[index++] = (char[]) element; 909 } else { 910 arguments[index-1] = (TypeReference[]) element; 911 } 912 } 913 long[] positions = new long[identCount]; 914 long pos = ((long) start << 32) + end; 915 for (int i = 0; i < identCount; i++) { 916 positions[i] = pos; 917 } 918 return new ParameterizedQualifiedTypeReference(tokens, arguments, dim, positions); 919 } 920 } 921 922 private TypeReference decodeType(char[] typeName, int length, int start, int end) { 923 int identCount = 1; 924 int dim = 0; 925 int nameFragmentStart = this.namePos, nameFragmentEnd = -1; 926 ArrayList fragments = null; 927 typeLoop: while (this.namePos < length) { 928 char currentChar = typeName[this.namePos]; 929 switch (currentChar) { 930 case '?' : 931 this.namePos++; while (typeName[this.namePos] == ' ') this.namePos++; 933 switch(typeName[this.namePos]) { 934 case 's' : 935 checkSuper: { 936 int max = TypeConstants.WILDCARD_SUPER.length-1; 937 for (int ahead = 1; ahead < max; ahead++) { 938 if (typeName[this.namePos+ahead] != TypeConstants.WILDCARD_SUPER[ahead+1]) { 939 break checkSuper; 940 } 941 } 942 this.namePos += max; 943 Wildcard result = new Wildcard(Wildcard.SUPER); 944 result.bound = decodeType(typeName, length, start, end); 945 result.sourceStart = start; 946 result.sourceEnd = end; 947 return result; 948 } 949 break; 950 case 'e' : 951 checkExtends: { 952 int max = TypeConstants.WILDCARD_EXTENDS.length-1; 953 for (int ahead = 1; ahead < max; ahead++) { 954 if (typeName[this.namePos+ahead] != TypeConstants.WILDCARD_EXTENDS[ahead+1]) { 955 break checkExtends; 956 } 957 } 958 this.namePos += max; 959 Wildcard result = new Wildcard(Wildcard.EXTENDS); 960 result.bound = decodeType(typeName, length, start, end); 961 result.sourceStart = start; 962 result.sourceEnd = end; 963 return result; 964 } 965 break; 966 } 967 Wildcard result = new Wildcard(Wildcard.UNBOUND); 968 result.sourceStart = start; 969 result.sourceEnd = end; 970 return result; 971 case '[' : 972 if (dim == 0) nameFragmentEnd = this.namePos-1; 973 dim++; 974 break; 975 case ']' : 976 break; 977 case '>' : 978 case ',' : 979 break typeLoop; 980 case '.' : 981 if (nameFragmentStart < 0) nameFragmentStart = this.namePos+1; identCount ++; 983 break; 984 case '<' : 985 if (!this.has1_5Compliance) 987 break typeLoop; 988 if (fragments == null) fragments = new ArrayList (2); 989 nameFragmentEnd = this.namePos-1; 990 char[][] identifiers = CharOperation.splitOn('.', typeName, nameFragmentStart, this.namePos); 991 fragments.add(identifiers); 992 this.namePos++; TypeReference[] arguments = decodeTypeArguments(typeName, length, start, end); fragments.add(arguments); 995 identCount = 0; 996 nameFragmentStart = -1; 997 nameFragmentEnd = -1; 998 break; 1000 } 1001 this.namePos++; 1002 } 1003 if (nameFragmentEnd < 0) nameFragmentEnd = this.namePos-1; 1004 if (fragments == null) { 1006 if (identCount == 1) { if (dim == 0) { 1008 char[] nameFragment; 1009 if (nameFragmentStart != 0 || nameFragmentEnd >= 0) { 1010 int nameFragmentLength = nameFragmentEnd - nameFragmentStart + 1; 1011 System.arraycopy(typeName, nameFragmentStart, nameFragment = new char[nameFragmentLength], 0, nameFragmentLength); 1012 } else { 1013 nameFragment = typeName; 1014 } 1015 return new SingleTypeReference(nameFragment, ((long) start << 32) + end); 1016 } else { 1017 int nameFragmentLength = nameFragmentEnd - nameFragmentStart + 1; 1018 char[] nameFragment = new char[nameFragmentLength]; 1019 System.arraycopy(typeName, nameFragmentStart, nameFragment, 0, nameFragmentLength); 1020 return new ArrayTypeReference(nameFragment, dim, ((long) start << 32) + end); 1021 } 1022 } else { long[] positions = new long[identCount]; 1024 long pos = ((long) start << 32) + end; 1025 for (int i = 0; i < identCount; i++) { 1026 positions[i] = pos; 1027 } 1028 char[][] identifiers = CharOperation.splitOn('.', typeName, nameFragmentStart, nameFragmentEnd+1); 1029 if (dim == 0) { 1030 return new QualifiedTypeReference(identifiers, positions); 1031 } else { 1032 return new ArrayQualifiedTypeReference(identifiers, dim, positions); 1033 } 1034 } 1035 } else { if (nameFragmentStart > 0 && nameFragmentStart < length) { 1039 char[][] identifiers = CharOperation.splitOn('.', typeName, nameFragmentStart, nameFragmentEnd+1); 1040 fragments.add(identifiers); 1041 } 1042 int fragmentLength = fragments.size(); 1043 if (fragmentLength == 2) { 1044 char[][] firstFragment = (char[][]) fragments.get(0); 1045 if (firstFragment.length == 1) { 1046 return new ParameterizedSingleTypeReference(firstFragment[0], (TypeReference[]) fragments.get(1), dim, ((long) start << 32) + end); 1048 } 1049 } 1050 identCount = 0; 1052 for (int i = 0; i < fragmentLength; i ++) { 1053 Object element = fragments.get(i); 1054 if (element instanceof char[][]) { 1055 identCount += ((char[][])element).length; 1056 } 1057 } 1058 char[][] tokens = new char[identCount][]; 1059 TypeReference[][] arguments = new TypeReference[identCount][]; 1060 int index = 0; 1061 for (int i = 0; i < fragmentLength; i ++) { 1062 Object element = fragments.get(i); 1063 if (element instanceof char[][]) { 1064 char[][] fragmentTokens = (char[][]) element; 1065 int fragmentTokenLength = fragmentTokens.length; 1066 System.arraycopy(fragmentTokens, 0, tokens, index, fragmentTokenLength); 1067 index += fragmentTokenLength; 1068 } else { 1069 arguments[index-1] = (TypeReference[]) element; 1070 } 1071 } 1072 long[] positions = new long[identCount]; 1073 long pos = ((long) start << 32) + end; 1074 for (int i = 0; i < identCount; i++) { 1075 positions[i] = pos; 1076 } 1077 return new ParameterizedQualifiedTypeReference(tokens, arguments, dim, positions); 1078 } 1079 } 1080 1081 private TypeReference[] decodeTypeArguments(char[] typeName, int length, int start, int end) { 1082 ArrayList argumentList = new ArrayList (1); 1083 int count = 0; 1084 argumentsLoop: while (this.namePos < length) { 1085 TypeReference argument = decodeType(typeName, length, start, end); 1086 count++; 1087 argumentList.add(argument); 1088 if (this.namePos >= length) break argumentsLoop; 1089 if (typeName[this.namePos] == '>') { 1090 break argumentsLoop; 1091 } 1092 this.namePos++; } 1094 TypeReference[] typeArguments = new TypeReference[count]; 1095 argumentList.toArray(typeArguments); 1096 return typeArguments; 1097 } 1098 1099 private TypeReference[] decodeTypeArguments(String typeSignature, int length, int start, int end) { 1100 ArrayList argumentList = new ArrayList (1); 1101 int count = 0; 1102 argumentsLoop: while (this.namePos < length) { 1103 TypeReference argument = decodeType(typeSignature, length, start, end); 1104 count++; 1105 argumentList.add(argument); 1106 if (this.namePos >= length) break argumentsLoop; 1107 if (typeSignature.charAt(this.namePos) == '>') { 1108 break argumentsLoop; 1109 } 1110 } 1111 TypeReference[] typeArguments = new TypeReference[count]; 1112 argumentList.toArray(typeArguments); 1113 return typeArguments; 1114 } 1115 1116 private char[][] extractIdentifiers(String typeSignature, int start, int endInclusive, int identCount) { 1117 char[][] result = new char[identCount][]; 1118 int charIndex = start; 1119 int i = 0; 1120 while (charIndex < endInclusive) { 1121 if (typeSignature.charAt(charIndex) == '.') { 1122 typeSignature.getChars(start, charIndex, result[i++] = new char[charIndex - start], 0); 1123 start = ++charIndex; 1124 } else 1125 charIndex++; 1126 } 1127 typeSignature.getChars(start, charIndex + 1, result[i++] = new char[charIndex - start + 1], 0); 1128 return result; 1129 } 1130 1131 private char[] getSource() { 1132 if (this.source == null) 1133 this.source = this.cu.getContents(); 1134 return this.source; 1135 } 1136 1137 private Expression parseMemberValue(char[] memberValue) { 1138 if (this.parser == null) { 1140 this.parser = new Parser(this.problemReporter, true); 1141 } 1142 return this.parser.parseMemberValue(memberValue, 0, memberValue.length, this.unit); 1143 } 1144} 1145 | Popular Tags |