JDT工具类的使用

1.获取CompilationUnit。这是读取java文件,生成的整个编译单元。是所有AST节点的根节点。

/**JDT方式,获取指定java文件的CompilationUnit
     * @param javaFilePath java文件的绝对路劲
     * @return CompilationUnit
     * @功能描述: get compilation unit of source code
     * @方法名称: getCompilationUnit
     * @创建时间 2021年5月8日 下午2:47:52
     * @version V1.0
     */
    public static CompilationUnit getCompilationUnit(String javaFilePath) {
        byte[] input = null;
        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(javaFilePath));
            input = new byte[bufferedInputStream.available()];
            bufferedInputStream.read(input);
            bufferedInputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ASTParser astParser = ASTParser.newParser(AST.JLS3);
        astParser.setSource(new String(input).toCharArray());
        astParser.setKind(ASTParser.K_COMPILATION_UNIT);
        CompilationUnit result = (CompilationUnit) (astParser.createAST(null));
        //result.getImports();
        return result;
    }

2.获取属性和方法

//Java编译单元AST节点类型。这是AST的根的类型
        CompilationUnit cu = getCompilationUnit(classPath);
        //类里面的类型声明的抽象子类,枚举声明以及注释类型声明和节点类型
        List<AbstractTypeDeclaration> types = cu.types();
//此处也可直接获取types.get(0)
for (AbstractTypeDeclaration type : types) {
            if (type.getNodeType() == ASTNode.TYPE_DECLARATION) {
                //返回方法
                /*TypeDeclaration typed =  (TypeDeclaration) type;
                MethodDeclaration[] methods = typed.getMethods();*/
                //返回所有主体声明
                List<BodyDeclaration> bodies = type.bodyDeclarations();
                for (BodyDeclaration body : bodies) {
                    //方法
                    if (body.getNodeType() == ASTNode.METHOD_DECLARATION) {
                        MethodDeclaration method = (MethodDeclaration) body;
                        //method.getName() 方法名
                        //method.parameters() 请求参数,数组
                        //method.getReturnType2() 返回参数
                        //method.getBody() 方法快
                        //method.getBody().statements() 方法快中的代码列表
                        
                    }
                    //属性
                    else if (body.getNodeType() == ASTNode.FIELD_DECLARATION) {
                        FieldDeclaration field = (FieldDeclaration) body;
                        System.out.println("field");
                        System.out.println(field.toString());
                        System.out.println(field.getType().toString());
                    }
                }
            }
        }

3.解析代码

List list = methodDeclaration.getBody().statements();

获取方法的代码块。此时的statements里面,如果有if、try等代码块,则需要再转

