Package com.redhat.ceylon.compiler.java.codegen

Source Code of com.redhat.ceylon.compiler.java.codegen.AttributeDefinitionBuilder

/*
* Copyright Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the authors tag. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*
* This particular file is subject to the "Classpath" exception as provided in the
* LICENSE file that accompanied this code.
*
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License,
* along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*/

package com.redhat.ceylon.compiler.java.codegen;

import com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException;
import com.redhat.ceylon.compiler.typechecker.model.MethodOrValue;
import com.redhat.ceylon.compiler.typechecker.model.ProducedType;
import com.redhat.ceylon.compiler.typechecker.model.ProducedTypedReference;
import com.redhat.ceylon.compiler.typechecker.model.TypedDeclaration;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCCatch;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
import com.sun.tools.javac.tree.JCTree.JCIf;
import com.sun.tools.javac.tree.JCTree.JCReturn;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;

/**
* Builds a class for global variables. See {@link GlobalTransformer} for an overview.
*
* The generated class can be customized by calling methods of this class.
*/
public class AttributeDefinitionBuilder {
    private boolean hasField = true;
    private final String fieldName;

    private final TypedDeclaration attrTypedDecl;
    private final String attrName;
    /**
     * If this is a wrapped attribute, and this builder is responsible for
     * generating the wrapper class, this is the name of the wrapper class
     */
    private final String javaClassName;
    /**
     * If this is a wrapped attribute, this is the class builder for the
     * wrapper class
     */
    private final ClassDefinitionBuilder classBuilder;
    private final int typeFlags;
    private final ProducedType attrType;
   
    private final boolean toplevel;
    private final boolean late;
    private final boolean variable;
   
    private long modifiers;

    private boolean readable = true;
    private final MethodDefinitionBuilder getterBuilder;

    private JCTree.JCExpression variableInit;
    private HasErrorException variableInitThrow;

    private boolean writable = true;
    private final MethodDefinitionBuilder setterBuilder;
   
    private AbstractTransformer owner;

    private int annotationFlags = Annotations.MODEL_AND_USER;
   
    // do we need a constructor that takes the initial value?
    private boolean valueConstructor;
   
    private ListBuffer<JCAnnotation> classAnnotations;
    private ListBuffer<JCAnnotation> modelAnnotations;
    private ListBuffer<JCAnnotation> userAnnotations;
    private ListBuffer<JCAnnotation> userAnnotationsSetter;
    private boolean isHash;
   
    private JCExpression setterClass;
    private JCExpression getterClass;

    private AttributeDefinitionBuilder(AbstractTransformer owner, TypedDeclaration attrType,
            String javaClassName, ClassDefinitionBuilder classBuilder, String attrName, String fieldName, boolean toplevel, boolean indirect) {
        int typeFlags = 0;
        ProducedTypedReference typedRef = owner.getTypedReference(attrType);
        ProducedTypedReference nonWideningTypedRef = owner.nonWideningTypeDecl(typedRef);
        ProducedType nonWideningType = owner.nonWideningType(typedRef, nonWideningTypedRef);
        if(attrType.isActual()
                && CodegenUtil.hasTypeErased(attrType))
            typeFlags |= AbstractTransformer.JT_RAW;
        if (!CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration())) {
            typeFlags |= AbstractTransformer.JT_NO_PRIMITIVES;
        }
        this.isHash = CodegenUtil.isHashAttribute((MethodOrValue) attrType);
        this.attrTypedDecl = attrType;
        this.owner = owner;
        this.javaClassName = javaClassName;
        if (javaClassName != null) {
            this.classBuilder =
                    ClassDefinitionBuilder
                    .klass(owner, javaClassName, null, false);
        } else {
            this.classBuilder = classBuilder;
        }
        this.attrType = nonWideningType;
        this.typeFlags = typeFlags;
        this.attrName = attrName;
        this.fieldName = fieldName;
        this.toplevel = toplevel;
        this.late = attrType.isLate();
        this.variable = attrType.isVariable();
       
