Eclipse AST 实现一个类信息统计小程序

这个是对Eclipse AST 获取与访问的介绍,http://blog.csdn.net/LoveLion/article/details/19050155  (我的老师的博客)

本文的工具类完全来自于该文章,其他的类有这篇文章的影子

首先是 工具类,不多讲,请看老师的介绍

package com.kyc.rec;

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
    */
    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));

        return result;
    }
}

接下来是DTO用来存储类中方法的相关信息

package com.kyc.rec;

public class MethodDTO {

	private String name;//方法名
	private int codeLength;//方法的代码长度
	private int numOfParam;//方法参数个数

	public MethodDTO(String name,int codeLength,int numOfParam){
		setName(name);
		setCodeLength(codeLength);
		setNumOfParam(numOfParam);

	}
	public MethodDTO(){

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getCodeLength() {
		return codeLength;
	}

	public void setCodeLength(int codeLength) {
		this.codeLength = codeLength;
	}

	public int getNumOfParam() {
		return numOfParam;
	}

	public void setNumOfParam(int numOfParam) {
		this.numOfParam = numOfParam;
	}

}

下面开始访问,其他访问都不难,只是在获取参数最多的方法的名字时,对我来说有点小麻烦,,因为我对AST的了解还很肤浅,不知道有没有更先进的技术可以使我的方法变得简单

package com.kyc.rec;

import java.util.ArrayList;

import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;

public class DemoVisitor extends ASTVisitor {
	/*类中方法的个数、
	 * 属性的个数、
	 * 源代码行数、
	 * 代码行最多的方法名以及
	 * 代码行数、
	 * 参数个数最多的方法名
	 * 及其参数的个数等信息*/
	public int numOfMethod=0;//方法个数
	public int numOffield=0;//属性个数
	public int codeLength=0;//代码总行数

	public int index=-1;//用于获取参数的时候,指向上一个方法;
	public int[] listOfParam=new int[100];
	private int numOfParam=0;

	private ArrayList<MethodDTO> arrayList =new ArrayList<MethodDTO>();//存储类中方法的相关信息

	public void print(){
		System.out.println("属性个数为:"+numOfMethod);
		System.out.println("方法个数为:"+numOffield);
		System.out.println("代码行数为:"+codeLength);
		System.out.println("代码行最多的方法:"+findLongestCodeLength().getName()+
				"行数为:"+findLongestCodeLength().getCodeLength());
		System.out.println("参数最多的方法:"+findMaxNumOfParam().getName()+
				"方法数为:"+findMaxNumOfParam().getNumOfParam());
//		for(int i=0;i<arrayList.size();i++){
//			System.out.println(arrayList.get(i).getName()+" - "+arrayList.get(i).getNumOfParam());
//		}
	}

	@Override
	public boolean visit(FieldDeclaration node) {
		numOffield++;
		return true;
	}

	@Override
	public boolean visit(MethodDeclaration node) {
		if(index!=-1){
			arrayList.get(index).setNumOfParam(numOfParam);
			numOfParam=0;
		}
		index++;
		//System.out.println("Method:\t" + node.getName()+" "+node.getLength());
		numOfMethod++;
		CountLength cl=new CountLength();
		cl.countLength(node.toString(), "\n");
		addToArrayList(new MethodDTO(node.getName().toString(), cl.getCodeLength(),0));

		return true;
	}

	@Override
	public boolean visit(TypeDeclaration node) {
		//该方法可访问类名
		//System.out.println("Class:\t" + node.getName());
		return true;
	}
	@Override
	public boolean visit(CompilationUnit node){
		//该方法可获得代码的总行数
		CountLength cl=new CountLength();
		cl.countLength(node.toString(), "\n");
		codeLength=cl.getCodeLength();
		return true;
	}

	public void addToArrayList(MethodDTO meDto) {
		arrayList.add(meDto);
	}

