当前位置: 首页 > 工具软件 > D Parser > 使用案例 >

javaparser - java源码分析修改框架

袁奇文
2023-12-01

javaparser 包含一组实现具有高级分析功能的 Java 1.0 - Java 15 Parser 的库。 这包括 Java 13 的预览功能,Java 14 预览功能正在进行中。

  • Analyse: 编写可以遍历 Java 源代码并查找您感兴趣的模式的代码。
  • Transform: 构建的工具不仅可以识别代码模式,还可以更改它们。
  • Generate: 聪明点,不要花时间编写样板,生成它!

使用 demo工程: 从官方demo fork的工程里可以看到大部分使用示例(对应于官方指导文档里使用说明)。

查找指定方法调用所在的行数、函数名、类名

示例代码:


    public static void main(String[] args) throws Exception {

        CompilationUnit cu = StaticJavaParser.parse(new FileInputStream(FILE_PATH));

        VoidVisitor<Void> methodCallVisitor = new MethodCallPrinter();
        methodCallVisitor.visit(cu, null);
    }

    private static class MethodCallPrinter extends VoidVisitorAdapter<Void> {

        @Override
        public void visit(MethodCallExpr mc, Void arg) {
            super.visit(mc, arg);
            Range range = mc.getRange().orElse(Range.range(-1, -1, -1, -1));
            int startLine = range.begin.line;
            int endLine = range.end.line;

            MethodDeclaration methodDeclaration = funcCalledByMethod(mc);
            ClassOrInterfaceDeclaration classDeclaration = funcCalledByClass(methodDeclaration);

            System.out.printf("Method call Printed -> method %s called in %s.%s() line [%d, %d]\n",
                    mc.getName().getIdentifier(), classDeclaration == null ? "" : classDeclaration.getName().getIdentifier(),
                    methodDeclaration == null ? "" : methodDeclaration.getName().getIdentifier(), startLine, endLine);
        }                                                                                                                       

执行结果:

Method call Printed -> method split called in ReversePolishNotation.calc() line [25, 25]
Method call Printed -> method pop called in ReversePolishNotation.calc() line [33, 33]
Method call Printed -> method pop called in ReversePolishNotation.calc() line [34, 34]
Method call Printed -> method push called in ReversePolishNotation.calc() line [35, 35]
Method call Printed -> method pop called in ReversePolishNotation.calc() line [38, 38]
Method call Printed -> method pop called in ReversePolishNotation.calc() line [39, 39]
Method call Printed -> method push called in ReversePolishNotation.calc() line [40, 40]
Method call Printed -> method pop called in ReversePolishNotation.calc() line [43, 43]
Method call Printed -> method pop called in ReversePolishNotation.calc() line [44, 44]
Method call Printed -> method push called in ReversePolishNotation.calc() line [45, 45]
Method call Printed -> method pop called in ReversePolishNotation.calc() line [48, 48]
Method call Printed -> method pop called in ReversePolishNotation.calc() line [49, 49]
Method call Printed -> method push called in ReversePolishNotation.calc() line [50, 50]
Method call Printed -> method valueOf called in ReversePolishNotation.calc() line [53, 53]
Method call Printed -> method push called in ReversePolishNotation.calc() line [53, 53]
Method call Printed -> method of called in ReversePolishNotation.calc() line [28, 28]
Method call Printed -> method forEach called in ReversePolishNotation.calc() line [28, 55]
Method call Printed -> method pop called in ReversePolishNotation.calc() line [56, 56]

查找所在函数的递归函数:


        /**
         * 查找节点在哪个函数里调用
         *
         * @param node 节点
         * @return 函数声明
         */
        private MethodDeclaration funcCalledByMethod(@Nullable Node node) {
            if (node == null) {
                return null;
            }

            Node parentNode = node.getParentNode().get();
            if (parentNode instanceof MethodDeclaration) {
                return (MethodDeclaration) parentNode;
            } else {
                return funcCalledByMethod(parentNode);
            }
        }

查找所在类的递归函数:

        /**
         * 查找节点在哪个类或接口里
         *
         * @param node 节点
         * @return 类或接口声明
         */
        private ClassOrInterfaceDeclaration funcCalledByClass(@Nullable Node node) {
            if (node == null) {
                return null;
            }

            Node parentNode = node.getParentNode().get();
            if (parentNode instanceof ClassOrInterfaceDeclaration) {
                return (ClassOrInterfaceDeclaration) parentNode;
            } else {
                return funcCalledByClass(parentNode);
            }
        }

参考文献

http://javaparser.org/

https://github.com/javaparser/javaparser

https://leanpub.com/javaparservisited

https://github.com/BlankLun/javaparser-visited

 类似资料: