private Expression transformMethodCallExpression(final MethodCallExpression exp) {
   Expression objectExpression = transform(exp.getObjectExpression());
   ClassNode traitReceiver = objectExpression.getNodeMetaData(SuperCallTraitTransformer.class);
   if (traitReceiver != null) {
     TraitHelpersTuple helpers = Traits.findHelpers(traitReceiver);
     // (SomeTrait.super).foo() --> SomeTrait$Helper.foo(this)
     ClassExpression receiver = new ClassExpression(helpers.getHelper());
     ArgumentListExpression newArgs = new ArgumentListExpression();
     Expression arguments = exp.getArguments();
     newArgs.addExpression(new VariableExpression("this"));
     if (arguments instanceof TupleExpression) {
       List<Expression> expressions = ((TupleExpression) arguments).getExpressions();
       for (Expression expression : expressions) {
         newArgs.addExpression(transform(expression));
       }
     } else {
       newArgs.addExpression(arguments);
     }
     MethodCallExpression result = new MethodCallExpression(receiver, exp.getMethod(), newArgs);
     result.setImplicitThis(false);
     result.setSpreadSafe(exp.isSpreadSafe());
     result.setSafe(exp.isSafe());
     result.setSourcePosition(exp);
     return result;
   }
   return super.transform(exp);
 }
  @Override
  public void visitConstructorCallExpression(final ConstructorCallExpression call) {
    super.visitConstructorCallExpression(call);

    MethodNode target = (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
    if (target == null && call.getLineNumber() > 0) {
      addError("Target constructor for constructor call expression hasn't been set", call);
    } else {
      if (target == null) {
        // try to find a target
        ArgumentListExpression argumentListExpression =
            InvocationWriter.makeArgumentList(call.getArguments());
        List<Expression> expressions = argumentListExpression.getExpressions();
        ClassNode[] args = new ClassNode[expressions.size()];
        for (int i = 0; i < args.length; i++) {
          args[i] = typeChooser.resolveType(expressions.get(i), classNode);
        }
        MethodNode constructor =
            findMethodOrFail(
                call, call.isSuperCall() ? classNode.getSuperClass() : classNode, "<init>", args);
        call.putNodeMetaData(DIRECT_METHOD_CALL_TARGET, constructor);
        target = constructor;
      }
    }
    if (target != null) {
      memorizeInitialExpressions(target);
    }
  }
示例#3
0
 private static ThrowStatement createMissingMethodThrowable(
     ClassNode classNode, MethodNode declaredMethodNode) {
   ArgumentListExpression exceptionArgs = new ArgumentListExpression();
   exceptionArgs.addExpression(new ConstantExpression(declaredMethodNode.getName()));
   exceptionArgs.addExpression(new ClassExpression(classNode));
   return new ThrowStatement(
       new ConstructorCallExpression(MISSING_METHOD_EXCEPTION, exceptionArgs));
 }
  private void printSpecialConstructorArgs(
      PrintWriter out, ConstructorNode node, ConstructorCallExpression constrCall) {
    // Select a constructor from our class, or super-class which is legal to call,
    // then write out an invoke w/nulls using casts to avoid ambiguous crapo

    Parameter[] params = selectAccessibleConstructorFromSuper(node);
    if (params != null) {
      out.print("super (");

      for (int i = 0; i < params.length; i++) {
        printDefaultValue(out, params[i].getType());
        if (i + 1 < params.length) {
          out.print(", ");
        }
      }

      out.println(");");
      return;
    }

    // Otherwise try the older method based on the constructor's call expression
    Expression arguments = constrCall.getArguments();

    if (constrCall.isSuperCall()) {
      out.print("super(");
    } else {
      out.print("this(");
    }

    // Else try to render some arguments
    if (arguments instanceof ArgumentListExpression) {
      ArgumentListExpression argumentListExpression = (ArgumentListExpression) arguments;
      List<Expression> args = argumentListExpression.getExpressions();

      for (Expression arg : args) {
        if (arg instanceof ConstantExpression) {
          ConstantExpression expression = (ConstantExpression) arg;
          Object o = expression.getValue();

          if (o instanceof String) {
            out.print("(String)null");
          } else {
            out.print(expression.getText());
          }
        } else {
          ClassNode type = getConstructorArgumentType(arg, node);
          printDefaultValue(out, type);
        }

        if (arg != args.get(args.size() - 1)) {
          out.print(", ");
        }
      }
    }

    out.println(");");
  }
  private void addAttributesAndBodyMethod(
      ClassNode classNode,
      MethodCallExpression tagLibraryLookupMethodCall,
      String tagName,
      boolean includeBody,
      boolean includeAttrs) {
    BlockStatement methodBody = new BlockStatement();
    ArgumentListExpression arguments = new ArgumentListExpression();
    arguments
        .addExpression(tagLibraryLookupMethodCall)
        .addExpression(
            new MethodCallExpression(
                new VariableExpression("this"),
                GET_TAG_LIB_NAMESPACE_METHOD_NAME,
                new ArgumentListExpression()))
        .addExpression(new ConstantExpression(tagName))
        .addExpression(
            includeAttrs
                ? new CastExpression(ClassHelper.make(Map.class), ATTRS_EXPRESSION)
                : new MapExpression())
        .addExpression(includeBody ? BODY_EXPRESSION : NULL_EXPRESSION)
        .addExpression(
            new CastExpression(
                ClassHelper.make(GrailsWebRequest.class), CURRENT_REQUEST_ATTRIBUTES_METHOD_CALL));

    methodBody.addStatement(
        new ExpressionStatement(
            new MethodCallExpression(
                new ClassExpression(GROOVY_PAGE_CLASS_NODE), "captureTagOutput", arguments)));

    if (includeBody && includeAttrs) {
      if (!methodExists(classNode, tagName, MAP_CLOSURE_PARAMETERS)) {
        classNode.addMethod(
            new MethodNode(
                tagName, Modifier.PUBLIC, OBJECT_CLASS, MAP_CLOSURE_PARAMETERS, null, methodBody));
      }
    } else if (includeAttrs && !includeBody) {
      if (!methodExists(classNode, tagName, MAP_PARAMETERS)) {
        classNode.addMethod(
            new MethodNode(
                tagName, Modifier.PUBLIC, OBJECT_CLASS, MAP_PARAMETERS, null, methodBody));
      }
    } else if (includeBody) {
      if (!methodExists(classNode, tagName, CLOSURE_PARAMETERS)) {
        classNode.addMethod(
            new MethodNode(
                tagName, Modifier.PUBLIC, OBJECT_CLASS, CLOSURE_PARAMETERS, null, methodBody));
      }
    } else {
      if (!methodExists(classNode, tagName, Parameter.EMPTY_ARRAY)) {
        classNode.addMethod(
            new MethodNode(
                tagName, Modifier.PUBLIC, OBJECT_CLASS, Parameter.EMPTY_ARRAY, null, methodBody));
      }
    }
  }
 private Expression findStaticPropertyAccessorByFullName(
     ClassNode staticImportType, String accessorMethodName) {
   // anything will do as we only check size == 1
   ArgumentListExpression dummyArgs = new ArgumentListExpression();
   dummyArgs.addExpression(new EmptyExpression());
   return findStaticMethod(
       staticImportType,
       accessorMethodName,
       (inLeftExpression ? dummyArgs : ArgumentListExpression.EMPTY_ARGUMENTS));
 }
 protected void addMockCollaborator(
     String mockType, ClassExpression targetClass, BlockStatement methodBody) {
   ArgumentListExpression args = new ArgumentListExpression();
   args.addExpression(targetClass);
   methodBody
       .getStatements()
       .add(
           0,
           new ExpressionStatement(
               new MethodCallExpression(THIS_EXPRESSION, "mock" + mockType, args)));
 }
示例#8
0
  /**
   * Creates an argument list from the given parameter types.
   *
   * @param parameterTypes The parameter types
   * @param thisAsFirstArgument Whether to include a reference to 'this' as the first argument
   * @return the arguments
   */
  public static ArgumentListExpression createArgumentListFromParameters(
      Parameter[] parameterTypes, boolean thisAsFirstArgument) {
    ArgumentListExpression arguments = new ArgumentListExpression();

    if (thisAsFirstArgument) {
      arguments.addExpression(AbstractGrailsArtefactTransformer.THIS_EXPRESSION);
    }

    for (Parameter parameterType : parameterTypes) {
      arguments.addExpression(new VariableExpression(parameterType.getName()));
    }
    return arguments;
  }
 private void addAttributesAndStringBodyMethod(ClassNode classNode, String tagName) {
   BlockStatement methodBody = new BlockStatement();
   ArgumentListExpression arguments = new ArgumentListExpression();
   ArgumentListExpression constructorArgs = new ArgumentListExpression();
   constructorArgs.addExpression(BODY_EXPRESSION);
   arguments
       .addExpression(new CastExpression(ClassHelper.make(Map.class), ATTRS_EXPRESSION))
       .addExpression(
           new ConstructorCallExpression(
               new ClassNode(GroovyPage.ConstantClosure.class), constructorArgs));
   methodBody.addStatement(
       new ExpressionStatement(
           new MethodCallExpression(new VariableExpression("this"), tagName, arguments)));
   classNode.addMethod(
       new MethodNode(
           tagName, Modifier.PUBLIC, OBJECT_CLASS, MAP_CHARSEQUENCE_PARAMETERS, null, methodBody));
 }
示例#10
0
  /**
   * Adds a static method to the given class node that delegates to the given method and resolves
   * the object to invoke the method on from the given expression.
   *
   * @param expression The expression
   * @param classNode The class node
   * @param delegateMethod The delegate method
   * @return The added method node or null if it couldn't be added
   */
  public static MethodNode addDelegateStaticMethod(
      Expression expression, ClassNode classNode, MethodNode delegateMethod) {
    Parameter[] parameterTypes = delegateMethod.getParameters();
    String declaredMethodName = delegateMethod.getName();
    if (classNode.hasDeclaredMethod(declaredMethodName, parameterTypes)) {
      return null;
    }

    BlockStatement methodBody = new BlockStatement();
    ArgumentListExpression arguments = new ArgumentListExpression();

    for (Parameter parameterType : parameterTypes) {
      arguments.addExpression(new VariableExpression(parameterType.getName()));
    }
    MethodCallExpression methodCallExpression =
        new MethodCallExpression(expression, declaredMethodName, arguments);
    methodCallExpression.setMethodTarget(delegateMethod);

    ThrowStatement missingMethodException = createMissingMethodThrowable(classNode, delegateMethod);
    VariableExpression apiVar = addApiVariableDeclaration(expression, delegateMethod, methodBody);
    IfStatement ifStatement =
        createIfElseStatementForApiMethodCall(methodCallExpression, apiVar, missingMethodException);

    methodBody.addStatement(ifStatement);
    ClassNode returnType = nonGeneric(delegateMethod.getReturnType());
    if (METHOD_MISSING_METHOD_NAME.equals(declaredMethodName)) {
      declaredMethodName = STATIC_METHOD_MISSING_METHOD_NAME;
    }
    MethodNode methodNode = classNode.getDeclaredMethod(declaredMethodName, parameterTypes);
    if (methodNode == null) {
      methodNode =
          new MethodNode(
              declaredMethodName,
              Modifier.PUBLIC | Modifier.STATIC,
              returnType,
              copyParameters(parameterTypes),
              GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY,
              methodBody);
      methodNode.addAnnotations(delegateMethod.getAnnotations());

      classNode.addMethod(methodNode);
    }
    return methodNode;
  }
示例#11
0
 /**
  * Wraps a method body in try / catch logic that catches any errors and logs an error, but does
  * not rethrow!
  *
  * @param methodNode The method node
  */
 public static void wrapMethodBodyInTryCatchDebugStatements(MethodNode methodNode) {
   BlockStatement code = (BlockStatement) methodNode.getCode();
   BlockStatement newCode = new BlockStatement();
   TryCatchStatement tryCatchStatement = new TryCatchStatement(code, new BlockStatement());
   newCode.addStatement(tryCatchStatement);
   methodNode.setCode(newCode);
   BlockStatement catchBlock = new BlockStatement();
   ArgumentListExpression logArguments = new ArgumentListExpression();
   logArguments.addExpression(
       new BinaryExpression(
           new ConstantExpression("Error initializing class: "),
           Token.newSymbol(Types.PLUS, 0, 0),
           new VariableExpression("e")));
   logArguments.addExpression(new VariableExpression("e"));
   catchBlock.addStatement(
       new ExpressionStatement(
           new MethodCallExpression(new VariableExpression("log"), "error", logArguments)));
   tryCatchStatement.addCatch(
       new CatchStatement(new Parameter(new ClassNode(Throwable.class), "e"), catchBlock));
 }
    @Override
    public void visitArgumentlistExpression(ArgumentListExpression expression) {
      // LOG.debug "Transforming expression '${expression}':"

      if (expression.getLineNumber() >= 0 && expression.getLineNumber() < lineNumbers.length) {
        // LOG.debug "   start from ${expression.lineNumber} to ${lineNumbers[expression.lineNumber
        // - 1]}"
        expression.setLineNumber(lineNumbers[expression.getLineNumber() - 1]);
      }

      if (expression.getLastLineNumber() > 0
          && expression.getLastLineNumber() < lineNumbers.length) {
        // LOG.debug "   end from ${expression.lastLineNumber} to
        // ${lineNumbers[expression.lastLineNumber - 1]}"
        expression.setLastLineNumber(lineNumbers[expression.getLastLineNumber() - 1]);
      }
      super.visitArgumentlistExpression(expression);
    }
  private IfStatement getAutowiringIfStatement(
      ClassExpression targetClass,
      VariableExpression fieldExpression,
      BinaryExpression testTargetAssignment) {
    VariableExpression appCtxVar = new VariableExpression("applicationContext");

    BooleanExpression applicationContextCheck =
        new BooleanExpression(
            new BinaryExpression(
                new BinaryExpression(
                    fieldExpression,
                    GrailsASTUtils.EQUALS_OPERATOR,
                    GrailsASTUtils.NULL_EXPRESSION),
                Token.newSymbol("&&", 0, 0),
                new BinaryExpression(
                    appCtxVar,
                    GrailsASTUtils.NOT_EQUALS_OPERATOR,
                    GrailsASTUtils.NULL_EXPRESSION)));
    BlockStatement performAutowireBlock = new BlockStatement();
    ArgumentListExpression arguments = new ArgumentListExpression();
    arguments.addExpression(fieldExpression);
    arguments.addExpression(new ConstantExpression(1));
    arguments.addExpression(new ConstantExpression(false));
    BlockStatement assignFromApplicationContext = new BlockStatement();
    ArgumentListExpression argWithClassName = new ArgumentListExpression();
    MethodCallExpression getClassNameMethodCall =
        new MethodCallExpression(targetClass, "getName", new ArgumentListExpression());
    argWithClassName.addExpression(getClassNameMethodCall);

    assignFromApplicationContext.addStatement(
        new ExpressionStatement(
            new BinaryExpression(
                fieldExpression,
                ASSIGN,
                new MethodCallExpression(appCtxVar, "getBean", argWithClassName))));
    BlockStatement elseBlock = new BlockStatement();
    elseBlock.addStatement(new ExpressionStatement(testTargetAssignment));
    performAutowireBlock.addStatement(
        new IfStatement(
            new BooleanExpression(
                new MethodCallExpression(appCtxVar, "containsBean", argWithClassName)),
            assignFromApplicationContext,
            elseBlock));
    performAutowireBlock.addStatement(
        new ExpressionStatement(
            new MethodCallExpression(
                new PropertyExpression(appCtxVar, "autowireCapableBeanFactory"),
                "autowireBeanProperties",
                arguments)));
    return new IfStatement(applicationContextCheck, performAutowireBlock, new BlockStatement());
  }