コード例 #1
0
ファイル: HandleToString.java プロジェクト: Reder/lombok
 private NameReference generateQualifiedNameRef(ASTNode source, char[]... varNames) {
   int pS = source.sourceStart, pE = source.sourceEnd;
   long p = (long) pS << 32 | pE;
   NameReference ref;
   if (varNames.length > 1)
     ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE);
   else ref = new SingleNameReference(varNames[0], p);
   Eclipse.setGeneratedBy(ref, source);
   return ref;
 }
コード例 #2
0
ファイル: EclipseType.java プロジェクト: redundent/lombok-pg
 public EclipseNode getAnnotation(final String typeName) {
   EclipseNode annotationNode = null;
   for (EclipseNode child : node().down()) {
     if (child.getKind() != Kind.ANNOTATION) continue;
     if (Eclipse.matchesType((Annotation) child.get(), typeName)) {
       annotationNode = child;
     }
   }
   return annotationNode;
 }
コード例 #3
0
 /** Give 2 clones! */
 private Expression longToIntForHashCode(Expression ref1, Expression ref2, ASTNode source) {
   int pS = source.sourceStart, pE = source.sourceEnd;
   /* (int)(ref >>> 32 ^ ref) */
   IntLiteral int32 = new IntLiteral("32".toCharArray(), pS, pE);
   Eclipse.setGeneratedBy(int32, source);
   BinaryExpression higherBits =
       new BinaryExpression(ref1, int32, OperatorIds.UNSIGNED_RIGHT_SHIFT);
   Eclipse.setGeneratedBy(higherBits, source);
   BinaryExpression xorParts = new BinaryExpression(ref2, higherBits, OperatorIds.XOR);
   Eclipse.setGeneratedBy(xorParts, source);
   TypeReference intRef = TypeReference.baseTypeReference(TypeIds.T_int, 0);
   intRef.sourceStart = pS;
   intRef.sourceEnd = pE;
   Eclipse.setGeneratedBy(intRef, source);
   CastExpression expr = new CastExpression(xorParts, intRef);
   expr.sourceStart = pS;
   expr.sourceEnd = pE;
   Eclipse.setGeneratedBy(expr, source);
   return expr;
 }
コード例 #4
0
  private MethodDeclaration createCanEqual(EclipseNode type, ASTNode source) {
    /* public boolean canEqual(final java.lang.Object other) {
     *     return other instanceof MyType;
     * }
     */
    int pS = source.sourceStart;
    int pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;

    char[] otherName = "other".toCharArray();

    MethodDeclaration method =
        new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(method, source);
    method.modifiers = EclipseHandlerUtil.toEclipseModifier(AccessLevel.PUBLIC);
    method.returnType = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
    method.returnType.sourceStart = pS;
    method.returnType.sourceEnd = pE;
    Eclipse.setGeneratedBy(method.returnType, source);
    method.selector = "canEqual".toCharArray();
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
    TypeReference objectRef =
        new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {p, p, p});
    Eclipse.setGeneratedBy(objectRef, source);
    method.arguments = new Argument[] {new Argument(otherName, 0, objectRef, Modifier.FINAL)};
    method.arguments[0].sourceStart = pS;
    method.arguments[0].sourceEnd = pE;
    Eclipse.setGeneratedBy(method.arguments[0], source);

    SingleNameReference otherRef = new SingleNameReference(otherName, p);
    Eclipse.setGeneratedBy(otherRef, source);

    SingleTypeReference typeReference =
        new SingleTypeReference(((TypeDeclaration) type.get()).name, p);
    Eclipse.setGeneratedBy(typeReference, source);

    InstanceOfExpression instanceOf = new InstanceOfExpression(otherRef, typeReference);
    instanceOf.sourceStart = pS;
    instanceOf.sourceEnd = pE;
    Eclipse.setGeneratedBy(instanceOf, source);

    ReturnStatement returnStatement = new ReturnStatement(instanceOf, pS, pE);
    Eclipse.setGeneratedBy(returnStatement, source);

    method.statements = new Statement[] {returnStatement};
    return method;
  }
コード例 #5
0
  public void generateEqualsAndHashCodeForType(EclipseNode typeNode, EclipseNode errorNode) {
    for (EclipseNode child : typeNode.down()) {
      if (child.getKind() == Kind.ANNOTATION) {
        if (Eclipse.annotationTypeMatches(EqualsAndHashCode.class, child)) {
          // The annotation will make it happen, so we can skip it.
          return;
        }
      }
    }

    generateMethods(typeNode, errorNode, null, null, null, false, FieldAccess.GETTER);
  }
コード例 #6
0
 private IfStatement generateCompareFloatOrDouble(
     Expression thisRef, Expression otherRef, char[] floatOrDouble, ASTNode source) {
   int pS = source.sourceStart, pE = source.sourceEnd;
   /* if (Float.compare(fieldName, other.fieldName) != 0) return false */
   MessageSend floatCompare = new MessageSend();
   floatCompare.sourceStart = pS;
   floatCompare.sourceEnd = pE;
   Eclipse.setGeneratedBy(floatCompare, source);
   floatCompare.receiver =
       generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.LANG, floatOrDouble);
   floatCompare.selector = "compare".toCharArray();
   floatCompare.arguments = new Expression[] {thisRef, otherRef};
   IntLiteral int0 = new IntLiteral(new char[] {'0'}, pS, pE);
   Eclipse.setGeneratedBy(int0, source);
   EqualExpression ifFloatCompareIsNot0 =
       new EqualExpression(floatCompare, int0, OperatorIds.NOT_EQUAL);
   ifFloatCompareIsNot0.sourceStart = pS;
   ifFloatCompareIsNot0.sourceEnd = pE;
   Eclipse.setGeneratedBy(ifFloatCompareIsNot0, source);
   FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
   Eclipse.setGeneratedBy(falseLiteral, source);
   ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE);
   Eclipse.setGeneratedBy(returnFalse, source);
   IfStatement ifStatement = new IfStatement(ifFloatCompareIsNot0, returnFalse, pS, pE);
   Eclipse.setGeneratedBy(ifStatement, source);
   return ifStatement;
 }
