一、AST
AST? abstract syntax tree (抽象语法结构树),是对java语言的一种抽象,每个节点都能对应到一种java语法,最终一个java文件就是由棵节点树构成
二、Tree
Tree是一个接口,是AST节点的抽象,内部有一个最重要的枚举Kind,定义了java中的每条语句的格式,也是对应着AST的一个节点
以下均为子接口,每个结构都定义了语法节点类型
Tree
- WildcardTree
- TypeParameterType
- StatementTree? ? ? (一个完整的语句,比如简单的"int a = 1;",注意最后的“;”)
- ThrowTree
- ReturnTree
- TryTree
- ContinueTree
- BreakTree
- BlockTree
- DoWhileLoopTree
- ClassTree
- VariableTree
- WhileLoopTree
- ForLoopTree
- SwitchTree
- SynchronizedTree
- EnhancedForLoopTree
- LabeedStatementTree
- AssertTree
- EmptyStatementTree
- IfTree
- ExpressionStatementTree
- CatchTree
- MethodTree
- ArrayTypeTree
- UnionTypeTree
- ModifiersTree
- ParameterizedTypeTree
- CaseTree
- ExpressionTree? ? ? ?(一个非完整的语句,比如简单的"a = 1",注意最后没有“;”)
- MemberReferenceTree
- LambdaExpressionTree
- UnaryTree
- MethodInvocationTree
- AnnotatedTypeTree
- CompoundAssignmentTree
- BinaryTree
- ErroneousTree
- MemberSelectTree
- ArrayAccessTree
- TypeCastTree
- NewClassTree
- ConditionalExpressionTree
- ParenthesizedTree
- AnnotationTree
- NewArrayType
- InstanceOfTree
- IdentifierTree
- AssignmentTree
- LiteralTree
- CompilationUnitTree
- IntersectionTypeTree
- PrimitiveTypeTree
- Import
三、Kind
AST 节点类型,对应着java的语法
枚举类型 | Tree节点(就是上面列出的接口) | 定义 | 示例 | ANNOTATED_TYPE | AnnotatedTypeTree | 注解类型,可以用在任何类型上 注解的Target为:TYPE_PARAMETER TYPE_USE | @NotNull String | ANNOTATION | AnnotationTree | 普通的注解 | @Data @JsonProperties(value="sdf") | TYPE_ANNOTATION | AnnotationTree | 跟ANNOTATION,待验证有什么区别 | | ARRAY_ACCESS | ArrayAccessTree | 数组访问 | array[3] | ARRAY_TYPE | ArrayTypeTree | 数组类型 | int[] | ASSIGNMENT | AssignmentTree | 赋值 | a = 1 | BLOCK | BlockTree | 语句块 | {} { statements } static { statements } | BREAK | BreakTree | break | break; break label; | CASE | CaseTree | case 语句 | case expression:statements default: statements | CATCH | CatchTree | catch 语句 | catch(parameter)? block 注:这些语句会有嵌套问题 | CLASS INTERFACE ENUM ANNOTATION_TYPE | ClassTree | class 定义 | modifiers class simpleName typeParameters ? ? ? ?extends extendsClause ? ? ? ?implements implementsClause { ? ?<em>members</em> } | COMPILATION_UNIT | CompilationUnitTree | 一个编译单元 包括源文件和package-info.java | | CONDITIONAL_EXPRESSION | ConditionalExpressionTree | 三元运算符 | a == 1 ? 1 : 0 | CONTINUE | ContinueTree | continue 语句 | continue; continue label; | DO_WHILE_LOOP | DoWhileLoopTree | do...while | | ENHANCED_FOR_LOOP | EnhancedForLoopTree | 增强for | for(int i: intlist) { statement } | EXPRESSION_STATEMENT | ExpressionStatementTree | 语句 | | MEMBER_SELECT | MemberSelectTree | 对象.操作 | aClass.aparams | MEMBER_REFERENCE | MemberReferenceTree | 成员引用表达式 | | FOR_LOOP | ForLoopTree | for循环 | | IDENTIFIER | IdentifierTree | 识别符,与literal区分开 | a = 1 a 就是一个identifier | IF | IfTree | | | IMPORT | ImportTree | | | INSTANCE_OF | InstanceOfTree | instanceof 表达式 | | LABELED_STATEMENT | LabeledStatementTree | label语法 | label : statement | METHOD | MethodTree | 方法定义 | 方法 modifiers typeParameters type name (parameters ) ? ?body ? 注解 modifiers type name () default defaultValue | METHOD_INVOCATION | MethodInvocationTree | method invoke语法 | | MODIFIERS | ModifiersTree | 修饰符(Modifier) 包括注解 | | NEW_ARRAY | NewArrayTree | | | NEW_CLASS | NewClassTree | | | LAMBDA_EXPRESSION | LambdaExpressionTree | lambda表达式 | | PRIMITIVE_TYPE | PrimitiveTypeTree | 基础类型 | | RETURN | ReturnTree | return | | EMPTY_STATEMENT | EmptyStatementTree | 空的";" | | SWITCH | SwitchTree | | | SYNCHRONIZED | SynchronizedTree | | | THROW | ThrowTree | | | TRY | TryTree | | | PARAMETERIZED_TYPE | ParameterizedTypeTree | 泛型 | List<Integer> | UNION_TYPE | UnionTypeTree | 多变量声明 | try { }catch(Exception e1 | Exception e2){ } | INTERSECTION_TYPE | IntersectionTypeTree | | T extends MyA & MyB | TYPE_CAST | TypeCastTree | 强转语句 | (int)a | TYPE_PARAMETER | TypeParameterTree | | | VARIABLE | VariableTree | 变量 | modifiers type name initializer ; modifiers type qualified-name.this | WHILE_LOOP | WhileLoopTree | | | POSTFIX_INCREMENT POSTFIX_DECREMENT PREFIX_INCREMENT PREFIX_DECREMENT UNARY_PLUS UNARY_MINUS BITWISE_COMPLEMENT LOGICAL_COMPLEMENT | UnaryTree | 运算符 | ++、--、+、-、~、!、*、/、% | MULTIPLY DIVIDE REMAINDER PLUS MINUS LEFT_SHIFT RIGHT_SHIFT UNSIGNED_RIGHT_SHIFT LESS_THAN GREATER_THAN LESS_THAN_EQUAL GREATER_THAN_EQUAL EQUAL_TO NOT_EQUAL_TO AND XOR OR CONDITIONAL_AND CONDITIONAL_OR | BinaryTree | 两元运算 | | MULTIPLY_ASSIGNMENT DIVIDE_ASSIGNMENT REMAINDER_ASSIGNMENT PLUS_ASSIGNMENT MINUS_ASSIGNMENT LEFT_SHIFT_ASSIGNMENT RIGHT_SHIFT_ASSIGNMENT UNSIGNED_RIGHT_SHIFT_ASSIGNMENT AND_ASSIGNMENT XOR_ASSIGNMENT OR_ASSIGNMENT | CompoundAssignmentTree | 赋值运算符 | +=、-=、*= | INT_LITERAL LONG_LITERAL FLOAT_LITERAL DOUBLE_LITERAL BOOLEAN_LITERAL CHAR_LITERAL STRING_LITERAL NULL_LITERAL | LiteralTree | 字面值 | a =? 1? (1就是) | OTHER | null | | |
?四、JCTree
com.sun.tools.javac.tree.JCTree 是Tree的一个抽象实现类,有各种实现类,代表着一个个的AST节点
JC具体类 | 实现Tree | Tag | Kind | 备注 | | LetExpr | | LETEXPR | 不支持 | | | JCErroneous | ErroneousTree | ERRONEOUS | ERRONEOUS | | | JCAnnotatedType | AnnotatedTypeTree | ANNOTATED_TYPE | ANNOTATED_TYPE | | | JCModifiers | ModifiersTree | MODIFIERS | MODIFIERS | ? | | JCAnnotation | AnnotationTree | | | ? | | JCTypeParameter | TypeParameterTree | TYPEPARAMETER | TYPE_PARAMETER | | | JCTypeIntersection | IntersectionTypeTree | TYPEINTERSECTION | INTERSECTION_TYPE | | | JCTypeUnion | UnionTypeTree | TYPEUNION | UNION_TYPE | | | JCTypeApply | ParameterizedTypeTree | TYPEAPPLY | PARAMETERIZED_TYPE | | | JCArrayTypeTree | ArrayTypeTree | TYPEARRAY | ARRAY_TYPE | | | JCPrimitiveTypeTree | PrimitiveTypeTree | TYPEIDENT | PRIMITIVE_TYPE | ? | | JCLiteral | LiteralTree | LITERAL | INT_LITERAL LONG_LITERAL ... 以LITERAL结尾的 | ? | | JCIdent | IdentifierTree | IDENT | IDENTIFIER | ? | | JCMemberReference | MemberReferenceTree | REFERENCE | MEMBER_REFERENCE | | | JCFieldAccess | MemberSelectTree | SELECT | MEMBER_SELECT | ? | | JCArrayAccess | ArrayAccessTree | INDEXED | ARRAY_ACCESS | ? | | JCInstanceOf | InstanceOfTree | TYPETEST | INSTANCE_OF | | | JCTypeCast | TypeCastTree | TYPE_CAST | TYPECAST | | | JCBinary | BinaryTree | 根据操作符定 | 根据tag映射 | | | JCAssignOp | CompoundAssignmentTree | 赋值,根据操作符定 支持的是 “+=”这种 | 根据tag映射 | | | JCAssign | AssignmentTree | ASSIGN 支持的是直接赋值 | ASSIGNMENT | ? | | JCParens | ParenthesizedTree | PARENS | PARENTHESIZED | | | JCLambda | LambdaExpressionTree | LAMBDA | LAMBDA_EXPRESSION | | | JCNewArray | NewArrayTree | NEWARRAY | NEW_ARRAY | | | JCNewClass | NewClassTree | NEWCLASS | NEW_CLASS | | | JCMethodInvocation | MethodInvocationTree | APPLY | METHOD_INVOCATION | | | JCAssert | AssertTree | ASSERT | ASSERT | | | JCThrow | ThrowTree | THROW | THROW | ? | | JCReturn | ReturnTree | RETURN | RETURN | ? | | JCContinue | ContinueTree | CONTINUE | CONTINUE | | | JCBreak | BreakTree | BREAK | BREAK | | | JCExpressionStatement | ExpressionStatementTree | EXEC | EXPRESSION_STATEMENT | | | JCIf | IfTree | IF | IF | | | JCConditional | ConditionalExpressionTree | CONDEXPR | CONDITIONAL_EXPRESSION | | | JCCatch | CatchTree | CATCH | CATCH | | | JCTry | TryTree | TRY | TRY | | | JCSynchronized | SynchronizedTree | SYNCHRONIZED | SYNCHRONIZED | | | JCCase | CaseTree | CASE | CASE | | | JCSwitch | SwitchTree | SWITCH | SWITCH | | | JCLabeledStatement | LabeledStatementTree | LABELLED | LABELED_STATEMENT | | | JCEnhancedForLoop | EnhancedForLoopTree | FOREACHLOOP | ENHANCED_FOR_LOOP | | | JCForLoop | ForLoopTree | FORLOOP | FOR_LOOP | | | JCWhileLoop | WhileLoopTree | WHILELOOP | WHILE_LOOP | | | JCDoWhileLoop | DoWhileLoopTree | DOLOOP | DO_WHILE_LOOP | | | JCBlock | BlockTree | BLOCK | BLOCK | | | JCSkip | EmptyStatementTree | SKIP | EMPTY_STATEMENT | | | JCVariableDecl | VariableTree | VARDEF | VARIABLE | ? | | JCMethodDecl | MethodTree | METHODDEF | METHOD | ? | | JCClassDecl | ClassTree | CLASSDEF | ANNOTATION_TYPE INTERFACE ENUM CLASS | ? | | JCImport | ImportTree | IMPORT | IMPORT | ? | | JCCompilationUnit | CompilationUnitTree | TOPLEVEL | COMPILATION_UNIT | | |
五、JC类的Factory
细心阅读会发现,各种JC类的构造函数都是protected,也就是说,并不能直接进行初始化,所以现在要使用Factory,Factory是各种JC类的工厂定义
六、TreeMaker
TreeMaker实现了Factory接口,所以我们它会是我们经常使用的一个类
还需要关注的一个Names,这个基本是创建一个节点的开始
Names: 用来存储和表示解析后的词法,每个字符集合都会是一个Name对象,所有的对象都存储在Name.Table内部类中。
在学习以下内容时,一定要熟练掌握JCIdent和Names。
Javac编译原理 - wade&luffy - 博客园
?
javac源码笔记与简单的编译原理 | Ren's Time Overflow Skyline ^_^
深入分析 Javac 编译原理 - 知乎
6.1、添加 import
// import com.leisure.lombok.thrift.AstTreeClass
// 获取标识符
JCTree.JCIdent jcIdent = treeMaker.Ident(names.fromString("com.leisure.lombok.thrift"));
// 获取标识符
Name className = names.fromString("AstTreeClass");
// 定义访问
JCTree.JCFieldAccess jcFieldAccess = treeMaker.Select(jcIdent, className);
// 添加import节点
JCTree.JCImport anImport = treeMaker.Import(jcFieldAccess, false);
// 加入AST树种
jcCompilationUnit.defs = jcCompilationUnit.defs.append(anImport);
6.2、定义属性
默认构造函数
//private AstTreeClass variable = new AstTreeClass()
// new AstTreeClass()
JCTree.JCNewClass newClass = treeMaker.NewClass(null, null, treeMaker.Ident(names.fromString("AstTreeClass")), List.nil(), null);
// private AstTreeClass variable = ...
JCTree.JCVariableDecl variableDecl = treeMaker.VarDef(treeMaker.Modifiers(Modifier.PRIVATE.ordinal()),
names.fromString("variable"), treeMaker.Ident(names.fromString("AstTreeClass")), newClass);
带参数的构造函数
使用这个我们就可以实现@Slf4j了(当然了,还需要有插件,才能真正像@Slf4j一样使用)
//public static final AstTreeClass staticVariable = new AstTreeClass(1)
JCTree.JCLiteral constantOne = treeMaker.Literal(1);
JCTree.JCNewClass newClass1 = treeMaker.NewClass(null, null, treeMaker.Ident(names.fromString("AstTreeClass")), List.of(constantOne), null);
JCTree.JCVariableDecl staticVariableDecl = treeMaker.VarDef(
treeMaker.Modifiers(Flags.PUBLIC + Flags.STATIC + Flags.FINAL),
names.fromString("staticVariable"),
treeMaker.Ident(names.fromString("AstTreeClass")),
newClass1
);
6.4、添加方法
String name = variableDecl.name.toString();
JCTree.JCExpression varType = variableDecl.vartype;
// getter,假设name长度大于1
String getterMethodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
// this.name
JCTree.JCExpression thisName = treeMaker.Select(treeMaker.This(classDecl.sym.type), names.fromString(name));
JCTree.JCReturn jcReturn = treeMaker.Return(thisName);
// public type getName() {return this.name;}
JCTree.JCMethodDecl getter = treeMaker.MethodDef(
treeMaker.Modifiers(Flags.PUBLIC), // 访问标识
names.fromString(getterMethodName), // 方法名字
varType, // 返回类型
List.nil(), // 泛型形参列表
List.nil(), // 参数列表
List.nil(), // 异常列表
treeMaker.Block(0, List.of(jcReturn)), // block
null // 默认方法
);
// setter
// public void setName(nameType name) {this.name = name;}
String setterMethodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
// 这里只是生成了this.name = name表达式
JCTree.JCAssign assign = treeMaker.Assign(thisName, treeMaker.Ident(names.fromString(name)));
// 生成一条语句 this.name = name;
JCTree.JCExpressionStatement assignStat = treeMaker.Exec(assign);
JCTree.JCMethodDecl setterMethodDecl = treeMaker.MethodDef(
treeMaker.Modifiers(Flags.PUBLIC), // 访问标识
names.fromString(setterMethodName), // 方法名
treeMaker.TypeIdent(TypeTag.VOID), // 返回类型
List.nil(), // 泛型形参列表
List.of(treeMaker.VarDef(
treeMaker.Modifiers(Flags.PARAMETER), // 普通参数
variableDecl.name,
varType,
null // 初始化为空,方法入参时为空即可
)
), // 参数列表
List.nil(), // 异常列表
treeMaker.Block(0, List.of(assignStat)), // 方法体
null //默认方法
);
解决TreeMaker AssertionError: Value of x -1_你倒是跑啊的博客-CSDN博客
TreeMaker? -> JCTree -> Tree?,接下来的一系列就是应用了
|