javaparser
作为开发人员,我们经常鄙视手动进行重复工作的人员。
我们认为, 他们应该实现这一目标 。
尽管如此,我们还是进行与编码有关的所有活动。 当然,我们使用的高级IDE可以为我们执行一些重构,但这基本上就结束了。 我们不品尝我们自己的药。
让我们改变一下。 让我们看看如何将代码编写为:
- 生成我们必须编写的无聊的重复性Java代码
- 分析我们的代码以回答有关它的一些问题
- 做一些代码处理和重构
好消息是,我们将使用一组库来实现所有这些功能:JavaParser和它的弟弟JavaSymbolSolver。
入门
好吧,这很简单:只需将JavaSymbolSolver添加到您的依赖项中即可。
什么是JavaSymbolSolver? 它是JavaParser的补充库,为它提供了一些非常强大的功能,这些功能对于回答关于代码的更复杂的问题是必需的。
JavaSymbolSolver依赖于JavaParser,因此您只需要添加JavaSymbolSolver,Maven或Gradle也会为您提供JavaParser。
我假设您知道如何使用Maven或Gradle。 如果您不喜欢,请停止阅读并开始学习!
使用javaparser生成代码
在几种情况下,您可能需要生成Java代码。 例如,您可能想基于一些外部数据生成代码,例如数据库架构或REST API。
您可能还需要将其他语言翻译成Java。 例如,我设计了用于生活的DSL,而当用户只能看到我为他们构建的DSL时,我经常在后台生成Java并将其编译。
有时候,您只想生成样板代码,就像我以前在使用JavaEE和所有这些层(谁能记住编写EJB的乏味?)时曾经使用过dp一样。
无论出于什么原因生成代码,都可以使用JavaParser。 JavaParser不会提出问题,它只是在帮助您。
让我们看看如何生成一个具有两个字段的类,一个构造函数和两个getter。 没什么特别先进的,但是它应该使您了解使用JavaParser进行代码生成的含义。
-
CompilationUnit cu = new CompilationUnit();
-
-
("");
-
-
ClassOrInterfaceDeclaration book = ("Book");
-
("String", "title");
-
("Person", "author");
-
-
()
-
.addParameter("String", "title")
-
.addParameter("Person", "author")
-
.setBody(new BlockStmt()
-
.addStatement(new ExpressionStmt(new AssignExpr(
-
new FieldAccessExpr(new ThisExpr(), "title"),
-
new NameExpr("title"),
-
)))
-
.addStatement(new ExpressionStmt(new AssignExpr(
-
new FieldAccessExpr(new ThisExpr(), "author"),
-
new NameExpr("author"),
-
))));
-
-
("getTitle", ).setBody(
-
new BlockStmt().addStatement(new ReturnStmt(new NameExpr("title"))));
-
-
("getAuthor", ).setBody(
-
new BlockStmt().addStatement(new ReturnStmt(new NameExpr("author"))));
-
-
(());
最后一条指令将打印出您的代码,并且可以立即进行编译。 您可能希望将代码保存到文件中而不是打印它,但是您明白了。
使用javaparser分析代码
您可能会询问有关代码的许多不同问题,以及许多不同的分析方式。
首先,让我们解析项目的所有源文件:
-
// Parse all source files
-
SourceRoot sourceRoot = new SourceRoot(());
-
(parserConfiguration);
-
List<ParseResult> parseResults = ("");
-
-
// Now get all compilation unitsList
-
allCus = ()
-
.filter(ParseResult::isSuccessful)
-
.map(r -> ().get())
-
.collect(());
我们还创建一个方法来获取所有编译单元中特定类型的所有节点:
-
public static List getNodes(List cus, Class nodeClass) {
-
List res = new LinkedList();
-
cus.forEach(cu -> res.addAll(cu.findAll(nodeClass)));
-
return res;
-
}
然后让我们开始提出问题,例如:
有多少种方法采用3个以上的参数?
-
long n = getNodes(allCus, MethodDeclaration.class) .stream() .filter(m -> ().size() > 3)
-
.count();("N of methods with 3+ params: " + n);
大多数方法中的三个*类别是什么?
-
getNodes(allCus, ClassOrInterfaceDeclaration.class) .stream() .filter(c -> !()) .sorted((o ->
-
-1 * ().size())) .limit(3) .forEach(c ->
-
(() + ": " + ().size() + " methods"));
好的,您知道了。 现在去检查您的代码。 您没有什么可隐藏的,对吗?
使用javaparser转换代码
假设您是某个库的满意用户。 几年前,您已将其添加到依赖项中,并从此以后就愉快地使用它。 时间已经过去,您已经在整个项目中越来越多地使用它。
有一天,该实用库的新版本出现了,您决定要更新依赖项。 现在,他们在新库中删除了您正在使用的方法之一。 确保已弃用它,并将其命名为oldMethod (可能告诉您一些信息……)。
现在oldMethod已被newMethod取代。 newMethod具有3个参数:前两个与oldMethod相同,只是将它们取反,第三个是布尔值,应将其设置为true以获得与oldMethod相同的行为。
您有对oldMethod的数百个调用…是否要一个一个地更改它们? 好吧,也许,如果您按小时收费。 或者,您可以只使用JavaParser代替。
首先让我们找到所有在JavaParser类parlanse老方法在某个文件,又名CompilationUnit的电话:
-
myCompilationUnit.findAll()
-
.stream()
-
.filter(m -> m.resolveInvokedMethod()
-
.getQualifiedSignature()
-
.equals("(, int)"))
-
.forEach(m -> m.replace(replaceCallsToOldMethod(m)));
然后让我们将旧调用转换为新调用:
-
public MethodCallExpr replaceCallsToOldMethod(MethodCallExpr methodCall) {
-
MethodCallExpr newMethodCall = new MethodCallExpr(
-
().get(), "newMethod");
-
((1));
-
((0));
-
(new BooleanLiteralExpr(true));
-
return newMethodCall;
-
}
太酷了,现在我们只需要获取修改后的CompilationUnit的代码并将其保存到Java文件即可。
newMethod使用寿命长 !
在哪里可以找到有关javaparser的更多信息
我们还没有看到JavaParser的众多功能:
- JavaParser可以处理注释,弄清楚它们所引用的元素
- JavaParser可以进行词法保留或漂亮的打印 :您的选择
- 它可以找出一个方法调用指向哪个方法声明,某个类具有哪个祖先,以及更多地归功于与JavaSymbolSolver的集成。
- 它可以将AST导出为JSON,XML,YAML,甚至可以使用Graphviz生成图表!
您在哪里可以了解所有这些东西?
这里有一些资源:
- 我们写了一本关于JavaParser和JavaSymbolSolver的书,免费提供。 它被命名为JavaParser:Visited
- Matozoid伟大的博客 :他是JavaParser的光荣维护者,这是不可阻挡的力量,它每隔一个星期就会推出新版本。 谁更了解JavaParser?
- 我关于语言工程的拙劣博客 。 我是JavaSymbolSolver的维护者,并且尝试作为JavaParser中的第二命令来提供帮助。 遥远的第二个&#55357;&#56898;
- 该项目的网站 :目前内容还不是很丰富,但是我们正在努力
- 烦恼频道 :您有问题吗? 在那儿问他们
摘要
几乎没有情况可以学习如何使用一种工具来完成三件不同的事情。 通过学习如何使用JavaParser,您可以分析,生成和修改Java代码。
好吧,感觉就像圣诞节,不是吗?
翻译自: /2017/12/
javaparser