コード例 #7
0
ファイル: Eclipse.java プロジェクト: barneypitt/lombok
  private static Object calculateValue(Expression e) {
    if (e instanceof Literal) {
      ((Literal) e).computeConstant();
      switch (e.constant.typeID()) {
        case TypeIds.T_int:
          return e.constant.intValue();
        case TypeIds.T_byte:
          return e.constant.byteValue();
        case TypeIds.T_short:
          return e.constant.shortValue();
        case TypeIds.T_char:
          return e.constant.charValue();
        case TypeIds.T_float:
          return e.constant.floatValue();
        case TypeIds.T_double:
          return e.constant.doubleValue();
        case TypeIds.T_boolean:
          return e.constant.booleanValue();
        case TypeIds.T_long:
          return e.constant.longValue();
        case TypeIds.T_JavaLangString:
          return e.constant.stringValue();
        default:
          return null;
      }
    } else if (e instanceof ClassLiteralAccess) {
      return Eclipse.toQualifiedName(((ClassLiteralAccess) e).type.getTypeName());
    } else if (e instanceof SingleNameReference) {
      return new String(((SingleNameReference) e).token);
    } else if (e instanceof QualifiedNameReference) {
      String qName = Eclipse.toQualifiedName(((QualifiedNameReference) e).tokens);
      int idx = qName.lastIndexOf('.');
      return idx == -1 ? qName : qName.substring(idx + 1);
    }

    return null;
  }
コード例 #8
0
ファイル: HandleToString.java プロジェクト: Reder/lombok
  public void generateToStringForType(EclipseNode typeNode, EclipseNode errorNode) {
    for (EclipseNode child : typeNode.down()) {
      if (child.getKind() == Kind.ANNOTATION) {
        if (Eclipse.annotationTypeMatches(ToString.class, child)) {
          // The annotation will make it happen, so we can skip it.
          return;
        }
      }
    }

    boolean includeFieldNames = true;
    try {
      includeFieldNames =
          ((Boolean) ToString.class.getMethod("includeFieldNames").getDefaultValue())
              .booleanValue();
    } catch (Exception ignore) {
    }
    generateToString(
        typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER);
  }
コード例 #9
0
ファイル: EclipseType.java プロジェクト: redundent/lombok-pg
 public static EclipseType typeOf(final EclipseNode node, final ASTNode source) {
   EclipseNode typeNode = Eclipse.typeNodeOf(node);
   return typeNode == null ? null : new EclipseType(typeNode, source);
 }
コード例 #10
0
ファイル: HandleData.java プロジェクト: serberoth/lombok
  private MethodDeclaration createStaticConstructor(
      String name, EclipseNode type, Collection<EclipseNode> fields, ASTNode source) {
    int pS = source.sourceStart, pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;

    MethodDeclaration constructor =
        new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(constructor, source);

    constructor.modifiers = PKG.toModifier(AccessLevel.PUBLIC) | Modifier.STATIC;
    TypeDeclaration typeDecl = (TypeDeclaration) type.get();
    if (typeDecl.typeParameters != null && typeDecl.typeParameters.length > 0) {
      TypeReference[] refs = new TypeReference[typeDecl.typeParameters.length];
      int idx = 0;
      for (TypeParameter param : typeDecl.typeParameters) {
        TypeReference typeRef =
            new SingleTypeReference(param.name, (long) param.sourceStart << 32 | param.sourceEnd);
        Eclipse.setGeneratedBy(typeRef, source);
        refs[idx++] = typeRef;
      }
      constructor.returnType = new ParameterizedSingleTypeReference(typeDecl.name, refs, 0, p);
    } else constructor.returnType = new SingleTypeReference(((TypeDeclaration) type.get()).name, p);
    Eclipse.setGeneratedBy(constructor.returnType, source);
    constructor.annotations = null;
    constructor.selector = name.toCharArray();
    constructor.thrownExceptions = null;
    constructor.typeParameters =
        copyTypeParams(((TypeDeclaration) type.get()).typeParameters, source);
    constructor.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    constructor.bodyStart =
        constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
    constructor.bodyEnd =
        constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;

    List<Argument> args = new ArrayList<Argument>();
    List<Expression> assigns = new ArrayList<Expression>();
    AllocationExpression statement = new AllocationExpression();
    statement.sourceStart = pS;
    statement.sourceEnd = pE;
    Eclipse.setGeneratedBy(statement, source);
    statement.type = copyType(constructor.returnType, source);

    for (EclipseNode fieldNode : fields) {
      FieldDeclaration field = (FieldDeclaration) fieldNode.get();
      long fieldPos = (((long) field.sourceStart) << 32) | field.sourceEnd;
      SingleNameReference nameRef = new SingleNameReference(field.name, fieldPos);
      Eclipse.setGeneratedBy(nameRef, source);
      assigns.add(nameRef);

      Argument argument = new Argument(field.name, fieldPos, copyType(field.type, source), 0);
      Eclipse.setGeneratedBy(argument, source);

      Annotation[] copiedAnnotations =
          copyAnnotations(
              findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN),
              findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN),
              source);
      if (copiedAnnotations.length != 0) argument.annotations = copiedAnnotations;
      args.add(new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL));
    }

    statement.arguments =
        assigns.isEmpty() ? null : assigns.toArray(new Expression[assigns.size()]);
    constructor.arguments = args.isEmpty() ? null : args.toArray(new Argument[args.size()]);
    constructor.statements =
        new Statement[] {new ReturnStatement(statement, (int) (p >> 32), (int) p)};
    Eclipse.setGeneratedBy(constructor.statements[0], source);
    return constructor;
  }
