Example usage for org.eclipse.jdt.internal.compiler.ast FieldReference FieldReference

List of usage examples for org.eclipse.jdt.internal.compiler.ast FieldReference FieldReference

Introduction

In this page you can find the example usage for org.eclipse.jdt.internal.compiler.ast FieldReference FieldReference.

Prototype

public FieldReference(char[] source, long pos) 

Source Link

Usage

From source file:lombok.eclipse.handlers.ast.EclipseASTMaker.java

License:Open Source License

@Override
public ASTNode visitFieldRef(final lombok.ast.FieldRef node, final Void p) {
    FieldReference fieldRef = new FieldReference(node.getName().toCharArray(), 0);
    fieldRef.receiver = build(node.getReceiver());
    setGeneratedByAndCopyPos(fieldRef, source, posHintOf(node));
    return fieldRef;
}

From source file:lombok.eclipse.handlers.EclipseHandlerUtil.java

License:Open Source License

static Expression createFieldAccessor(EclipseNode field, FieldAccess fieldAccess, ASTNode source) {
    int pS = source == null ? 0 : source.sourceStart, pE = source == null ? 0 : source.sourceEnd;
    long p = (long) pS << 32 | pE;

    boolean lookForGetter = lookForGetter(field, fieldAccess);

    GetterMethod getter = lookForGetter ? findGetter(field) : null;

    if (getter == null) {
        FieldDeclaration fieldDecl = (FieldDeclaration) field.get();
        FieldReference ref = new FieldReference(fieldDecl.name, p);
        if ((fieldDecl.modifiers & ClassFileConstants.AccStatic) != 0) {
            EclipseNode containerNode = field.up();
            if (containerNode != null && containerNode.get() instanceof TypeDeclaration) {
                ref.receiver = new SingleNameReference(((TypeDeclaration) containerNode.get()).name, p);
            } else {
                Expression smallRef = new FieldReference(field.getName().toCharArray(), p);
                if (source != null)
                    setGeneratedBy(smallRef, source);
                return smallRef;
            }//  w  w w  .  ja  va 2  s . c  om
        } else {
            ref.receiver = new ThisReference(pS, pE);
        }

        if (source != null) {
            setGeneratedBy(ref, source);
            setGeneratedBy(ref.receiver, source);
        }
        return ref;
    }

    MessageSend call = new MessageSend();
    setGeneratedBy(call, source);
    call.sourceStart = pS;
    call.statementEnd = call.sourceEnd = pE;
    call.receiver = new ThisReference(pS, pE);
    setGeneratedBy(call.receiver, source);
    call.selector = getter.name;
    return call;
}

From source file:lombok.eclipse.handlers.HandleBuilder.java

License:Open Source License

private MethodDeclaration generateToBuilderMethod(String methodName, String builderClassName, EclipseNode type,
        TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source) {
    // return new ThingieBuilder<A, B>().setA(this.a).setB(this.b);

    int pS = source.sourceStart, pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;

    MethodDeclaration out = new MethodDeclaration(
            ((CompilationUnitDeclaration) type.top().get()).compilationResult);
    out.selector = methodName.toCharArray();
    out.modifiers = ClassFileConstants.AccPublic;
    out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    out.returnType = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
    AllocationExpression invoke = new AllocationExpression();
    invoke.type = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);

    Expression receiver = invoke;
    for (BuilderFieldData bfd : builderFields) {
        char[] setterName = fluent ? bfd.name
                : HandlerUtil.buildAccessorName("set", new String(bfd.name)).toCharArray();
        MessageSend ms = new MessageSend();
        if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
            char[] fieldName = bfd.obtainVia == null ? bfd.rawName : bfd.obtainVia.field().toCharArray();
            FieldReference fr = new FieldReference(fieldName, 0);
            fr.receiver = new ThisReference(0, 0);
            ms.arguments = new Expression[] { fr };
        } else {/*from w  w  w.  j  a  v  a2 s.c  o m*/
            String obtainName = bfd.obtainVia.method();
            boolean obtainIsStatic = bfd.obtainVia.isStatic();
            MessageSend obtainExpr = new MessageSend();
            obtainExpr.receiver = obtainIsStatic ? new SingleNameReference(type.getName().toCharArray(), 0)
                    : new ThisReference(0, 0);
            obtainExpr.selector = obtainName.toCharArray();
            if (obtainIsStatic)
                obtainExpr.arguments = new Expression[] { new ThisReference(0, 0) };
            ms.arguments = new Expression[] { obtainExpr };
        }
        ms.receiver = receiver;
        ms.selector = setterName;
        receiver = ms;
    }

    out.statements = new Statement[] { new ReturnStatement(receiver, pS, pE) };

    out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
    return out;

}

