基于Eclipse-JDT生成Java源代码的AST

参考链接:

1.【Eclipse AST】AST与ASTView简介

2.【Eclipse AST】AST的获取与访问

3.安装和配置Maven,并在Eclipse中进行集成

4.maven是干什么用的?为啥要使用Maven

5.Maven搜索jar包依赖的网址

阅读指南:

  1. 首先要看一下参考链接1——AST和ASTView的简介,然后下载ASTView包,实践感受一下。由于参考链接1里面提供的那个下载ASTView的插件网址moved了,所以我下面给出了一个ASTView包的下载链接;
  2. 其次我们要看参考链接2,在Eclipse中实现AST的获取与访问,在实现AST之前,要先安装和配置Maven,可以看参考链接3和4;
  3. 最后我们写代码来实现一个实例:如何将Java源代码转换为AST,即解析源代码。

 

1.ASTView包的下载与ASTView的使用

  • ASTView包的下载

地址:https://archive.eclipse.org/jdt/ui/update-site/plugins/

我下载的是:

直接将org.eclipse.jdt.astview_1.1.9.201406161921.jar复制到eclipse的dropins文件夹中,再打开Eclipse就可以用了,具体来说:依次点击 Window -> Show View -> Other,然后搜索ASTView,打开即可得到ASTView视图。如下图。

 

  • ASTView的使用见参考链接1 

 

2.如何将Java源代码转换为AST,即解析源代码——实例

  • 为什么要用Maven呢?

Maven很方便呀。主要它可以进行依赖管理: Maven通过中央仓库和本地仓库来管理项目的依赖库,开发人员只需要在项目配置文件中声明所需的依赖,Maven会自动下载并管理这些依赖。当然它还有很多特别好的功能,具体看参考链接4。

  • 安装和配置Maven见参考链接3

 图2.1 我的Maven版本

  • 准备好Maven之后,写代码将Java源代码转换为AST

可以先导入本项目所需依赖:

        在pom.xml文件中添加我们所需要的jar包依赖,可以去官网查找,地址为:https://mvnrepository.com/,每一个依赖都复制其<dependency>的内容,然后粘贴到pom文件中即可

 我的pom.xml文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.my.ast</groupId>
    <artifactId>ast_test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <!-- 依赖管理部分,将所有的依赖放在dependencies标签内 -->
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.eclipse.jdt/org.eclipse.jdt.core -->
        <dependency>
            <groupId>org.eclipse.jdt</groupId>
            <artifactId>org.eclipse.jdt.core</artifactId>
            <version>3.40.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.eclipse.platform/org.eclipse.osgi -->
		<dependency>
    		<groupId>org.eclipse.platform</groupId>
    		<artifactId>org.eclipse.osgi</artifactId>
    		<version>3.22.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.eclipse.platform/org.eclipse.equinox.preferences -->
		<dependency>
    		<groupId>org.eclipse.platform</groupId>
    		<artifactId>org.eclipse.equinox.preferences</artifactId>
    		<version>3.11.200</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.eclipse.platform/org.eclipse.equinox.common -->
		<dependency>
    		<groupId>org.eclipse.platform</groupId>
    		<artifactId>org.eclipse.equinox.common</artifactId>
    		<version>3.19.200</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.eclipse.platform/org.eclipse.core.runtime -->
		<dependency>
    		<groupId>org.eclipse.platform</groupId>
    		<artifactId>org.eclipse.core.runtime</artifactId>
    		<version>3.32.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.eclipse.platform/org.eclipse.core.resources -->
		<dependency>
    		<groupId>org.eclipse.platform</groupId>
    		<artifactId>org.eclipse.core.resources</artifactId>
    		<version>3.22.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.eclipse.platform/org.eclipse.core.jobs -->
		<dependency>
    		<groupId>org.eclipse.platform</groupId>
    		<artifactId>org.eclipse.core.jobs</artifactId>
    		<version>3.15.400</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.eclipse.platform/org.eclipse.core.contenttype -->
		<dependency>
    		<groupId>org.eclipse.platform</groupId>
    		<artifactId>org.eclipse.core.contenttype</artifactId>
    		<version>3.9.600</version>
		</dependency>
    </dependencies>    
</project>

 

1.首先,新建一个Maven项目,如果没看见Maven Project,可以去  其它   里面搜一下;

2.点击下一步之后,出现下面界面,继续点击下一步;

3.填写Group Id和Artifact Id,点击完成,我们就得到了如下目录;

  1. 这个是大佬给的注释:

    这个是我填写的

得到目录:

 4.在 src/main/java 里面新建一个工具类 JdtAstUtil,用于将源代码以字符数组形式解析为AST;

 

 JdtAstUtil类代码:

package ast_test;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;