コード例 #11
0
ファイル: HandleData.java プロジェクト: serberoth/lombok
  private ConstructorDeclaration createConstructor(
      boolean isPublic, EclipseNode type, Collection<EclipseNode> fields, ASTNode source) {
    long p = (long) source.sourceStart << 32 | source.sourceEnd;

    ConstructorDeclaration constructor =
        new ConstructorDeclaration(
            ((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(constructor, source);

    constructor.modifiers = PKG.toModifier(isPublic ? AccessLevel.PUBLIC : AccessLevel.PRIVATE);
    constructor.annotations = null;
    constructor.selector = ((TypeDeclaration) type.get()).name;
    constructor.constructorCall =
        new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
    Eclipse.setGeneratedBy(constructor.constructorCall, source);
    constructor.thrownExceptions = null;
    constructor.typeParameters = null;
    constructor.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    constructor.bodyStart =
        constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
    constructor.bodyEnd =
        constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;
    constructor.arguments = null;

    List<Argument> args = new ArrayList<Argument>();
    List<Statement> assigns = new ArrayList<Statement>();
    List<Statement> nullChecks = new ArrayList<Statement>();

    for (EclipseNode fieldNode : fields) {
      FieldDeclaration field = (FieldDeclaration) fieldNode.get();
      FieldReference thisX =
          new FieldReference(("this." + new String(field.name)).toCharArray(), p);
      Eclipse.setGeneratedBy(thisX, source);
      thisX.receiver = new ThisReference((int) (p >> 32), (int) p);
      Eclipse.setGeneratedBy(thisX.receiver, source);
      thisX.token = field.name;

      SingleNameReference assignmentNameRef = new SingleNameReference(field.name, p);
      Eclipse.setGeneratedBy(assignmentNameRef, source);
      Assignment assignment = new Assignment(thisX, assignmentNameRef, (int) p);
      Eclipse.setGeneratedBy(assignment, source);
      assigns.add(assignment);
      long fieldPos = (((long) field.sourceStart) << 32) | field.sourceEnd;
      Argument argument =
          new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL);
      Eclipse.setGeneratedBy(argument, source);
      Annotation[] nonNulls = findAnnotations(field, TransformationsUtil.NON_NULL_PATTERN);
      Annotation[] nullables = findAnnotations(field, TransformationsUtil.NULLABLE_PATTERN);
      if (nonNulls.length != 0) {
        Statement nullCheck = generateNullCheck(field, source);
        if (nullCheck != null) nullChecks.add(nullCheck);
      }
      Annotation[] copiedAnnotations = copyAnnotations(nonNulls, nullables, source);
      if (copiedAnnotations.length != 0) argument.annotations = copiedAnnotations;
      args.add(argument);
    }

    nullChecks.addAll(assigns);
    constructor.statements =
        nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]);
    constructor.arguments = args.isEmpty() ? null : args.toArray(new Argument[args.size()]);
    return constructor;
  }
コード例 #12
0
ファイル: HandleSynchronized.java プロジェクト: Reder/lombok
  @Override
  public boolean handle(
      AnnotationValues<Synchronized> annotation, Annotation source, EclipseNode annotationNode) {
    int p1 = source.sourceStart - 1;
    int p2 = source.sourceStart - 2;
    long pos = (((long) p1) << 32) | p2;
    EclipseNode methodNode = annotationNode.up();
    if (methodNode == null
        || methodNode.getKind() != Kind.METHOD
        || !(methodNode.get() instanceof MethodDeclaration)) {
      annotationNode.addError("@Synchronized is legal only on methods.");
      return true;
    }

    MethodDeclaration method = (MethodDeclaration) methodNode.get();
    if (method.isAbstract()) {
      annotationNode.addError("@Synchronized is legal only on concrete methods.");
      return true;
    }

    char[] lockName = annotation.getInstance().value().toCharArray();
    boolean autoMake = false;
    if (lockName.length == 0) {
      autoMake = true;
      lockName = method.isStatic() ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME;
    }

    if (fieldExists(new String(lockName), methodNode) == MemberExistsResult.NOT_EXISTS) {
      if (!autoMake) {
        annotationNode.addError("The field " + new String(lockName) + " does not exist.");
        return true;
      }
      FieldDeclaration fieldDecl = new FieldDeclaration(lockName, 0, -1);
      Eclipse.setGeneratedBy(fieldDecl, source);
      fieldDecl.declarationSourceEnd = -1;

      fieldDecl.modifiers =
          (method.isStatic() ? Modifier.STATIC : 0) | Modifier.FINAL | Modifier.PRIVATE;

      // We use 'new Object[0];' because quite unlike 'new Object();', empty arrays *ARE*
      // serializable!
      ArrayAllocationExpression arrayAlloc = new ArrayAllocationExpression();
      Eclipse.setGeneratedBy(arrayAlloc, source);
      arrayAlloc.dimensions = new Expression[] {new IntLiteral(new char[] {'0'}, 0, 0)};
      Eclipse.setGeneratedBy(arrayAlloc.dimensions[0], source);
      arrayAlloc.type =
          new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {0, 0, 0});
      Eclipse.setGeneratedBy(arrayAlloc.type, source);
      fieldDecl.type =
          new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {0, 0, 0});
      Eclipse.setGeneratedBy(fieldDecl.type, source);
      fieldDecl.initialization = arrayAlloc;
      injectFieldSuppressWarnings(annotationNode.up().up(), fieldDecl);
    }

    if (method.statements == null) return false;

    Block block = new Block(0);
    Eclipse.setGeneratedBy(block, source);
    block.statements = method.statements;
    Expression lockVariable;
    if (method.isStatic())
      lockVariable =
          new QualifiedNameReference(
              new char[][] {methodNode.up().getName().toCharArray(), lockName},
              new long[] {pos, pos},
              p1,
              p2);
    else {
      lockVariable = new FieldReference(lockName, pos);
      ThisReference thisReference = new ThisReference(p1, p2);
      Eclipse.setGeneratedBy(thisReference, source);
      ((FieldReference) lockVariable).receiver = thisReference;
    }
    Eclipse.setGeneratedBy(lockVariable, source);

    method.statements = new Statement[] {new SynchronizedStatement(lockVariable, block, 0, 0)};
    Eclipse.setGeneratedBy(method.statements[0], source);

    methodNode.rebuild();

    return true;
  }
