JDT.AST:抽象语法树-源码管理

近期有代码检查的项目,用到了抽象语法树,才接触到这类知识点,做个记录

  1. 根据pom文件引入依赖
 <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.jibx.config.3rdparty.org.eclipse</groupId>
      <artifactId>org.eclipse.core.contenttype</artifactId>
      <version>3.4.100.v20110423-0524</version>
    </dependency>
    <dependency>
      <groupId>org.jibx.config.3rdparty.org.eclipse</groupId>
      <artifactId>org.eclipse.core.jobs</artifactId>
      <version>3.5.100.v20110404</version>
    </dependency>
    <dependency>
      <groupId>org.jibx.config.3rdparty.org.eclipse</groupId>
      <artifactId>org.eclipse.core.resources</artifactId>
      <version>3.7.100.v20110510-0712</version>
    </dependency>
    <dependency>
      <groupId>org.jibx.config.3rdparty.org.eclipse</groupId>
      <artifactId>org.eclipse.core.runtime</artifactId>
      <version>3.7.0.v20110110</version>
    </dependency>
    <dependency>
      <groupId>org.jibx.config.3rdparty.org.eclipse</groupId>
      <artifactId>org.eclipse.equinox.common</artifactId>
      <version>3.6.0.v20110523</version>
    </dependency>
    <dependency>
      <groupId>org.jibx.config.3rdparty.org.eclipse</groupId>
      <artifactId>org.eclipse.equinox.preferences</artifactId>
      <version>3.4.0.v20110502</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jdt</groupId>
      <artifactId>org.eclipse.jdt.core</artifactId>
      <version>3.7.1</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse</groupId>
      <artifactId>org.eclipse.osgi</artifactId>
      <version>3.8.0.v20120529-1548</version>
    </dependency>
  1. 创建JdtAst类,对java类进行处理,生成一个ASTNode类,强转成CompilationUnit编译单元
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;

public class JdtAst {
    private ASTParser astParser = ASTParser.newParser(AST.JLS3); // 非常慢

    /**
     * 获得java源文件的结构CompilationUnit
     */
    public CompilationUnit getCompilationUnit(String javaFilePath)
            throws Exception {

        BufferedInputStream bufferedInputStream = new BufferedInputStream(
                new FileInputStream(javaFilePath));

        byte[] input = new byte[bufferedInputStream.available()];
        bufferedInputStream.read(input);
        bufferedInputStream.close();
        this.astParser.setSource(new String(input).toCharArray());
        /*
        * asparser.createAST方法创建返回一个ASTNode类,ASTNode是语法树各节点的抽象基类,
        * 它的子类分别代表各种类型的的节点比如CompilationUnit(编译单元), Statement, Expression, Comment,PackageDeclaration等
        * 编译单元为一个java文件(可能有多个类)
        * */
        CompilationUnit result = (CompilationUnit) (this.astParser
                .createAST(null)); // 很慢,

        return result;  //返回CompilationUnit编译单元,

    }
}

3 获取类和方法进行处理

import java.util.ArrayList;
import java.util.List;

import com.sun.org.apache.xerces.internal.xs.StringList;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
import org.eclipse.jdt.core.dom.*;

public class testApp {

    public static void main(String[] args) throws Exception {
        //定义java文件路径
        String javaFilePath = "E:\\code\\HolidaysAideService.java";
        JdtAst jdt = new JdtAst();
        /**
         result是使用ASTParser类对Java文件进行解析以后得到的CompilationUnit类的编译单元----   .java文件是一个编译单元,每个编译单元顶多只有public标记的类
         .java文件中有几个类,就会编译成几个文件
         *
         */
        //生成编译单元
       CompilationUnit result = jdt.getCompilationUnit(javaFilePath);

       List importList = result.imports();// 获取导入的包


       //获取第一个类,返回的为list强转成TypeDeclaration类型,后续可以使用TypeDeclaration的方法进行处理,获得方法和返回值等
       TypeDeclaration type = (TypeDeclaration) result.types().get(0);
       TypeDeclaration[] file=type.getTypes(); //获取全局变量
       //获取类中的方法
        MethodDeclaration[] methods=type.getMethods();

        //对类中方法进行遍历处理,操作方法
        for (MethodDeclaration method:methods){
            //获得方法的名字   method.getName()为SimpleName类型,不能强转成String可以通过toString转成String类型
             String name=method.getName().toString();
            System.out.println(name);

             //获取方法的内容
            Block method_block = method.getBody();

            //获取方法的参数
            List methodParamertes=method.parameters();


             //获取方法的返回值   getReturnType2()为空则为构造函数
            if (null!=method.getReturnType2()){
                //加入返回值为泛型,如果只要类型不需要具体泛型可以处理(如果为Map<String,String>,只需要具体类型Map)
                if (method.getReturnType2().isParameterizedType()){ //判断是否是泛型
                    //获取类型强转成ParameterizedType,再获得具体类型
                    //ParameterizedType  extends type 都可以通过tostring来转化成String类型
                   String returnType2=((ParameterizedType)method.getReturnType2()).getType().toString();
                }

            }else {
                System.out.println("为空则该方法为构造函数");
            }

            //获取javadoc,javadoc为方法前面的/**  **/ 单行注释不计入javadoc
            Javadoc javadoc=method.getJavadoc();

            //获取方法的位置,获取方法起始的位置,包括javadoc,位置的计算为字符为单位,不是以行为单位,如果要以行为单位,可以通过result进行转化
            int startPositionByChar=method.getStartPosition(); //会计算出所有的资产,然后得出当前方法的日志的字符的位置

            //通过ASTNode换算出行数
            int realPosition=result.getLineNumber(startPositionByChar);  //行数所在的真正位置

            //得出方法的总字符数,也可以通过ASTNode计算出行数来的出方法总共所占的行数
            int methodLenth=method.getLength();
            //方法总共占的行数
            int methodAllLine=result.getLineNumber(startPositionByChar+methodLenth);


            List statements = method_block.statements();// 获取方法内容的所有行,一个statement为一行计数而非真正的行数,一个if/else为一行
            for (int i=0;i<statements.size();i++){
                System.out.println("获取方法内容的所有行"+i+statements.get(i));

            }




        }
    }
}

知识接触面少,暂时记录到此,以后有时间再回顾深入,相关文档记载如下

  1. —入门文档
    1. Eclipse Corner Article: Abstract Syntax Tree(英文,AST的概述,细节代码不多)

  2. — 探索Eclipse的ASTParser
    ASTParser(中文,相对详细的讲解和代码)

  3. —AST使用
    Eclipse JDT–AST and JavaModel Tutorial(英文,代码很多,但需要有更多的背景知识)

  4. –使用指南
    Eclipse AST 使用指南(pdf文档,更加详细地说明了AST 相关类与方法,可以与eclipse documentation结合使用)

  5. 官方文档
    Eclipse documentation

  6. —使用文献
    Yet another AST tutorial(英文,有大量代码,从易到难讲解)

  7. 使用相关
    使用AST出现问题?不知道使用什么jar包?看看这里吧

  8. 插件
    想亲眼看看你源文件的AST是什么样的?为你的Eclipse装一个ASTview插件吧!

此文为引用,感谢原创,附上链接

https://blog.csdn.net/flying881114/article/details/6187061
https://www.oschina.net/code/piece_full?code=26446

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值