Example usage for org.eclipse.jdt.internal.compiler.ast MethodDeclaration traverse

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

Introduction

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

Prototype

@Override
    public void traverse(ASTVisitor visitor, ClassScope classScope) 

Source Link

Usage

From source file:com.codenvy.ide.ext.java.server.internal.core.search.matching.MatchLocatorParser.java

License:Open Source License

/**
 * Parses the member bodies in the given type.
 * @param type TypeDeclaration//from w  w  w  . j ava  2  s .  c o  m
 * @param unit CompilationUnitDeclaration
 */
protected void parseBodies(TypeDeclaration type, CompilationUnitDeclaration unit) {
    FieldDeclaration[] fields = type.fields;
    if (fields != null) {
        for (int i = 0; i < fields.length; i++) {
            FieldDeclaration field = fields[i];
            if (field instanceof Initializer)
                this.parse((Initializer) field, type, unit);
            field.traverse(this.localDeclarationVisitor, null);
        }
    }

    AbstractMethodDeclaration[] methods = type.methods;
    if (methods != null) {
        for (int i = 0; i < methods.length; i++) {
            AbstractMethodDeclaration method = methods[i];
            if (method.sourceStart >= type.bodyStart) { // if not synthetic
                if (method instanceof MethodDeclaration) {
                    MethodDeclaration methodDeclaration = (MethodDeclaration) method;
                    this.parse(methodDeclaration, unit);
                    methodDeclaration.traverse(this.localDeclarationVisitor, (ClassScope) null);
                } else if (method instanceof ConstructorDeclaration) {
                    ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) method;
                    this.parse(constructorDeclaration, unit, false);
                    constructorDeclaration.traverse(this.localDeclarationVisitor, (ClassScope) null);
                }
            } else if (method.isDefaultConstructor()) {
                method.parseStatements(this, unit);
            }
        }
    }

    TypeDeclaration[] memberTypes = type.memberTypes;
    if (memberTypes != null) {
        for (int i = 0; i < memberTypes.length; i++) {
            TypeDeclaration memberType = memberTypes[i];
            this.parseBodies(memberType, unit);
            memberType.traverse(this.localDeclarationVisitor, (ClassScope) null);
        }
    }
}

From source file:lombok.eclipse.agent.PatchDelegate.java

License:Open Source License

private static void generateDelegateMethods(EclipseNode typeNode, List<BindingTuple> methods,
        DelegateReceiver delegateReceiver) {
    CompilationUnitDeclaration top = (CompilationUnitDeclaration) typeNode.top().get();
    for (BindingTuple pair : methods) {
        EclipseNode annNode = typeNode.getAst().get(pair.responsible);
        MethodDeclaration method = createDelegateMethod(pair.fieldName, typeNode, pair, top.compilationResult,
                annNode, delegateReceiver);
        if (method != null) {
            SetGeneratedByVisitor visitor = new SetGeneratedByVisitor(annNode.get());
            method.traverse(visitor, ((TypeDeclaration) typeNode.get()).scope);
            injectMethod(typeNode, method);
        }//from ww  w .ja v  a2 s  .c  om
    }
}

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  www .  j  a v  a  2 s.  com*/
            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) {//  w w w .j av a  2 s.co  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  va2s .c  om*/

    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.HandleBuilder.java

License:Open Source License

public MethodDeclaration generateBuilderMethod(String builderMethodName, String builderClassName,
        EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
    int pS = source.sourceStart, pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;

    MethodDeclaration out = new MethodDeclaration(
            ((CompilationUnitDeclaration) type.top().get()).compilationResult);
    out.selector = builderMethodName.toCharArray();
    out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic;
    out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    out.returnType = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
    out.typeParameters = copyTypeParams(typeParams, source);
    AllocationExpression invoke = new AllocationExpression();
    invoke.type = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
    out.statements = new Statement[] { new ReturnStatement(invoke, pS, pE) };

    out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
    return out;//from  w  w w  .ja  va 2s .c  o  m
}

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

License:Open Source License

public MethodDeclaration createStaticConstructor(AccessLevel level, 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);

    constructor.modifiers = toEclipseModifier(level) | ClassFileConstants.AccStatic;
    TypeDeclaration typeDecl = (TypeDeclaration) type.get();
    constructor.returnType = EclipseHandlerUtil.namePlusTypeParamsToTypeReference(typeDecl.name,
            typeDecl.typeParameters, p);
    constructor.annotations = null;//w w w .j a  v  a 2  s .c o  m
    constructor.selector = name.toCharArray();
    constructor.thrownExceptions = null;
    constructor.typeParameters = copyTypeParams(((TypeDeclaration) type.get()).typeParameters, source);
    constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
    constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;

    List<Argument> params = new ArrayList<Argument>();
    List<Expression> assigns = new ArrayList<Expression>();
    AllocationExpression statement = new AllocationExpression();
    statement.sourceStart = pS;
    statement.sourceEnd = pE;
    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);
        assigns.add(nameRef);

        Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL);
        parameter.annotations = copyAnnotations(source, findAnnotations(field, NON_NULL_PATTERN),
                findAnnotations(field, NULLABLE_PATTERN));
        params.add(parameter);
    }

    statement.arguments = assigns.isEmpty() ? null : assigns.toArray(new Expression[assigns.size()]);
    constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]);
    constructor.statements = new Statement[] { new ReturnStatement(statement, (int) (p >> 32), (int) p) };

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

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