コード例 #13
0
  private MethodDeclaration createEquals(
      EclipseNode type,
      Collection<EclipseNode> fields,
      boolean callSuper,
      ASTNode source,
      FieldAccess fieldAccess,
      boolean needsCanEqual) {
    int pS = source.sourceStart;
    int pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;
    TypeDeclaration typeDecl = (TypeDeclaration) type.get();

    MethodDeclaration method =
        new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(method, source);
    method.modifiers = EclipseHandlerUtil.toEclipseModifier(AccessLevel.PUBLIC);
    method.returnType = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
    method.returnType.sourceStart = pS;
    method.returnType.sourceEnd = pE;
    Eclipse.setGeneratedBy(method.returnType, source);
    method.annotations =
        new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
    method.selector = "equals".toCharArray();
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
    TypeReference objectRef =
        new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {p, p, p});
    Eclipse.setGeneratedBy(objectRef, source);
    method.arguments =
        new Argument[] {new Argument(new char[] {'o'}, 0, objectRef, Modifier.FINAL)};
    method.arguments[0].sourceStart = pS;
    method.arguments[0].sourceEnd = pE;
    Eclipse.setGeneratedBy(method.arguments[0], source);

    List<Statement> statements = new ArrayList<Statement>();

    /* if (o == this) return true; */ {
      SingleNameReference oRef = new SingleNameReference(new char[] {'o'}, p);
      Eclipse.setGeneratedBy(oRef, source);
      ThisReference thisRef = new ThisReference(pS, pE);
      Eclipse.setGeneratedBy(thisRef, source);
      EqualExpression otherEqualsThis = new EqualExpression(oRef, thisRef, OperatorIds.EQUAL_EQUAL);
      Eclipse.setGeneratedBy(otherEqualsThis, source);

      TrueLiteral trueLiteral = new TrueLiteral(pS, pE);
      Eclipse.setGeneratedBy(trueLiteral, source);
      ReturnStatement returnTrue = new ReturnStatement(trueLiteral, pS, pE);
      Eclipse.setGeneratedBy(returnTrue, source);
      IfStatement ifOtherEqualsThis = new IfStatement(otherEqualsThis, returnTrue, pS, pE);
      Eclipse.setGeneratedBy(ifOtherEqualsThis, source);
      statements.add(ifOtherEqualsThis);
    }

    /* if (!(o instanceof MyType) return false; */ {
      SingleNameReference oRef = new SingleNameReference(new char[] {'o'}, p);
      Eclipse.setGeneratedBy(oRef, source);

      SingleTypeReference typeReference = new SingleTypeReference(typeDecl.name, p);
      Eclipse.setGeneratedBy(typeReference, source);

      InstanceOfExpression instanceOf = new InstanceOfExpression(oRef, typeReference);
      instanceOf.sourceStart = pS;
      instanceOf.sourceEnd = pE;
      Eclipse.setGeneratedBy(instanceOf, source);

      Expression notInstanceOf = new UnaryExpression(instanceOf, OperatorIds.NOT);
      Eclipse.setGeneratedBy(notInstanceOf, source);

      FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
      Eclipse.setGeneratedBy(falseLiteral, source);

      ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE);
      Eclipse.setGeneratedBy(returnFalse, source);

      IfStatement ifNotInstanceOf = new IfStatement(notInstanceOf, returnFalse, pS, pE);
      Eclipse.setGeneratedBy(ifNotInstanceOf, source);
      statements.add(ifNotInstanceOf);
    }

    char[] otherName = "other".toCharArray();

    /* MyType<?> other = (MyType<?>) o; */ {
      if (!fields.isEmpty() || needsCanEqual) {
        LocalDeclaration other = new LocalDeclaration(otherName, pS, pE);
        other.modifiers |= ClassFileConstants.AccFinal;
        Eclipse.setGeneratedBy(other, source);
        char[] typeName = typeDecl.name;
        Expression targetType;
        if (typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0) {
          targetType = new SingleNameReference(((TypeDeclaration) type.get()).name, p);
          Eclipse.setGeneratedBy(targetType, source);
          other.type = new SingleTypeReference(typeName, p);
          Eclipse.setGeneratedBy(other.type, source);
        } else {
          TypeReference[] typeArgs = new TypeReference[typeDecl.typeParameters.length];
          for (int i = 0; i < typeArgs.length; i++) {
            typeArgs[i] = new Wildcard(Wildcard.UNBOUND);
            typeArgs[i].sourceStart = pS;
            typeArgs[i].sourceEnd = pE;
            Eclipse.setGeneratedBy(typeArgs[i], source);
          }
          targetType = new ParameterizedSingleTypeReference(typeName, typeArgs, 0, p);
          Eclipse.setGeneratedBy(targetType, source);
          other.type =
              new ParameterizedSingleTypeReference(typeName, copyTypes(typeArgs, source), 0, p);
          Eclipse.setGeneratedBy(other.type, source);
        }
        NameReference oRef = new SingleNameReference(new char[] {'o'}, p);
        Eclipse.setGeneratedBy(oRef, source);
        other.initialization = new CastExpression(oRef, targetType);
        Eclipse.setGeneratedBy(other.initialization, source);
        statements.add(other);
      }
    }

    /* if (!other.canEqual((java.lang.Object) this)) return false; */ {
      if (needsCanEqual) {
        MessageSend otherCanEqual = new MessageSend();
        otherCanEqual.sourceStart = pS;
        otherCanEqual.sourceEnd = pE;
        Eclipse.setGeneratedBy(otherCanEqual, source);
        otherCanEqual.receiver = new SingleNameReference(otherName, p);
        Eclipse.setGeneratedBy(otherCanEqual.receiver, source);
        otherCanEqual.selector = "canEqual".toCharArray();

        ThisReference thisReference = new ThisReference(pS, pE);
        Eclipse.setGeneratedBy(thisReference, source);
        CastExpression castThisRef =
            new CastExpression(
                thisReference, generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_OBJECT));
        Eclipse.setGeneratedBy(castThisRef, source);
        castThisRef.sourceStart = pS;
        castThisRef.sourceEnd = pE;

        otherCanEqual.arguments = new Expression[] {castThisRef};

        Expression notOtherCanEqual = new UnaryExpression(otherCanEqual, OperatorIds.NOT);
        Eclipse.setGeneratedBy(notOtherCanEqual, source);

        FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
        Eclipse.setGeneratedBy(falseLiteral, source);

        ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE);
        Eclipse.setGeneratedBy(returnFalse, source);

        IfStatement ifNotCanEqual = new IfStatement(notOtherCanEqual, returnFalse, pS, pE);
        Eclipse.setGeneratedBy(ifNotCanEqual, source);

        statements.add(ifNotCanEqual);
      }
    }

    /* if (!super.equals(o)) return false; */
    if (callSuper) {
      MessageSend callToSuper = new MessageSend();
      callToSuper.sourceStart = pS;
      callToSuper.sourceEnd = pE;
      Eclipse.setGeneratedBy(callToSuper, source);
      callToSuper.receiver = new SuperReference(pS, pE);
      Eclipse.setGeneratedBy(callToSuper.receiver, source);
      callToSuper.selector = "equals".toCharArray();
      SingleNameReference oRef = new SingleNameReference(new char[] {'o'}, p);
      Eclipse.setGeneratedBy(oRef, source);
      callToSuper.arguments = new Expression[] {oRef};
      Expression superNotEqual = new UnaryExpression(callToSuper, OperatorIds.NOT);
      Eclipse.setGeneratedBy(superNotEqual, source);
      FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
      Eclipse.setGeneratedBy(falseLiteral, source);
      ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE);
      Eclipse.setGeneratedBy(returnFalse, source);
      IfStatement ifSuperEquals = new IfStatement(superNotEqual, returnFalse, pS, pE);
      Eclipse.setGeneratedBy(ifSuperEquals, source);
      statements.add(ifSuperEquals);
    }

    for (EclipseNode field : fields) {
      TypeReference fType = getFieldType(field, fieldAccess);
      char[] token = fType.getLastToken();
      Expression thisFieldAccessor = createFieldAccessor(field, fieldAccess, source);
      Expression otherFieldAccessor = createFieldAccessor(field, fieldAccess, source, otherName);

      if (fType.dimensions() == 0 && token != null) {
        if (Arrays.equals(TypeConstants.FLOAT, token)) {
          statements.add(
              generateCompareFloatOrDouble(
                  thisFieldAccessor, otherFieldAccessor, "Float".toCharArray(), source));
        } else if (Arrays.equals(TypeConstants.DOUBLE, token)) {
          statements.add(
              generateCompareFloatOrDouble(
                  thisFieldAccessor, otherFieldAccessor, "Double".toCharArray(), source));
        } else if (BUILT_IN_TYPES.contains(new String(token))) {
          EqualExpression fieldsNotEqual =
              new EqualExpression(thisFieldAccessor, otherFieldAccessor, OperatorIds.NOT_EQUAL);
          Eclipse.setGeneratedBy(fieldsNotEqual, source);
          FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
          Eclipse.setGeneratedBy(falseLiteral, source);
          ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE);
          Eclipse.setGeneratedBy(returnStatement, source);
          IfStatement ifStatement = new IfStatement(fieldsNotEqual, returnStatement, pS, pE);
          Eclipse.setGeneratedBy(ifStatement, source);
          statements.add(ifStatement);
        } else /* objects */ {
          NullLiteral nullLiteral = new NullLiteral(pS, pE);
          Eclipse.setGeneratedBy(nullLiteral, source);
          EqualExpression fieldIsNull =
              new EqualExpression(thisFieldAccessor, nullLiteral, OperatorIds.EQUAL_EQUAL);
          nullLiteral = new NullLiteral(pS, pE);
          Eclipse.setGeneratedBy(nullLiteral, source);
          EqualExpression otherFieldIsntNull =
              new EqualExpression(otherFieldAccessor, nullLiteral, OperatorIds.NOT_EQUAL);
          MessageSend equalsCall = new MessageSend();
          equalsCall.sourceStart = pS;
          equalsCall.sourceEnd = pE;
          Eclipse.setGeneratedBy(equalsCall, source);
          equalsCall.receiver = createFieldAccessor(field, fieldAccess, source);
          equalsCall.selector = "equals".toCharArray();
          Expression equalsArg = createFieldAccessor(field, fieldAccess, source, otherName);
          CastExpression castEqualsArg =
              new CastExpression(
                  equalsArg, generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_OBJECT));
          Eclipse.setGeneratedBy(castEqualsArg, source);
          castEqualsArg.sourceStart = pS;
          castEqualsArg.sourceEnd = pE;
          equalsCall.arguments = new Expression[] {castEqualsArg};
          UnaryExpression fieldsNotEqual = new UnaryExpression(equalsCall, OperatorIds.NOT);
          fieldsNotEqual.sourceStart = pS;
          fieldsNotEqual.sourceEnd = pE;
          Eclipse.setGeneratedBy(fieldsNotEqual, source);
          ConditionalExpression fullEquals =
              new ConditionalExpression(fieldIsNull, otherFieldIsntNull, fieldsNotEqual);
          fullEquals.sourceStart = pS;
          fullEquals.sourceEnd = pE;
          Eclipse.setGeneratedBy(fullEquals, source);
          FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
          Eclipse.setGeneratedBy(falseLiteral, source);
          ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE);
          Eclipse.setGeneratedBy(returnStatement, source);
          IfStatement ifStatement = new IfStatement(fullEquals, returnStatement, pS, pE);
          Eclipse.setGeneratedBy(ifStatement, source);
          statements.add(ifStatement);
        }
      } else if (fType.dimensions() > 0 && token != null) {
        MessageSend arraysEqualCall = new MessageSend();
        arraysEqualCall.sourceStart = pS;
        arraysEqualCall.sourceEnd = pE;
        Eclipse.setGeneratedBy(arraysEqualCall, source);
        arraysEqualCall.receiver =
            generateQualifiedNameRef(
                source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
        if (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) {
          arraysEqualCall.selector = "deepEquals".toCharArray();
        } else {
          arraysEqualCall.selector = "equals".toCharArray();
        }
        arraysEqualCall.arguments = new Expression[] {thisFieldAccessor, otherFieldAccessor};
        UnaryExpression arraysNotEqual = new UnaryExpression(arraysEqualCall, OperatorIds.NOT);
        arraysNotEqual.sourceStart = pS;
        arraysNotEqual.sourceEnd = pE;
        Eclipse.setGeneratedBy(arraysNotEqual, source);
        FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
        Eclipse.setGeneratedBy(falseLiteral, source);
        ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE);
        Eclipse.setGeneratedBy(returnStatement, source);
        IfStatement ifStatement = new IfStatement(arraysNotEqual, returnStatement, pS, pE);
        Eclipse.setGeneratedBy(ifStatement, source);
        statements.add(ifStatement);
      }
    }

    /* return true; */ {
      TrueLiteral trueLiteral = new TrueLiteral(pS, pE);
      Eclipse.setGeneratedBy(trueLiteral, source);
      ReturnStatement returnStatement = new ReturnStatement(trueLiteral, pS, pE);
      Eclipse.setGeneratedBy(returnStatement, source);
      statements.add(returnStatement);
    }
    method.statements = statements.toArray(new Statement[statements.size()]);
    return method;
  }
