예제 #1
0
 @Override
 void accept(ExpressionWriter writer, int lprec, int rprec) {
   writer.append("new ").append(type).list("(\n", ",\n", ")", arguments);
   if (memberDeclarations != null) {
     writer.list("{\n", "", "}", memberDeclarations);
   }
 }
  @Override
  void accept(ExpressionWriter writer, int lprec, int rprec) {
    // "new Function1() {
    //    public Result apply(T1 p1, ...) {
    //        <body>
    //    }
    //    // bridge method
    //    public Object apply(Object p1, ...) {
    //        return apply((T1) p1, ...);
    //    }
    // }
    //
    // if any arguments are primitive there is an extra bridge method:
    //
    //  new Function1() {
    //    public double apply(double p1, int p2) {
    //      <body>
    //    }
    //    // box bridge method
    //    public Double apply(Double p1, Integer p2) {
    //      return apply(p1.doubleValue(), p2.intValue());
    //    }
    //    // bridge method
    //    public Object apply(Object p1, Object p2) {
    //      return apply((Double) p1, (Integer) p2);
    //    }
    List<String> params = new ArrayList<String>();
    List<String> bridgeParams = new ArrayList<String>();
    List<String> bridgeArgs = new ArrayList<String>();
    List<String> boxBridgeParams = new ArrayList<String>();
    List<String> boxBridgeArgs = new ArrayList<String>();
    for (ParameterExpression parameterExpression : parameterList) {
      final Type parameterType = parameterExpression.getType();
      final Type parameterBoxType = Types.box(parameterType);
      final String parameterBoxTypeName = Types.className(parameterBoxType);
      params.add(parameterExpression.declString());
      bridgeParams.add(parameterExpression.declString(Object.class));
      bridgeArgs.add("(" + parameterBoxTypeName + ") " + parameterExpression.name);

      boxBridgeParams.add(parameterExpression.declString(parameterBoxType));
      boxBridgeArgs.add(
          parameterExpression.name
              + (Primitive.is(parameterType)
                  ? "." + Primitive.of(parameterType).primitiveName + "Value()"
                  : ""));
    }
    Type bridgeResultType = Functions.FUNCTION_RESULT_TYPES.get(this.type);
    if (bridgeResultType == null) {
      bridgeResultType = body.getType();
    }
    Type resultType2 = bridgeResultType;
    if (bridgeResultType == Object.class
        && !params.equals(bridgeParams)
        && !(body.getType() instanceof TypeVariable)) {
      resultType2 = body.getType();
    }
    String methodName = getAbstractMethodName();
    writer
        .append("new ")
        .append(type)
        .append("()")
        .begin(" {\n")
        .append("public ")
        .append(Types.className(resultType2))
        .list(" " + methodName + "(", ", ", ") ", params)
        .append(Blocks.toFunctionBlock(body));

    // Generate an intermediate bridge method if at least one parameter is
    // primitive.
    if (!boxBridgeParams.equals(params)) {
      writer
          .append("public ")
          .append(Types.boxClassName(bridgeResultType))
          .list(" " + methodName + "(", ", ", ") ", boxBridgeParams)
          .begin("{\n")
          .list("return " + methodName + "(\n", ",\n", ");\n", boxBridgeArgs)
          .end("}\n");
    }

    // Generate a bridge method. Argument types are looser (as if every
    // type parameter is set to 'Object').
    //
    // Skip the bridge method if there are no arguments. It would have the
    // same overload as the regular method.
    if (!bridgeParams.equals(params)) {
      writer
          .append("public ")
          .append(Types.boxClassName(bridgeResultType))
          .list(" " + methodName + "(", ", ", ") ", bridgeParams)
          .begin("{\n")
          .list("return " + methodName + "(\n", ",\n", ");\n", bridgeArgs)
          .end("}\n");
    }

    writer.end("}\n");
  }