首页 > 解决方案 > 使用 ANTLR4 解析 java 文件时,如何保存方法名称和在该方法中调用的所有方法的名称?

问题描述

我正在开发一个程序,该程序使用来自 ANTLRs github 的 Java9 词法分析器和语法来解析 Java 文件。解析文件时,我想将每个方法名称以及在该方法中调用的所有方法的名称保存在HashMap<String, Set<String>>.

我使用侦听器模式,其中我使用方法exitMethodDeclaration来获取方法名称和exitMethodInvocation来获取方法调用。问题是这两种方法是在解析树的不同节点上调用的,因此它们将不同的上下文作为参数。因此,据我所知,我无法调用该方法来获取exitMethodDeclaration内部的调用。我尝试构建自己的递归,这样我就可以通过将 methodDeclarationContext 作为参数传递给exitMethodInvocation来解决类型问题。不过,这将非常复杂,我想使用 ANTLRs 功能。

使用下面的代码,每个方法的 hashSet 包含整个文件的所有方法调用,而不仅仅是特定方法。

private HashMap<String, HashSet<String>> methodCalls = new HashMap<>();
private HashSet<String> methodCallNames = new HashSet<>();

public void exitMethodDeclaration(Java9Parser.MethodDeclarationContext ctx) {
        String methodName = ctx.methodHeader().methodDeclarator().identifier().getText();
        methodCalls.put(methodName, methodCallNames);
    }

public void exitMethodInvocation(Java9Parser.MethodInvocationContext ctx) {
    try {
        String m = ctx.methodName().identifier().getText();
        methodCallNames.add(m);
    } catch (Exception e) {
    }
}

任何关于如何在同一方法中收集不同上下文类型的节点、访问侦听器/访问者方法中的子树或其他想法的想法都非常受欢迎!

标签: javaparsinglistenerantlr4method-invocation

解决方案


您可以创建一个 ArrayLists 堆栈。

每次,您enterMethodDeclaration将一个新的 Empty ArrayList 推送到您的 Stack。

每次您enterMethodInvocation(或者exit...如果您愿意),您可以将 methodName 添加到您在 stack.peek() 上的 ArrayList 中。

每当你exitMethodDeclartationstack.pop() 你 ArrayList 时,它都会列出你在该方法调用中直接遇到的所有方法名称。而且,方法名称就在 Context 参数中exitMethodDeclaration


推荐阅读