如何对java 源码进行分析, 统计出每个方法被引用的次数

使用 JavaParser 统计源码中每个方法的引用次数是一个可行且有效的方法。JavaParser 是一个用于解析 Java 源代码并生成抽象语法树(AST)的库,它提供了丰富的 API 来遍历和操作 AST。下面是一个详细的指南,说明如何使用 JavaParser 来统计每个方法的引用次数。

步骤 1: 设置项目

确保项目中包含了 JavaParser 的依赖。如果使用的是 Maven 构建工具,可以在 pom.xml 文件中添加以下依赖项:

<dependency>
    <groupId>com.github.javaparsergroupId>
    <artifactId>javaparser-coreartifactId>
    <version>3.25.9version>
dependency>

<dependency>
    <groupId>com.github.javaparsergroupId>
    <artifactId>javaparser-symbol-solver-coreartifactId>
    <version>3.25.9version>
dependency>

步骤 2: 编写代码

接下来是编写代码来加载源文件、构建模型并统计方法调用次数:

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class SourceParser {

  private static final Map<String, Integer> methodCalls = new HashMap<>();

  public static void main(String[] args) throws IOException {
    // 待解析的源代码路径
    Path sourcePath = Paths.get("D:/test/es-boot/src/main/java"); // 避坑:路径使用右斜杠
    // 配置符号解析器
    CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
    // combinedTypeSolver.add(new ReflectionTypeSolver());
    combinedTypeSolver.add(new JavaParserTypeSolver("D:/test/es-boot/src/main/java")); // 避坑:路径使用右斜杠

    JavaSymbolSolver javaSymbolSolver = new JavaSymbolSolver(combinedTypeSolver);
    StaticJavaParser.getParserConfiguration().setSymbolResolver(javaSymbolSolver);

    // 遍历源代码
    Files.walk(sourcePath)
      .filter(Files::isRegularFile)
      .filter(path -> path.toString().endsWith(".java"))
      .forEach(SourceParser::processFile);

    methodCalls.entrySet().stream()
      .sorted((e1, e2) -> e2.getKey().compareTo(e1.getKey()))
      .map(el -> el.getKey() + " - " + el.getValue())
      .forEach(System.out::println);
  }

  private static void processFile(Path path) {
    try(FileInputStream in = new FileInputStream(path.toFile())) {
      CompilationUnit cu = StaticJavaParser.parse(in);
      new VoidVisitorAdapter<Void>() {
        @Override
        public void visit(MethodCallExpr mce, Void arg) {
          super.visit(mce, arg);
          ResolvedMethodDeclaration resolve = null;
          try {
            resolve = mce.resolve();
            String qualifiedName = resolve.getQualifiedName();
            methodCalls.compute(qualifiedName, (k, v) -> v == null? 1 : v + 1);
          } catch (Exception e) {
            // do nothing.
          }
        }
      }.visit(cu, null);
    } catch (Exception e) {
      // do nothing.
    }
  }

}

解释

  • CompilationUnit:代表一个 Java 源文件的 AST。
  • VoidVisitorAdapter:这是一个访问者模式实现,允许遍历 AST 并对特定类型的节点执行操作。
  • MethodDeclaration:表示一个方法声明。
  • MethodCallExpr:表示一个方法调用表达式。

通过这种方式,可以利用 JavaParser 的强大功能来深入分析 Java 源代码,并轻松地完成诸如统计方法调用次数这样的任务。

你可能感兴趣的:(源码分析,java)