/**
     * 获取代码块
     * @param list
     * @return
     */
    public static ArrayList<MethodInvocation> getMethodInvocationFromCode(List list){
        ArrayList<MethodInvocation> finalCode = new ArrayList<MethodInvocation>();
        for(int i=0; i < list.size(); i ++){
            //try代码块
            if(list.get(i) instanceof TryStatement){
                //try
                List ts = ((TryStatement) list.get(i)).getBody().statements();
                finalCode.addAll(getMethodInvocationFromCode(ts));
                //catch
                List cs = ((TryStatement) list.get(i)).catchClauses();
                finalCode.addAll(getMethodInvocationFromCode(cs));
                //finally
                Block bf = ((TryStatement) list.get(i)).getFinally();
                if(bf != null){
                    List newlist = new ArrayList();
                    newlist.add(bf);
                    finalCode.addAll(getMethodInvocationFromCode(newlist));
                }
            }
            //catch的代码块
            else if(list.get(i) instanceof CatchClause){
                List ts = ((CatchClause) list.get(i)).getBody().statements();
                finalCode.addAll(getMethodInvocationFromCode(ts));
            }
            //if代码块
            else if(list.get(i) instanceof IfStatement){
                IfStatement ifs = (IfStatement) list.get(i);
                //条件表达式
                Expression expression = ifs.getExpression();
                //if语句
                Statement ifstatement = ifs.getThenStatement();
                //else语句
                Statement elsestatement = ifs.getElseStatement();
                //if(tx.get() != null)
                if(expression instanceof  InfixExpression){
                    InfixExpression inf = (InfixExpression) expression;
                    //左表达式
                    Expression l = inf.getLeftOperand();
                    //右表达式
                    Expression r = inf.getRightOperand();
                    //多于2个条件是,其余条件在extendedOperands里面
                    List other = inf.extendedOperands();
                    List newlist = new ArrayList();
                    if(l instanceof MethodInvocation){
                        newlist.add(l);
                    }
                    if(r instanceof MethodInvocation){
                        newlist.add(r);
                    }
                    if(other != null && other.size() > 0){
                        for(int j=0; j < other.size(); j++){
                            if(other.get(j) instanceof MethodInvocation){
                                newlist.add(other.get(j));
                            }
                        }
                    }
                    if(newlist.size() > 0){
                        finalCode.addAll(getMethodInvocationFromCode(newlist));
                    }
                }
                else{
                    //if(ts.check())
                    List newlist = new ArrayList();
                    newlist.add(expression);
                    finalCode.addAll(getMethodInvocationFromCode(newlist));
                }
                if(ifstatement instanceof  Block){
                    List ts = ((Block) ifstatement).statements();
                    finalCode.addAll(getMethodInvocationFromCode(ts));
                }else{
                    System.out.println("IfStatement例外"+list.get(i).toString());
                }
                //只有一个else时,直接读Block
                //有多个else if时,elsestatement会再被分成if和esle
                if(elsestatement != null){
                    if(elsestatement instanceof  Block){
                        List ts = ((Block) elsestatement).statements();
                        finalCode.addAll(getMethodInvocationFromCode(ts));
                    }else{
                        List newlist = new ArrayList();
                        newlist.add(elsestatement);
                        finalCode.addAll(getMethodInvocationFromCode(newlist));
                    }
                }
            }
            //for代码块
            else if(list.get(i) instanceof ForStatement){
                Statement statement =((ForStatement) list.get(i)).getBody();
                if(statement instanceof  Block){
                    List ts = ((Block) statement).statements();
                    finalCode.addAll(getMethodInvocationFromCode(ts));
                }else{
                    System.out.println("ForStatement例外"+list.get(i).toString());
                }
            }
            //do代码块
            else if(list.get(i) instanceof DoStatement){
                DoStatement ds = (DoStatement) list.get(i);
                //do块
                Statement statement =ds.getBody();
                //while块
                Expression expression = ds.getExpression();
                if(statement instanceof  Block){
                    List ts = ((Block) statement).statements();
                    finalCode.addAll(getMethodInvocationFromCode(ts));
                }else{
                    System.out.println("DoStatement例外"+list.get(i).toString());
                }
                if(expression != null){
                    List newlist = new ArrayList();
                    newlist.add(expression);
                    finalCode.addAll(getMethodInvocationFromCode(newlist));
                }
            }
            //while代码块
            else if(list.get(i) instanceof WhileStatement){
                WhileStatement ws = (WhileStatement) list.get(i);
                //while条件
                Expression expression = ws.getExpression();
                //while内容
                Statement statement =ws.getBody();
                if(expression != null){
                    List newlist = new ArrayList();
                    newlist.add(expression);
                    finalCode.addAll(getMethodInvocationFromCode(newlist));
                }
                if(statement instanceof  Block){
                    List ts = ((Block) statement).statements();
                    finalCode.addAll(getMethodInvocationFromCode(ts));
                }else{
                    System.out.println("WhileStatement例外"+list.get(i).toString());
                }
            }
            //增强型语句,比如foreach
            else if(list.get(i) instanceof EnhancedForStatement){
                Statement statement =((EnhancedForStatement) list.get(i)).getBody();
                if(statement instanceof  Block){
                    List ts = ((Block) statement).statements();
                    finalCode.addAll(getMethodInvocationFromCode(ts));
                }else{
                    System.out.println("EnhancedForStatement例外"+list.get(i).toString());
                }
            }
            //switch代码块
            else if(list.get(i) instanceof SwitchStatement){
                //list内是SwitchCase的list
                List ts = ((SwitchStatement) list.get(i)).statements();
                finalCode.addAll(getMethodInvocationFromCode(ts));
            }
            //switch下的每个子元素
            else if(list.get(i) instanceof SwitchCase){
                //不做处理
                System.out.println("SwitchCase代码:"+list.get(i).toString());
            }
            //break
            else if(list.get(i) instanceof BreakStatement){
                //不做处理
                System.out.println("BreakStatement代码:"+list.get(i).toString());
            }
            //continue
            else if(list.get(i) instanceof ContinueStatement){
                //不做处理
                System.out.println("ContinueStatement代码:"+list.get(i).toString());
            }
            //Synchronized
            else if(list.get(i) instanceof SynchronizedStatement){
                List ts = ((SynchronizedStatement) list.get(i)).getBody().statements();
                finalCode.addAll(getMethodInvocationFromCode(ts));
            }
            //Throw
            else if(list.get(i) instanceof ThrowStatement){
                //不做处理
                System.out.println("ThrowStatement代码:"+list.get(i).toString());
            }
            //变量声明语句
            //声明变量是一个new Class时,进此分支
            else if(list.get(i) instanceof VariableDeclarationStatement){
                VariableDeclarationStatement v = (VariableDeclarationStatement) list.get(i);
                finalCode.addAll(getMethodInvocationFromCode(v.fragments()));
            }
            //VariableDeclarationStatement的右边碎片
            else if(list.get(i) instanceof VariableDeclarationFragment){
                VariableDeclarationFragment v = (VariableDeclarationFragment) list.get(i);
                if(v.getInitializer() != null){
                    List newlist = new ArrayList();
                    newlist.add(v.getInitializer());
                    finalCode.addAll(getMethodInvocationFromCode(newlist));
                }
            }
            //表达式,变量赋值语句
            else if(list.get(i) instanceof ExpressionStatement){
                ExpressionStatement expressionStatement = (ExpressionStatement) list.get(i);
                Expression expression = expressionStatement.getExpression();
                if(expression instanceof Assignment){
                    System.out.println("=====");
                    Assignment assign=(Assignment) expression;
                    System.out.println("左边:"+assign.getLeftHandSide());
                    System.out.println("符号:"+assign.getOperator());
                    System.out.println("右边:"+assign.getRightHandSide());
                    List newlist = new ArrayList();
                    if(assign.getLeftHandSide() instanceof  CastExpression){
                        CastExpression cas = (CastExpression) assign.getLeftHandSide();
                        newlist.add(cas.getExpression());
                    }
                    if(assign.getRightHandSide() instanceof  CastExpression){
                        CastExpression cas = (CastExpression) assign.getRightHandSide();
                        newlist.add(cas.getExpression());
                    }
                    if(newlist.size() > 0){
                        finalCode.addAll(getMethodInvocationFromCode(newlist));
                    }
                }
                else /*if(expression instanceof MethodInvocation)*/{
                    List newlist = new ArrayList();
                    newlist.add(expression);
                    finalCode.addAll(getMethodInvocationFromCode(newlist));
                }
                /*else{
                    System.out.println("ExpressionStatement例外"+list.get(i).toString());
                }*/
            }
            //方法调用
            else if(list.get(i) instanceof MethodInvocation){
                System.out.println("++++");
                MethodInvocation methodInvocation = (MethodInvocation) list.get(i);
                System.out.println(methodInvocation.toString());
                System.out.println("属性:"+methodInvocation.getExpression());
                System.out.println("方法名:"+methodInvocation.getName());
                System.out.println("参数:"+methodInvocation.arguments());
                List newlist = new ArrayList();
                //ts.get().toString()
                if(methodInvocation.getExpression() instanceof MethodInvocation
                    || methodInvocation.getExpression() instanceof ClassInstanceCreation){
                    newlist.add(methodInvocation.getExpression());
                }else{
                    finalCode.add(methodInvocation);
                }
                if(methodInvocation.arguments() != null && methodInvocation.arguments().size() > 0){
                    for(int j = 0; j < methodInvocation.arguments().size(); j ++){
                        //参数是一个方法,或一个实例化类
                        if(methodInvocation.arguments().get(j) instanceof MethodInvocation
                            || methodInvocation.arguments().get(j) instanceof ClassInstanceCreation){
                            newlist.add(methodInvocation.arguments().get(j));
                        }
                    }
                }
                if(newlist.size() > 0){
                    finalCode.addAll(getMethodInvocationFromCode(newlist));
                }
            }
            //实例化类
            else if(list.get(i) instanceof ClassInstanceCreation){
                ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) list.get(i);
                //匿名类声明
                AnonymousClassDeclaration anonymousClassDeclaration = classInstanceCreation.getAnonymousClassDeclaration();
                if(anonymousClassDeclaration != null){
                    //获取类的属性、方法
                    List l = anonymousClassDeclaration.bodyDeclarations();
                    finalCode.addAll(getMethodInvocationFromCode(l));
                }
            }
            //方法
            else if(list.get(i) instanceof MethodDeclaration){
                MethodDeclaration methodDeclaration = (MethodDeclaration) list.get(i);
                List l = methodDeclaration.getBody().statements();
                finalCode.addAll(getMethodInvocationFromCode(l));
                //方法参数
                List pars = methodDeclaration.parameters();
            }
            //父方法调用
            else if(list.get(i) instanceof SuperMethodInvocation){
                System.out.println("SuperMethodInvocation代码:"+list.get(i).toString());
            }
            //未知???
            else if(list.get(i) instanceof EmptyStatement){
                //不做处理
                System.out.println("EmptyStatement代码:"+list.get(i).toString());
            }
            //Return
            else if(list.get(i) instanceof ReturnStatement){
                //不做处理
            }
            else{
                //不做处理
                System.out.println("未知代码:"+list.get(i).toString());
            }
        }
        return finalCode;
    }

