private void autoAnnotateSetupTeardown(ClassNode classNode) {
    MethodNode setupMethod =
        classNode.getMethod(SET_UP_METHOD, GrailsArtefactClassInjector.ZERO_PARAMETERS);
    if (setupMethod != null && setupMethod.getAnnotations(BEFORE_CLASS_NODE).size() == 0) {
      setupMethod.addAnnotation(BEFORE_ANNOTATION);
    }

    MethodNode tearDown =
        classNode.getMethod(TEAR_DOWN_METHOD, GrailsArtefactClassInjector.ZERO_PARAMETERS);
    if (tearDown != null && tearDown.getAnnotations(AFTER_CLASS_NODE).size() == 0) {
      tearDown.addAnnotation(AFTER_ANNOTATION);
    }
  }
  /**
   * Main entry point for the calling the TestForTransformation programmatically.
   *
   * @param classNode The class node that represents th test
   * @param ce The class expression that represents the class to test
   */
  public void testFor(ClassNode classNode, ClassExpression ce) {
    boolean junit3Test = isJunit3Test(classNode);

    // make sure the 'log' property is not the one from GroovyTestCase
    FieldNode log = classNode.getField("log");
    if (log == null || log.getDeclaringClass().equals(GROOVY_TEST_CASE_CLASS)) {
      LoggingTransformer.addLogField(classNode, classNode.getName());
    }
    boolean isSpockTest = isSpockTest(classNode);

    if (!isSpockTest && !junit3Test) {
      // assume JUnit 4
      Map<String, MethodNode> declaredMethodsMap = classNode.getDeclaredMethodsMap();
      for (String methodName : declaredMethodsMap.keySet()) {
        MethodNode methodNode = declaredMethodsMap.get(methodName);
        if (isCandidateMethod(methodNode) && methodNode.getName().startsWith("test")) {
          if (methodNode.getAnnotations().size() == 0) {
            methodNode.addAnnotation(TEST_ANNOTATION);
          }
        }
      }
    }

    final MethodNode methodToAdd = weaveMock(classNode, ce, true);
    if (methodToAdd != null && junit3Test) {
      addMethodCallsToMethod(classNode, SET_UP_METHOD, Arrays.asList(methodToAdd));
    }
  }
  /**
   * Adds the necessary field and methods to support resource locating.
   *
   * @param declaringClass the class to which we add the support field and methods
   */
  public static void apply(@Nonnull ClassNode declaringClass, @Nullable String beanName) {
    injectInterface(declaringClass, EVENT_PUBLISHER_CNODE);

    FieldNode epField =
        injectField(
            declaringClass, EVENT_ROUTER_FIELD_NAME, PRIVATE, EVENT_PUBLISHER_FIELD_CNODE, null);

    Parameter erParam = param(EVENT_ROUTER_CNODE, EVENT_ROUTER_PROPERTY);
    if (!isBlank(beanName)) {
      AnnotationNode namedAnnotation = new AnnotationNode(NAMED_TYPE);
      namedAnnotation.addMember("value", new ConstantExpression(beanName));
      erParam.addAnnotation(namedAnnotation);
    }

    MethodNode setter =
        new MethodNode(
            METHOD_SET_EVENT_ROUTER,
            PRIVATE,
            VOID_TYPE,
            params(erParam),
            NO_EXCEPTIONS,
            stmnt(call(field(epField), METHOD_SET_EVENT_ROUTER, args(var(EVENT_ROUTER_PROPERTY)))));
    setter.addAnnotation(new AnnotationNode(INJECT_TYPE));
    injectMethod(declaringClass, setter);

    addDelegateMethods(declaringClass, EVENT_PUBLISHER_CNODE, field(epField));
  }
 private BlockStatement getJunit4Setup(ClassNode classNode) {
   MethodNode setupMethod =
       classNode.getMethod(SET_UP_METHOD, GrailsArtefactClassInjector.ZERO_PARAMETERS);
   if (setupMethod == null) {
     setupMethod =
         new MethodNode(
             SET_UP_METHOD,
             Modifier.PUBLIC,
             ClassHelper.VOID_TYPE,
             GrailsArtefactClassInjector.ZERO_PARAMETERS,
             null,
             new BlockStatement());
     setupMethod.addAnnotation(MIXIN_METHOD_ANNOTATION);
     classNode.addMethod(setupMethod);
   }
   if (setupMethod.getAnnotations(BEFORE_CLASS_NODE).size() == 0) {
     setupMethod.addAnnotation(BEFORE_ANNOTATION);
   }
   return getOrCreateMethodBody(classNode, setupMethod, SET_UP_METHOD);
 }
  /**
   * This method is used to add "bridge" methods for private methods of an inner/outer class, so
   * that the outer class is capable of calling them. It does basically the same job as access$000
   * like methods in Java.
   *
   * @param node an inner/outer class node for which to generate bridge methods
   */
  @SuppressWarnings("unchecked")
  private void addPrivateBridgeMethods(final ClassNode node) {
    Set<ASTNode> accessedMethods =
        (Set<ASTNode>) node.getNodeMetaData(StaticTypesMarker.PV_METHODS_ACCESS);
    if (accessedMethods == null) return;
    List<MethodNode> methods = new ArrayList<MethodNode>(node.getAllDeclaredMethods());
    Map<MethodNode, MethodNode> privateBridgeMethods =
        (Map<MethodNode, MethodNode>) node.getNodeMetaData(PRIVATE_BRIDGE_METHODS);
    if (privateBridgeMethods != null) {
      // private bridge methods already added
      return;
    }
    privateBridgeMethods = new HashMap<MethodNode, MethodNode>();
    int i = -1;
    final int access = Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC;
    for (MethodNode method : methods) {
      if (accessedMethods.contains(method)) {
        i++;
        Parameter[] methodParameters = method.getParameters();
        Parameter[] newParams = new Parameter[methodParameters.length + 1];
        System.arraycopy(methodParameters, 0, newParams, 1, methodParameters.length);
        newParams[0] = new Parameter(node.getPlainNodeReference(), "$that");
        Expression arguments;
        if (method.getParameters() == null || method.getParameters().length == 0) {
          arguments = ArgumentListExpression.EMPTY_ARGUMENTS;
        } else {
          List<Expression> args = new LinkedList<Expression>();
          for (Parameter parameter : methodParameters) {
            args.add(new VariableExpression(parameter));
          }
          arguments = new ArgumentListExpression(args);
        }
        Expression receiver =
            method.isStatic() ? new ClassExpression(node) : new VariableExpression(newParams[0]);
        MethodCallExpression mce = new MethodCallExpression(receiver, method.getName(), arguments);
        mce.setMethodTarget(method);

        ExpressionStatement returnStatement = new ExpressionStatement(mce);
        MethodNode bridge =
            node.addMethod(
                "access$" + i,
                access,
                method.getReturnType(),
                newParams,
                method.getExceptions(),
                returnStatement);
        privateBridgeMethods.put(method, bridge);
        bridge.addAnnotation(new AnnotationNode(COMPILESTATIC_CLASSNODE));
      }
    }
    if (!privateBridgeMethods.isEmpty()) {
      node.setNodeMetaData(PRIVATE_BRIDGE_METHODS, privateBridgeMethods);
    }
  }
  @Test
  public void transformationOfAnnotationOnMethod() {
    ClassNode classNode = new ClassNode("Test", 0, new ClassNode(Object.class));
    this.moduleNode.addClass(classNode);

    MethodNode methodNode =
        new MethodNode(
            "test", 0, new ClassNode(Void.class), new Parameter[0], new ClassNode[0], null);
    methodNode.addAnnotation(this.grabAnnotation);
    classNode.addMethod(methodNode);

    assertGrabAnnotationHasBeenTransformed();
  }
  protected MethodNode addClassUnderTestMethod(
      ClassNode classNode, ClassExpression targetClass, String type) {

    String methodName = "setup" + type + "UnderTest";
    String fieldName = GrailsNameUtils.getPropertyName(type);
    String getterName = GrailsNameUtils.getGetterName(fieldName);
    fieldName = '$' + fieldName;

    if (classNode.getField(fieldName) == null) {
      classNode.addField(fieldName, Modifier.PRIVATE, targetClass.getType(), null);
    }

    MethodNode methodNode =
        classNode.getMethod(methodName, GrailsArtefactClassInjector.ZERO_PARAMETERS);

    VariableExpression fieldExpression = new VariableExpression(fieldName);
    if (methodNode == null) {
      BlockStatement setupMethodBody = new BlockStatement();
      addMockCollaborator(type, targetClass, setupMethodBody);

      methodNode =
          new MethodNode(
              methodName,
              Modifier.PUBLIC,
              ClassHelper.VOID_TYPE,
              GrailsArtefactClassInjector.ZERO_PARAMETERS,
              null,
              setupMethodBody);
      methodNode.addAnnotation(BEFORE_ANNOTATION);
      methodNode.addAnnotation(MIXIN_METHOD_ANNOTATION);
      classNode.addMethod(methodNode);
    }

    MethodNode getter =
        classNode.getMethod(getterName, GrailsArtefactClassInjector.ZERO_PARAMETERS);
    if (getter == null) {
      BlockStatement getterBody = new BlockStatement();
      getter =
          new MethodNode(
              getterName,
              Modifier.PUBLIC,
              targetClass.getType().getPlainNodeReference(),
              GrailsArtefactClassInjector.ZERO_PARAMETERS,
              null,
              getterBody);

      BinaryExpression testTargetAssignment =
          new BinaryExpression(
              fieldExpression,
              ASSIGN,
              new ConstructorCallExpression(
                  targetClass.getType(), GrailsArtefactClassInjector.ZERO_ARGS));

      IfStatement autowiringIfStatement =
          getAutowiringIfStatement(targetClass, fieldExpression, testTargetAssignment);
      getterBody.addStatement(autowiringIfStatement);

      getterBody.addStatement(new ReturnStatement(fieldExpression));
      classNode.addMethod(getter);
    }

    return methodNode;
  }