Eclipse plugins 插件开发学习 - 使用 IScanner 扫描 Java 源代码
来源:互联网 发布:软件外包交易平台 编辑:程序博客网 时间:2024/05/18 15:30
怎样分析 Java 代码以进行修改?
JDT 提供了几个工具来帮助您分析代码。本文有意选择了最简单的 IScanner 接口进行演示,它的作用域也最有限。这个接口属于 JDT 工具箱,可以通过 JDT 的 ToolFactory 类访问它。其 createScanner 方法返回一个扫描程序,该扫描程序会简化对一串 Java 代码作标记的工作。它不处理任何特别困难的操作,只是对所返回的标记进行简单的解析和分类。例如,它指出下一个标记是 public 关键字,其后的标记是一个标识符,再后面的标记是左圆括号,等等。随后,只有当您希望分析一小段代码(您明确理解想要在这段代码中得到什么)时,这个扫描 程序才是合适的。您决不会使用扫描程序分析整个 Java 源代码;因为您会转而使用一些对编译器迷而言十分熟悉的工具:JDT 的抽象语法树(Abstract Syntax Tree,AST)框架。
与简单的扫描程序不同,AST 理解语言元素(它们不再只是“标记”)之间的关系。它可以识别象局部变量、实例变量、表达式以及 if 语句等六十多种不同的语言元素。它将帮助您进行涉及范围广泛的重构,或难以满足对标记进行一对一分类的模糊程度特别高的重构。要更清晰地了解何时使用扫描 程序与何时使用 AST 之间的差别,请考虑清单 1 中的代码。
清单 1. 模糊的变量引用
如果作为重构的一部分,您希望查找对实例变量 foo 的引用,那么就会明白一个单纯的解析会使区分本地引用和实例变量引用成为一个难题。AST 创建了完整的分析树,其中表示了 Java 源代码的每个元素并对这些元素进行了区分。在这个特例中,不同的类会考虑“foo”引用的上下文,将“foo”引用表示成 AST 的节点(如 FieldDeclaration、SimpleName 和 ThisExpression),因此您会很轻松地识别它们。
正如前面提到的,本文将只讨论我们所选择的简单例子。
创建 IScanner
基本方法:
IScanner.getNextToken()
IScanner.getCurrentTokenSource()
IScanner.getCurrentTokenStartPosition()
IScanner.getCurrentTokenEndPosition()
IScanner.resetTo()
将扫描结果配合 IBuffer 就可以修改源代码了
// Replace Code
buffer.replace(
scanner.getCurrentTokenStartPosition(),
scanner.getCurrentTokenEndPosition() - scanner.getCurrentTokenStartPosition() + 1,
text
);
// Insert Code
buffer.replace(
scanner.getCurrentTokenStartPosition(),
0,
text
);
// Delete Code
buffer.replace(
scanner.getCurrentTokenStartPosition(),
scanner.getCurrentTokenEndPosition() - scanner.getCurrentTokenStartPosition() + 1,
""
);
JDT 提供了几个工具来帮助您分析代码。本文有意选择了最简单的 IScanner 接口进行演示,它的作用域也最有限。这个接口属于 JDT 工具箱,可以通过 JDT 的 ToolFactory 类访问它。其 createScanner 方法返回一个扫描程序,该扫描程序会简化对一串 Java 代码作标记的工作。它不处理任何特别困难的操作,只是对所返回的标记进行简单的解析和分类。例如,它指出下一个标记是 public 关键字,其后的标记是一个标识符,再后面的标记是左圆括号,等等。随后,只有当您希望分析一小段代码(您明确理解想要在这段代码中得到什么)时,这个扫描 程序才是合适的。您决不会使用扫描程序分析整个 Java 源代码;因为您会转而使用一些对编译器迷而言十分熟悉的工具:JDT 的抽象语法树(Abstract Syntax Tree,AST)框架。
与简单的扫描程序不同,AST 理解语言元素(它们不再只是“标记”)之间的关系。它可以识别象局部变量、实例变量、表达式以及 if 语句等六十多种不同的语言元素。它将帮助您进行涉及范围广泛的重构,或难以满足对标记进行一对一分类的模糊程度特别高的重构。要更清晰地了解何时使用扫描 程序与何时使用 AST 之间的差别,请考虑清单 1 中的代码。
清单 1. 模糊的变量引用
public class Foo {
int foo = 1;
public int foo(int foo) {
return foo + this.foo;
}
public int getFoo() {
return foo;
}
}
int foo = 1;
public int foo(int foo) {
return foo + this.foo;
}
public int getFoo() {
return foo;
}
}
如果作为重构的一部分,您希望查找对实例变量 foo 的引用,那么就会明白一个单纯的解析会使区分本地引用和实例变量引用成为一个难题。AST 创建了完整的分析树,其中表示了 Java 源代码的每个元素并对这些元素进行了区分。在这个特例中,不同的类会考虑“foo”引用的上下文,将“foo”引用表示成 AST 的节点(如 FieldDeclaration、SimpleName 和 ThisExpression),因此您会很轻松地识别它们。
正如前面提到的,本文将只讨论我们所选择的简单例子。
创建 IScanner
IType objectClass = ....;
ICompilationUnit cu = objectClass.getCompilationUnit();
IBuffer buffer = cu.getBuffer();
IScanner scanner = ToolFactory.createScanner(false, false, false, false);
scanner.setSource(this.buffer.getCharacters());
// 不扫描 package 和 import 部分
ISourceRange sr = objectClass.getSourceRange();
scanner.resetTo(sr.getOffset(), sr.getOffset() + sr.getLength() - 1);
ICompilationUnit cu = objectClass.getCompilationUnit();
IBuffer buffer = cu.getBuffer();
IScanner scanner = ToolFactory.createScanner(false, false, false, false);
scanner.setSource(this.buffer.getCharacters());
// 不扫描 package 和 import 部分
ISourceRange sr = objectClass.getSourceRange();
scanner.resetTo(sr.getOffset(), sr.getOffset() + sr.getLength() - 1);
基本方法:
IScanner.getNextToken()
IScanner.getCurrentTokenSource()
IScanner.getCurrentTokenStartPosition()
IScanner.getCurrentTokenEndPosition()
IScanner.resetTo()
将扫描结果配合 IBuffer 就可以修改源代码了
// Replace Code
buffer.replace(
scanner.getCurrentTokenStartPosition(),
scanner.getCurrentTokenEndPosition() - scanner.getCurrentTokenStartPosition() + 1,
text
);
// Insert Code
buffer.replace(
scanner.getCurrentTokenStartPosition(),
0,
text
);
// Delete Code
buffer.replace(
scanner.getCurrentTokenStartPosition(),
scanner.getCurrentTokenEndPosition() - scanner.getCurrentTokenStartPosition() + 1,
""
);
- Eclipse plugins 插件开发学习 - 使用 IScanner 扫描 Java 源代码
- Eclipse plugins 插件开发学习 - IScanner 和 IBuffer 封装的高级应用类
- Eclipse plugins 插件开发学习 - 在 plugin.xml 中使用资源文件 plugin.properties
- Eclipse plugins 插件开发学习 - 扩展点介绍
- Eclipse plugins 插件开发学习 - 第三方Jar包依赖
- Eclipse plugins 插件开发学习 - 扩展点介绍
- Eclipse开发TC插件打包到TC_ROOT\portal\plugins
- Eclipse+JFreeChart+Plugins开发
- 阿里巴巴Java开发手册及Java代码规约扫描eclipse和IDEA插件
- 阿里巴巴Java开发手册及Java代码规约扫描eclipse和IDEA插件
- 阿里巴巴Java开发手册及Java代码规约扫描eclipse插件安装
- Eclipse插件开发学习
- [java] eclipse 插件开发
- Eclipse开发java插件
- 《阿里巴巴Java开发手册》扫描插件正式发布--插件安装和使用分析
- 《阿里巴巴Java开发手册》扫描插件正式发布--插件安装和使用分析
- 学习工具篇 - eclipse 中使用autotools plugins
- 《阿里巴巴Java开发规约》扫描插件介绍
- Visual C#实现Windows信使服务
- 仿射变换
- 本人的Reapter分页控件
- 在日本的软件工程师之路
- js 处理Cookie 总结
- Eclipse plugins 插件开发学习 - 使用 IScanner 扫描 Java 源代码
- Asp.net2.0 中自定义过滤器对Response内容进行处理(生成静态页面)
- 各种数据库的JDBC驱动下载及连接字符串URL写法
- 三大portal与其他系统集成SSO探密
- C#简单计算器
- Eclipse plugins 插件开发学习 - IScanner 和 IBuffer 封装的高级应用类
- Accordion(可折叠)控件学习
- TAOCP V4.F2 格雷码(2)
- 什么是DirectX