From source file:lombok.eclipse.handlers.HandleBuilder.java

License:Open Source License

private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType,
        ASTNode source) {//  ww w.  ja  v a 2s.  c  o  m
    List<Statement> statements = new ArrayList<Statement>();

    for (BuilderFieldData bfd : builderFields) {
        if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
            bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, builderType, statements);
        }
    }

    FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
    thisUnclean.receiver = new ThisReference(0, 0);
    statements.add(new Assignment(thisUnclean, new FalseLiteral(0, 0), 0));
    MethodDeclaration decl = new MethodDeclaration(
            ((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
    decl.selector = CLEAN_METHOD_NAME;
    decl.modifiers = ClassFileConstants.AccPrivate;
    decl.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    decl.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
    decl.statements = statements.toArray(new Statement[0]);
    decl.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
    return decl;
}

From source file:lombok.eclipse.handlers.HandleBuilder.java

License:Open Source License

public MethodDeclaration generateBuildMethod(String name, char[] staticName, TypeReference returnType,
        List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions,
        boolean addCleaning, ASTNode source) {
    MethodDeclaration out = new MethodDeclaration(
            ((CompilationUnitDeclaration) type.top().get()).compilationResult);
    out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    List<Statement> statements = new ArrayList<Statement>();

    if (addCleaning) {
        FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
        thisUnclean.receiver = new ThisReference(0, 0);
        Expression notClean = new UnaryExpression(thisUnclean, OperatorIds.NOT);
        MessageSend invokeClean = new MessageSend();
        invokeClean.selector = CLEAN_METHOD_NAME;
        statements.add(new IfStatement(notClean, invokeClean, 0, 0));
    }/*from w  w w. j a  v  a 2s. co m*/

    for (BuilderFieldData bfd : builderFields) {
        if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
            bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name);
        }
    }

    List<Expression> args = new ArrayList<Expression>();
    for (BuilderFieldData bfd : builderFields) {
        args.add(new SingleNameReference(bfd.name, 0L));
    }

    if (addCleaning) {
        FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
        thisUnclean.receiver = new ThisReference(0, 0);
        statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0));
    }

    out.modifiers = ClassFileConstants.AccPublic;
    out.selector = name.toCharArray();
    out.thrownExceptions = copyTypes(thrownExceptions);
    out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    out.returnType = returnType;

    if (staticName == null) {
        AllocationExpression allocationStatement = new AllocationExpression();
        allocationStatement.type = copyType(out.returnType);
        allocationStatement.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]);
        statements.add(new ReturnStatement(allocationStatement, 0, 0));
    } else {
        MessageSend invoke = new MessageSend();
        invoke.selector = staticName;
        invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0);
        TypeParameter[] tps = ((TypeDeclaration) type.get()).typeParameters;
        if (tps != null) {
            TypeReference[] trs = new TypeReference[tps.length];
            for (int i = 0; i < trs.length; i++) {
                trs[i] = new SingleTypeReference(tps[i].name, 0);
            }
            invoke.typeArguments = trs;
        }
        invoke.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]);
        if (returnType instanceof SingleTypeReference
                && Arrays.equals(TypeConstants.VOID, ((SingleTypeReference) returnType).token)) {
            statements.add(invoke);
        } else {
            statements.add(new ReturnStatement(invoke, 0, 0));
        }
    }
    out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[statements.size()]);
    out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
    return out;
}

From source file:lombok.eclipse.handlers.HandleConstructor.java

License:Open Source License