License:Open Source License

public void generateMethods(EclipseNode typeNode, EclipseNode errorNode, List<String> excludes,
        List<String> includes, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess,
        List<Annotation> onParam) {
    assert excludes == null || includes == null;

    TypeDeclaration typeDecl = null;//from w w  w . ja v  a2s .c  o  m

    if (typeNode.get() instanceof TypeDeclaration)
        typeDecl = (TypeDeclaration) typeNode.get();
    int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
    boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation
            | ClassFileConstants.AccEnum)) != 0;

    if (typeDecl == null || notAClass) {
        errorNode.addError("@EqualsAndHashCode is only supported on a class.");
        return;
    }

    boolean implicitCallSuper = callSuper == null;

    if (callSuper == null) {
        try {
            callSuper = ((Boolean) EqualsAndHashCode.class.getMethod("callSuper").getDefaultValue())
                    .booleanValue();
        } catch (Exception ignore) {
            throw new InternalError(
                    "Lombok bug - this cannot happen - can't find callSuper field in EqualsAndHashCode annotation.");
        }
    }

    boolean isDirectDescendantOfObject = true;

    if (typeDecl.superclass != null) {
        String p = typeDecl.superclass.toString();
        isDirectDescendantOfObject = p.equals("Object") || p.equals("java.lang.Object");
    }

    if (isDirectDescendantOfObject && callSuper) {
        errorNode.addError("Generating equals/hashCode with a supercall to java.lang.Object is pointless.");
        return;
    }

    if (!isDirectDescendantOfObject && !callSuper && implicitCallSuper) {
        errorNode.addWarning(
                "Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
    }

    List<EclipseNode> nodesForEquality = new ArrayList<EclipseNode>();
    if (includes != null) {
        for (EclipseNode child : typeNode.down()) {
            if (child.getKind() != Kind.FIELD)
                continue;
            FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
            if (includes.contains(new String(fieldDecl.name)))
                nodesForEquality.add(child);
        }
    } else {
        for (EclipseNode child : typeNode.down()) {
            if (child.getKind() != Kind.FIELD)
                continue;
            FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
            if (!filterField(fieldDecl))
                continue;

            //Skip transient fields.
            if ((fieldDecl.modifiers & ClassFileConstants.AccTransient) != 0)
                continue;
            //Skip excluded fields.
            if (excludes != null && excludes.contains(new String(fieldDecl.name)))
                continue;
            nodesForEquality.add(child);
        }
    }

    boolean isFinal = (typeDecl.modifiers & ClassFileConstants.AccFinal) != 0;
    boolean needsCanEqual = !isFinal || !isDirectDescendantOfObject;
    MemberExistsResult equalsExists = methodExists("equals", typeNode, 1);
    MemberExistsResult hashCodeExists = methodExists("hashCode", typeNode, 0);
    MemberExistsResult canEqualExists = methodExists("canEqual", typeNode, 1);
    switch (Collections.max(Arrays.asList(equalsExists, hashCodeExists))) {
    case EXISTS_BY_LOMBOK:
        return;
    case EXISTS_BY_USER:
        if (whineIfExists) {
            String msg = "Not generating equals and hashCode: A method with one of those names already exists. (Either both or none of these methods will be generated).";
            errorNode.addWarning(msg);
        } else if (equalsExists == MemberExistsResult.NOT_EXISTS
                || hashCodeExists == MemberExistsResult.NOT_EXISTS) {
            // This means equals OR hashCode exists and not both.
            // Even though we should suppress the message about not generating these, this is such a weird and surprising situation we should ALWAYS generate a warning.
            // The user code couldn't possibly (barring really weird subclassing shenanigans) be in a shippable state anyway; the implementations of these 2 methods are
            // all inter-related and should be written by the same entity.
            String msg = String.format("Not generating %s: One of equals or hashCode exists. "
                    + "You should either write both of these or none of these (in the latter case, lombok generates them).",
                    equalsExists == MemberExistsResult.NOT_EXISTS ? "equals" : "hashCode");
            errorNode.addWarning(msg);
        }
        return;
    case NOT_EXISTS:
    default:
        //fallthrough
    }

    MethodDeclaration equalsMethod = createEquals(typeNode, nodesForEquality, callSuper, errorNode.get(),
            fieldAccess, needsCanEqual, onParam);
    equalsMethod.traverse(new SetGeneratedByVisitor(errorNode.get()), ((TypeDeclaration) typeNode.get()).scope);
    injectMethod(typeNode, equalsMethod);

    if (needsCanEqual && canEqualExists == MemberExistsResult.NOT_EXISTS) {
        MethodDeclaration canEqualMethod = createCanEqual(typeNode, errorNode.get(), onParam);
        canEqualMethod.traverse(new SetGeneratedByVisitor(errorNode.get()),
                ((TypeDeclaration) typeNode.get()).scope);
        injectMethod(typeNode, canEqualMethod);
    }

    MethodDeclaration hashCodeMethod = createHashCode(typeNode, nodesForEquality, callSuper, errorNode.get(),
            fieldAccess);
    hashCodeMethod.traverse(new SetGeneratedByVisitor(errorNode.get()),
            ((TypeDeclaration) typeNode.get()).scope);
    injectMethod(typeNode, hashCodeMethod);
}

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