        // Make sure we use the declaration for building the getter/setter names, as we might be trying to
        // override a JavaBean property with an "isFoo" getter, or non-Ceylon casing, and we have to respect that.
        getterBuilder = MethodDefinitionBuilder
            .getter(owner, attrType, indirect)
            .block(generateDefaultGetterBlock())
            .isOverride(attrType.isActual())
            .isTransient(Decl.isTransient(attrType))
            .modelAnnotations(attrType.getAnnotations())
            .resultType(attrType(), attrType);
       
        ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(owner, attrName);
        pdb.modifiers(Flags.FINAL);
       
        pdb.aliasName(attrName);
        pdb.type(MethodDefinitionBuilder.paramType(owner, nonWideningTypedRef.getDeclaration(), nonWideningType, 0, true),
                owner.makeJavaTypeAnnotations(attrType));
       
       
        setterBuilder = MethodDefinitionBuilder
            .setter(owner, attrType)
            .block(generateDefaultSetterBlock())
            // only actual if the superclass is also variable
            .isOverride(attrType.isActual() && ((TypedDeclaration)attrType.getRefinedDeclaration()).isVariable())
            .parameter(pdb);
    }
   
    public static AttributeDefinitionBuilder wrapped(AbstractTransformer owner,
            String javaClassName, ClassDefinitionBuilder classBuilder, String attrName, TypedDeclaration attrType,
            boolean toplevel) {
        return new AttributeDefinitionBuilder(owner, attrType, javaClassName, classBuilder, attrName, "value", toplevel, false);
    }
   
    public static AttributeDefinitionBuilder indirect(AbstractTransformer owner,
            String javaClassName, String attrName, TypedDeclaration attrType,
            boolean toplevel) {
        return new AttributeDefinitionBuilder(owner, attrType, javaClassName, null, attrName, "value", toplevel, true);
    }
   
    public static AttributeDefinitionBuilder getter(AbstractTransformer owner,
            String attrAndFieldName, TypedDeclaration attrType) {
        return new AttributeDefinitionBuilder(owner, attrType, null, null,
                attrAndFieldName, attrAndFieldName, false, false)
            .skipField()
            .immutable();
    }
   
    public static AttributeDefinitionBuilder setter(AbstractTransformer owner,
            String attrAndFieldName, TypedDeclaration attrType) {
        return new AttributeDefinitionBuilder(owner, attrType, null, null,
                attrAndFieldName, attrAndFieldName, false, false)
            .skipField()
            .skipGetter();
    }
   
    public AttributeDefinitionBuilder modelAnnotations(List<JCAnnotation> annotations) {
        if (annotations != null) {
            if (this.modelAnnotations == null) {
                this.modelAnnotations = ListBuffer.lb();
            }
            this.modelAnnotations.appendList(annotations);
        }
        return this;
    }

    public AttributeDefinitionBuilder classAnnotations(List<JCAnnotation> annotations) {
        if (annotations != null) {
            if (this.classAnnotations == null) {
                this.classAnnotations = ListBuffer.lb();
            }
            this.classAnnotations.appendList(annotations);
        }
        return this;
    }

    public AttributeDefinitionBuilder userAnnotations(List<JCAnnotation> annotations) {
        if (annotations != null) {
            if (this.userAnnotations == null) {
                this.userAnnotations = ListBuffer.lb();
            }
            this.userAnnotations.appendList(annotations);
        }
        return this;
    }
   
    public AttributeDefinitionBuilder userAnnotationsSetter(List<JCAnnotation> annotations) {
        if (annotations != null) {
            if (this.userAnnotationsSetter == null) {
                this.userAnnotationsSetter = ListBuffer.lb();
            }
            this.userAnnotationsSetter.appendList(annotations);
        }
        return this;
    }
   
    /**
     * Generates the class and returns the generated tree.
     * @return the generated class tree, to be added to the appropriate {@link JCTree.JCCompilationUnit}.
     */
    public List<JCTree> build() {
        ListBuffer<JCTree> defs = ListBuffer.lb();
        appendDefinitionsTo(defs);
        if (javaClassName != null) {
            classBuilder
                    .modifiers(Flags.FINAL | (modifiers & (Flags.PUBLIC | Flags.PRIVATE)))
                    .constructorModifiers(Flags.PRIVATE)
                    .defs(defs.toList());
            if(getterClass == null){
                classBuilder.annotations(owner.makeAtAttribute(setterClass))
                    .annotations(owner.makeAtName(attrName))
                    .satisfies(getSatisfies());
            }else{
                classBuilder.annotations(owner.makeAtIgnore());
                classBuilder.annotations(owner.makeAtSetter(getterClass));
            }

            if(classAnnotations != null)
                classBuilder.annotations(classAnnotations.toList());
            if(valueConstructor && hasField)
                generateValueConstructor(classBuilder.addConstructor());
            return classBuilder.build();
        } else {
            return defs.toList();
        }
    }

    /**
     * Appends to <tt>defs</tt> the definitions that would go into the class generated by {@link #build()}
     * @param defs a {@link ListBuffer} to which the definitions will be appended.
     */
    public void appendDefinitionsTo(ListBuffer<JCTree> defs) {
        if (hasField) {
            if (variableInitThrow == null) {
                defs.append(generateField());
                if (hasInitFlag()) {
                    defs.append(generateInitFlagField());
                }
                if(isDeferredInitError())
                    defs.append(generateInitExceptionField());
                if(variableInit != null) {
                    defs.append(generateFieldInit());
                }
            }
        }
       
        if (readable) {
            if (variableInitThrow != null) {
                getterBuilder.block(owner.make().Block(0, List.<JCStatement>of(owner.makeThrowUnresolvedCompilationError(variableInitThrow))));
            }
            getterBuilder.modifiers(getGetSetModifiers());
            getterBuilder.annotationFlags(annotationFlags);
            if (this.modelAnnotations != null) {
                getterBuilder.modelAnnotations(this.modelAnnotations.toList());
            }
            if (this.userAnnotations != null) {
                getterBuilder.userAnnotations(this.userAnnotations.toList());
            }
            defs.append(getterBuilder.build());
        }

        if (writable) {
            if (variableInitThrow != null) {
                setterBuilder.block(owner.make().Block(0, List.<JCStatement>of(owner.makeThrowUnresolvedCompilationError(variableInitThrow))));
            }
            setterBuilder.modifiers(getGetSetModifiers());
            // mark it with @Ignore if it's late but not variable
            setterBuilder.annotationFlags(annotationFlags | (late && !variable ? Annotations.IGNORE : 0));
            if (this.userAnnotationsSetter != null) {
                setterBuilder.userAnnotations(this.userAnnotationsSetter.toList());
            }
            defs.append(setterBuilder.build());
        }
    }

    private boolean isDeferredInitError() {
        return toplevel && !late;
    }

    private List<ProducedType> getSatisfies() {
        List<ProducedType> types = List.<ProducedType>nil();
        if (javaClassName != null && readable && !toplevel) {
            types = types.append(owner.getGetterInterfaceType(attrTypedDecl));
        }
        return types;
    }
   
    private void generateValueConstructor(MethodDefinitionBuilder methodDefinitionBuilder) {
        ParameterDefinitionBuilder paramBuilder = ParameterDefinitionBuilder.systemParameter(owner, fieldName).type(attrType(), null);
        JCTree.JCAssign init = owner.make().Assign(owner.makeQualIdent(owner.naming.makeThis(), fieldName), owner.makeUnquotedIdent(fieldName));
        methodDefinitionBuilder.parameter(paramBuilder).body(owner.make().Exec(init));
    }

    private JCExpression attrType(){
        // make sure we generate int getters for hash
        if(this.isHash){
            return owner.make().Type(owner.syms().intType);
        }else{
            return owner.makeJavaType(attrType, typeFlags);
        }
    }

    private JCExpression attrTypeRaw(){
        // make sure we generate int getters for hash
        if(this.isHash){
            return owner.make().Type(owner.syms().intType);
        }else{
            return owner.makeJavaType(attrType, AbstractTransformer.JT_RAW);
        }
    }

    private long getGetSetModifiers() {
        long mods = modifiers;
        if (javaClassName != null) {
            mods |= Flags.PUBLIC;
        }
        return mods & (Flags.PUBLIC | Flags.PRIVATE | Flags.ABSTRACT | Flags.FINAL | Flags.STATIC);
    }

    private JCTree generateField() {
        long flags = Flags.PRIVATE | (modifiers & Flags.STATIC);
        // only make it final if we have an init, otherwise we still have to initialise it
        if (!writable && (variableInit != null || valueConstructor)) {
            flags |= Flags.FINAL;
        }

        return owner.make().VarDef(
                owner.make().Modifiers(flags),
                owner.names().fromString(Naming.quoteFieldName(fieldName)),
                attrType(),
                null
        );
    }
   
    private JCTree generateInitFlagField() {
        long flags = Flags.PRIVATE | (modifiers & Flags.STATIC) | Flags.VOLATILE;
       
        return owner.make().VarDef(
                owner.make().Modifiers(flags),
                owner.names().fromString(Naming.getInitializationFieldName(fieldName)),
                owner.make().Type(owner.syms().booleanType),
                owner.make().Literal(false)
        );
    }

    private JCTree generateInitExceptionField() {
        long flags = Flags.PRIVATE | Flags.STATIC | Flags.FINAL;

        return owner.make().VarDef(
                owner.make().Modifiers(flags),
                owner.names().fromString(Naming.quoteIfJavaKeyword(Naming.getToplevelAttributeSavedExceptionName())),
                owner.makeJavaType(owner.syms().throwableType.tsym),
                null
        );
    }

    private JCTree generateFieldInit() {
        long flags = (modifiers & Flags.STATIC);
       
        JCTree.JCExpression varInit = variableInit;
        if (hasInitFlag()) {
            varInit = variableInit;
        }
        JCTree.JCAssign init = owner.make().Assign(owner.makeUnquotedIdent(fieldName), varInit);
        List<JCStatement> stmts;
        if(isDeferredInitError()){
            // surround the init expression with a try/catch that saves the exception
           
            String exceptionName = "x"; // doesn't matter
           
            // $initException$ = x
            JCStatement saveException = owner.make().Exec(owner.make().Assign(
                    owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName()),
                    owner.makeUnquotedIdent(exceptionName)));
            // value = null
            JCStatement nullValue = owner.make().Exec(owner.make().Assign(owner.makeUnquotedIdent(fieldName), owner.makeDefaultExprForType(this.attrType)));
            // the catch statements
            JCStatement initFlagFalse = owner.make().Exec(owner.make().Assign(
                    owner.naming.makeUnquotedIdent(Naming.getInitializationFieldName(fieldName)),
                    owner.make().Literal(false)));
            JCBlock handlerBlock = owner.make().Block(0, List.<JCTree.JCStatement>of(saveException, nullValue, initFlagFalse));
           
            // the catch block
            JCExpression throwableType = owner.makeJavaType(owner.syms().throwableType.tsym);
            JCVariableDecl exceptionParam = owner.make().VarDef(owner.make().Modifiers(0),
                    owner.naming.makeUnquotedName(exceptionName),
                    throwableType , null);
            JCCatch catchers = owner.make().Catch(exceptionParam, handlerBlock);
           
            // $initException$ = null
            JCTree.JCAssign nullException = owner.make().Assign(owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName()),
                    owner.makeNull());
            // $init$value = true;
            JCTree.JCAssign initFlagTrue = owner.make().Assign(
                    owner.naming.makeUnquotedIdent(Naming.getInitializationFieldName(fieldName)),
                    owner.make().Literal(true));
            // save the value, mark the exception as null
            List<JCStatement> body = List.<JCTree.JCStatement>of(
                    owner.make().Exec(init),
                    owner.make().Exec(nullException),
                    owner.make().Exec(initFlagTrue));
           
            // the try/catch
            JCTree.JCTry try_ = owner.make().Try(owner.make().Block(0, body), List.<JCTree.JCCatch>of(catchers), null);
            stmts = List.<JCTree.JCStatement>of(try_);
        }else{
            stmts = List.<JCTree.JCStatement>of(owner.make().Exec(init));
        }
        return owner.make().Block(flags, stmts);
    }

    private JCTree.JCBlock generateDefaultGetterBlock() {
        JCTree.JCExpression returnExpr = owner.makeQuotedIdent(fieldName);
        // make sure we turn hash long to int properly
        if(isHash)
            returnExpr = owner.convertToIntForHashAttribute(returnExpr);
        JCReturn returnValue = owner.make().Return(returnExpr);
        List<JCStatement> stmts;
       
        stmts = List.<JCTree.JCStatement>of(returnValue);
       
        JCTree.JCBlock block;
        if (hasInitFlag()) {
            JCExpression msg = owner.make().Literal(late ? "Accessing uninitialized 'late' attribute '"+attrName+"'" : "Cyclic initialization trying to read the value of '"+attrName+"' before it was set");
            JCTree.JCThrow throwStmt = owner.make().Throw(owner.makeNewClass(owner.makeIdent(owner.syms().ceylonInitializationErrorType),
                    List.<JCExpression>of(msg)));
            List<JCStatement> catchStmts;
            if(isDeferredInitError()){
                JCStatement rethrow = owner.make().Exec(owner.utilInvocation().rethrow(
                        owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName())));
                // rethrow the init exception if we have one
                JCIf ifThrow = owner.make().If(owner.make().Binary(JCTree.NE, owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName()),
                        owner.makeNull()), rethrow, null);
                catchStmts = List.<JCTree.JCStatement>of(ifThrow, throwStmt);
            }else{
                catchStmts = List.<JCTree.JCStatement>of(throwStmt);
            }
            block = owner.make().Block(0L, List.<JCTree.JCStatement>of(
                    owner.make().If(makeInitFlagExpr(),
                    owner.make().Block(0, stmts),
                    owner.make().Block(0, catchStmts))));
        } else {
            block = owner.make().Block(0L, stmts);
        }
        return block;
    }
   
   
    private boolean hasInitFlag() {
        return toplevel || late;
    }

    public JCTree.JCBlock generateDefaultSetterBlock() {
        JCExpression fld = fld();
        JCExpressionStatement assign = owner.make().Exec(
                owner.make().Assign(
                        fld,
                        owner.makeQuotedIdent(attrName)));
        List<JCStatement> stmts = List.<JCTree.JCStatement>of(assign);
        if (late) {
           
            JCExpressionStatement makeInit = owner.make().Exec(
                    owner.make().Assign(
                            makeInitFlagExpr(),
                            owner.make().Literal(true)));
            if (variable) {
                stmts = List.<JCStatement>of(assign, makeInit);
            } else {
                stmts = List.of(
                    owner.make().If(
                        owner.make().Unary(JCTree.NOT, makeInitFlagExpr()),
                        owner.make().Block(0, List.<JCStatement>of(
                                assign,
                                makeInit,
                                owner.make().Return(null))), null),
                        owner.make().Throw(owner.makeNewClass(
                                owner.make().Type(owner.syms().ceylonInitializationErrorType),
                                List.<JCExpression>of(owner.make().Literal("Re-initialization of 'late' attribute")))
                ));
            }
        }
        return owner.make().Block(0L, stmts);
    }

    private JCExpression makeInitFlagExpr() {
        final JCExpression initFlagFieldOwner;
        if (toplevel) {
            if (classBuilder != null) {
                // TODO Needs to be qualified name
                initFlagFieldOwner = owner.naming.makeUnquotedIdent(classBuilder.getClassName());
            } else {
                initFlagFieldOwner = owner.naming.makeUnquotedIdent(javaClassName);
            }
        } else {
            initFlagFieldOwner = owner.naming.makeThis();
        }
        return owner.naming.makeQualIdent(initFlagFieldOwner, Naming.getInitializationFieldName(fieldName));
    }

    private JCExpression fld() {
        JCExpression fld;
        if (fieldName.equals(attrName)) {
            fld = owner.makeSelect("this", Naming.quoteFieldName(fieldName));
        } else {
            fld = owner.makeQuotedIdent(fieldName);
        }
        return fld;
    }

    public AttributeDefinitionBuilder modifiers(long... modifiers) {
        long mods = 0;
        for (long mod : modifiers) {
            mods |= mod;
        }
        this.modifiers = mods;
        return this;
    }

    public AttributeDefinitionBuilder is(long flag, boolean value) {
        if (value) {
            this.modifiers |= flag;
        } else {
            this.modifiers &= ~flag;
        }
        return this;
    }

    public AttributeDefinitionBuilder noModelAnnotations() {
        this.annotationFlags = Annotations.noModel(annotationFlags);
        return this;
    }
   
    public AttributeDefinitionBuilder ignoreAnnotations() {
        this.annotationFlags = Annotations.noUserOrModel(Annotations.ignore(annotationFlags));
        return this;
    }

    public AttributeDefinitionBuilder noAnnotations() {
        this.annotationFlags = 0;
        return this;
    }

    public AttributeDefinitionBuilder isFormal(boolean isFormal) {
        getterBuilder.isAbstract(isFormal);
        setterBuilder.isAbstract(isFormal);
        return this;
    }

    /**
     * Causes no field to be generated.
     * @return this instance for method chaining
     */
    public AttributeDefinitionBuilder skipField() {
        this.hasField = false;
        return this;
    }

    /**
     * Sets the code block to use for the generated getter. If no getter is generated the code block will be
     * silently ignored.
     * @param getterBlock a code block
     * @return this instance for method chaining
     */
    public AttributeDefinitionBuilder getterBlock(JCTree.JCBlock getterBlock) {
        skipField();
        getterBuilder.block(getterBlock);
        return this;
    }

    /**
     * Causes no getter to be generated.
     * @return this instance for method chaining
     */
    public AttributeDefinitionBuilder skipGetter() {
        this.readable = false;
        return this;
    }

    /**
     * Sets the code block to use for the generated setter. If no setter is generated the code block will be
     * silently ignored.
     * @param setterBlock a code block
     * @return this instance for method chaining
     */
    public AttributeDefinitionBuilder setterBlock(JCTree.JCBlock setterBlock) {
        setterBuilder.block(setterBlock);
        return this;
    }

    /**
     * Causes the generated attribute to be immutable. The <tt>value</tt> field is declared <tt>final</tt> and no
     * setter is generated.
     * @return this instance for method chaining
     */
    public AttributeDefinitionBuilder immutable() {
        this.writable = false;
        return this;
    }

    /**
     * The <tt>value</tt> field will be declared with the initial value given by the parameter
     * @param initialValue the initial value of the global.
     * @return this instance for method chaining
     */
    public AttributeDefinitionBuilder initialValue(JCTree.JCExpression initialValue) {
        this.variableInit = initialValue;
        return this;
    }
   

    public AttributeDefinitionBuilder initialValueError(HasErrorException variableInitThrow) {
        this.variableInitThrow = variableInitThrow;
        return this;
    }

    /**
     * Marks the getter/setter methods as not actual. In general <tt>actual</tt> is derived from
     * the model while creating this builder so it will be correct. You can only disable this
     * computation. Enabling <tt>actual</tt> would otherwise depend on the question of whether the
     * getter is or not actual which may be different for the setter if the refined decl is not variable
     * so we'd need two parameters.
     */
    public AttributeDefinitionBuilder notActual() {
        getterBuilder.isOverride(false);
        setterBuilder.isOverride(false);
        return this;
    }
    /**
     * Produces a constructor that receives the initial value for this attribute.
     */
    public AttributeDefinitionBuilder valueConstructor(){
        valueConstructor = true;
        return this;
    }

    /**
     * Makes a reference to the setter class for this setter
     */
    public void setterClass(JCExpression setterClass) {
        this.setterClass = setterClass;
    }

    /**
     * Marks this attribute as a setter and skip generating an @Attribute annotation for it,
     * use a @Setter(getterClass) instead
     */
    public void isSetter(JCExpression getterClass) {
        this.getterClass = getterClass;
    }
}
TOP

Related Classes of com.redhat.ceylon.compiler.java.codegen.AttributeDefinitionBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.