コード例 #14
0
  private MethodDeclaration createHashCode(
      EclipseNode type,
      Collection<EclipseNode> fields,
      boolean callSuper,
      ASTNode source,
      FieldAccess fieldAccess) {
    int pS = source.sourceStart, pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;

    MethodDeclaration method =
        new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(method, source);

    method.modifiers = EclipseHandlerUtil.toEclipseModifier(AccessLevel.PUBLIC);
    method.returnType = TypeReference.baseTypeReference(TypeIds.T_int, 0);
    Eclipse.setGeneratedBy(method.returnType, source);
    method.annotations =
        new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
    method.selector = "hashCode".toCharArray();
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
    method.arguments = null;

    List<Statement> statements = new ArrayList<Statement>();
    List<Expression> intoResult = new ArrayList<Expression>();

    final char[] PRIME = "PRIME".toCharArray();
    final char[] RESULT = "result".toCharArray();
    final boolean isEmpty = fields.isEmpty();

    /* final int PRIME = 31; */ {
      /* Without fields, PRIME isn't used, and that would trigger a 'local variable not used' warning. */
      if (!isEmpty || callSuper) {
        LocalDeclaration primeDecl = new LocalDeclaration(PRIME, pS, pE);
        Eclipse.setGeneratedBy(primeDecl, source);
        primeDecl.modifiers |= Modifier.FINAL;
        primeDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
        primeDecl.type.sourceStart = pS;
        primeDecl.type.sourceEnd = pE;
        Eclipse.setGeneratedBy(primeDecl.type, source);
        primeDecl.initialization = new IntLiteral("31".toCharArray(), pS, pE);
        Eclipse.setGeneratedBy(primeDecl.initialization, source);
        statements.add(primeDecl);
      }
    }

    /* int result = 1; */ {
      LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE);
      Eclipse.setGeneratedBy(resultDecl, source);
      resultDecl.initialization = new IntLiteral("1".toCharArray(), pS, pE);
      Eclipse.setGeneratedBy(resultDecl.initialization, source);
      resultDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
      resultDecl.type.sourceStart = pS;
      resultDecl.type.sourceEnd = pE;
      Eclipse.setGeneratedBy(resultDecl.type, source);
      statements.add(resultDecl);
    }

    if (callSuper) {
      MessageSend callToSuper = new MessageSend();
      Eclipse.setGeneratedBy(callToSuper, source);
      callToSuper.sourceStart = pS;
      callToSuper.sourceEnd = pE;
      callToSuper.receiver = new SuperReference(pS, pE);
      Eclipse.setGeneratedBy(callToSuper.receiver, source);
      callToSuper.selector = "hashCode".toCharArray();
      intoResult.add(callToSuper);
    }

    int tempCounter = 0;
    for (EclipseNode field : fields) {
      TypeReference fType = getFieldType(field, fieldAccess);
      char[] token = fType.getLastToken();
      Expression fieldAccessor = createFieldAccessor(field, fieldAccess, source);
      if (fType.dimensions() == 0 && token != null) {
        if (Arrays.equals(TypeConstants.FLOAT, token)) {
          /* Float.floatToIntBits(fieldName) */
          MessageSend floatToIntBits = new MessageSend();
          floatToIntBits.sourceStart = pS;
          floatToIntBits.sourceEnd = pE;
          Eclipse.setGeneratedBy(floatToIntBits, source);
          floatToIntBits.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_FLOAT);
          floatToIntBits.selector = "floatToIntBits".toCharArray();
          floatToIntBits.arguments = new Expression[] {fieldAccessor};
          intoResult.add(floatToIntBits);
        } else if (Arrays.equals(TypeConstants.DOUBLE, token)) {
          /* longToIntForHashCode(Double.doubleToLongBits(fieldName)) */
          MessageSend doubleToLongBits = new MessageSend();
          doubleToLongBits.sourceStart = pS;
          doubleToLongBits.sourceEnd = pE;
          Eclipse.setGeneratedBy(doubleToLongBits, source);
          doubleToLongBits.receiver =
              generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_DOUBLE);
          doubleToLongBits.selector = "doubleToLongBits".toCharArray();
          doubleToLongBits.arguments = new Expression[] {fieldAccessor};
          final char[] tempName = ("temp" + ++tempCounter).toCharArray();
          LocalDeclaration tempVar = new LocalDeclaration(tempName, pS, pE);
          Eclipse.setGeneratedBy(tempVar, source);
          tempVar.initialization = doubleToLongBits;
          tempVar.type = TypeReference.baseTypeReference(TypeIds.T_long, 0);
          tempVar.type.sourceStart = pS;
          tempVar.type.sourceEnd = pE;
          Eclipse.setGeneratedBy(tempVar.type, source);
          tempVar.modifiers = Modifier.FINAL;
          statements.add(tempVar);
          SingleNameReference copy1 = new SingleNameReference(tempName, p);
          Eclipse.setGeneratedBy(copy1, source);
          SingleNameReference copy2 = new SingleNameReference(tempName, p);
          Eclipse.setGeneratedBy(copy2, source);
          intoResult.add(longToIntForHashCode(copy1, copy2, source));
        } else if (Arrays.equals(TypeConstants.BOOLEAN, token)) {
          /* booleanField ? 1231 : 1237 */
          IntLiteral int1231 = new IntLiteral("1231".toCharArray(), pS, pE);
          Eclipse.setGeneratedBy(int1231, source);
          IntLiteral int1237 = new IntLiteral("1237".toCharArray(), pS, pE);
          Eclipse.setGeneratedBy(int1237, source);
          ConditionalExpression int1231or1237 =
              new ConditionalExpression(fieldAccessor, int1231, int1237);
          Eclipse.setGeneratedBy(int1231or1237, source);
          intoResult.add(int1231or1237);
        } else if (Arrays.equals(TypeConstants.LONG, token)) {
          intoResult.add(
              longToIntForHashCode(
                  fieldAccessor, createFieldAccessor(field, fieldAccess, source), source));
        } else if (BUILT_IN_TYPES.contains(new String(token))) {
          intoResult.add(fieldAccessor);
        } else /* objects */ {
          /* this.fieldName == null ? 0 : this.fieldName.hashCode() */
          MessageSend hashCodeCall = new MessageSend();
          hashCodeCall.sourceStart = pS;
          hashCodeCall.sourceEnd = pE;
          Eclipse.setGeneratedBy(hashCodeCall, source);
          hashCodeCall.receiver = createFieldAccessor(field, fieldAccess, source);
          hashCodeCall.selector = "hashCode".toCharArray();
          NullLiteral nullLiteral = new NullLiteral(pS, pE);
          Eclipse.setGeneratedBy(nullLiteral, source);
          EqualExpression objIsNull =
              new EqualExpression(fieldAccessor, nullLiteral, OperatorIds.EQUAL_EQUAL);
          Eclipse.setGeneratedBy(objIsNull, source);
          IntLiteral int0 = new IntLiteral("0".toCharArray(), pS, pE);
          Eclipse.setGeneratedBy(int0, source);
          ConditionalExpression nullOrHashCode =
              new ConditionalExpression(objIsNull, int0, hashCodeCall);
          nullOrHashCode.sourceStart = pS;
          nullOrHashCode.sourceEnd = pE;
          Eclipse.setGeneratedBy(nullOrHashCode, source);
          intoResult.add(nullOrHashCode);
        }
      } else if (fType.dimensions() > 0 && token != null) {
        /* Arrays.deepHashCode(array)  //just hashCode for simple arrays */
        MessageSend arraysHashCodeCall = new MessageSend();
        arraysHashCodeCall.sourceStart = pS;
        arraysHashCodeCall.sourceEnd = pE;
        Eclipse.setGeneratedBy(arraysHashCodeCall, source);
        arraysHashCodeCall.receiver =
            generateQualifiedNameRef(
                source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
        if (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) {
          arraysHashCodeCall.selector = "deepHashCode".toCharArray();
        } else {
          arraysHashCodeCall.selector = "hashCode".toCharArray();
        }
        arraysHashCodeCall.arguments = new Expression[] {fieldAccessor};
        intoResult.add(arraysHashCodeCall);
      }
    }

    /* fold each intoResult entry into:
    result = result * PRIME + (item); */ {
      for (Expression ex : intoResult) {
        SingleNameReference resultRef = new SingleNameReference(RESULT, p);
        Eclipse.setGeneratedBy(resultRef, source);
        SingleNameReference primeRef = new SingleNameReference(PRIME, p);
        Eclipse.setGeneratedBy(primeRef, source);
        BinaryExpression multiplyByPrime =
            new BinaryExpression(resultRef, primeRef, OperatorIds.MULTIPLY);
        multiplyByPrime.sourceStart = pS;
        multiplyByPrime.sourceEnd = pE;
        Eclipse.setGeneratedBy(multiplyByPrime, source);
        BinaryExpression addItem = new BinaryExpression(multiplyByPrime, ex, OperatorIds.PLUS);
        addItem.sourceStart = pS;
        addItem.sourceEnd = pE;
        Eclipse.setGeneratedBy(addItem, source);
        resultRef = new SingleNameReference(RESULT, p);
        Eclipse.setGeneratedBy(resultRef, source);
        Assignment assignment = new Assignment(resultRef, addItem, pE);
        assignment.sourceStart = pS;
        assignment.sourceEnd = pE;
        Eclipse.setGeneratedBy(assignment, source);
        statements.add(assignment);
      }
    }

    /* return result; */ {
      SingleNameReference resultRef = new SingleNameReference(RESULT, p);
      Eclipse.setGeneratedBy(resultRef, source);
      ReturnStatement returnStatement = new ReturnStatement(resultRef, pS, pE);
      Eclipse.setGeneratedBy(returnStatement, source);
      statements.add(returnStatement);
    }
    method.statements = statements.toArray(new Statement[statements.size()]);
    return method;
  }