这是解析方法的代码,获取方法内调用其他方法的集合

各种节点对象

CompilationUnit:Java编译单元,是整个源文件,即一个Java文件或class文件,包括前导和尾随空格和注释。它是所有AST节点的根节点。
PackageDeclaration:对应编译单元包声明部分(包括包前的注释注解等)。
ImportDeclaration:对应编译单元import部分。
TypeDeclaration:每个类或接口类型的声明为一个TypeDeclaration 节点,包括注释文档。同一编译单元可以有多个类声明。
BodyDeclaration:类的主体,即类大括号中的内容(不包括大括号本身)。
Block:块,在type中的每个大括号的内容为一个块(包括大括号本身)。
MethodDeclaration:方法,包括方法声明和方法体定义。
SingleVariableDeclaration:方法的参数列表,单形参的变量声明,如“FileNotFoundException  e”。
FieldDeclaration:属性声明语句
TypeDeclarationStatement:在类内部将一个类声明包装到一个语句块里,如“{class hh{}}”,此处的“class hh{}”是一个TypeDeclarationStatement节点。
VariableDeclarationStatement:局部变量声明语句。
VariableDeclarationFragment:全局属性或局部变量声明的片段,类型之后的变量名以及初始化部分。
VariableDeclarationExpression:变量声明表达式,如for(int i=0;;)循环中的“int i=0”。区别于方法中的变量声明语句VariableDeclarationStatement
EnhancedForStatement :for-each语句。
IfStatement:if语句
ExpressionStatement:表达式语句,执行某操作。如标准输出语句,方法调用等。
ReturnStatement :return语句。
BreakStatement:break语句
WhileStatement:while语句
TryStatement:try语句,包括try(或try-with-resources)块catch块和finally块
ThrowStatement:抛出异常语句
MethodInvocation :方法调用节点
SuperMethodInvocation:调用父类方法
SwitchStatement:switch语句
SwitchCase:case字句或default字句,不包含该字句后的内容,如“case 1:”或“default:”。
SynchronizedStatement:同步控制语句,如synchronized ( new String() ){ }
ThisExpression:返回类的引用或在构造器中调用另一个构造函数。
TypeParameter:参数化类型的类型参数,如List<T>中的参数T
WildcardType:通配符类型,如List<?> 的“?”
UnionType:联合类型(C/C++中特有)
AnnotationTypeDeclaration:注解类型节点
AnnotationTypeMemberDeclaration:注解类型节点的成员声明节点,如抽象方法或默认方法。
AnonymousClassDeclaration:内部类声明节点。包括枚举的内部类实现。
ArrayCreation:数组初始化部分的节点。如new int[2]或new int[]{1,2}。(整个数组创建语句“int array[]=new int[]{1,2};”是一个VariableDeclarationStatement节点)
ArrayInitializer:数组初始化的赋值部分。如{1,2}。
ArrayAccess:访问数组的节点,如访问索引值为0的数组值:array[0]
ArrayType:数组类型节点,如“int[]  array;”的int[]部分,这与int array[]是有区别的。后者的类型为PrimitiveType(int型)。
AssertStatement:断言语句(形如:assert Expression [ : Expression ] ;)。assert不常用,一般用于测试。IDE工具默认关闭断言检查功能,即assert在运行时不会生效。
Assignment:赋值语句,如“i=1”
BooleanLiteral:布尔值(true/false)。
CharacterLiteral:字符常量值,如‘char’
StringLiteral:字符串常量值,如“String”
NumberLiteral:数字常量值,包括int、double、float、long等类型的值
TypeLiteral:类型常量
CastExpression:强制类型转换子句,如(int) 11.0
CatchClause:catch块
ClassInstanceCreation:类实例化的new部分,如“new DemoClass()”
ConditionalExpression:条件从句。如“true?1:0”
ConstructorInvocation:构造器调用,在构造方法中出现。如“this();”
SuperConstructorInvocation:父类构造器调用
ContinueStatement:continue语句
DoStatement:do-while循环语句,如“do{}while(i==0);”
EmptyStatement:只有一个结束符号的空语句,即“ ; ”
EnumConstantDeclaration:枚举常量,包含常量前的文档注释
EnumDeclaration:枚举类型声明节点,包含Javadoc
FieldAccess:一般变量访问语句
SuperFieldAccess:使用关键词super访问父类变量语句
InfixExpression:判断表达式,返回布尔值
Initializer: AST节点类型,形如:[ static ] Block。区别“static int i;”和“static {int i;}”,前者是FieldDeclaration,后者是Initializer
InstanceofExpression:instanceof 语句
LabeledStatement:标记语句,用于循环中,如“label:for(;;){for(;;){break label;}}”
Modifier:修饰词节点,包括public、protected、private、static、abstract、final、native、synchronized、transient、volatile、strictfp
ParameterizedType:参数化类型(泛型)节点
PrimitiveType:原始类型节点,8种Java原始类型加上void类型
ParenthesizedExpression:括号表达式,形如:( Expression )
PrefixExpression :前缀表达式, 如++i;
PostfixExpression:后缀表达式,如i++;
QualifiedName:完整名,QualifiedName中每一个名为一个独立的SimpleName
SimpleName:直接名,simple与qualified的区别:前者只是给出了最后的一项命名,后者给出了完整的命名,如java.io.IOException是QualifiedName,而IOException为SimpleName。类比于相对路径与绝对路径的区别。
*QualifiedType:
    Type . SimpleName