public class JdtAstUtil {
    /**
    * get compilation unit of source code
    * @param javaFilePath 
    * @return CompilationUnit
    */
	//CompilationUnit 代表一个 Java 编译单元,即一个 Java 源文件
	//输入参数为需解析的Java源代码文件路径,返回值为该文件对应的CompilationUnit节点
    public static CompilationUnit getCompilationUnit(String javaFilePath){
    	//begin
    	//读取指定路径的 Java 源文件内容,并将其存储在字节数组 input 中,判断输入文件是否存在和可用
        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();
		}
		//end
		
        //创建ASTParser并将Java源文件解析成AST:
		ASTParser astParser = ASTParser.newParser(AST.JLS3);
        astParser.setSource(new String(input).toCharArray());
        
        //设置要解析的类型,包含下面四种,可按需选择
        //K_COMPILATION_UNIT:编译单元,即一个Java文件
        //K_CLASS_BODY_DECLARATIONS:类的声明
        //K_EXPRESSION:单个表达式
        //K_STATEMENTS:语句块
        astParser.setKind(ASTParser.K_COMPILATION_UNIT);
 
        //获取代码的AST,实现AST解析
        CompilationUnit result = (CompilationUnit) (astParser.createAST(null));
        
        return result;
    }
}

 小Tip:平时自己写代码的时候,可以写完class以后使用Ctrl + Shift + O 自动补全相应的import语句

 5.将源代码转化为了AST之后,接下来要做的就是访问节点,需要学习两个Eclipse AST的核心类;以下出自参考链接2

  •  ASTNode:AST节点类,所有的节点类型都是ASTNode的子类,至于某一个节点源代码具体到底是什么节点,可以通过ASTView来查看。
  • ASTVisitor:AST访问者类,它针对不同类型的节点提供了一系列重载的visit()和endvisit()方法,意思就是访问到该类型的节点时执行visit()方法,访问完该类型节点后执行endvisit()方法。其中,visit()方法需返回boolean类型的返回值,表示是否继续访问子节点。另外ASTVisitor还提供了preVisit()和postVisit()方法,参数类型为ASTNode,也就是说不论哪种类型的节点,访问前后都要分别执行preVisit()和postVisit()。这些方法的具体实现由ASTVisitor的子类负责,如果不需要对所访问到的节点做处理,则无需在ASTVisitor的子类中覆盖这些方法。

通过ASTView可以确定类、方法和属性的声明对应的AST节点分别是TypeDeclaration、MethodDeclaration和FieldDeclaration;

FieldDeclaration类比较特殊,因为一个FieldDeclaration下可能有多个同类型的属性被声明,也就是说,我们遍历FieldDeclaration时,需要遍历它的子节点VariableDeclarationFragment,

在 src/main/java 里面新建一个访问者子类DemoVisitor,继承自ASTVisitor,并覆盖参数类型为TypeDeclaration、MethodDeclaration和FieldDeclaration的visit()方法,由于需要遍历所有节点,因此将返回值都设为true。

 DemoVisitor代码:

package ast_test;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
 
public class DemoVisitor extends ASTVisitor {
    //实现节点的打印,重写父类的一些方法实现节点打印
	@Override
	public boolean visit(FieldDeclaration node) {
		for (Object obj: node.fragments()) {
			VariableDeclarationFragment v = (VariableDeclarationFragment)obj;
			System.out.println("Field:\t" + v.getName());
		}
		
		return true;
		
	}
 
	@Override
	public boolean visit(MethodDeclaration node) {
		System.out.println("Method:\t" + node.getName());
		return true;
	}
 
	@Override
	public boolean visit(TypeDeclaration node) {
		System.out.println("Class:\t" + node.getName());
		return true;
	}
}

 6.写测试类Main,对上述解析源代码的工具类(JdtAstUtil)和访问AST的访问者类(DemoVisitor )进行测试

在 src/test/java 里面新建类Main和ClassDemo

Main类代码:

其中JdtAstUtil.getCompilationUnit()参数为需解析的Java源代码文件路径,示例:

D:\\Eclipse2\\ast_test\\src\\test\\java\\ast_test\\classDemo.java

package ast_test;
import org.eclipse.jdt.core.dom.CompilationUnit;

public class Main {
	public static void main(String[] args) {
		//源码与AST转换
		CompilationUnit comp = JdtAstUtil.getCompilationUnit("D:\\Eclipse2\\ast_test\\src\\test\\java\\ast_test\\classDemo.java");
		//实例化访问者类,配合前面写的工具类访问节点
		demoVisitor visitor = new demoVisitor();
		comp.accept(visitor);
	}
}

 7.写一个简单的Java源代码文件(ClassDemo.java)如下,对它进行AST解析

package ast_test;
public class ClassDemo {
	
	private String text = "Hello World!", text2;
	
	public void print(int value) {
		System.out.println(value);
	}
	
	public void input(String value) {
		text2 = value;
	}
}

 

End......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值