public static ConstructorDeclaration createConstructor(AccessLevel level, EclipseNode type,
        Collection<EclipseNode> fields, boolean allToDefault, Boolean suppressConstructorProperties,
        EclipseNode sourceNode, List<Annotation> onConstructor) {

    ASTNode source = sourceNode.get();/* ww  w.  j  a  v a 2  s. co  m*/
    TypeDeclaration typeDeclaration = ((TypeDeclaration) type.get());
    long p = (long) source.sourceStart << 32 | source.sourceEnd;

    boolean isEnum = (((TypeDeclaration) type.get()).modifiers & ClassFileConstants.AccEnum) != 0;

    if (isEnum)
        level = AccessLevel.PRIVATE;

    if (suppressConstructorProperties == null) {
        if (fields.isEmpty()) {
            suppressConstructorProperties = false;
        } else {
            suppressConstructorProperties = Boolean.TRUE.equals(type.getAst()
                    .readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
        }
    }

    ConstructorDeclaration constructor = new ConstructorDeclaration(
            ((CompilationUnitDeclaration) type.top().get()).compilationResult);

    constructor.modifiers = toEclipseModifier(level);
    constructor.selector = typeDeclaration.name;
    constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
    constructor.constructorCall.sourceStart = source.sourceStart;
    constructor.constructorCall.sourceEnd = source.sourceEnd;
    constructor.thrownExceptions = null;
    constructor.typeParameters = null;
    constructor.bits |= 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> params = new ArrayList<Argument>();
    List<Statement> assigns = new ArrayList<Statement>();
    List<Statement> nullChecks = new ArrayList<Statement>();

    for (EclipseNode fieldNode : fields) {
        FieldDeclaration field = (FieldDeclaration) fieldNode.get();
        char[] rawName = field.name;
        char[] fieldName = removePrefixFromField(fieldNode);
        FieldReference thisX = new FieldReference(rawName, p);
        int s = (int) (p >> 32);
        int e = (int) p;
        thisX.receiver = new ThisReference(s, e);

        Expression assignmentExpr = allToDefault ? getDefaultExpr(field.type, s, e)
                : new SingleNameReference(fieldName, p);

        Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p);
        assignment.sourceStart = (int) (p >> 32);
        assignment.sourceEnd = assignment.statementEnd = (int) (p >> 32);
        assigns.add(assignment);
        if (!allToDefault) {
            long fieldPos = (((long) field.sourceStart) << 32) | field.sourceEnd;
            Argument parameter = new Argument(fieldName, fieldPos, copyType(field.type, source),
                    Modifier.FINAL);
            Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
            Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
            if (nonNulls.length != 0) {
                Statement nullCheck = generateNullCheck(field, sourceNode);
                if (nullCheck != null)
                    nullChecks.add(nullCheck);
            }
            parameter.annotations = copyAnnotations(source, nonNulls, nullables);
            params.add(parameter);
        }
    }

    nullChecks.addAll(assigns);
    constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]);
    constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]);

    /* Generate annotations that must  be put on the generated method, and attach them. */ {
        Annotation[] constructorProperties = null;
        if (!allToDefault && !suppressConstructorProperties && level != AccessLevel.PRIVATE
                && level != AccessLevel.PACKAGE && !isLocalType(type)) {
            constructorProperties = createConstructorProperties(source, fields);
        }

        constructor.annotations = copyAnnotations(source, onConstructor.toArray(new Annotation[0]),
                constructorProperties);
    }

    constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
    return constructor;
}

From source file:lombok.eclipse.handlers.HandleSuperBuilder.java

License:Open Source License

/**
 * Generates a constructor that has a builder as the only parameter.
 * The values from the builder are used to initialize the fields of new instances.
 *
 * @param typeNode//from w w w  .jav  a2s .  co m
 *            the type (with the {@code @Builder} annotation) for which a
 *            constructor should be generated.
 * @param typeParams
 * @param builderFields a list of fields in the builder which should be assigned to new instances.
 * @param source the annotation (used for setting source code locations for the generated code).
 * @param callBuilderBasedSuperConstructor
 *            If {@code true}, the constructor will explicitly call a super
 *            constructor with the builder as argument. Requires
 *            {@code builderClassAsParameter != null}.
 */