License:Open Source License

public MethodDeclaration createGetter(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier,
        ASTNode source, boolean lazy, List<Annotation> onMethod) {
    FieldDeclaration field = (FieldDeclaration) fieldNode.get();

    // Remember the type; lazy will change it;
    TypeReference returnType = copyType(((FieldDeclaration) fieldNode.get()).type, source);

    Statement[] statements;//from  w w  w.j  a v a 2  s.  c  o m
    if (lazy) {
        statements = createLazyGetterBody(source, fieldNode);
    } else {
        statements = createSimpleGetterBody(source, fieldNode);
    }

    MethodDeclaration method = new MethodDeclaration(parent.compilationResult);
    method.modifiers = modifier;
    method.returnType = returnType;
    method.annotations = null;
    method.arguments = null;
    method.selector = name.toCharArray();
    method.binding = null;
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
    method.statements = statements;

    EclipseHandlerUtil.registerCreatedLazyGetter((FieldDeclaration) fieldNode.get(), method.selector,
            returnType);

    /* Generate annotations that must  be put on the generated method, and attach them. */ {
        Annotation[] deprecated = null;
        if (isFieldDeprecated(fieldNode)) {
            deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
        }

        method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]),
                findAnnotations(field, NON_NULL_PATTERN), findAnnotations(field, NULLABLE_PATTERN),
                findDelegatesAndMarkAsHandled(fieldNode), deprecated);
    }

    method.traverse(new SetGeneratedByVisitor(source), parent.scope);
    return method;
}

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

License:Open Source License

static MethodDeclaration createSetter(TypeDeclaration parent, EclipseNode fieldNode, String name,
        boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod,
        List<Annotation> onParam) {
    FieldDeclaration field = (FieldDeclaration) fieldNode.get();
    ASTNode source = sourceNode.get();/*w w w  .  ja  va  2  s  .com*/
    int pS = source.sourceStart, pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;
    MethodDeclaration method = new MethodDeclaration(parent.compilationResult);
    method.modifiers = modifier;
    if (shouldReturnThis) {
        method.returnType = cloneSelfType(fieldNode, source);
    }

    if (method.returnType == null) {
        method.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
        method.returnType.sourceStart = pS;
        method.returnType.sourceEnd = pE;
        shouldReturnThis = false;
    }
    Annotation[] deprecated = null;
    if (isFieldDeprecated(fieldNode)) {
        deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
    }
    method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated);
    Argument param = new Argument(field.name, p, copyType(field.type, source), Modifier.FINAL);
    param.sourceStart = pS;
    param.sourceEnd = pE;
    method.arguments = new Argument[] { param };
    method.selector = name.toCharArray();
    method.binding = null;
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
    Expression fieldRef = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source);
    NameReference fieldNameRef = new SingleNameReference(field.name, p);
    Assignment assignment = new Assignment(fieldRef, fieldNameRef, (int) p);
    assignment.sourceStart = pS;
    assignment.sourceEnd = assignment.statementEnd = pE;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;

    Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
    Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
    List<Statement> statements = new ArrayList<Statement>(5);
    if (nonNulls.length == 0) {
        statements.add(assignment);
    } else {
        Statement nullCheck = generateNullCheck(field, sourceNode);
        if (nullCheck != null)
            statements.add(nullCheck);
        statements.add(assignment);
    }

    if (shouldReturnThis) {
        ThisReference thisRef = new ThisReference(pS, pE);
        ReturnStatement returnThis = new ReturnStatement(thisRef, pS, pE);
        statements.add(returnThis);
    }
    method.statements = statements.toArray(new Statement[0]);
    param.annotations = copyAnnotations(source, nonNulls, nullables, onParam.toArray(new Annotation[0]));

    method.traverse(new SetGeneratedByVisitor(source), parent.scope);
    return method;
}