	public MethodDTO findLongestCodeLength(){
		//获取代码行数最多的方法
		int maxLength=0;
		MethodDTO  methodDTO=new MethodDTO();
		for(int i=0;i<arrayList.size();i++){
			if(arrayList.get(i).getCodeLength()>maxLength){
				maxLength=arrayList.get(i).getCodeLength();
			}
		}
		for(int i=0;i<arrayList.size();i++){
			if(arrayList.get(i).getCodeLength()==maxLength){
				methodDTO=arrayList.get(i);
				break;
			}
		}
		return methodDTO;
	}
	public MethodDTO findMaxNumOfParam(){
		//获取参数最多的方法
		//这个方法与上一个方法存在明显的代码的坏味道(重复代码),可以对此进行优化
		int maxNum=0;
		MethodDTO  methodDTO=new MethodDTO();
		for(int i=0;i<arrayList.size();i++){
			if(arrayList.get(i).getNumOfParam()>maxNum){
				maxNum=arrayList.get(i).getNumOfParam();
			}
		}
		for(int i=0;i<arrayList.size();i++){
			if(arrayList.get(i).getNumOfParam()==maxNum){
				methodDTO=arrayList.get(i);
				break;
			}
		}
		return methodDTO;
	}
	@Override
	public boolean visit(SingleVariableDeclaration node){
		//本方法在执行visit(MethodDeclaration node)后执行 Method中的参数次;

		numOfParam++;
		return true;

	}
	public void dotheEndParam(){
		arrayList.get(index).setNumOfParam(numOfParam);
	}

}

统计行数类

package com.kyc.rec;

public class CountLength {
	//此类用于获取字符串中换行字符的个数,str2代表子字符串
	private int codeLength=0;
	public int getCodeLength() {
		return codeLength;
	}
	public void setCodeLength(int codeLength) {
		this.codeLength = codeLength;
	}
	public int countLength(String str1, String str2) {
        if (str1.indexOf(str2) == -1) {
            return 0;
        } else if (str1.indexOf(str2) != -1) {
        	codeLength++;
        	countLength(str1.substring(str1.indexOf(str2) +
                   str2.length()), str2);
               return codeLength ;
        }
            return 0;
    }
}

test  类

package com.kyc.rec;

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

public class DemoVisitorTest {

	public DemoVisitorTest(String path) {
		CompilationUnit comp = JdtAstUtil.getCompilationUnit(path);

		DemoVisitor visitor = new DemoVisitor();

		comp.accept(visitor);
		visitor.dotheEndParam();
		visitor.print();
	}

