Java 来自字符串的 AST 形式注释

Java AST form annotation from String

我正在尝试从包含其他注释的内部字符串创建注释。

这是应该处理的 SimpleAnnotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface SimpleAnnotation {
    String[] value() default {};
}

这是注释class

@SimpleAnnotation({
                   "@com.demo.annotations.Entity(name = \"simple_name\")", 
                   "@com.demo.annotations.CustomAnnotation"
                 })
public class Simple {
}

注释class的编译结果应该是

@com.demo.annotations.Entity(name = "simple_name")
@com.demo.annotations.CustomAnnotation                     
public class Simple {
}

我试过使用自定义注释处理器 处理 class 声明。它获取带有注释的 class 修饰符,并将派生注释分析为树

    public class SimpleAnnotationProcessor extends AbstractProcessor {

        private Messager messager;

        private Trees trees;
        private ChangeTranslator visitor;

        @Override
        public Set<String> getSupportedAnnotationTypes() {
            return Collections.singleton(SimpleAnnotation.class.getCanonicalName());
        }

        @Override
        public SourceVersion getSupportedSourceVersion() {
            return SourceVersion.RELEASE_8;
        }


        @Override
        public synchronized void init(ProcessingEnvironment processingEnv) {
        ............
        }

        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(SimpleAnnotation.class);

            for (Element element : elementsAnnotatedWith) {
                Name simpleName = element.getSimpleName();
                System.out.println(simpleName);
                messager.printMessage(Diagnostic.Kind.NOTE, "found with annotation " + simpleName);

                JCTree tree = (JCTree) trees.getTree(element);

                visitor.setElement(element);

                tree.accept(visitor);
            }

            return true;
        }


       public class ChangeTranslator extends TreeTranslator {

        private JavacProcessingEnvironment javacProcessingEnvironment;
        private TreeMaker treeMaker;
        private Messager messager;

        public ChangeTranslator(JavacProcessingEnvironment javacProcessingEnvironment, TreeMaker treeMaker, Messager messager) {
            this.javacProcessingEnvironment = javacProcessingEnvironment;
            this.treeMaker = treeMaker;
            this.messager = messager;
        }    

        @Override
        public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {
            super.visitClassDef(jcClassDecl);

            if (isNeedProcessing(jcClassDecl)) {

                JCTree.JCModifiers modifiers = jcClassDecl.getModifiers();

                List<JCTree.JCAnnotation> annotations = modifiers.getAnnotations();

                List<JCTree.JCAnnotation> jcAnnotations = List.nil();

                for (JCTree.JCAnnotation a : annotations) {
                    if (a.getAnnotationType().toString().contains(SimpleAnnotation.class.getSimpleName())) {                           
                        List<JCTree.JCExpression> arguments = a.getArguments();

                        for (JCTree.JCExpression arg : arguments) {

                            JCTree.JCNewArray expressions = (JCTree.JCNewArray) ((JCTree.JCAssign) arg).getExpression();
                            List<JCTree.JCExpression> elems = expressions.elems;
                            for (JCTree.JCExpression expression : elems) {                                    


                               // parse annotation from string
                               String value = (String) ((JCTree.JCLiteral) expression).getValue();

                          // e.g com.demo.annotations.Entity
                          String substringName = value.trim().substring(1, 28);
                                Class<? extends Class> aClass = null;

                                try {
                                    aClass = Class.forName(substringName);                                      

                                } catch (ClassNotFoundException e) {
                                    e.printStackTrace();
                                }



                                // 1 - attribute to create annotation from 
                                Attribute attribute = new Attribute.Compound(aClass, null);

                                // 2 - place where annotation should be created
                                treeMaker.Annotation(attribute);
                            }
                        }
                    }
                }

                modifiers.annotations = jcAnnotations;

                System.out.println(result);
            }

        }

        private boolean isNeedProcessing(JCTree.JCClassDecl jcClassDecl) {
            return jcClassDecl.getModifiers().toString().contains("@SimpleAnnotation");
        }

    }
}

问题是从 Class 类型获取信息以创建用于创建 JCAnnotation 的 com.sun.tools.javac.code.Type.ClassType。

感谢任何帮助。

public class SimpleAnnotationProcessor extends AbstractProcessor {

    ...
    @Override
    public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {
        ...
        ListBuffer<JCTree.JCExpression> params = new ListBuffer<JCTree.JCExpression>();
        params.append(treeMaker.Assign(treeMaker.Ident(names.fromString("name")), treeMaker.Literal("simple_name")));
        JCTree.JCAnnotation entity = treeMaker.Annotation(select("com.demo.annotations.Entity"), params.toList());
        JCTree.JCAnnotation customAnnotation = treeMaker.Annotation(select("com.demo.annotations.CustomAnnotation"), List.nil());
        // then append annotation to modifiers of you want
        // NOTE: List<A>.append() method will return a new List in javac
        ...
    }

    JCTree.JCExpression select(String path) {
        JCTree.JCExpression expression = null;
        int i = 0;
        for (String split : path.split("\.")) {
            if (i == 0)
                expression = treeMaker.Ident(names.fromString(split));
            else {
                expression = treeMaker.Select(expression, names.fromString(split));
            }
            i++;
        }

        return expression;
    }
}

希望对遇到同样问题的人有所帮助