0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.parser;
0011:
0012: /**
0013: * Converter from source element type to parsed compilation unit.
0014: *
0015: * Limitation:
0016: * | The source element field does not carry any information for its constant part, thus
0017: * | the converted parse tree will not include any field initializations.
0018: * | Therefore, any binary produced by compiling against converted source elements will
0019: * | not take advantage of remote field constant inlining.
0020: * | Given the intended purpose of the conversion is to resolve references, this is not
0021: * | a problem.
0022: *
0023: */
0024:
0025: import java.util.ArrayList;
0026: import java.util.HashMap;
0027:
0028: import org.eclipse.jdt.core.IImportDeclaration;
0029: import org.eclipse.jdt.core.IJavaElement;
0030: import org.eclipse.jdt.core.JavaModelException;
0031: import org.eclipse.jdt.core.Signature;
0032: import org.eclipse.jdt.core.compiler.CharOperation;
0033: import org.eclipse.jdt.internal.compiler.CompilationResult;
0034: import org.eclipse.jdt.internal.compiler.ast.*;
0035: import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
0036: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
0037: import org.eclipse.jdt.internal.compiler.env.*;
0038:
0039: import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
0040: import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
0041: import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
0042: import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
0043: import org.eclipse.jdt.internal.core.*;
0044: import org.eclipse.jdt.internal.core.util.Util;
0045:
0046: public class SourceTypeConverter {
0047:
0048: /*
0049: * Exception thrown while converting an anonymous type of a member type
0050: * in this case, we must parse the source as the enclosing instance cannot be recreated
0051: * from the model
0052: */
0053: static class AnonymousMemberFound extends RuntimeException {
0054: private static final long serialVersionUID = 1L;
0055: }
0056:
0057: public static final int FIELD = 0x01;
0058: public static final int CONSTRUCTOR = 0x02;
0059: public static final int METHOD = 0x04;
0060: public static final int MEMBER_TYPE = 0x08;
0061: public static final int FIELD_INITIALIZATION = 0x10;
0062: public static final int FIELD_AND_METHOD = FIELD | CONSTRUCTOR
0063: | METHOD;
0064: public static final int LOCAL_TYPE = 0x20;
0065: public static final int NONE = 0;
0066:
0067: private int flags;
0068: private CompilationUnitDeclaration unit;
0069: private Parser parser;
0070: private ProblemReporter problemReporter;
0071: private ICompilationUnit cu;
0072: private char[] source;
0073: private HashMap annotationPositions;
0074: private boolean has1_5Compliance;
0075:
0076: int namePos;
0077:
0078: private SourceTypeConverter(int flags,
0079: ProblemReporter problemReporter) {
0080: this .flags = flags;
0081: this .problemReporter = problemReporter;
0082: this .has1_5Compliance = problemReporter.options.complianceLevel >= ClassFileConstants.JDK1_5;
0083: }
0084:
0085: /*
0086: * Convert a set of source element types into a parsed compilation unit declaration
0087: * The argument types are then all grouped in the same unit. The argument types must
0088: * at least contain one type.
0089: * Can optionally ignore fields & methods or member types or field initialization
0090: */
0091: public static CompilationUnitDeclaration buildCompilationUnit(
0092: ISourceType[] sourceTypes, int flags,
0093: ProblemReporter problemReporter,
0094: CompilationResult compilationResult) {
0095:
0096: // long start = System.currentTimeMillis();
0097: SourceTypeConverter converter = new SourceTypeConverter(flags,
0098: problemReporter);
0099: try {
0100: return converter.convert(sourceTypes, compilationResult);
0101: } catch (JavaModelException e) {
0102: return null;
0103: /* } finally {
0104: System.out.println("Spent " + (System.currentTimeMillis() - start) + "ms to convert " + ((JavaElement) converter.cu).toStringWithAncestors());
0105: */}
0106: }
0107:
0108: /*
0109: * Convert a set of source element types into a parsed compilation unit declaration
0110: * The argument types are then all grouped in the same unit. The argument types must
0111: * at least contain one type.
0112: */
0113: private CompilationUnitDeclaration convert(
0114: ISourceType[] sourceTypes,
0115: CompilationResult compilationResult)
0116: throws JavaModelException {
0117: this .unit = new CompilationUnitDeclaration(
0118: this .problemReporter, compilationResult, 0);
0119: // not filled at this point
0120:
0121: if (sourceTypes.length == 0)
0122: return this .unit;
0123: SourceTypeElementInfo topLevelTypeInfo = (SourceTypeElementInfo) sourceTypes[0];
0124: org.eclipse.jdt.core.ICompilationUnit cuHandle = topLevelTypeInfo
0125: .getHandle().getCompilationUnit();
0126: this .cu = (ICompilationUnit) cuHandle;
0127: this .annotationPositions = ((CompilationUnitElementInfo) ((JavaElement) this .cu)
0128: .getElementInfo()).annotationPositions;
0129:
0130: if (this .has1_5Compliance && this .annotationPositions != null
0131: && this .annotationPositions.size() > 10) { // experimental value
0132: // if more than 10 annotations, diet parse as this is faster
0133: return new Parser(this .problemReporter, true).dietParse(
0134: this .cu, compilationResult);
0135: }
0136:
0137: /* only positions available */
0138: int start = topLevelTypeInfo.getNameSourceStart();
0139: int end = topLevelTypeInfo.getNameSourceEnd();
0140:
0141: /* convert package and imports */
0142: String[] packageName = ((PackageFragment) cuHandle.getParent()).names;
0143: if (packageName.length > 0)
0144: // if its null then it is defined in the default package
0145: this .unit.currentPackage = createImportReference(
0146: packageName, start, end, false,
0147: ClassFileConstants.AccDefault);
0148: IImportDeclaration[] importDeclarations = topLevelTypeInfo
0149: .getHandle().getCompilationUnit().getImports();
0150: int importCount = importDeclarations.length;
0151: this .unit.imports = new ImportReference[importCount];
0152: for (int i = 0; i < importCount; i++) {
0153: ImportDeclaration importDeclaration = (ImportDeclaration) importDeclarations[i];
0154: ISourceImport sourceImport = (ISourceImport) importDeclaration
0155: .getElementInfo();
0156: String nameWithoutStar = importDeclaration
0157: .getNameWithoutStar();
0158: this .unit.imports[i] = createImportReference(Util.splitOn(
0159: '.', nameWithoutStar, 0, nameWithoutStar.length()),
0160: sourceImport.getDeclarationSourceStart(),
0161: sourceImport.getDeclarationSourceEnd(),
0162: importDeclaration.isOnDemand(), sourceImport
0163: .getModifiers());
0164: }
0165: /* convert type(s) */
0166: try {
0167: int typeCount = sourceTypes.length;
0168: final TypeDeclaration[] types = new TypeDeclaration[typeCount];
0169: /*
0170: * We used a temporary types collection to prevent this.unit.types from being null during a call to
0171: * convert(...) when the source is syntactically incorrect and the parser is flushing the unit's types.
0172: * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=97466
0173: */
0174: for (int i = 0; i < typeCount; i++) {
0175: SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) sourceTypes[i];
0176: types[i] = convert((SourceType) typeInfo.getHandle(),
0177: compilationResult);
0178: }
0179: this .unit.types = types;
0180: return this .unit;
0181: } catch (AnonymousMemberFound e) {
0182: return new Parser(this .problemReporter, true).parse(
0183: this .cu, compilationResult);
0184: }
0185: }
0186:
0187: private void addIdentifiers(String typeSignature, int start,
0188: int endExclusive, int identCount, ArrayList fragments) {
0189: if (identCount == 1) {
0190: char[] identifier;
0191: typeSignature.getChars(start, endExclusive,
0192: identifier = new char[endExclusive - start], 0);
0193: fragments.add(identifier);
0194: } else
0195: fragments.add(extractIdentifiers(typeSignature, start,
0196: endExclusive - 1, identCount));
0197: }
0198:
0199: /*
0200: * Convert an initializerinfo into a parsed initializer declaration
0201: */
0202: private Initializer convert(InitializerElementInfo initializerInfo,
0203: CompilationResult compilationResult)
0204: throws JavaModelException {
0205:
0206: Block block = new Block(0);
0207: Initializer initializer = new Initializer(block,
0208: ClassFileConstants.AccDefault);
0209:
0210: int start = initializerInfo.getDeclarationSourceStart();
0211: int end = initializerInfo.getDeclarationSourceEnd();
0212:
0213: initializer.sourceStart = initializer.declarationSourceStart = start;
0214: initializer.sourceEnd = initializer.declarationSourceEnd = end;
0215: initializer.modifiers = initializerInfo.getModifiers();
0216:
0217: /* convert local and anonymous types */
0218: IJavaElement[] children = initializerInfo.getChildren();
0219: int typesLength = children.length;
0220: if (typesLength > 0) {
0221: Statement[] statements = new Statement[typesLength];
0222: for (int i = 0; i < typesLength; i++) {
0223: SourceType type = (SourceType) children[i];
0224: TypeDeclaration localType = convert(type,
0225: compilationResult);
0226: if ((localType.bits & ASTNode.IsAnonymousType) != 0) {
0227: QualifiedAllocationExpression expression = new QualifiedAllocationExpression(
0228: localType);
0229: expression.type = localType.super class;
0230: localType.super class = null;
0231: localType.super Interfaces = null;
0232: localType.allocation = expression;
0233: statements[i] = expression;
0234: } else {
0235: statements[i] = localType;
0236: }
0237: }
0238: block.statements = statements;
0239: }
0240:
0241: return initializer;
0242: }
0243:
0244: /*
0245: * Convert a field source element into a parsed field declaration
0246: */
0247: private FieldDeclaration convert(SourceField fieldHandle,
0248: TypeDeclaration type, CompilationResult compilationResult)
0249: throws JavaModelException {
0250:
0251: SourceFieldElementInfo fieldInfo = (SourceFieldElementInfo) fieldHandle
0252: .getElementInfo();
0253: FieldDeclaration field = new FieldDeclaration();
0254:
0255: int start = fieldInfo.getNameSourceStart();
0256: int end = fieldInfo.getNameSourceEnd();
0257:
0258: field.name = fieldHandle.getElementName().toCharArray();
0259: field.sourceStart = start;
0260: field.sourceEnd = end;
0261: field.declarationSourceStart = fieldInfo
0262: .getDeclarationSourceStart();
0263: field.declarationSourceEnd = fieldInfo
0264: .getDeclarationSourceEnd();
0265: int modifiers = fieldInfo.getModifiers();
0266: boolean isEnumConstant = (modifiers & ClassFileConstants.AccEnum) != 0;
0267: if (isEnumConstant) {
0268: field.modifiers = modifiers & ~ClassFileConstants.AccEnum; // clear AccEnum bit onto AST (binding will add it)
0269: } else {
0270: field.modifiers = modifiers;
0271: field.type = createTypeReference(fieldInfo.getTypeName(),
0272: start, end);
0273: }
0274:
0275: // convert 1.5 specific constructs only if compliance is 1.5 or above
0276: if (this .has1_5Compliance) {
0277: /* convert annotations */
0278: field.annotations = convertAnnotations(fieldHandle);
0279: }
0280:
0281: /* conversion of field constant */
0282: if ((this .flags & FIELD_INITIALIZATION) != 0) {
0283: char[] initializationSource = fieldInfo
0284: .getInitializationSource();
0285: if (initializationSource != null) {
0286: if (this .parser == null) {
0287: this .parser = new Parser(this .problemReporter, true);
0288: }
0289: this .parser.parse(field, type, this .unit,
0290: initializationSource);
0291: }
0292: }
0293:
0294: /* conversion of local and anonymous types */
0295: if ((this .flags & LOCAL_TYPE) != 0) {
0296: IJavaElement[] children = fieldInfo.getChildren();
0297: int childrenLength = children.length;
0298: if (childrenLength == 1) {
0299: field.initialization = convert(children[0],
0300: isEnumConstant ? field : null,
0301: compilationResult);
0302: } else if (childrenLength > 1) {
0303: ArrayInitializer initializer = new ArrayInitializer();
0304: field.initialization = initializer;
0305: Expression[] expressions = new Expression[childrenLength];
0306: initializer.expressions = expressions;
0307: for (int i = 0; i < childrenLength; i++) {
0308: expressions[i] = convert(children[i],
0309: isEnumConstant ? field : null,
0310: compilationResult);
0311: }
0312: }
0313: }
0314: return field;
0315: }
0316:
0317: private QualifiedAllocationExpression convert(
0318: IJavaElement localType, FieldDeclaration enumConstant,
0319: CompilationResult compilationResult)
0320: throws JavaModelException {
0321: TypeDeclaration anonymousLocalTypeDeclaration = convert(
0322: (SourceType) localType, compilationResult);
0323: QualifiedAllocationExpression expression = new QualifiedAllocationExpression(
0324: anonymousLocalTypeDeclaration);
0325: expression.type = anonymousLocalTypeDeclaration.super class;
0326: anonymousLocalTypeDeclaration.super class = null;
0327: anonymousLocalTypeDeclaration.super Interfaces = null;
0328: anonymousLocalTypeDeclaration.allocation = expression;
0329: if (enumConstant != null) {
0330: anonymousLocalTypeDeclaration.modifiers &= ~ClassFileConstants.AccEnum;
0331: expression.enumConstant = enumConstant;
0332: expression.type = null;
0333: }
0334: return expression;
0335: }
0336:
0337: /*
0338: * Convert a method source element into a parsed method/constructor declaration
0339: */
0340: private AbstractMethodDeclaration convert(
0341: SourceMethod methodHandle,
0342: SourceMethodElementInfo methodInfo,
0343: CompilationResult compilationResult)
0344: throws JavaModelException {
0345: AbstractMethodDeclaration method;
0346:
0347: /* only source positions available */
0348: int start = methodInfo.getNameSourceStart();
0349: int end = methodInfo.getNameSourceEnd();
0350:
0351: // convert 1.5 specific constructs only if compliance is 1.5 or above
0352: TypeParameter[] typeParams = null;
0353: if (this .has1_5Compliance) {
0354: /* convert type parameters */
0355: char[][] typeParameterNames = methodInfo
0356: .getTypeParameterNames();
0357: if (typeParameterNames != null) {
0358: int parameterCount = typeParameterNames.length;
0359: if (parameterCount > 0) { // method's type parameters must be null if no type parameter
0360: char[][][] typeParameterBounds = methodInfo
0361: .getTypeParameterBounds();
0362: typeParams = new TypeParameter[parameterCount];
0363: for (int i = 0; i < parameterCount; i++) {
0364: typeParams[i] = createTypeParameter(
0365: typeParameterNames[i],
0366: typeParameterBounds[i], start, end);
0367: }
0368: }
0369: }
0370: }
0371:
0372: int modifiers = methodInfo.getModifiers();
0373: if (methodInfo.isConstructor()) {
0374: ConstructorDeclaration decl = new ConstructorDeclaration(
0375: compilationResult);
0376: decl.bits &= ~ASTNode.IsDefaultConstructor;
0377: method = decl;
0378: decl.typeParameters = typeParams;
0379: } else {
0380: MethodDeclaration decl;
0381: if (methodInfo.isAnnotationMethod()) {
0382: AnnotationMethodDeclaration annotationMethodDeclaration = new AnnotationMethodDeclaration(
0383: compilationResult);
0384:
0385: /* conversion of default value */
0386: SourceAnnotationMethodInfo annotationMethodInfo = (SourceAnnotationMethodInfo) methodInfo;
0387: boolean hasDefaultValue = annotationMethodInfo.defaultValueStart != -1
0388: || annotationMethodInfo.defaultValueEnd != -1;
0389: if ((this .flags & FIELD_INITIALIZATION) != 0) {
0390: if (hasDefaultValue) {
0391: char[] defaultValueSource = CharOperation
0392: .subarray(
0393: getSource(),
0394: annotationMethodInfo.defaultValueStart,
0395: annotationMethodInfo.defaultValueEnd + 1);
0396: if (defaultValueSource != null) {
0397: Expression expression = parseMemberValue(defaultValueSource);
0398: if (expression != null) {
0399: annotationMethodDeclaration.defaultValue = expression;
0400: }
0401: } else {
0402: // could not retrieve the default value
0403: hasDefaultValue = false;
0404: }
0405: }
0406: }
0407: if (hasDefaultValue)
0408: modifiers |= ClassFileConstants.AccAnnotationDefault;
0409: decl = annotationMethodDeclaration;
0410: } else {
0411: decl = new MethodDeclaration(compilationResult);
0412: }
0413:
0414: // convert return type
0415: decl.returnType = createTypeReference(methodInfo
0416: .getReturnTypeName(), start, end);
0417:
0418: // type parameters
0419: decl.typeParameters = typeParams;
0420:
0421: method = decl;
0422: }
0423: method.selector = methodHandle.getElementName().toCharArray();
0424: boolean isVarargs = (modifiers & ClassFileConstants.AccVarargs) != 0;
0425: method.modifiers = modifiers & ~ClassFileConstants.AccVarargs;
0426: method.sourceStart = start;
0427: method.sourceEnd = end;
0428: method.declarationSourceStart = methodInfo
0429: .getDeclarationSourceStart();
0430: method.declarationSourceEnd = methodInfo
0431: .getDeclarationSourceEnd();
0432:
0433: // convert 1.5 specific constructs only if compliance is 1.5 or above
0434: if (this .has1_5Compliance) {
0435: /* convert annotations */
0436: method.annotations = convertAnnotations(methodHandle);
0437: }
0438:
0439: /* convert arguments */
0440: String[] argumentTypeSignatures = methodHandle
0441: .getParameterTypes();
0442: char[][] argumentNames = methodInfo.getArgumentNames();
0443: int argumentCount = argumentTypeSignatures == null ? 0
0444: : argumentTypeSignatures.length;
0445: if (argumentCount > 0) {
0446: long position = ((long) start << 32) + end;
0447: method.arguments = new Argument[argumentCount];
0448: for (int i = 0; i < argumentCount; i++) {
0449: TypeReference typeReference = createTypeReference(
0450: argumentTypeSignatures[i], start, end);
0451: if (isVarargs && i == argumentCount - 1) {
0452: typeReference.bits |= ASTNode.IsVarArgs;
0453: }
0454: method.arguments[i] = new Argument(argumentNames[i],
0455: position, typeReference,
0456: ClassFileConstants.AccDefault);
0457: // do not care whether was final or not
0458: }
0459: }
0460:
0461: /* convert thrown exceptions */
0462: char[][] exceptionTypeNames = methodInfo
0463: .getExceptionTypeNames();
0464: int exceptionCount = exceptionTypeNames == null ? 0
0465: : exceptionTypeNames.length;
0466: if (exceptionCount > 0) {
0467: method.thrownExceptions = new TypeReference[exceptionCount];
0468: for (int i = 0; i < exceptionCount; i++) {
0469: method.thrownExceptions[i] = createTypeReference(
0470: exceptionTypeNames[i], start, end);
0471: }
0472: }
0473:
0474: /* convert local and anonymous types */
0475: if ((this .flags & LOCAL_TYPE) != 0) {
0476: IJavaElement[] children = methodInfo.getChildren();
0477: int typesLength = children.length;
0478: if (typesLength != 0) {
0479: Statement[] statements = new Statement[typesLength];
0480: for (int i = 0; i < typesLength; i++) {
0481: SourceType type = (SourceType) children[i];
0482: TypeDeclaration localType = convert(type,
0483: compilationResult);
0484: if ((localType.bits & ASTNode.IsAnonymousType) != 0) {
0485: QualifiedAllocationExpression expression = new QualifiedAllocationExpression(
0486: localType);
0487: expression.type = localType.super class;
0488: localType.super class = null;
0489: localType.super Interfaces = null;
0490: localType.allocation = expression;
0491: statements[i] = expression;
0492: } else {
0493: statements[i] = localType;
0494: }
0495: }
0496: method.statements = statements;
0497: }
0498: }
0499:
0500: return method;
0501: }
0502:
0503: /*
0504: * Convert a source element type into a parsed type declaration
0505: */
0506: private TypeDeclaration convert(SourceType typeHandle,
0507: CompilationResult compilationResult)
0508: throws JavaModelException {
0509: SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) typeHandle
0510: .getElementInfo();
0511: if (typeInfo.isAnonymousMember())
0512: throw new AnonymousMemberFound();
0513: /* create type declaration - can be member type */
0514: TypeDeclaration type = new TypeDeclaration(compilationResult);
0515: if (typeInfo.getEnclosingType() == null) {
0516: if (typeHandle.isAnonymous()) {
0517: type.name = CharOperation.NO_CHAR;
0518: type.bits |= (ASTNode.IsAnonymousType | ASTNode.IsLocalType);
0519: } else {
0520: if (typeHandle.isLocal()) {
0521: type.bits |= ASTNode.IsLocalType;
0522: }
0523: }
0524: } else {
0525: type.bits |= ASTNode.IsMemberType;
0526: }
0527: if ((type.bits & ASTNode.IsAnonymousType) == 0) {
0528: type.name = typeInfo.getName();
0529: }
0530: type.name = typeInfo.getName();
0531: int start, end; // only positions available
0532: type.sourceStart = start = typeInfo.getNameSourceStart();
0533: type.sourceEnd = end = typeInfo.getNameSourceEnd();
0534: type.modifiers = typeInfo.getModifiers();
0535: type.declarationSourceStart = typeInfo
0536: .getDeclarationSourceStart();
0537: type.declarationSourceEnd = typeInfo.getDeclarationSourceEnd();
0538: type.bodyEnd = type.declarationSourceEnd;
0539:
0540: // convert 1.5 specific constructs only if compliance is 1.5 or above
0541: if (this .has1_5Compliance) {
0542: /* convert annotations */
0543: type.annotations = convertAnnotations(typeHandle);
0544:
0545: /* convert type parameters */
0546: char[][] typeParameterNames = typeInfo
0547: .getTypeParameterNames();
0548: if (typeParameterNames.length > 0) {
0549: int parameterCount = typeParameterNames.length;
0550: char[][][] typeParameterBounds = typeInfo
0551: .getTypeParameterBounds();
0552: type.typeParameters = new TypeParameter[parameterCount];
0553: for (int i = 0; i < parameterCount; i++) {
0554: type.typeParameters[i] = createTypeParameter(
0555: typeParameterNames[i],
0556: typeParameterBounds[i], start, end);
0557: }
0558: }
0559: }
0560:
0561: /* set superclass and superinterfaces */
0562: if (typeInfo.getSuperclassName() != null) {
0563: type.super class = createTypeReference(typeInfo
0564: .getSuperclassName(), start, end);
0565: type.super class.bits |= ASTNode.IsSuperType;
0566: }
0567: char[][] interfaceNames = typeInfo.getInterfaceNames();
0568: int interfaceCount = interfaceNames == null ? 0
0569: : interfaceNames.length;
0570: if (interfaceCount > 0) {
0571: type.super Interfaces = new TypeReference[interfaceCount];
0572: for (int i = 0; i < interfaceCount; i++) {
0573: type.super Interfaces[i] = createTypeReference(
0574: interfaceNames[i], start, end);
0575: type.super Interfaces[i].bits |= ASTNode.IsSuperType;
0576: }
0577: }
0578: /* convert member types */
0579: if ((this .flags & MEMBER_TYPE) != 0) {
0580: SourceType[] sourceMemberTypes = typeInfo
0581: .getMemberTypeHandles();
0582: int sourceMemberTypeCount = sourceMemberTypes.length;
0583: type.memberTypes = new TypeDeclaration[sourceMemberTypeCount];
0584: for (int i = 0; i < sourceMemberTypeCount; i++) {
0585: type.memberTypes[i] = convert(sourceMemberTypes[i],
0586: compilationResult);
0587: }
0588: }
0589:
0590: /* convert intializers and fields*/
0591: InitializerElementInfo[] initializers = null;
0592: int initializerCount = 0;
0593: if ((this .flags & LOCAL_TYPE) != 0) {
0594: initializers = typeInfo.getInitializers();
0595: initializerCount = initializers.length;
0596: }
0597: SourceField[] sourceFields = null;
0598: int sourceFieldCount = 0;
0599: if ((this .flags & FIELD) != 0) {
0600: sourceFields = typeInfo.getFieldHandles();
0601: sourceFieldCount = sourceFields.length;
0602: }
0603: int length = initializerCount + sourceFieldCount;
0604: if (length > 0) {
0605: type.fields = new FieldDeclaration[length];
0606: for (int i = 0; i < initializerCount; i++) {
0607: type.fields[i] = convert(initializers[i],
0608: compilationResult);
0609: }
0610: int index = 0;
0611: for (int i = initializerCount; i < length; i++) {
0612: type.fields[i] = convert(sourceFields[index++], type,
0613: compilationResult);
0614: }
0615: }
0616:
0617: /* convert methods - need to add default constructor if necessary */
0618: boolean needConstructor = (this .flags & CONSTRUCTOR) != 0;
0619: boolean needMethod = (this .flags & METHOD) != 0;
0620: if (needConstructor || needMethod) {
0621:
0622: SourceMethod[] sourceMethods = typeInfo.getMethodHandles();
0623: int sourceMethodCount = sourceMethods.length;
0624:
0625: /* source type has a constructor ? */
0626: /* by default, we assume that one is needed. */
0627: int extraConstructor = 0;
0628: int methodCount = 0;
0629: int kind = TypeDeclaration.kind(type.modifiers);
0630: boolean isAbstract = kind == TypeDeclaration.INTERFACE_DECL
0631: || kind == TypeDeclaration.ANNOTATION_TYPE_DECL;
0632: if (!isAbstract) {
0633: extraConstructor = needConstructor ? 1 : 0;
0634: for (int i = 0; i < sourceMethodCount; i++) {
0635: if (sourceMethods[i].isConstructor()) {
0636: if (needConstructor) {
0637: extraConstructor = 0; // Does not need the extra constructor since one constructor already exists.
0638: methodCount++;
0639: }
0640: } else if (needMethod) {
0641: methodCount++;
0642: }
0643: }
0644: } else {
0645: methodCount = needMethod ? sourceMethodCount : 0;
0646: }
0647: type.methods = new AbstractMethodDeclaration[methodCount
0648: + extraConstructor];
0649: if (extraConstructor != 0) { // add default constructor in first position
0650: type.methods[0] = type.createDefaultConstructor(false,
0651: false);
0652: }
0653: int index = 0;
0654: boolean hasAbstractMethods = false;
0655: for (int i = 0; i < sourceMethodCount; i++) {
0656: SourceMethod sourceMethod = sourceMethods[i];
0657: SourceMethodElementInfo methodInfo = (SourceMethodElementInfo) sourceMethod
0658: .getElementInfo();
0659: boolean isConstructor = methodInfo.isConstructor();
0660: if ((methodInfo.getModifiers() & ClassFileConstants.AccAbstract) != 0) {
0661: hasAbstractMethods = true;
0662: }
0663: if ((isConstructor && needConstructor)
0664: || (!isConstructor && needMethod)) {
0665: AbstractMethodDeclaration method = convert(
0666: sourceMethod, methodInfo, compilationResult);
0667: if (isAbstract || method.isAbstract()) { // fix-up flag
0668: method.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
0669: }
0670: type.methods[extraConstructor + index++] = method;
0671: }
0672: }
0673: if (hasAbstractMethods)
0674: type.bits |= ASTNode.HasAbstractMethods;
0675: }
0676:
0677: return type;
0678: }
0679:
0680: private Annotation[] convertAnnotations(JavaElement element) {
0681: if (this .annotationPositions == null)
0682: return null;
0683: char[] cuSource = getSource();
0684: long[] positions = (long[]) this .annotationPositions
0685: .get(element);
0686: if (positions == null)
0687: return null;
0688: int length = positions.length;
0689: Annotation[] annotations = new Annotation[length];
0690: int recordedAnnotations = 0;
0691: for (int i = 0; i < length; i++) {
0692: long position = positions[i];
0693: int start = (int) (position >>> 32);
0694: int end = (int) position;
0695: char[] annotationSource = CharOperation.subarray(cuSource,
0696: start, end + 1);
0697: if (annotationSource != null) {
0698: Expression expression = parseMemberValue(annotationSource);
0699: /*
0700: * expression can be null or not an annotation if the source has changed between
0701: * the moment where the annotation source positions have been retrieved and the moment were
0702: * this parsing occured.
0703: * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=90916
0704: */
0705: if (expression instanceof Annotation) {
0706: annotations[recordedAnnotations++] = (Annotation) expression;
0707: }
0708: }
0709: }
0710: if (length != recordedAnnotations) {
0711: // resize to remove null annotations
0712: System
0713: .arraycopy(
0714: annotations,
0715: 0,
0716: (annotations = new Annotation[recordedAnnotations]),
0717: 0, recordedAnnotations);
0718: }
0719: return annotations;
0720: }
0721:
0722: /*
0723: * Build an import reference from an import name, e.g. java.lang.*
0724: */
0725: private ImportReference createImportReference(String[] importName,
0726: int start, int end, boolean onDemand, int modifiers) {
0727:
0728: int length = importName.length;
0729: long[] positions = new long[length];
0730: long position = ((long) start << 32) + end;
0731: char[][] qImportName = new char[length][];
0732: for (int i = 0; i < length; i++) {
0733: qImportName[i] = importName[i].toCharArray();
0734: positions[i] = position; // dummy positions
0735: }
0736: return new ImportReference(qImportName, positions, onDemand,
0737: modifiers);
0738: }
0739:
0740: private TypeParameter createTypeParameter(char[] typeParameterName,
0741: char[][] typeParameterBounds, int start, int end) {
0742:
0743: TypeParameter parameter = new TypeParameter();
0744: parameter.name = typeParameterName;
0745: parameter.sourceStart = start;
0746: parameter.sourceEnd = end;
0747: if (typeParameterBounds != null) {
0748: int length = typeParameterBounds.length;
0749: if (length > 0) {
0750: parameter.type = createTypeReference(
0751: typeParameterBounds[0], start, end);
0752: if (length > 1) {
0753: parameter.bounds = new TypeReference[length - 1];
0754: for (int i = 1; i < length; i++) {
0755: TypeReference bound = createTypeReference(
0756: typeParameterBounds[i], start, end);
0757: bound.bits |= ASTNode.IsSuperType;
0758: parameter.bounds[i - 1] = bound;
0759: }
0760: }
0761: }
0762: }
0763: return parameter;
0764: }
0765:
0766: /*
0767: * Build a type reference from a readable name, e.g. java.lang.Object[][]
0768: */
0769: private TypeReference createTypeReference(char[] typeName,
0770: int start, int end) {
0771:
0772: int length = typeName.length;
0773: this .namePos = 0;
0774: return decodeType(typeName, length, start, end);
0775: }
0776:
0777: /*
0778: * Build a type reference from a type signature, e.g. Ljava.lang.Object;
0779: */
0780: private TypeReference createTypeReference(String typeSignature,
0781: int start, int end) {
0782:
0783: int length = typeSignature.length();
0784: this .namePos = 0;
0785: return decodeType(typeSignature, length, start, end);
0786: }
0787:
0788: private TypeReference decodeType(String typeSignature, int length,
0789: int start, int end) {
0790: int identCount = 1;
0791: int dim = 0;
0792: int nameFragmentStart = this .namePos, nameFragmentEnd = -1;
0793: boolean nameStarted = false;
0794: ArrayList fragments = null;
0795: typeLoop: while (this .namePos < length) {
0796: char currentChar = typeSignature.charAt(this .namePos);
0797: switch (currentChar) {
0798: case Signature.C_BOOLEAN:
0799: if (!nameStarted) {
0800: this .namePos++;
0801: if (dim == 0)
0802: return new SingleTypeReference(
0803: TypeBinding.BOOLEAN.simpleName,
0804: ((long) start << 32) + end);
0805: else
0806: return new ArrayTypeReference(
0807: TypeBinding.BOOLEAN.simpleName, dim,
0808: ((long) start << 32) + end);
0809: }
0810: break;
0811: case Signature.C_BYTE:
0812: if (!nameStarted) {
0813: this .namePos++;
0814: if (dim == 0)
0815: return new SingleTypeReference(
0816: TypeBinding.BYTE.simpleName,
0817: ((long) start << 32) + end);
0818: else
0819: return new ArrayTypeReference(
0820: TypeBinding.BYTE.simpleName, dim,
0821: ((long) start << 32) + end);
0822: }
0823: break;
0824: case Signature.C_CHAR:
0825: if (!nameStarted) {
0826: this .namePos++;
0827: if (dim == 0)
0828: return new SingleTypeReference(
0829: TypeBinding.CHAR.simpleName,
0830: ((long) start << 32) + end);
0831: else
0832: return new ArrayTypeReference(
0833: TypeBinding.CHAR.simpleName, dim,
0834: ((long) start << 32) + end);
0835: }
0836: break;
0837: case Signature.C_DOUBLE:
0838: if (!nameStarted) {
0839: this .namePos++;
0840: if (dim == 0)
0841: return new SingleTypeReference(
0842: TypeBinding.DOUBLE.simpleName,
0843: ((long) start << 32) + end);
0844: else
0845: return new ArrayTypeReference(
0846: TypeBinding.DOUBLE.simpleName, dim,
0847: ((long) start << 32) + end);
0848: }
0849: break;
0850: case Signature.C_FLOAT:
0851: if (!nameStarted) {
0852: this .namePos++;
0853: if (dim == 0)
0854: return new SingleTypeReference(
0855: TypeBinding.FLOAT.simpleName,
0856: ((long) start << 32) + end);
0857: else
0858: return new ArrayTypeReference(
0859: TypeBinding.FLOAT.simpleName, dim,
0860: ((long) start << 32) + end);
0861: }
0862: break;
0863: case Signature.C_INT:
0864: if (!nameStarted) {
0865: this .namePos++;
0866: if (dim == 0)
0867: return new SingleTypeReference(
0868: TypeBinding.INT.simpleName,
0869: ((long) start << 32) + end);
0870: else
0871: return new ArrayTypeReference(
0872: TypeBinding.INT.simpleName, dim,
0873: ((long) start << 32) + end);
0874: }
0875: break;
0876: case Signature.C_LONG:
0877: if (!nameStarted) {
0878: this .namePos++;
0879: if (dim == 0)
0880: return new SingleTypeReference(
0881: TypeBinding.LONG.simpleName,
0882: ((long) start << 32) + end);
0883: else
0884: return new ArrayTypeReference(
0885: TypeBinding.LONG.simpleName, dim,
0886: ((long) start << 32) + end);
0887: }
0888: break;
0889: case Signature.C_SHORT:
0890: if (!nameStarted) {
0891: this .namePos++;
0892: if (dim == 0)
0893: return new SingleTypeReference(
0894: TypeBinding.SHORT.simpleName,
0895: ((long) start << 32) + end);
0896: else
0897: return new ArrayTypeReference(
0898: TypeBinding.SHORT.simpleName, dim,
0899: ((long) start << 32) + end);
0900: }
0901: break;
0902: case Signature.C_VOID:
0903: if (!nameStarted) {
0904: this .namePos++;
0905: new SingleTypeReference(
0906: TypeBinding.VOID.simpleName,
0907: ((long) start << 32) + end);
0908: }
0909: break;
0910: case Signature.C_RESOLVED:
0911: case Signature.C_UNRESOLVED:
0912: if (!nameStarted) {
0913: nameFragmentStart = this .namePos + 1;
0914: nameStarted = true;
0915: }
0916: break;
0917: case Signature.C_STAR:
0918: this .namePos++;
0919: Wildcard result = new Wildcard(Wildcard.UNBOUND);
0920: result.sourceStart = start;
0921: result.sourceEnd = end;
0922: return result;
0923: case Signature.C_EXTENDS:
0924: this .namePos++;
0925: result = new Wildcard(Wildcard.EXTENDS);
0926: result.bound = decodeType(typeSignature, length, start,
0927: end);
0928: result.sourceStart = start;
0929: result.sourceEnd = end;
0930: return result;
0931: case Signature.C_SUPER:
0932: this .namePos++;
0933: result = new Wildcard(Wildcard.SUPER);
0934: result.bound = decodeType(typeSignature, length, start,
0935: end);
0936: result.sourceStart = start;
0937: result.sourceEnd = end;
0938: return result;
0939: case Signature.C_ARRAY:
0940: dim++;
0941: break;
0942: case Signature.C_GENERIC_END:
0943: case Signature.C_SEMICOLON:
0944: nameFragmentEnd = this .namePos - 1;
0945: this .namePos++;
0946: break typeLoop;
0947: case Signature.C_DOT:
0948: case Signature.C_DOLLAR:
0949: if (!nameStarted) {
0950: nameFragmentStart = this .namePos + 1;
0951: nameStarted = true;
0952: } else if (this .namePos > nameFragmentStart) // handle name starting with a $ (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=91709)
0953: identCount++;
0954: break;
0955: case Signature.C_GENERIC_START:
0956: nameFragmentEnd = this .namePos - 1;
0957: // convert 1.5 specific constructs only if compliance is 1.5 or above
0958: if (!this .has1_5Compliance)
0959: break typeLoop;
0960: if (fragments == null)
0961: fragments = new ArrayList(2);
0962: addIdentifiers(typeSignature, nameFragmentStart,
0963: nameFragmentEnd + 1, identCount, fragments);
0964: this .namePos++; // skip '<'
0965: TypeReference[] arguments = decodeTypeArguments(
0966: typeSignature, length, start, end); // positionned on '>' at end
0967: fragments.add(arguments);
0968: identCount = 1;
0969: nameStarted = false;
0970: // next increment will skip '>'
0971: break;
0972: }
0973: this .namePos++;
0974: }
0975: if (fragments == null) { // non parameterized
0976: /* rebuild identifiers and dimensions */
0977: if (identCount == 1) { // simple type reference
0978: if (dim == 0) {
0979: char[] nameFragment = new char[nameFragmentEnd
0980: - nameFragmentStart + 1];
0981: typeSignature.getChars(nameFragmentStart,
0982: nameFragmentEnd + 1, nameFragment, 0);
0983: return new SingleTypeReference(nameFragment,
0984: ((long) start << 32) + end);
0985: } else {
0986: char[] nameFragment = new char[nameFragmentEnd
0987: - nameFragmentStart + 1];
0988: typeSignature.getChars(nameFragmentStart,
0989: nameFragmentEnd + 1, nameFragment, 0);
0990: return new ArrayTypeReference(nameFragment, dim,
0991: ((long) start << 32) + end);
0992: }
0993: } else { // qualified type reference
0994: long[] positions = new long[identCount];
0995: long pos = ((long) start << 32) + end;
0996: for (int i = 0; i < identCount; i++) {
0997: positions[i] = pos;
0998: }
0999: char[][] identifiers = extractIdentifiers(
1000: typeSignature, nameFragmentStart,
1001: nameFragmentEnd, identCount);
1002: if (dim == 0) {
1003: return new QualifiedTypeReference(identifiers,
1004: positions);
1005: } else {
1006: return new ArrayQualifiedTypeReference(identifiers,
1007: dim, positions);
1008: }
1009: }
1010: } else { // parameterized
1011: // rebuild type reference from available fragments: char[][], arguments, char[][], arguments...
1012: // check trailing qualified name
1013: if (nameStarted) {
1014: addIdentifiers(typeSignature, nameFragmentStart,
1015: nameFragmentEnd + 1, identCount, fragments);
1016: }
1017: int fragmentLength = fragments.size();
1018: if (fragmentLength == 2) {
1019: Object firstFragment = fragments.get(0);
1020: if (firstFragment instanceof char[]) {
1021: // parameterized single type
1022: return new ParameterizedSingleTypeReference(
1023: (char[]) firstFragment,
1024: (TypeReference[]) fragments.get(1), dim,
1025: ((long) start << 32) + end);
1026: }
1027: }
1028: // parameterized qualified type
1029: identCount = 0;
1030: for (int i = 0; i < fragmentLength; i++) {
1031: Object element = fragments.get(i);
1032: if (element instanceof char[][]) {
1033: identCount += ((char[][]) element).length;
1034: } else if (element instanceof char[])
1035: identCount++;
1036: }
1037: char[][] tokens = new char[identCount][];
1038: TypeReference[][] arguments = new TypeReference[identCount][];
1039: int index = 0;
1040: for (int i = 0; i < fragmentLength; i++) {
1041: Object element = fragments.get(i);
1042: if (element instanceof char[][]) {
1043: char[][] fragmentTokens = (char[][]) element;
1044: int fragmentTokenLength = fragmentTokens.length;
1045: System.arraycopy(fragmentTokens, 0, tokens, index,
1046: fragmentTokenLength);
1047: index += fragmentTokenLength;
1048: } else if (element instanceof char[]) {
1049: tokens[index++] = (char[]) element;
1050: } else {
1051: arguments[index - 1] = (TypeReference[]) element;
1052: }
1053: }
1054: long[] positions = new long[identCount];
1055: long pos = ((long) start << 32) + end;
1056: for (int i = 0; i < identCount; i++) {
1057: positions[i] = pos;
1058: }
1059: return new ParameterizedQualifiedTypeReference(tokens,
1060: arguments, dim, positions);
1061: }
1062: }
1063:
1064: private TypeReference decodeType(char[] typeName, int length,
1065: int start, int end) {
1066: int identCount = 1;
1067: int dim = 0;
1068: int nameFragmentStart = this .namePos, nameFragmentEnd = -1;
1069: ArrayList fragments = null;
1070: typeLoop: while (this .namePos < length) {
1071: char currentChar = typeName[this .namePos];
1072: switch (currentChar) {
1073: case '?':
1074: this .namePos++; // skip '?'
1075: while (typeName[this .namePos] == ' ')
1076: this .namePos++;
1077: switch (typeName[this .namePos]) {
1078: case 's':
1079: checkSuper: {
1080: int max = TypeConstants.WILDCARD_SUPER.length - 1;
1081: for (int ahead = 1; ahead < max; ahead++) {
1082: if (typeName[this .namePos + ahead] != TypeConstants.WILDCARD_SUPER[ahead + 1]) {
1083: break checkSuper;
1084: }
1085: }
1086: this .namePos += max;
1087: Wildcard result = new Wildcard(Wildcard.SUPER);
1088: result.bound = decodeType(typeName, length,
1089: start, end);
1090: result.sourceStart = start;
1091: result.sourceEnd = end;
1092: return result;
1093: }
1094: break;
1095: case 'e':
1096: checkExtends: {
1097: int max = TypeConstants.WILDCARD_EXTENDS.length - 1;
1098: for (int ahead = 1; ahead < max; ahead++) {
1099: if (typeName[this .namePos + ahead] != TypeConstants.WILDCARD_EXTENDS[ahead + 1]) {
1100: break checkExtends;
1101: }
1102: }
1103: this .namePos += max;
1104: Wildcard result = new Wildcard(Wildcard.EXTENDS);
1105: result.bound = decodeType(typeName, length,
1106: start, end);
1107: result.sourceStart = start;
1108: result.sourceEnd = end;
1109: return result;
1110: }
1111: break;
1112: }
1113: Wildcard result = new Wildcard(Wildcard.UNBOUND);
1114: result.sourceStart = start;
1115: result.sourceEnd = end;
1116: return result;
1117: case '[':
1118: if (dim == 0)
1119: nameFragmentEnd = this .namePos - 1;
1120: dim++;
1121: break;
1122: case ']':
1123: break;
1124: case '>':
1125: case ',':
1126: break typeLoop;
1127: case '.':
1128: if (nameFragmentStart < 0)
1129: nameFragmentStart = this .namePos + 1; // member type name
1130: identCount++;
1131: break;
1132: case '<':
1133: // convert 1.5 specific constructs only if compliance is 1.5 or above
1134: if (!this .has1_5Compliance)
1135: break typeLoop;
1136: if (fragments == null)
1137: fragments = new ArrayList(2);
1138: nameFragmentEnd = this .namePos - 1;
1139: char[][] identifiers = CharOperation.splitOn('.',
1140: typeName, nameFragmentStart, this .namePos);
1141: fragments.add(identifiers);
1142: this .namePos++; // skip '<'
1143: TypeReference[] arguments = decodeTypeArguments(
1144: typeName, length, start, end); // positionned on '>' at end
1145: fragments.add(arguments);
1146: identCount = 0;
1147: nameFragmentStart = -1;
1148: nameFragmentEnd = -1;
1149: // next increment will skip '>'
1150: break;
1151: }
1152: this .namePos++;
1153: }
1154: if (nameFragmentEnd < 0)
1155: nameFragmentEnd = this .namePos - 1;
1156: if (fragments == null) { // non parameterized
1157: /* rebuild identifiers and dimensions */
1158: if (identCount == 1) { // simple type reference
1159: if (dim == 0) {
1160: char[] nameFragment;
1161: if (nameFragmentStart != 0 || nameFragmentEnd >= 0) {
1162: int nameFragmentLength = nameFragmentEnd
1163: - nameFragmentStart + 1;
1164: System
1165: .arraycopy(
1166: typeName,
1167: nameFragmentStart,
1168: nameFragment = new char[nameFragmentLength],
1169: 0, nameFragmentLength);
1170: } else {
1171: nameFragment = typeName;
1172: }
1173: return new SingleTypeReference(nameFragment,
1174: ((long) start << 32) + end);
1175: } else {
1176: int nameFragmentLength = nameFragmentEnd
1177: - nameFragmentStart + 1;
1178: char[] nameFragment = new char[nameFragmentLength];
1179: System.arraycopy(typeName, nameFragmentStart,
1180: nameFragment, 0, nameFragmentLength);
1181: return new ArrayTypeReference(nameFragment, dim,
1182: ((long) start << 32) + end);
1183: }
1184: } else { // qualified type reference
1185: long[] positions = new long[identCount];
1186: long pos = ((long) start << 32) + end;
1187: for (int i = 0; i < identCount; i++) {
1188: positions[i] = pos;
1189: }
1190: char[][] identifiers = CharOperation.splitOn('.',
1191: typeName, nameFragmentStart,
1192: nameFragmentEnd + 1);
1193: if (dim == 0) {
1194: return new QualifiedTypeReference(identifiers,
1195: positions);
1196: } else {
1197: return new ArrayQualifiedTypeReference(identifiers,
1198: dim, positions);
1199: }
1200: }
1201: } else { // parameterized
1202: // rebuild type reference from available fragments: char[][], arguments, char[][], arguments...
1203: // check trailing qualified name
1204: if (nameFragmentStart > 0 && nameFragmentStart < length) {
1205: char[][] identifiers = CharOperation.splitOn('.',
1206: typeName, nameFragmentStart,
1207: nameFragmentEnd + 1);
1208: fragments.add(identifiers);
1209: }
1210: int fragmentLength = fragments.size();
1211: if (fragmentLength == 2) {
1212: char[][] firstFragment = (char[][]) fragments.get(0);
1213: if (firstFragment.length == 1) {
1214: // parameterized single type
1215: return new ParameterizedSingleTypeReference(
1216: firstFragment[0],
1217: (TypeReference[]) fragments.get(1), dim,
1218: ((long) start << 32) + end);
1219: }
1220: }
1221: // parameterized qualified type
1222: identCount = 0;
1223: for (int i = 0; i < fragmentLength; i++) {
1224: Object element = fragments.get(i);
1225: if (element instanceof char[][]) {
1226: identCount += ((char[][]) element).length;
1227: }
1228: }
1229: char[][] tokens = new char[identCount][];
1230: TypeReference[][] arguments = new TypeReference[identCount][];
1231: int index = 0;
1232: for (int i = 0; i < fragmentLength; i++) {
1233: Object element = fragments.get(i);
1234: if (element instanceof char[][]) {
1235: char[][] fragmentTokens = (char[][]) element;
1236: int fragmentTokenLength = fragmentTokens.length;
1237: System.arraycopy(fragmentTokens, 0, tokens, index,
1238: fragmentTokenLength);
1239: index += fragmentTokenLength;
1240: } else {
1241: arguments[index - 1] = (TypeReference[]) element;
1242: }
1243: }
1244: long[] positions = new long[identCount];
1245: long pos = ((long) start << 32) + end;
1246: for (int i = 0; i < identCount; i++) {
1247: positions[i] = pos;
1248: }
1249: return new ParameterizedQualifiedTypeReference(tokens,
1250: arguments, dim, positions);
1251: }
1252: }
1253:
1254: private TypeReference[] decodeTypeArguments(char[] typeName,
1255: int length, int start, int end) {
1256: ArrayList argumentList = new ArrayList(1);
1257: int count = 0;
1258: argumentsLoop: while (this .namePos < length) {
1259: TypeReference argument = decodeType(typeName, length,
1260: start, end);
1261: count++;
1262: argumentList.add(argument);
1263: if (this .namePos >= length)
1264: break argumentsLoop;
1265: if (typeName[this .namePos] == '>') {
1266: break argumentsLoop;
1267: }
1268: this .namePos++; // skip ','
1269: }
1270: TypeReference[] typeArguments = new TypeReference[count];
1271: argumentList.toArray(typeArguments);
1272: return typeArguments;
1273: }
1274:
1275: private TypeReference[] decodeTypeArguments(String typeSignature,
1276: int length, int start, int end) {
1277: ArrayList argumentList = new ArrayList(1);
1278: int count = 0;
1279: argumentsLoop: while (this .namePos < length) {
1280: TypeReference argument = decodeType(typeSignature, length,
1281: start, end);
1282: count++;
1283: argumentList.add(argument);
1284: if (this .namePos >= length)
1285: break argumentsLoop;
1286: if (typeSignature.charAt(this .namePos) == '>') {
1287: break argumentsLoop;
1288: }
1289: }
1290: TypeReference[] typeArguments = new TypeReference[count];
1291: argumentList.toArray(typeArguments);
1292: return typeArguments;
1293: }
1294:
1295: private char[][] extractIdentifiers(String typeSignature,
1296: int start, int endInclusive, int identCount) {
1297: char[][] result = new char[identCount][];
1298: int charIndex = start;
1299: int i = 0;
1300: while (charIndex < endInclusive) {
1301: if (typeSignature.charAt(charIndex) == '.') {
1302: typeSignature.getChars(start, charIndex,
1303: result[i++] = new char[charIndex - start], 0);
1304: start = ++charIndex;
1305: } else
1306: charIndex++;
1307: }
1308: typeSignature.getChars(start, charIndex + 1,
1309: result[i++] = new char[charIndex - start + 1], 0);
1310: return result;
1311: }
1312:
1313: private char[] getSource() {
1314: if (this .source == null)
1315: this .source = this .cu.getContents();
1316: return this .source;
1317: }
1318:
1319: private Expression parseMemberValue(char[] memberValue) {
1320: // memberValue must not be null
1321: if (this .parser == null) {
1322: this .parser = new Parser(this .problemReporter, true);
1323: }
1324: return this .parser.parseMemberValue(memberValue, 0,
1325: memberValue.length, this.unit);
1326: }
1327: }
|