如类型 "A.B" 可以有两种方式表示:
QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))
SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))
在ASTView中一般以第二种方式表示。
SimpleType:直接类型,如List<String>中的“List”和“String”分别是一个SimpleType节点。java.lang.String也为SimpleType
MarkerAnnotation:标记注解,如@Controller功能同NormalAnnotation的@Controller()
NormalAnnotation:标记注解,如@Controller()
SingleMemberAnnotation:单值注解,如@Controller(“String”),作用同NormalAnnotation的@Controller(value=”string”)。
MemberValuePair:注解中的赋值对,如@Controller(value="string")中的“value="string"”。
BlockComment:块注释。/* */
LineComment:行注释。//
Javadoc:注释文档。
MemberRef:Javadoc中成员引用,如
/**
* @see  #i
* @see #print(int)
*/
中的“#i”,其中i是类的成员属性,print(int i)为成员方法。常用的标记有@see、@link。
MethodRef:Javadoc中方法引用。类似于MemberRef。如例@see #print(int)中的“#print(int)”。
MethodRefParameter:Javadoc中引用方法的参数类型。如例@see #print(int)中的“int”。
TextElement:Javadoc中的的文本内容,包含标记名与标记内容之间的空格,不包括注释结束符“/** * */”
TagElement:包括标记名和标记内容。如@author  leiy。标记内容可以是:TextElement、Name、MethodRef、MemberRef,也可以嵌套一个{TagElement}。