コード例 #15
0
ファイル: HandleToString.java プロジェクト: Reder/lombok
  private MethodDeclaration createToString(
      EclipseNode type,
      Collection<EclipseNode> fields,
      boolean includeFieldNames,
      boolean callSuper,
      ASTNode source,
      FieldAccess fieldAccess) {
    String typeName = getTypeName(type);
    char[] suffix = ")".toCharArray();
    String infixS = ", ";
    char[] infix = infixS.toCharArray();
    int pS = source.sourceStart, pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;
    final int PLUS = OperatorIds.PLUS;

    char[] prefix;

    if (callSuper) {
      prefix = (typeName + "(super=").toCharArray();
    } else if (fields.isEmpty()) {
      prefix = (typeName + "()").toCharArray();
    } else if (includeFieldNames) {
      prefix =
          (typeName
                  + "("
                  + new String(((FieldDeclaration) fields.iterator().next().get()).name)
                  + "=")
              .toCharArray();
    } else {
      prefix = (typeName + "(").toCharArray();
    }

    boolean first = true;
    Expression current = new StringLiteral(prefix, pS, pE, 0);
    Eclipse.setGeneratedBy(current, source);

    if (callSuper) {
      MessageSend callToSuper = new MessageSend();
      callToSuper.sourceStart = pS;
      callToSuper.sourceEnd = pE;
      Eclipse.setGeneratedBy(callToSuper, source);
      callToSuper.receiver = new SuperReference(pS, pE);
      Eclipse.setGeneratedBy(callToSuper, source);
      callToSuper.selector = "toString".toCharArray();
      current = new BinaryExpression(current, callToSuper, PLUS);
      Eclipse.setGeneratedBy(current, source);
      first = false;
    }

    for (EclipseNode field : fields) {
      TypeReference fType = getFieldType(field, fieldAccess);
      Expression fieldAccessor = createFieldAccessor(field, fieldAccess, source);

      Expression ex;
      if (fType.dimensions() > 0) {
        MessageSend arrayToString = new MessageSend();
        arrayToString.sourceStart = pS;
        arrayToString.sourceEnd = pE;
        arrayToString.receiver =
            generateQualifiedNameRef(
                source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
        arrayToString.arguments = new Expression[] {fieldAccessor};
        Eclipse.setGeneratedBy(arrayToString.arguments[0], source);
        if (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(fType.getLastToken()))) {
          arrayToString.selector = "deepToString".toCharArray();
        } else {
          arrayToString.selector = "toString".toCharArray();
        }
        ex = arrayToString;
      } else {
        ex = fieldAccessor;
      }
      Eclipse.setGeneratedBy(ex, source);

      if (first) {
        current = new BinaryExpression(current, ex, PLUS);
        current.sourceStart = pS;
        current.sourceEnd = pE;
        Eclipse.setGeneratedBy(current, source);
        first = false;
        continue;
      }

      StringLiteral fieldNameLiteral;
      if (includeFieldNames) {
        char[] namePlusEqualsSign = (infixS + field.getName() + "=").toCharArray();
        fieldNameLiteral = new StringLiteral(namePlusEqualsSign, pS, pE, 0);
      } else {
        fieldNameLiteral = new StringLiteral(infix, pS, pE, 0);
      }
      Eclipse.setGeneratedBy(fieldNameLiteral, source);
      current = new BinaryExpression(current, fieldNameLiteral, PLUS);
      Eclipse.setGeneratedBy(current, source);
      current = new BinaryExpression(current, ex, PLUS);
      Eclipse.setGeneratedBy(current, source);
    }
    if (!first) {
      StringLiteral suffixLiteral = new StringLiteral(suffix, pS, pE, 0);
      Eclipse.setGeneratedBy(suffixLiteral, source);
      current = new BinaryExpression(current, suffixLiteral, PLUS);
      Eclipse.setGeneratedBy(current, source);
    }

    ReturnStatement returnStatement = new ReturnStatement(current, pS, pE);
    Eclipse.setGeneratedBy(returnStatement, source);

    MethodDeclaration method =
        new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(method, source);
    method.modifiers = toEclipseModifier(AccessLevel.PUBLIC);
    method.returnType =
        new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p, p, p});
    Eclipse.setGeneratedBy(method.returnType, source);
    method.annotations =
        new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
    method.arguments = null;
    method.selector = "toString".toCharArray();
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
    method.statements = new Statement[] {returnStatement};
    return method;
  }