eclipseJDTeclipseast抽象语法树文档格式.docx
《eclipseJDTeclipseast抽象语法树文档格式.docx》由会员分享,可在线阅读,更多相关《eclipseJDTeclipseast抽象语法树文档格式.docx(18页珍藏版)》请在冰豆网上搜索。
有try,catch语句块,用JLS4,
*2,你要告诉parser需要解析的内容类型。
ASTParser支持对以下四种内容的解析:
a.K_COMPILATION_UNIT:
一个编译单元,一般就是完整的Java文件
b.K_STATEMENTS:
Javastatements,比如赋值语句,或是if语句块,while语句块等。
此类型不需要文件是完整的编译单元,但需要是完整的statements。
比如if语句块要作为一个完整的statement输入,否则会报错。
c.K_EXPRESSION:
Javaexpressions
d.K_CLASS_BODY_DECLARATIONS:
Javaclass里的元素
*3,设置java代码,java代码可以通过文件流从java文件中得到,也可以自己拼接String,记得需要的是一个char[]
*4,如果解析的内容类型的一个完整的java类,则可以不用设置,如果只是片断,则需要设定为true.
*5,需要Parser得到一个AST根对象CompilationUnit
1-2,在Util类添加一个读取java文件的方法:
publicstaticStringgetJavaFromFile(StringjavaFilePath)throwsException{
FileInputStreamreader=newFileInputStream(newFile(javaFilePath));
byte[]bs=newbyte[reader.available()];
reader.read(bs,0,reader.available());
StringjavaContent=newString(bs);
returnjavaContent;
}
2-1,ASTNode结构图
2-2,java结构说明:
2-2-1,一个java文件中:
主要包含三大块(如图):
其中包引入可以有多个,类申明也可以有多个。
当然还有注释和注解两部分:
2-2-2在类中也主要包含三大块:
全局变量(Field),方法(Method),内部类(InnerClass),另外还有:
方法注解,变量注解,方法注释,字段注释,static块,如图:
2-3,解释ASTNode
通过上面对java结构的介绍,以及2-1的图,我们可以通过
CompilationUnitunit=(CompilationUnit)parser.createAST(null);
得到ASTNode得到ast的根节点,即:
ASTNoderootNode=unit.getAST();
他表示一个java文件,或者一个完事的java片段,我们以一个完事的java文件为例,如果是一个java文件,那么,
unit相对的子节点就是多个:
package{1},import{*},class{*},javadoc{*},annotation{*},
而其中java代码主要是写类中的,所以class又有多个子节点:
field{*},constructor{*},method{*},javadoc{*},annotation{*},staticblock{*},constructor(构造方法)只是特殊的方法,所以可以归为一类,
在java中,java的表达式,逻辑主要是在method中,method中还很多了节点,即各种表达式的子节点,这个这里就不说了。
这样一来,一个java文件就够成了一棵java方法树了。
下面就开始对java结构按上面的分析出的结构逐一的分析与遍历
EclipseJDT--AST遍历
(2)JAVA结构遍历
1,遍历整个java文件:
(以附件的java内容为例),如果有不理解的地方,请仔细看上面的结构图
1-1包申明
PackageDeclarationpackageDeclaration=unit.getPackage();
得到申明的包,即:
packagexm.bean;
packageDeclaration.toString();
==>
packagexm.bean
packageDeclaration.getName();
xm.bean
1-2导入包遍历
ListimportDeclarations=unit.imports();
for(Objectobject:
importDeclarations){
ImportDeclarationimportDec=(ImportDeclaration)object;
System.out.println(importDec.getName());
//print:
java.util.List
System.out.println(importDec);
//print:
importjava.util.List
System.out.println(importDec.isOnDemand());
//print:
如果是:
importjava.util.*;
true
如果是静态导入:
importstaticjava.lang.Math.*;
true;
System.out.println(importDec.isStatic());
1-2java类遍历(在一个java文件中,如果class关键字没有public申明,则一个java文件中可以存在多个类,如果用public申明,则只有一个java类),所以TypeDeclaration得到的是一个集合:
ListtypeDeclarations=unit.types();
如果java文件中有一个类,则:
TypeDeclarationclazzNode=(TypeDeclaration)typeDeclarations.get(0);
如果有多个类,则:
for(Objectobject:
typeDeclarations){
TypeDeclarationclazzNode=(TypeDeclaration)object;
System.out.println(clazzNode.getName());
if("
Balance"
.equals(clazzNode.getName())){
//遍历类里面
}elseif(...){
...
}...
2遍历整个java类头部:
2-1,注释遍历:
java的注释分为如下三种:
a:
doc注释,这个注释可以在javadoc里面体现出来,格式:
/**
*@Description金融行业记录帐户余额信息
*一般分为:
openingbalance,coloseingbalance,availablebalence等
*@author.x.m
*@Time2013/04/22
*/
b:
块注释,与类注释不同的是:
类注释开头是:
/**而块注释是:
/*
c:
行注释//后面跟注释内容
2-2,注释遍历:
注释在AST的分析与解释
以上类注释的解释,
AST,将类注释javadoc视为由多个TagElement组成的List=javadoc.tags();
注释文件从头开始,每遇到一个@则视为一个TagElement,如上图则有4个TagElement,
而每个TagElement都是由optinonalTagName(@author)和多个TextElement,每换一次行则视为一个TextElement。
如图:
@Description这个TagElement则一个optinonalTagName(@Description)和两个TextElement组成。
2-3,注释遍历:
代码,有了如上的分析,则可以很轻松的遍历出每一行注释,当然如果没有其它的必要的话,你就可以直接javadoc.toString();
Javadocclassdoc=clazz.getJavadoc();
//得到类上面的注释javadoc
Listtargs=classdoc.tags();
//得到TagElement集合
targs){
TagElementtagElement=(TagElement)object;
StringoptionalTagName=tagElement.getTagName();
//得到注释名如:
@author
ListtextElements=tagElement.fragments();
//得到注释的内容集合:
ListTextElement
for(Objectobject2:
textElements){
TextElementtextElement=(TextElement)object2;
System.out.println(textElement.getText());
//得到一个TextElement的内容
}
2-4,java类信息:
publicclassAdapter{}//这个包含修饰符:
public,类名:
Adapter
publicabstractclassAdapter{}//这个包含修饰符:
public,abstract,类名:
Adapter
publicclassAdapterextendsAbsAdapter{}//修饰符:
public,父类:
AbsAdapter,类名:
publicclassAdapterextendsAbsAdapter<
Entity>
{}//修饰符:
Adapter,泛型:
Entity
publicclassAdapterextendsabsAdapter<
TextendsEntity>
{}
publicinterfaceAdapter{}
publicinterfaceMyAdapterextendsAdapter{}
publicinterfaceMyAdapterextendsAdapter<
publicclassAdapter<
Integer,String>
2-5:
得到各种类型信息(代码如下)
TypeDeclarationclazz=(TypeDeclaration)typeDeclarations.get
(1);
System.out.println("
ClassName:
"
+clazz.getName());
for(Objectobj:
clazz.modifiers()){//得到修辞符如:
public,static,abstract,
Modifiermodifier=(Modifier)obj;
modifier.getKeyword();
clazz.isInterface();
//是不是接口
//得到类型信息pulicclassMyAdapter<
中的<
clazz.typeParameters()){
TypeParametertypeParameter=(TypeParameter)object;
SimpleNamegenericName=typeParameter.getName();
//T
typeParameter.typeBounds()){//Entity
SimpleTypesuperGrnericType=(SimpleType)object2;
StringsuperGrnericName=superGrnericType.getName().getFullyQualifiedName();
//extendsAdapter<
TypesuperType=clazz.getSuperclassType();
System.out.println(superType);
//implementsAdapter<
BaseBean{}
ListinterfaceType=clazz.superInterfaceTypes();
for(Objectobj:
interfaceType){
ParameterizedTypeparameterizedType=(ParameterizedType)obj;
for(Objectobj1:
parameterizedType.typeArguments()){
SimpleTypesimpleType=(SimpleType)obj1;
simpleType.getName().getFullyQualifiedName();
EclipseJDT--AST遍历(3)Java类遍历
到目前已经遍历了java的大致结构了,接下来就是进行java类里面的信息进行遍历,由上面可知道,java类主要由三部分组成,这里只对这三部分来做分析(FieldDeclaration,MethodDeclaration,内部类:
TypeDeclaration),
这部分遍历有两种方式:
1,整体遍历:
因为FieldDecliaration,MethodDeclaration,TypeDeclaration都是BodyDeclaration的子类,所以可以将他们归结为同一类型的结点,于是就有:
List<
?
>
bodyDecliarations=clazz.bodyDeclarations();
然后循环得到每一个节点,如下:
clazz.bodyDeclarations()){
System.out.println(obj.getClass());
//printfield
if(objinstanceofTypeDeclaration){//innerclass
TypeDeclarationinnerClass=(TypeDeclaration)obj;
for(ObjectbodyType:
innerClass.bodyDeclarations()){
if(bodyTypeinstanceofMethodDeclaration){
MethodDeclarationinnerMethod=(MethodDeclaration)bodyType;
innerMethod.getBody();
}
}
System.out.println(innerClass.toString());
}elseif(objinstanceofFieldDeclaration){//field
}elseif(objinstanceofMethodDeclaration){//method
2:
分类遍历
2-1,字段遍历:
先分析下,字段由注释,注解,修辞符(publicstatic等),变量类型,变量名,变量值(变量值可以是常量,一个表达示,也可是调用某个类的某个方法),这里省略:
注释,注解,变量值也只针对常值的解析),其它情况在针对方法体遍历的时候说明。
下面代码片段用于字段遍历说明:
importjava.util.Date;
importjava.util.List;
publicclassFieldTest{
//基本类型
privateintintA;
//对象类型
privateDatedate;
//数组类型
privateString[]xmAccounts;
//泛型类型
privateList<
String>
xmAccountList;
//多个修辞符
publicfinalstaticdoublePI=3.141592653;
//赋空值的
privateStringxm=null;
//调用方法的
privatelongcurrentTimes=System.currentTimeMillis();
//表达式的
privatebooleanflag=100/5==20?
true:
false;
2-1-1,变量类型的说明(这里只是按ast中变量类型归类说明)
基本数据类型:
PrimitiveType,java中的基本数据类型,如:
int,float等,可以通过isPrimitiveType来判断是不是基本数据类型
复杂数据类型(对象):
SimpleType,java中的对象类型,isSimpleType断是不是对象数据类型
数组数据类型:
ArrayType,java中的数组类型
泛型数据类型:
ParameterizedType,泛型
2-1-2,由于一个类可以有多个字段申明,所以我们可以通过到getFieldDeclarations(),得到一个List数组。
然后我们通过for循环遍历这个数组,得到这个字段的相关信息,如
修辞符(private,static等)field.modifiers();
字段的类型信息:
isPrimitiveType,isSimpleType,isArrayType,isParameterizedType等方法来判断是什么类型,这样就可以得到类型名。
变量名:
注意:
一个类型可以申明多个变量:
比如:
privateinta,b,c;
所以会返回一个数组
如果只有一个变量名,我们可以直接get(0),如果多个,我们也可以遍历逐个得到。
相关代码如下:
FieldDeclaration[]fields=clazz.getFields();
for(FieldDeclarationfieldDeclaration:
fields){
Stringfield="
;
Listmodifier=fieldDeclaration.modifiers();
for(inti=0;
i<
modifier.size();
i++){
field+=modifier.get(i)+"
"
//这里得到字段类型
TypefieldType=fieldDeclaration.getType();
if(fieldType.isPrimitiveType()){
PrimitiveTypep=(PrimitiveType)fieldType;
field+=p.getPrimitiveTypeCode()+"
elseif(fieldType.isArrayType()){//数组
ArrayTypea=(ArrayType)fieldType;
field+=a.getComponentType()+"
[]"
elseif(fieldType.isSimpleType()){//对象
SimpleTypes=(SimpleType)fieldType;
field+=s.getName().getFullyQualifiedName()+"
elseif(fieldType.isParameterizedType()){//泛型,泛型,
//泛型的类型,也可能是上面两种类型,也有可能是还是泛型对象(泛型不能是基本类型)
//List<
List<
O