分享
 
 
 

扩展Eclipse的Java开发工具(四)

王朝java/jsp·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

怎样分析 Java 代码以进行修改?

JDT 提供了几个工具来帮助您分析代码。本文有意选择了最简单的 IScanner 接口进行演示,它的作用域也最有限。这个接口属于 JDT 工具箱,可以通过 JDT 的 ToolFactory 类访问它。其 createScanner 方法返回一个扫描程序,该扫描程序会简化对一串 Java 代码作标记的工作。它不处理任何特别困难的操作,只是对所返回的标记进行简单的解析和分类。例如,它指出下一个标记是 public 关键字,其后的标记是一个标识符,再后面的标记是左圆括号,等等。随后,只有当您希望分析一小段代码(您明确理解想要在这段代码中得到什么)时,这个扫描程序才是合适的。您决不会使用扫描程序分析整个 Java 源代码;因为您会转而使用一些对编译器迷而言十分熟悉的工具:JDT 的抽象语法树(Abstract Syntax Tree,AST)框架。

与简单的扫描程序不同,AST 理解语言元素(它们不再只是“标记”)之间的关系。它可以识别象局部变量、实例变量、表达式以及 if 语句等六十多种不同的语言元素。它将帮助您进行涉及范围广泛的重构,或难以满足对标记进行一对一分类的模糊程度特别高的重构。要更清晰地了解何时使用扫描程序与何时使用 AST 之间的差别,请考虑清单 10 中的代码。

清单 10. 模糊的变量引用

public class 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 的实例以确定并替换源代码中确定成员可视性的关键字。我们将处理的可视性修饰符是 public、private、protected 和 final。通过采用“蛮力”方法,我们可以简化这个解决方案,即,采用两个步骤就可以完成。首先删除方法特征符中所有的可视性修饰符(或至少扫描查找它们,如果找到,就删除),然后插入所希望的修饰符。特别地:

如果在方法特征符中找到 public、private 或 protected,就删除它们。

插入所请求的可视性修饰符(对于包可视性的情况,不作任何操作,因为这是缺省操作;即没有任何修饰符)。

final 修饰符很简单。因为所希望的行为就是插入和除去这个修饰符,所以如果它存在,我们除去它;否则就插入它。清单 11 中的代码只显示了一个例子,它无条件地将成员的可视性从 pubilc 改成 private。在与本文相关的解决方案中,您将看到每个操作的公共代码都被移到了抽象超类中。它基本上与下面的代码相同,只不过稍作了整理以避免冗余。

清单 11. 扫描是否有 pubilc 关键字

ICompilationUnit cu = member.getCompilationUnit();

if (cu.isWorkingCopy()) {

IBuffer buffer = cu.getBuffer();

IScanner scanner =

ToolFactory.createScanner(false, false, false, false);

scanner.setSource(buffer.getCharacters());

ISourceRange sr = member.getSourceRange();

scanner.resetTo(

sr.getOffset(),

sr.getOffset() + sr.getLength() - 1);

int token = scanner.getNextToken();

while (token != ITerminalSymbols.TokenNameEOF

&& token != ITerminalSymbols.TokenNameLPAREN)

token = scanner.getNextToken();

if (token == ITerminalSymbols.TokenNamePUBLIC) {

buffer.replace(

scanner.getCurrentTokenStartPosition(),

scanner.getCurrentTokenEndPosition(),

scanner.getCurrentTokenStartPosition() + 1,

"private");

break;

}

}

cu.reconcile();

}

注:ITerminalSymbols 定义了扫描程序可以返回的标记名称,它们对应于 Java 语法的标准标记。您可以进一步查询扫描程序以询问当前标记在缓冲区中开始和结束的具体位置,它出现在哪一行上,当然还有标记本身(特别是象 ITerminalSymbols.TokenNameStringLiteral 和 ITerminalSymbols.TokenNameIdentifier 这样的例子,它们不是保留的关键字)。

上述代码片段中,向 scanner.setSource 方法提供了编译单元的完整源代码,即 Java 源文件中的所有内容。正如前面提到的,扫描程序并不非常适合于大型分析,所以我们必须将它限制用于只有以目标方法的第一个字符开始,一直到调用 setSourceRange 方法作为结束的那部分源代码。IMember 接口继承了 ISourceReference,ISourceReference 是一个允许您查询包含编译单元内的源代码字符串和源代码位置的接口。这使我们不必确定目标方法在 Java 源代码内开始和结束的位置。原本可以用 AST 实现这一点,而 ISourceReference 接口使 AST 成了多余的工具。由于 Java 方法特征符易于解析,所以 IScanner 接口的解析能力和它很匹配。我们必须做的就是查找 public 关键字,它出现在方法声明的前一个字符之后,参数声明的左圆括号之前,用 private 关键字替换它。当然,在该解决方案中,这个接口将处理所有的可能情况,不管该方法最初是 public、private、protected 还是 package(缺省)。

下一步是什么?

本文设定的目标是向您提供一个对 Eclipse 的 Java 开发环境颇具价值的扩展,这样的扩展增强了这个开发环境的生产率。坦率地说,出于简洁性考虑,我多次跳过了一些细节。该解决方案本身就作了一些简化假设,象只允许在编辑器中对已打开的 Java 源代码进行修改。您可能希望在更完整的实现中取消这个限制。

虽然如此,但我还是希望您能感受到什么是可能的,并确信这样做不是特别困难。本文中我们讨论的是 The Java Developer's Guide to Eclipse 一书某一高级章节的部分内容。该书中有十一个比较浅显的章节讨论了插件开发的基础。象本文一样,大多数章节都包含了一个已文档化的工作解决方案,它可以强化您所学到的知识,大多数内容是以本文中您已看到的相同风格编写的(不过可能没有以这么快的节奏进行讨论!)。

重要:您可能需要向工作空间添加必要的插件,这样解决方案才能编译和运行。选择 Window Preferences Plug-in Development Target Platform,然后选择 Not in Workspace。这将确保解决方案所依赖的基础插件在导入和重新编译过程中可用。

一旦导入完成,您可能需要切换至 Plug-in Development 透视图,在 com.ibm.lab.soln.jdt.excerpt 项目中选择 plugin.xml,然后选择 Update Classpath。这将修改由于 Eclipse 安装路径和解决方案的安装路径不同所引起的编译错误。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有