Пример #1
0
  public void testMethods() throws Exception {
    ClassNode classNode = new ClassNode("Foo", ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
    classNode.addConstructor(new ConstructorNode(ACC_PUBLIC, null));

    Statement statementA = new ReturnStatement(new ConstantExpression("calledA"));
    Statement statementB = new ReturnStatement(new ConstantExpression("calledB"));
    Statement emptyStatement = new BlockStatement();

    classNode.addMethod(
        new MethodNode(
            "a",
            ACC_PUBLIC,
            ClassHelper.OBJECT_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            statementA));
    classNode.addMethod(
        new MethodNode(
            "b", ACC_PUBLIC, null, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, statementB));

    classNode.addMethod(
        new MethodNode(
            "noReturnMethodA",
            ACC_PUBLIC,
            null,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            emptyStatement));
    classNode.addMethod(
        new MethodNode(
            "noReturnMethodB",
            ACC_PUBLIC,
            ClassHelper.OBJECT_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            emptyStatement));

    classNode.addMethod(
        new MethodNode(
            "c",
            ACC_PUBLIC,
            ClassHelper.VOID_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            emptyStatement));

    Class fooClass = loadClass(classNode);
    assertTrue("Loaded a new class", fooClass != null);

    Object bean = fooClass.newInstance();
    assertTrue("Created instance of class: " + bean, bean != null);

    assertCallMethod(bean, "a", "calledA");
    assertCallMethod(bean, "b", "calledB");
    assertCallMethod(bean, "noReturnMethodA", null);
    assertCallMethod(bean, "noReturnMethodB", null);
    assertCallMethod(bean, "c", null);
  }
  /**
   * Main loop entry.
   *
   * <p>First, it delegates to the super visitClass so we can collect the relevant annotations in an
   * AST tree walk.
   *
   * <p>Second, it calls the visit method on the transformation for each relevant annotation found.
   *
   * @param classNode the class to visit
   */
  public void visitClass(ClassNode classNode) {
    // only descend if we have annotations to look for
    Map<Class<? extends ASTTransformation>, Set<ASTNode>> baseTransforms =
        classNode.getTransforms(phase);
    if (!baseTransforms.isEmpty()) {
      final Map<Class<? extends ASTTransformation>, ASTTransformation> transformInstances =
          new HashMap<Class<? extends ASTTransformation>, ASTTransformation>();
      for (Class<? extends ASTTransformation> transformClass : baseTransforms.keySet()) {
        try {
          transformInstances.put(transformClass, transformClass.newInstance());
        } catch (InstantiationException e) {
          source
              .getErrorCollector()
              .addError(
                  new SimpleMessage(
                      "Could not instantiate Transformation Processor "
                          + transformClass, // + " declared by " +
                                            // annotation.getClassNode().getName(),
                      source));
        } catch (IllegalAccessException e) {
          source
              .getErrorCollector()
              .addError(
                  new SimpleMessage(
                      "Could not instantiate Transformation Processor "
                          + transformClass, // + " declared by " +
                                            // annotation.getClassNode().getName(),
                      source));
        }
      }

      // invert the map, is now one to many
      transforms = new HashMap<ASTNode, List<ASTTransformation>>();
      for (Map.Entry<Class<? extends ASTTransformation>, Set<ASTNode>> entry :
          baseTransforms.entrySet()) {
        for (ASTNode node : entry.getValue()) {
          List<ASTTransformation> list = transforms.get(node);
          if (list == null) {
            list = new ArrayList<ASTTransformation>();
            transforms.put(node, list);
          }
          list.add(transformInstances.get(entry.getKey()));
        }
      }

      targetNodes = new LinkedList<ASTNode[]>();

      // first pass, collect nodes
      super.visitClass(classNode);

      // second pass, call visit on all of the collected nodes
      for (ASTNode[] node : targetNodes) {
        for (ASTTransformation snt : transforms.get(node[0])) {
          if (snt instanceof CompilationUnitAware) {
            ((CompilationUnitAware) snt).setCompilationUnit(context.getCompilationUnit());
          }
          snt.visit(node, source);
        }
      }
    }
  }
 private static void addPhaseOperationsForGlobalTransforms(
     CompilationUnit compilationUnit, Map<String, URL> transformNames, boolean isFirstScan) {
   GroovyClassLoader transformLoader = compilationUnit.getTransformLoader();
   for (Map.Entry<String, URL> entry : transformNames.entrySet()) {
     try {
       Class gTransClass = transformLoader.loadClass(entry.getKey(), false, true, false);
       // no inspection unchecked
       GroovyASTTransformation transformAnnotation =
           (GroovyASTTransformation) gTransClass.getAnnotation(GroovyASTTransformation.class);
       if (transformAnnotation == null) {
         compilationUnit
             .getErrorCollector()
             .addWarning(
                 new WarningMessage(
                     WarningMessage.POSSIBLE_ERRORS,
                     "Transform Class "
                         + entry.getKey()
                         + " is specified as a global transform in "
                         + entry.getValue().toExternalForm()
                         + " but it is not annotated by "
                         + GroovyASTTransformation.class.getName()
                         + " the global transform associated with it may fail and cause the compilation to fail.",
                     null,
                     null));
         continue;
       }
       if (ASTTransformation.class.isAssignableFrom(gTransClass)) {
         final ASTTransformation instance = (ASTTransformation) gTransClass.newInstance();
         if (instance instanceof CompilationUnitAware) {
           ((CompilationUnitAware) instance).setCompilationUnit(compilationUnit);
         }
         CompilationUnit.SourceUnitOperation suOp =
             new CompilationUnit.SourceUnitOperation() {
               public void call(SourceUnit source) throws CompilationFailedException {
                 instance.visit(new ASTNode[] {source.getAST()}, source);
               }
             };
         if (isFirstScan) {
           compilationUnit.addPhaseOperation(suOp, transformAnnotation.phase().getPhaseNumber());
         } else {
           compilationUnit.addNewPhaseOperation(
               suOp, transformAnnotation.phase().getPhaseNumber());
         }
       } else {
         compilationUnit
             .getErrorCollector()
             .addError(
                 new SimpleMessage(
                     "Transform Class "
                         + entry.getKey()
                         + " specified at "
                         + entry.getValue().toExternalForm()
                         + " is not an ASTTransformation.",
                     null));
       }
     } catch (Exception e) {
       compilationUnit
           .getErrorCollector()
           .addError(
               new SimpleMessage(
                   "Could not instantiate global transform class "
                       + entry.getKey()
                       + " specified at "
                       + entry.getValue().toExternalForm()
                       + "  because of exception "
                       + e.toString(),
                   null));
     }
   }
 }