【问题标题】:How to save a method name and names of all methods called inside that method when parsing a java file with ANTLR4?使用 ANTLR4 解析 java 文件时,如何保存方法名称和在该方法中调用的所有方法的名称?
【发布时间】:2021-12-19 13:19:16
【问题描述】:

我正在开发一个程序,该程序使用来自 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) {
    }
}

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

【问题讨论】:

  • 如果在方法foo 中有一个匿名类,并且在该匿名类中有一个调用baz 的方法bar。您是否也将baz 视为foo 调用的方法之一?
  • @Sweeper 这不是我考虑过的事情,但感谢您提出!理想情况下,我会将baz 视为foo 调用的方法之一,但任何关于如何在不考虑这一点的情况下解决问题的想法也将不胜感激。
  • 最容易写的是methodInvocation_lfno_primarymethodInvocation的访问者,只要遍历父链,直到得到methodDeclarator,然后将调用的方法与方法关联起来。现在,您还需要收集没有调用的方法,因此您必须为所有 methodDeclarator 创建一个空的方法列表(如果不存在)。编写此代码需要 3 分钟——非常简单。效率不高,但更大的问题是你会发现 java/java9 没有优化——解析慢。
  • 我不会默默地接受这样的异常:catch (Exception e) {}。如果事情出错,你永远不知道。至少记录,或将错误打印到控制台:catch(Exception e) { e.printStackTrace(); }

标签: java parsing listener antlr4 method-invocation


【解决方案1】:

您可以创建一个 ArrayLists 堆栈。

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 2011-01-17
    • 2010-11-18
    • 2018-02-08
    相关资源
    最近更新 更多