1 /*
2  * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
3  * Use of this file is governed by the BSD 3-clause license that
4  * can be found in the LICENSE.txt file in the project root.
5  */
6 
7 package org.antlr.v4.test.runtime;
8 
9 import com.sun.tools.javac.model.JavacElements;
10 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
11 import com.sun.tools.javac.tree.JCTree;
12 import com.sun.tools.javac.tree.TreeMaker;
13 import com.sun.tools.javac.util.List;
14 
15 import javax.annotation.processing.AbstractProcessor;
16 import javax.annotation.processing.ProcessingEnvironment;
17 import javax.annotation.processing.RoundEnvironment;
18 import javax.annotation.processing.SupportedAnnotationTypes;
19 import javax.annotation.processing.SupportedSourceVersion;
20 import javax.lang.model.SourceVersion;
21 import javax.lang.model.element.Element;
22 import javax.lang.model.element.TypeElement;
23 import java.util.Set;
24 
25 /**
26  I think I figured out how to use annotation processors in maven.  It's
27  more or less automatic and you don't even need to tell maven, with one minor
28  exception. The idea is to create a project for the annotation and another
29  for the annotation processor. Then, a project that uses the annotation
30  can simply set up the dependency on the other projects. You have to turn
31  off processing, -proc:none on the processor project itself but other than
32  that, java 6+ more or less tries to apply any processors it finds during
33  compilation. maven just works.
34 
35  Also you need a META-INF/services/javax.annotation.processing.Processor file
36  with "org.antlr.v4.test.runtime.CommentHasStringValueProcessor" in it.
37  */
38 @SupportedAnnotationTypes({"org.antlr.v4.test.runtime.CommentHasStringValue"})
39 @SupportedSourceVersion(SourceVersion.RELEASE_7)
40 public class CommentHasStringValueProcessor extends AbstractProcessor {
41 	protected JavacElements utilities;
42 	protected TreeMaker treeMaker;
43 
44 	@Override
init(ProcessingEnvironment processingEnv)45 	public synchronized void init(ProcessingEnvironment processingEnv) {
46 		super.init(processingEnv);
47 //		Messager messager = processingEnv.getMessager();
48 //		messager.printMessage(Diagnostic.Kind.NOTE, "WOW INIT--------------------");
49 		JavacProcessingEnvironment javacProcessingEnv = (JavacProcessingEnvironment) processingEnv;
50 		utilities = javacProcessingEnv.getElementUtils();
51 		treeMaker = TreeMaker.instance(javacProcessingEnv.getContext());
52 	}
53 
54 	@Override
process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)55 	public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
56 //		Messager messager = processingEnv.getMessager();
57 //		messager.printMessage(Diagnostic.Kind.NOTE, "PROCESS--------------------");
58 		Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(CommentHasStringValue.class);
59 		for (Element annotatedElement : annotatedElements) {
60 			String docComment = utilities.getDocComment(annotatedElement);
61 			JCTree.JCLiteral literal = treeMaker.Literal(docComment!=null ? docComment : "");
62 			JCTree elementTree = utilities.getTree(annotatedElement);
63 			if ( elementTree instanceof JCTree.JCVariableDecl ) {
64 				((JCTree.JCVariableDecl)elementTree).init = literal;
65 			}
66 			else if ( elementTree instanceof JCTree.JCMethodDecl ) {
67 				JCTree.JCStatement[] statements = new JCTree.JCStatement[1];
68 				statements[0] = treeMaker.Return(literal);
69 				JCTree.JCBlock body = treeMaker.Block(0, List.from(statements));
70 				((JCTree.JCMethodDecl)elementTree).body = body;
71 			}
72 		}
73 		return true;
74 	}
75 
76 	@Override
getSupportedSourceVersion()77 	public SourceVersion getSupportedSourceVersion() {
78 		return SourceVersion.latestSupported();
79 	}
80 }
81