	public static void main(String[] args) {
		new DemoVisitorTest("DemoVisitor.java");

	}
}

结果如下:

jar包可私信

时间: 2024-08-08 22:29:07

Eclipse AST 实现一个类信息统计小程序的相关文章

输出多行字符的一个简单JAVA小程序

1 public class JAVA 2 { 3 public static void main(String[] args) 4 { 5 System.out.println("----------------------"); 6 System.out.println("|| 我要学会 ||"); 7 System.out.println("|| JAVA语言 ||"); 8 System.out.println("-------

构思一个重量级的小程序

早在我大学的时候,我就曾经做过一个电影类的小程序,数据全部由豆瓣提供,功能比较单一,设计也很一般,链接如下: 今天在博客园瞎逛的时候,看到有一位博主做了个汽车销量的小程序,由于本人也是个汽车爱好者,便毫不犹豫地点了进去. 在认真地把所有功能都用了一遍之后,开发一个融入自己很多想法的汽车类小程序便开始萌芽. 我重新下载了微信web开发者工具,并开始阅读官方文档,发现很多api都有了不小的变化,尤其一个新的板块非常吸引人,就是云开发. 我草草地看了一下,感觉这个概念非常有意思,它似乎意味着前后端的工

手把手教你构建一个音视频小程序

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯视频云终端团队发表于云+社区专栏 腾讯云提供了全套技术文档和源码来帮助您快速构建一个音视频小程序,但是再好的源码和文档也有学习成本,为了尽快的能调试起来,我们还提供了一个免费的一键部署服务:您只需轻点几下鼠标,就可以在自己的账号下获得一个音视频小程序,同时附送一台拥有独立域名的测试服务器,让您可以在 5 分钟内快速构建出自己的测试环境. 通过微信公众平台授权登录腾讯云 打开 微信公众平台 注册并登录小程序,按如下步骤操作: 单

一个Java恶搞小程序

运用Java程序控制某个应用程序的运行(以网易云音乐为例),步骤如下 1.建立bat文件分别是start.bat(控制程序的运行)和kill.bat(控制程序的结束): start.bat 的内容如下,功能是运行程序: cmd /c start F:\\00网易云音乐\\CloudMusic\\cloudmusic.exe exit 具体情况可以视具体情况改写你的应用的安装路径即可 kill.bat的内容如下,功能是结束程序进程: taskkill /f /im "cloudmusic.exe&

一个python爬虫小程序

起因 深夜忽然想下载一点电子书来扩充一下kindle,就想起来python学得太浅,什么“装饰器”啊.“多线程”啊都没有学到. 想到廖雪峰大神的python教程很经典.很著名.就想找找有木有pdf版的下载,结果居然没找到!!CSDN有个不完整的还骗走了我一个积分!!尼玛!! 怒了,准备写个程序直接去爬廖雪峰的教程,然后再html转成电子书. 过程 过程很有趣呢,用浅薄的python知识,写python程序,去爬python教程,来学习python.想想有点小激动…… 果然python很是方便,5

做一个开源的小程序登录模块组件(token)

先了解下SSO 对于单点登陆浅显一点的说就是两种,一种web端的基于Cookie.另一种是跨端的基于Token,一般想要做的都优先做Token吧,个人建议,因为后期扩展也方便哦. 小程序也是呢,做成token的形式是较好的. 流程图 PS:图中4的文字打错了~ 1.启动服务 2.小程序初次加载app.js校验token,使用code去换取token 3.检测User信息是否存在code,不存在则注册新用户,最后返回对应用户Id 4.将随机Token与UserId一起存入Redis中 5.返回To

从零开始写个一个豆瓣电影 (小程序教程1)

微信小程序内测至今也有20天左右,也有很多人作出了很多不错的DEMO并发布到github了.前几日看见了豆瓣电影这个demo,感觉很不错,也跟着做了一个,作为复习巩固文档API用. 废话不多说,直接进入正题: 第一节只写一个首页的展示,数据用的是自己写的虚拟的数据 新建一个demo,不要使用微信自带的DEMO,直接从零开始写起: 首先创建3个文件: app.json app.js apps.wxss app.json  : 主要写配置项:内容如下,具体的每个key值对应的意思,这里就不再细说了,

初遇C#:一个简单的小程序(圆形周长,面积计算器)

作为一个面向对象的语言,与用户的交互很关键! 在此,我们可以先分析一下我们这个小程序要与用户交互的内容:1.命名很重要,让用户看见这个程序就知道这个程序的作用. 2.当用户打开这个程序时,提示用户输入的内容. 下面开始编码: Console.Write("请输入圆形的半径:"); double r=double.Parse(Console.ReadLine());//接收用户的输入并将用户的输入转换成双精度型并赋值给r double area,circle;//定义两个变量area和c

Python3的tkinter写一个简单的小程序

一.这个学期开始学习python,但是看了python2和python3,最后还是选择了python3 本着熟悉python的原因,并且也想做一些小程序来增加自己对python的熟练度.所以写了一个简单的程序,这个小程序实现了basa64.base32的加解码.并且添加了一个md5生成的功能.ps:觉得python开发也挺好玩的... 二.运行程序截图: 上面的就是程序的整体界面了.. 三.程序的设计: 源代码就在下面贴图了,并且需要的文档可以--------------搜索吧..... imp