提示:javalang包分两段理解:一段是代码片段解析成语法树的过程 一段是语法树节点操作
参考文档:https://github.com/c2nes/javalang
语法树
获取语法树
>>> import javalang >>> tree = javalang.parse.parse("package javalang.brewtab.com; class Test {}")
解析后将会返回一个CompilationUnit类型实例,这个对象是ast树的根节点,可以利用它来遍历所有节点,然后提取信息
>>> tree.package.name u'javalang.brewtab.com' >>> tree.types[0] ClassDeclaration >>> tree.types[0].name u'Test
传递给javalang.parse.parse()的字符串必须一个完整的、有效的java代码片段,其他在javalang.parse模块中的方法不必是完整、有效的代码片段
使用语法树
CompilationUnit是javalang.ast.Node的一个子类,它的子节点也是如此,javalang.tree模块定义了不同类型Node子类,每一个代表着java代码中的语法元素,更多的信息在javalang/tree.py
Node 实例支持迭代
>>> for path, node in tree: ... print path, node () CompilationUnit (CompilationUnit,) PackageDeclaration (CompilationUnit, [ClassDeclaration]) ClassDeclaration
获取方法信息
fd = open("./javalangTest.java", "r", encoding="utf-8") treenode = javalang.parse.parse(fd.read()) for path, node in treenode: if isinstance(node, tree.ClassDeclaration): #TODO if node.name.startswith("test"): print("class_name: " + node.name) for path_1, node_1 in node: if isinstance(node_1, tree.MethodDeclaration): if node_1.name.startswith("test"): if node_1.annotations[0].name == "Test": print("function_name: " + node_1.name) print(node_1.position) for path_2, node_2 in node_1: try: print(node_2.position[0]) except TypeError: continue
组件使用
在内部,javalang.parse.parse 方法创建token流,并用token流创建javalang.parser.Parser实例,然后调用parser的parse()方法,返回结果CompilationUnit实例,tokenizer、Parser这些组件可以单独调用
def parse(s): tokens = tokenize(s) parser = Parser(tokens) return parser.parse()
分词器(tokenizer)
分词器可以通过javalang.tokenizer.tokenize直接调用tokenizer
>>> javalang.tokenizer.tokenize('System.out.println("Hello " + "world");') <generator object tokenize at 0x1ce5190>
每个token携带位置信息(line, column)和value信息
>>> tokens = list(javalang.tokenizer.tokenize('System.out.println("Hello " + "world");')) >>> tokens[6].value u'"Hello "' >>> tokens[6].position (1, 19)
javalang包下面的模块
模块名称 | 常用类和函数 | 描述 |
ast | class MetaNode(type): class Node(object):语法树节点类 def children(self): def position(self): def walk_tree(root):通过跟节点遍历语法树 def dump(ast, file): 显示语法树 def load(file):加载文件 |
|
javadoc |
| 每个javatoken都会带这个,基本无用 |
parse | def parse(s): tokens = tokenize(s) parser = Parser(tokens) return parser.parse() | 对分词器、解析器等封装,提供parse()等方法 |
parser | tree.CompilationUnit(package=package, imports=import_declarations, types=type_declarations) | 解析器组件,通过指定tokens流创建语法树 |
tokenizer |
| 分词器组件,将代码片段进行分割成token |
tree | 比如: class CompilationUnit(Node): class Import(Node): class PackageDeclaration(Declaration, Documented): class ClassDeclaration(TypeDeclaration): class Annotation(Node): class MethodDeclaration(Member, Declaration):
| 定义了ast模块Node类的子类 |
util |
| 工具类,比如迭代器 |