java 方法描述符_Java代码分析器(三): 以强大的属性描述符写出通用代码

原文发表于2015-02-05。

上篇介绍的形形色色的语法元素大概让人眼花缭乱了,而且每种元素都对应一个Java类。知道是一回事,使用就是另一回事了,这么多个类,要给每个类写对应的处理代码,不胜其烦。ASTVisitor虽然能自动遍历语法树,但是并不能帮你处理每一种结点。

好在JDT提供了更加抽象的属性描述符(property descriptor),寥寥几个类就能掌控所有Java语法。用术语来说,上篇的那些类属于异构AST,本篇讲的是同构AST。

对任何AST结点都可调用方法structuralPropertiesForType(),你会得到List,其中每一项都代表这个结点所属的类的一个结构性字段(就是跟AST有关的字段)。

StructuralPropertyDescriptor 是一个抽象类,有三个子类:SimplePropertyDescriptor, ChildPropertyDescriptor, ChildListPropertyDescriptor。这些东西是元数据,用来描述各种语法元素的固有结构,使用它们有种在用Java反射的感觉。

SimplePropertyDescriptor 表示这个字段存放的不是AST结点,而是个值,可能是int, String,Operator之类的,SimplePropertyDescriptor.valueType 能告诉我们这个值是什么类型。

ChildPropertyDescriptor 表示这个字段存放的是一个AST结点,比如我们解析了一个class,得到typeDeclaration结点,然后调用typeDeclaration.structuralPropertiesForType(),得到的list中有一项就是typeName的描述符,嗯,就是AbstractTypeDeclaration类的typeName字段,字段类型为SimpleName。

ChildListPropertyDescriptor 表示这个字段存放的是一组AST结点! 比如AbstractTypeDeclaration拥有一组bodyDeclarations,而CompilationUnit则拥有一组imports。bodyDeclarations和imports都是List!

有了描述符能做什么呢? 可以自由访问一棵语法树了。

我们来想象一个流程:你有一个java文件,你把它交给JDT的parser,解析出一个CompilationUnit cu,也就是一棵语法树的根结点。调用cu.structuralPropertiesForType(),得到描述符的list,循环遍历list,对每个描述符prop,用instanceof判断具体类型(总共就3个类型),分别做"不同处理"。

不同处理:instanceof操作发现某个描述符是ChildListPropertyDescriptor, 于是你把描述符强转(cast)成该类型,调用prop.getId()得到"imports",哦,是imports字段啊,调用prop.getElementType()得到ImportDeclaration.class,确认了这一发现。然后你调用cu.getStructuralProperty(prop)得到一个object,你知道它实际是List,因此你将它强转为这个List类型,遍历它,对每个ImportDeclaration,调用getName().getFullyQualifiedName(),就得到了每个import的名称。(当然,对ImportDeclaration也可以假装不知道其类型,也用元数据来操控之)

由此你就完成了一个分析流程。因为不用关心具体的结点类型,所以你可以方便地进行一些宏观、抽象的分析。

最后提供一段我用Scala写的代码供参考(50行就能把任意Java代码结构转换成JSON输出, 使用了lift json库):

https://github.com/sorra/Lanka/blob/fa52cdaa2f94aadfcc29f8be2711a88da3c8cbb3/src/sorra/lanka/json/MetaConversion.scala

利用强大的属性描述符,写出通用的JSON转换代码,避免了给每个结点类写对应的JSON转换代码(几十种结点类,要死啊)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值