public static MethodDefinitionBuilder main(AbstractTransformer gen) {
   MethodDefinitionBuilder mdb =
       new MethodDefinitionBuilder(gen, false, "main").modifiers(PUBLIC | STATIC);
   ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.instance(mdb.gen, "args");
   pdb.type(
       gen.make().TypeArray(gen.make().Type(gen.syms().stringType)), List.<JCAnnotation>nil());
   return mdb.parameter(pdb);
 }
  public JCNewClass build() {
    // Generate a subclass of Callable
    ListBuffer<JCTree> classBody = new ListBuffer<JCTree>();
    int numParams = paramLists.getParameters().size();
    int minimumParams = 0;
    for (Parameter p : paramLists.getParameters()) {
      if (p.isDefaulted() || p.isSequenced()) break;
      minimumParams++;
    }
    boolean isVariadic = minimumParams != numParams;
    if (parameterListTree != null) {
      // generate a method for each defaulted param
      for (Tree.Parameter p : parameterListTree.getParameters()) {
        if (p.getDefaultArgument() != null || p.getDeclarationModel().isSequenced()) {
          MethodDefinitionBuilder methodBuilder =
              gen.classGen().makeParamDefaultValueMethod(false, null, parameterListTree, p);
          classBody.append(methodBuilder.build());
        }
      }
    }

    // collect each parameter type from the callable type model rather than the declarations to get
    // them all bound
    java.util.List<ProducedType> parameterTypes = new ArrayList<ProducedType>(numParams);
    if (forwardCallTo != null) {
      for (int i = 0; i < numParams; i++)
        parameterTypes.add(gen.getParameterTypeOfCallable(typeModel, i));
    } else {
      // get them from our declaration
      for (Parameter p : paramLists.getParameters()) parameterTypes.add(p.getType());
    }

    // now generate a method for each supported minimum number of parameters below 4
    // which delegates to the $call$typed method if required
    for (int i = minimumParams, max = Math.min(numParams, 4); i < max; i++) {
      classBody.append(makeDefaultedCall(i, isVariadic, parameterTypes));
    }
    // generate the $call method for the max number of parameters,
    // which delegates to the $call$typed method if required
    classBody.append(makeDefaultedCall(numParams, isVariadic, parameterTypes));
    // generate the $call$typed method if required
    if (isVariadic && forwardCallTo == null)
      classBody.append(makeCallTypedMethod(body, parameterTypes));

    JCClassDecl classDef =
        gen.make().AnonymousClassDef(gen.make().Modifiers(0), classBody.toList());

    JCNewClass instance =
        gen.make()
            .NewClass(
                null,
                null,
                gen.makeJavaType(typeModel, JT_EXTENDS | JT_CLASS_NEW),
                List.<JCExpression>of(gen.make().Literal(typeModel.getProducedTypeName(true))),
                classDef);
    return instance;
  }
  private AttributeDefinitionBuilder(
      AbstractTransformer owner,
      TypedDeclaration attrType,
      String javaClassName,
      String attrName,
      String fieldName,
      boolean toplevel) {
    int typeFlags = 0;
    ProducedTypedReference typedRef = owner.getTypedReference(attrType);
    ProducedTypedReference nonWideningTypedRef = owner.nonWideningTypeDecl(typedRef);
    ProducedType nonWideningType = owner.nonWideningType(typedRef, nonWideningTypedRef);
    if (!CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration())) {
      typeFlags |= AbstractTransformer.JT_NO_PRIMITIVES;
    }

    this.attrType = owner.makeJavaType(nonWideningType, typeFlags);
    this.attrTypeRaw = owner.makeJavaType(nonWideningType, AbstractTransformer.JT_RAW);
    this.owner = owner;
    this.javaClassName = javaClassName;
    this.attrName = attrName;
    this.fieldName = fieldName;
    this.toplevel = toplevel;

    // 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.method2(owner, Naming.getGetterName(attrType))
            .block(generateDefaultGetterBlock())
            .isOverride(attrType.isActual())
            .annotations(owner.makeAtAnnotations(attrType.getAnnotations()))
            .resultType(this.attrType, attrType);
    setterBuilder =
        MethodDefinitionBuilder.method2(owner, Naming.getSetterName(attrType))
            .block(generateDefaultSetterBlock())
            // only actual if the superclass is also variable
            .isOverride(
                attrType.isActual()
                    && ((TypedDeclaration) attrType.getRefinedDeclaration()).isVariable())
            .parameter(
                Flags.FINAL,
                attrName,
                attrType,
                nonWideningTypedRef.getDeclaration(),
                nonWideningType,
                0);
  }
 private void generateValueConstructor(MethodDefinitionBuilder methodDefinitionBuilder) {
   ParameterDefinitionBuilder paramBuilder =
       ParameterDefinitionBuilder.instance(owner, fieldName).type(attrType, null);
   JCTree.JCAssign init =
       owner
           .make()
           .Assign(
               owner.makeQualIdent(owner.makeUnquotedIdent("this"), fieldName),
               owner.makeUnquotedIdent(fieldName));
   methodDefinitionBuilder.parameter(paramBuilder).body(owner.make().Exec(init));
 }
  /**
   * 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) {
      defs.append(generateField());
      if (variableInit != null) defs.append(generateFieldInit());
    }

    if (readable) {
      getterBuilder.modifiers(getGetSetModifiers());
      getterBuilder.noAnnotations(noAnnotations);
      defs.append(getterBuilder.build());
    }

    if (writable) {
      setterBuilder.modifiers(getGetSetModifiers());
      setterBuilder.noAnnotations(noAnnotations);
      defs.append(setterBuilder.build());
    }
  }
 private JCTree makeCallTypedMethod(
     List<JCStatement> body, java.util.List<ProducedType> parameterTypes) {
   // make the method
   MethodDefinitionBuilder methodBuilder =
       MethodDefinitionBuilder.method(gen, false, Naming.getCallableTypedMethodName());
   methodBuilder.modifiers(Flags.PRIVATE);
   ProducedType returnType = gen.getReturnTypeOfCallable(typeModel);
   methodBuilder.resultType(gen.makeJavaType(returnType, JT_NO_PRIMITIVES), null);
   // add all parameters
   int i = 0;
   for (Parameter param : paramLists.getParameters()) {
     ParameterDefinitionBuilder parameterBuilder =
         ParameterDefinitionBuilder.instance(gen, param.getName());
     JCExpression paramType = gen.makeJavaType(parameterTypes.get(i));
     parameterBuilder.type(paramType, null);
     methodBuilder.parameter(parameterBuilder);
     i++;
   }
   // Return the call result, or null if a void method
   methodBuilder.body(body);
   return methodBuilder.build();
 }
  private JCTree makeCallMethod(List<JCStatement> body, int numParams) {
    MethodDefinitionBuilder callMethod = MethodDefinitionBuilder.callable(gen);
    callMethod.isOverride(true);
    callMethod.modifiers(Flags.PUBLIC);
    ProducedType returnType = gen.getReturnTypeOfCallable(typeModel);
    callMethod.resultType(gen.makeJavaType(returnType, JT_NO_PRIMITIVES), null);
    // Now append formal parameters
    switch (numParams) {
      case 3:
        callMethod.parameter(makeCallableCallParam(0, numParams - 3));
        // fall through
      case 2:
        callMethod.parameter(makeCallableCallParam(0, numParams - 2));
        // fall through
      case 1:
        callMethod.parameter(makeCallableCallParam(0, numParams - 1));
        break;
      case 0:
        break;
      default: // use varargs
        callMethod.parameter(makeCallableCallParam(Flags.VARARGS, 0));
    }

    // Return the call result, or null if a void method
    callMethod.body(body);
    return callMethod.build();
  }
 /**
  * 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;
 }
 /**
  * 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;
 }
 /**
  * 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;
 }
 public AttributeDefinitionBuilder isFormal(boolean isFormal) {
   getterBuilder.isAbstract(isFormal);
   setterBuilder.isAbstract(isFormal);
   return this;
 }