private void generateBuilderBasedConstructor(EclipseNode typeNode, TypeParameter[] typeParams,
        List<BuilderFieldData> builderFields, EclipseNode sourceNode, String builderClassName,
        boolean callBuilderBasedSuperConstructor) {

    ASTNode source = sourceNode.get();

    TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get());
    long p = (long) source.sourceStart << 32 | source.sourceEnd;

    ConstructorDeclaration constructor = new ConstructorDeclaration(
            ((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);

    constructor.modifiers = toEclipseModifier(AccessLevel.PROTECTED);
    constructor.selector = typeDeclaration.name;
    if (callBuilderBasedSuperConstructor) {
        constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super);
        constructor.constructorCall.arguments = new Expression[] {
                new SingleNameReference(BUILDER_VARIABLE_NAME, p) };
    } else {
        constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
    }
    constructor.constructorCall.sourceStart = source.sourceStart;
    constructor.constructorCall.sourceEnd = source.sourceEnd;
    constructor.thrownExceptions = null;
    constructor.typeParameters = null;
    constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
    constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;

    TypeReference[] wildcards = new TypeReference[] { new Wildcard(Wildcard.UNBOUND),
            new Wildcard(Wildcard.UNBOUND) };
    TypeReference builderType = new ParameterizedSingleTypeReference(builderClassName.toCharArray(),
            mergeToTypeReferences(typeParams, wildcards), 0, p);
    constructor.arguments = new Argument[] {
            new Argument(BUILDER_VARIABLE_NAME, p, builderType, Modifier.FINAL) };

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

    for (BuilderFieldData fieldNode : builderFields) {
        char[] fieldName = removePrefixFromField(fieldNode.originalFieldNode);
        FieldReference fieldInThis = new FieldReference(fieldNode.rawName, p);
        int s = (int) (p >> 32);
        int e = (int) p;
        fieldInThis.receiver = new ThisReference(s, e);

        Expression assignmentExpr;
        if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) {
            fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode,
                    statements, fieldNode.name, BUILDER_VARIABLE_NAME_STRING);
            assignmentExpr = new SingleNameReference(fieldNode.name, p);
        } else {
            char[][] variableInBuilder = new char[][] { BUILDER_VARIABLE_NAME, fieldName };
            long[] positions = new long[] { p, p };
            assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e);
        }
        Statement assignment = new Assignment(fieldInThis, assignmentExpr, (int) p);

        // In case of @Builder.Default, set the value to the default if it was NOT set in the builder.
        if (fieldNode.nameOfSetFlag != null) {
            char[][] setVariableInBuilder = new char[][] { BUILDER_VARIABLE_NAME, fieldNode.nameOfSetFlag };
            long[] positions = new long[] { p, p };
            QualifiedNameReference setVariableInBuilderRef = new QualifiedNameReference(setVariableInBuilder,
                    positions, s, e);

            MessageSend defaultMethodCall = new MessageSend();
            defaultMethodCall.sourceStart = source.sourceStart;
            defaultMethodCall.sourceEnd = source.sourceEnd;
            defaultMethodCall.receiver = new SingleNameReference(((TypeDeclaration) typeNode.get()).name, 0L);
            defaultMethodCall.selector = fieldNode.nameOfDefaultProvider;
            defaultMethodCall.typeArguments = typeParameterNames(
                    ((TypeDeclaration) typeNode.get()).typeParameters);

            Statement defaultAssignment = new Assignment(fieldInThis, defaultMethodCall, (int) p);
            IfStatement ifBlockForDefault = new IfStatement(setVariableInBuilderRef, assignment,
                    defaultAssignment, s, e);
            statements.add(ifBlockForDefault);
        } else {
            statements.add(assignment);
        }

        if (hasNonNullAnnotations(fieldNode.originalFieldNode)) {
            Statement nullCheck = generateNullCheck((FieldDeclaration) fieldNode.originalFieldNode.get(),
                    sourceNode);
            if (nullCheck != null)
                statements.add(nullCheck);
        }
    }

    constructor.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);

    constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);

    injectMethod(typeNode, constructor);
}

From source file:lombok.eclipse.handlers.HandleSuperBuilder.java

License:Open Source License

private MessageSend createSetterCallWithInstanceValue(BuilderFieldData bfd, EclipseNode type, ASTNode source) {
    char[] setterName = bfd.name;
    MessageSend ms = new MessageSend();
    Expression[] tgt = new Expression[bfd.singularData == null ? 1 : 2];

    if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
        char[] fieldName = bfd.obtainVia == null ? bfd.rawName : bfd.obtainVia.field().toCharArray();
        for (int i = 0; i < tgt.length; i++) {
            FieldReference fr = new FieldReference(fieldName, 0);
            fr.receiver = new SingleNameReference(INSTANCE_VARIABLE_NAME, 0);
            tgt[i] = fr;/*from  w  w  w  .  ja v  a2  s  . com*/
        }
    } else {
        String obtainName = bfd.obtainVia.method();
        boolean obtainIsStatic = bfd.obtainVia.isStatic();
        for (int i = 0; i < tgt.length; i++) {
            MessageSend obtainExpr = new MessageSend();
            obtainExpr.receiver = obtainIsStatic ? new SingleNameReference(type.getName().toCharArray(), 0)
                    : new SingleNameReference(INSTANCE_VARIABLE_NAME, 0);
            obtainExpr.selector = obtainName.toCharArray();
            if (obtainIsStatic)
                obtainExpr.arguments = new Expression[] { new SingleNameReference(INSTANCE_VARIABLE_NAME, 0) };
            tgt[i] = obtainExpr;
        }
    }
    if (bfd.singularData == null) {
        ms.arguments = tgt;
    } else {
        Expression ifNull = new EqualExpression(tgt[0], new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
        MessageSend emptyList = new MessageSend();
        emptyList.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL,
                "Collections".toCharArray());
        emptyList.selector = EMPTY_LIST;
        ms.arguments = new Expression[] { new ConditionalExpression(ifNull, emptyList, tgt[1]) };
    }
    ms.receiver = new SingleNameReference(BUILDER_VARIABLE_NAME, 0);
    ms.selector = setterName;
    return ms;
}

