JavaParser使用指南

JavaParser使用指南

前言

以下翻译自官网的书

入门-Start

JavaParser Class

用途:把Java源码转换成 JavaParser定义的Statement对象

Eg:

Statement expression = JavaParser.parseStatement("int a=0;");

CompilationUnit Class

用途:是一个完整的类文件的表示
在AST中,你可以把这个类看成是AST的根节点

Visitor Classes

用途:用于找到某个类型的节点

A Simple Visitor

package com.github.javaparser;

import com.github.javaparser.*;
import com.github.javaparser.ast.*;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.EnumDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import com.github.javaparser.utils.SourceRoot;

import java.io.File;

public class VoidVisitorStarter {
	private static final String FILE_PATH = "ReversePolishNotation.java";
			
	public static void main(String[] args) throws Exception {
			
			CompilationUnit cu = JavaParser.parse(new File(FILE_PATH));
			
	}
}

上面的parse方法能够将FILE_PATH所定义的类文件编译成CompilationUnit(可以理解为AST树的根节点,存有被编译的源代码的一切信息),接下来我们就可以通过遍历CompilationUnit来获得我们想要得到的信息啦!

Comments

一个节点(node)只能有一个comment
可以在他的comment域中访问

comment的类型

  • LineComment
  • BlockComment
  • JavadocComment

Orphan Comment:
不能归为AST树中的某一个节点的Comment

Pretty Printing and Lexical Preservation

Pretty Printing: 打印出格式化的代码
Lexical Preservation: 原来的代码什么样,现在的代码就什么样

Javaparser-Solving Symbols and References

JavaParser开发者教程

Symbol的定义
Java code中的所有name都可以称作为symbol

TypeSolver的作用
确定寻找类的位置

原文:What the hell is a Type Solver It is the object which knows where to look for classes. When processing source code you will typically have references to code that is not yet compiled, but it is just present in other source files. You could also use classes contained in JARs or classes from the Java standard libraries. You have just to tell to your TypeSolver where to look for classes and it will figure it out.

由于在解析symbol的时候,我们需要知道这个symbol来自哪里(i.e. 是类内定义的,还是类外定义的…),因此JavaSymbolSolver有这样几种类型去确定类来自哪里,

简单来说下面这些类就是 JavaSymbolSolver查找类的方式

TypeSolver的类型

类型

功能

JarTypeSolver

在.jar文件中寻找类,我们需要传入一个.jar文件的位置

JavaParserTypeSolve

在souce file中寻找文件,我们只需传入根目录即可

ReflectionTypeSolver

一些类作为语言的一部分被定义,比如 java.lang.Object

MemoryTypeSolver

简单地返回我们记录的文件,多用于测试

CombinedTypeSolver

将几个不同的solver合并成一个

其他:

类(com.github.javaparser.symbolsolver)

功能

JavaSymbolSolver

创建后插入CompilationUnit可以创建符号解析
使用方法:ParserConfiguration.setSymbolResolver(SymbolResolver)

Ex1: 获取变量(引用)的类型

public class GetTypeOfReference {

private static final String FILE_PATH = "src/main/java/org/javaparser/exampl

4 es/chapter5/Bar.java";

public static void main(String[] args) throws FileNotFoundException {
	TypeSolver typeSolver = new CombinedTypeSolver();

	JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);
	JavaParser.getStaticConfiguration().setSymbolResolver(symbolSolver);

	CompilationUnit cu = JavaParser.parse(new File(FILE_PATH));

	cu.findAll(AssignExpr.class).forEach(ae -> {
		ResolvedType resolvedType = ae.calculateResolvedType();
		System.out.println(ae.toString() + " is a: " + resolvedType);
	});
}
}

Ex2: 使用absolute name直接解析类型

package com.github.awesomelemon;

import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;

public class UsingTypeSolver {
	private static void showReferenceTypeDeclaration(
			ResolvedReferenceTypeDeclaration resolvedReferenceTypeDeclaration) {

		System.out.println(String.format("== %s ==", resolvedReferenceTypeDeclaration.getQualifiedName()));
		System.out.println(" fields:");
		resolvedReferenceTypeDeclaration.getAllFields()
				.forEach(f -> System.out.println(String.format(" %s %s", f.getType(), f.getName())));
		System.out.println(" methods:");
		resolvedReferenceTypeDeclaration.getAllMethods()
				.forEach(m -> System.out.println(String.format(" %s", m.getQualifiedSignature())));
		System.out.println();
	}

	public static void main(String[] args) {
		TypeSolver typeSolver = new ReflectionTypeSolver();

		showReferenceTypeDeclaration(typeSolver.solveType("java.lang.Object"));
		showReferenceTypeDeclaration(typeSolver.solveType("java.lang.String"));
		showReferenceTypeDeclaration(typeSolver.solveType("java.util.List"));
	}
}

作用是返回以下三个包里面的 symbol是作为field还是method

  • java.lang.Object
  • java.lang.String
  • java.util.List

Ex3 Resolving a Type in a context

这个例子应用如下的场景:
解析一个变量的类型是来自哪里

懒得截代码了,大家自己找官网的pdf看吧

Ex4 Resolving method calls

可以知道一个method调用的对应的函数签名(signature)

Ex5 Using the Combined Type Solver

使用结合的type solver

Ex6 Using the MemoryTypeSolver

JavaSymbolSolver

JavaSymbolSolver

  • combinedsolver
java精神(基于函数式组合子逻辑的javaparser框架) 一。 释名。 为什么叫精神? 如果你熟悉c++,那么你可能知道一个叫做”spirit”的parser库。它利用c++的模板元编程能力,使用c++语言本身提供了一个递归下降文法解析的框架。 我这里介绍的jparsec库,就是一个java里面的递归下降文法解析框架。 不过,它并非是spirit的java版本。 Jparsec的蓝本来自Haskell语言的parsec库。Parsec是一个基于monad的parser组合子库。 这个库的目的是要在java中提供一个类似parsec, spirit的库,这种组合子库并非c++的专利,java/c#也可以做到。这个库还将在java5.0上被改写,类型安全上它将也不再逊色于c++。 那么,为什么叫“函数式”呢?java是面向对象的嘛。 如果你使用过haskell, lisp等语言,这个函数式不用解释你也知道是怎么回事了。 如果你是一个老牌的c++/java程序员,那么这里还要稍微解释一下。当然如果您对这些虚头八脑的名词不感兴趣,那么,你尽可以跳过这一章,不知道什么是“函数式”,并不会影响你对这个库的理解的。 C++这几年随着gp的普及,“函数式”这个老孔乙己逐渐又被人从角落里面拽了出来。一个c++程序员所熟悉的“函数式”很可能是stl的for_each, transform,count_if这些函数。 怎么说呢,就象我不能否定str.length()这个调用属于OO一样,我也无法说for_each, transform不是函数式。 但是,“函数式”的精髓不在于此。 一般归纳起来,就像我们说OO是什么多态,封装,继承一样,“函数式”的特征被总结为: 1。无副作用。 2。高阶函数。 3。延迟计算 而最最有意义的(至少我认为如此),是基于高阶函数的函数组合能力。一些人把这叫做glue。 简短地说,什么让函数式编程如此强大?是用简单的函数组合出复杂函数的能力。 我可以想象,说到这里,你还是一头雾水。“什么是组合?1+1不是也把两个1组合成2了吗?new A(new B(), new C())不也是从B和C组合成A了?”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值