Last active
October 20, 2023 02:44
-
-
Save pietrocaselani/8624554 to your computer and use it in GitHub Desktop.
Generate main method using Annotation Processor.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.pc.hello; | |
import com.sun.source.util.Trees; | |
import com.sun.tools.javac.code.Flags; | |
import com.sun.tools.javac.code.TypeTags; | |
import com.sun.tools.javac.processing.JavacProcessingEnvironment; | |
import com.sun.tools.javac.tree.TreeMaker; | |
import com.sun.tools.javac.util.Context; | |
import com.sun.tools.javac.util.List; | |
import com.sun.tools.javac.util.Name; | |
import java.util.Set; | |
import javax.annotation.processing.AbstractProcessor; | |
import javax.annotation.processing.ProcessingEnvironment; | |
import javax.annotation.processing.RoundEnvironment; | |
import javax.annotation.processing.SupportedAnnotationTypes; | |
import javax.annotation.processing.SupportedSourceVersion; | |
import javax.lang.model.element.Element; | |
import javax.lang.model.element.TypeElement; | |
import static com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; | |
import static com.sun.tools.javac.tree.JCTree.JCBlock; | |
import static com.sun.tools.javac.tree.JCTree.JCClassDecl; | |
import static com.sun.tools.javac.tree.JCTree.JCExpression; | |
import static com.sun.tools.javac.tree.JCTree.JCFieldAccess; | |
import static com.sun.tools.javac.tree.JCTree.JCIdent; | |
import static com.sun.tools.javac.tree.JCTree.JCMethodDecl; | |
import static com.sun.tools.javac.tree.JCTree.JCMethodInvocation; | |
import static com.sun.tools.javac.tree.JCTree.JCModifiers; | |
import static com.sun.tools.javac.tree.JCTree.JCNewClass; | |
import static com.sun.tools.javac.tree.JCTree.JCStatement; | |
import static com.sun.tools.javac.tree.JCTree.JCTypeParameter; | |
import static com.sun.tools.javac.tree.JCTree.JCVariableDecl; | |
import static com.sun.tools.javac.util.Name.Table; | |
import static javax.lang.model.SourceVersion.RELEASE_6; | |
/** | |
* Created by Pietro Caselani | |
* On 25/01/14 | |
* Hello | |
*/ | |
@SupportedAnnotationTypes("com.pc.hello.MakeHello") | |
@SupportedSourceVersion(RELEASE_6) | |
public class HelloProcessor extends AbstractProcessor { | |
//region Fields | |
private Trees mTrees; | |
private TreeMaker mTreeMaker; | |
//endregion | |
//region Processor | |
@Override public synchronized void init(ProcessingEnvironment processingEnv) { | |
mTreeMaker = TreeMaker.instance(((JavacProcessingEnvironment) processingEnv).getContext()); | |
mTrees = Trees.instance(processingEnv); | |
super.init(processingEnv); | |
} | |
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) { | |
Set<? extends Element> elements = env.getElementsAnnotatedWith(MakeHello.class); | |
if (elements.size() > 0) { | |
for (Element element : elements) { | |
JCClassDecl classDecl = (JCClassDecl) mTrees.getTree(element); | |
addMainMethod(classDecl, element.toString()); | |
addHelloMethod(classDecl); | |
} | |
} | |
return true; | |
} | |
//endregion | |
//region Private | |
private void addMainMethod(JCClassDecl classDecl, String className) { | |
JCModifiers modifiers = mTreeMaker.Modifiers(Flags.PUBLIC | Flags.STATIC); | |
JCExpression returnType = mTreeMaker.TypeIdent(TypeTags.VOID); | |
List<JCVariableDecl> parameters = makeMainParameters(); | |
List<JCTypeParameter> generics = List.nil(); | |
List<JCExpression> throwz = List.nil(); | |
JCBlock methodBody = makeMainBody(className); | |
Name methodName = getName("main"); | |
JCMethodDecl mainMethodDecl = | |
mTreeMaker.MethodDef(modifiers, methodName, returnType, generics, parameters, throwz, | |
methodBody, null); | |
classDecl.defs = classDecl.defs.append(mainMethodDecl); | |
} | |
private List<JCVariableDecl> makeMainParameters() { | |
JCIdent paramType = mTreeMaker.Ident(getName("String")); | |
JCArrayTypeTree paramArray = mTreeMaker.TypeArray(paramType); | |
JCVariableDecl paramDecl = | |
mTreeMaker.VarDef(mTreeMaker.Modifiers(Flags.PARAMETER), getName("args"), paramArray, null); | |
return List.from(new JCVariableDecl[]{paramDecl}); | |
} | |
private JCBlock makeMainBody(String className) { | |
String[] strings = className.split("\\."); | |
JCExpression classNameIdent = mTreeMaker.Ident(getName(strings[0])); | |
for (int i = 1; i < strings.length; i++) { | |
classNameIdent = mTreeMaker.Select(classNameIdent, getName(strings[i])); | |
} | |
JCNewClass classObj = mTreeMaker.NewClass(null, List.<JCExpression>nil(), classNameIdent, | |
List.<JCExpression>nil(), null); | |
JCFieldAccess printHello = mTreeMaker.Select(classObj, getName("printHello")); | |
JCMethodInvocation printHelloInv = | |
mTreeMaker.Apply(List.<JCExpression>nil(), printHello, List.<JCExpression>nil()); | |
JCStatement exec = mTreeMaker.Exec(printHelloInv); | |
List<JCStatement> statements = List.of(exec); | |
return mTreeMaker.Block(0, statements); | |
} | |
private void addHelloMethod(JCClassDecl classDecl) { | |
JCModifiers modifiers = mTreeMaker.Modifiers(Flags.PRIVATE | Flags.FINAL); | |
JCExpression returnType = mTreeMaker.TypeIdent(TypeTags.VOID); | |
List<JCVariableDecl> parameters = List.nil(); | |
List<JCTypeParameter> generics = List.nil(); | |
Name methodName = getName("printHello"); | |
List<JCExpression> throwz = List.nil(); | |
JCBlock methodBody = makeHelloBody(); | |
JCMethodDecl helloMethodDecl = | |
mTreeMaker.MethodDef(modifiers, methodName, returnType, generics, parameters, throwz, | |
methodBody, null); | |
classDecl.defs = classDecl.defs.append(helloMethodDecl); | |
} | |
private JCBlock makeHelloBody() { | |
JCExpression printExpression = mTreeMaker.Ident(getName("System")); | |
printExpression = mTreeMaker.Select(printExpression, getName("out")); | |
printExpression = mTreeMaker.Select(printExpression, getName("println")); | |
List<JCExpression> printArgs = List.from(new JCExpression[] {mTreeMaker.Literal("Hello from HelloProcessor!")}); | |
printExpression = mTreeMaker.Apply(List.<JCExpression>nil(), printExpression, printArgs); | |
JCStatement call = mTreeMaker.Exec(printExpression); | |
List<JCStatement> statements = List.from(new JCStatement[]{call}); | |
return mTreeMaker.Block(0, statements); | |
} | |
private Name getName(String string) { | |
Context context = ((JavacProcessingEnvironment) processingEnv).getContext(); | |
return Name.fromString(Table.instance(context), string); | |
} | |
//endregion | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
com.pc.hello.HelloProcessor |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.pc.helloimpl; | |
import com.pc.hello.MakeHello; | |
/** | |
* Created by Pietro Caselani | |
* On 25/01/14 | |
* HelloImpl | |
*/ | |
@MakeHello | |
public final class Main {} | |
/* | |
package com.pc.helloimpl; | |
import com.pc.hello.MakeHello; | |
import java.io.PrintStream; | |
@MakeHello | |
public final class Main | |
{ | |
public static void main(String[] args) | |
{ | |
new Main().printHello(); | |
} | |
private final void printHello() { | |
System.out.println("Hello from HelloProcessor!"); | |
} | |
} | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.pc.hello; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.Target; | |
import static java.lang.annotation.ElementType.TYPE; | |
import static java.lang.annotation.RetentionPolicy.CLASS; | |
/** | |
* Created by Pietro Caselani | |
* On 25/01/14 | |
* Hello | |
*/ | |
@Retention(CLASS) | |
@Target(TYPE) | |
public @interface MakeHello {} |
hi @pietrocaselani,
Name.fromString
seemed not working for me. It is a java version compatibility issue
How to modify( delete ) some imports of the class?
https://blog.csdn.net/nideshouhu/article/details/90757952
then modify compilationUnit.defs
hi @pietrocaselani,
Name.fromString
seemed not working for me. It is a java version compatibility issue
Though this API is marked as one which can change without notice, the following implementation does the job
return Names.instance(context).fromString(string);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks this is really help