编译单元的属性:PACKAGE、IMPORTS、TYPES(对应编译单元中除了PACKAGE和IMPORTS部分的全部内容)、EnumDeclaration、AnnotationTypeDeclaration 。
TypeDeclaration节点属性:JAVADOC、MODIFIERS、INTERFACE、NAME、TYPE_PARAMETERS、SUPERCLASS_TYPE、SUPER_INTERFACE_TYPES、BODY_DECLARATIONS等
FieldDeclaration节点属性:TYPE、FRAGMENTS、MODIFIERS、JAVADOC等
MethodDeclaration节点属性:JAVADOC、MODIFIERS、CONSTRUCTOR、TYPE_PARAMETERS、RETURN_TYPE2、NAME、RECEIVER_TYPE、RECEIVER_QUALIFIER、PARAMETERS、EXTRA_DIMENSIONS2、THROWN_EXCEPTION_TYPES、BODY。
BODY:方法的主体,即方法大括号中的内容(包括大括号本身)。
STATEMENTS:方法体中STATEMENTS会从第一个非注释行开始,忽略之前的注释,但包含之后的注释。
EXPRESSION:表达式,可以为一个变量或赋值或比较句子。
THEN_STATEMENT:if语句的then处理块
ELSE_STATEMENT:if语句的else处理块
ARGUMENTS:方法的实参


{context}