From source file:lombok.eclipse.handlers.HandleSynchronized.java

License:Open Source License

@Override
public void handle(AnnotationValues<Synchronized> annotation, Annotation source, EclipseNode annotationNode) {
    handleFlagUsage(annotationNode, ConfigurationKeys.SYNCHRONIZED_FLAG_USAGE, "@Synchronized");

    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;/*from  www .j  a  v a2 s. com*/
    }

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

    char[] lockName = createLockField(annotation, annotationNode, method.isStatic(), true);
    if (lockName == null)
        return;
    if (method.statements == null)
        return;

    Block block = new Block(0);
    setGeneratedBy(block, source);
    block.statements = method.statements;

    // Positions for in-method generated nodes are special
    block.sourceEnd = method.bodyEnd;
    block.sourceStart = method.bodyStart;

    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);
        setGeneratedBy(thisReference, source);
        ((FieldReference) lockVariable).receiver = thisReference;
    }
    setGeneratedBy(lockVariable, source);

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

    // Positions for in-method generated nodes are special
    method.statements[0].sourceEnd = method.bodyEnd;
    method.statements[0].sourceStart = method.bodyStart;

    setGeneratedBy(method.statements[0], source);

    methodNode.rebuild();
}

From source file:lombok.eclipse.handlers.singulars.EclipseGuavaSingularizer.java

License:Open Source License

void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data,
        EclipseNode builderType, boolean fluent) {
    boolean mapMode = isMap();
    char[] keyName = !mapMode ? data.getSingularName()
            : (new String(data.getSingularName()) + "$key").toCharArray();
    char[] valueName = !mapMode ? null : (new String(data.getSingularName()) + "$value").toCharArray();

    MethodDeclaration md = new MethodDeclaration(
            ((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
    md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    md.modifiers = ClassFileConstants.AccPublic;

    List<Statement> statements = new ArrayList<Statement>();
    statements.add(createConstructBuilderVarIfNeeded(data, builderType));

    FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
    thisDotField.receiver = new ThisReference(0, 0);
    MessageSend thisDotFieldDotAdd = new MessageSend();
    if (mapMode) {
        thisDotFieldDotAdd.arguments = new Expression[] { new SingleNameReference(keyName, 0L),
                new SingleNameReference(valueName, 0L) };
    } else {//from ww  w.  j  av a  2  s .  c o m
        thisDotFieldDotAdd.arguments = new Expression[] { new SingleNameReference(keyName, 0L) };
    }
    thisDotFieldDotAdd.receiver = thisDotField;
    thisDotFieldDotAdd.selector = (mapMode ? "put" : "add").toCharArray();
    statements.add(thisDotFieldDotAdd);
    if (returnStatement != null)
        statements.add(returnStatement);
    md.statements = statements.toArray(new Statement[statements.size()]);

    if (mapMode) {
        TypeReference keyType = cloneParamType(0, data.getTypeArgs(), builderType);
        Argument keyParam = new Argument(keyName, 0, keyType, 0);
        TypeReference valueType = cloneParamType(1, data.getTypeArgs(), builderType);
        Argument valueParam = new Argument(valueName, 0, valueType, 0);
        md.arguments = new Argument[] { keyParam, valueParam };
    } else {
        TypeReference paramType = cloneParamType(0, data.getTypeArgs(), builderType);
        Argument param = new Argument(keyName, 0, paramType, 0);
        md.arguments = new Argument[] { param };
    }
    md.returnType = returnType;
    md.selector = fluent ? data.getSingularName()
            : HandlerUtil.buildAccessorName(mapMode ? "put" : "add", new String(data.getSingularName()))
                    .toCharArray();

    data.setGeneratedByRecursive(md);
    injectMethod(builderType, md);
}