从 AST 获取方法调用信息

发布于 2024-12-14 07:31:34 字数 1664 浏览 0 评论 0原文

如何使用 AST(抽象语法树)解析器获取程序的每个方法声明中调用的方法的名称?到目前为止,我已经成功获取了方法声明的所有名称以及正在调用的方法的所有名称,但我想知道哪个方法调用了哪个方法。例如,我想看到方法 m1 调用方法 mAmB,而方法 m2 调用方法 < code>mC 和 mD 等。

[编辑 11/9/2011 IDB,将新手的扩展评论转录回原始问题的正文中。我希望我已经正确地转录了它。我希望作者回来并根据需要进行修改]:

我的问题似乎是(Eclipse 的)MethodDeclaration api 没有可以调用的 GetInvokedMethodName 函数。这是我的代码:

 public class MethodVisitor extends ASTVisitor { 

         List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();

         @Override public boolean visit(MethodDeclaration node) { 
             methods.add(node); 
             return super.visit(node); } 

         public List<MethodDeclaration> getMethods() 
             { return methods; }

         List<MethodInvocation> methods1 = new ArrayList<MethodInvocation>();

         @Override public boolean visit(MethodInvocation node)
             { methods1.add(node); 
               return super.visit(node); } 

        public List<MethodInvocation> getMethods1() 
             { return methods1; } 
        } 

    ...

    for (MethodDeclaration method : visitor .getMethods()) 
        { System.out.println("Method name: " + method.getName() 
                            + " Return type: " + method.getReturnType2() 
                            + " Is constructor: " + method.isConstructor()
                            + " Method invoked: " + ASTNode.METHOD_INVOCATION );
           ); }

    for (MethodInvocation method1 : visitor .getMethods1())
           { System.out.println("Method name invoked: " + method1.getName() ); }

How can I get the names of the methods invoked in each method declaration of a program using AST (Abstract Syntax Tree) parser? So far, I have managed to get all the names of the methods' declaration and all the names of the methods being invoked, but I want to know which method call which methods. For example, I want to see that method m1 calls methods mA and mB, while method m2 calls methods mC and mD, etc.

[EDIT 11/9/2011 IDB, transcribing newbie's extended comment back in the body of the original question. I hope I have transcribed it correctly. I hope the author comes back and revises as necessary]:

My problem seems to be that (Eclipse's) MethodDeclaration api doesn't have a GetInvokedMethodName function to call. Here is my code:

 public class MethodVisitor extends ASTVisitor { 

         List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();

         @Override public boolean visit(MethodDeclaration node) { 
             methods.add(node); 
             return super.visit(node); } 

         public List<MethodDeclaration> getMethods() 
             { return methods; }

         List<MethodInvocation> methods1 = new ArrayList<MethodInvocation>();

         @Override public boolean visit(MethodInvocation node)
             { methods1.add(node); 
               return super.visit(node); } 

        public List<MethodInvocation> getMethods1() 
             { return methods1; } 
        } 

    ...

    for (MethodDeclaration method : visitor .getMethods()) 
        { System.out.println("Method name: " + method.getName() 
                            + " Return type: " + method.getReturnType2() 
                            + " Is constructor: " + method.isConstructor()
                            + " Method invoked: " + ASTNode.METHOD_INVOCATION );
           ); }

    for (MethodInvocation method1 : visitor .getMethods1())
           { System.out.println("Method name invoked: " + method1.getName() ); }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情深已缘浅 2024-12-21 07:31:34

我也有同样的问题。这是我的解决方案:

final HashMap<MethodDeclaration, ArrayList<MethodInvocation>> invocationsForMethods =
    new HashMap<MethodDeclaration, ArrayList<MethodInvocation>>();

        CompilationUnit cu = (CompilationUnit) ap.createAST(null);
        cu.accept(new ASTVisitor() {

            private MethodDeclaration activeMethod;

            @Override
            public boolean visit(MethodDeclaration node) {
                activeMethod = node;
                return super.visit(node);
            }

            @Override
            public boolean visit(MethodInvocation node) {
                if (invocationsForMethods.get(activeMethod) == null) {
                    invocationsForMethods.put(activeMethod, new ArrayList<MethodInvocation>());
                }
                invocationsForMethods.get(activeMethod).add(node);
                return super.visit(node);
            }

        });

现在,我们可以要求 invokingsForMethods.keySet() 获取所使用的 ASTinvokingsForMethods.get( key) 返回作为键给出的声明的所有方法调用。

I had the same problem. This was my solution to it:

final HashMap<MethodDeclaration, ArrayList<MethodInvocation>> invocationsForMethods =
    new HashMap<MethodDeclaration, ArrayList<MethodInvocation>>();

        CompilationUnit cu = (CompilationUnit) ap.createAST(null);
        cu.accept(new ASTVisitor() {

            private MethodDeclaration activeMethod;

            @Override
            public boolean visit(MethodDeclaration node) {
                activeMethod = node;
                return super.visit(node);
            }

            @Override
            public boolean visit(MethodInvocation node) {
                if (invocationsForMethods.get(activeMethod) == null) {
                    invocationsForMethods.put(activeMethod, new ArrayList<MethodInvocation>());
                }
                invocationsForMethods.get(activeMethod).add(node);
                return super.visit(node);
            }

        });

Now, one can ask the invocationsForMethods.keySet() to get all the method declarations for the used AST and invocationsForMethods.get(key) returns all method invocations for the declaration given as a key.

美男兮 2024-12-21 07:31:34

如果您想知道 m1 调用了哪个特定方法 mB(在您庞大的类数组中所有名为“mB”的方法中),您需要的不仅仅是 AST。您需要一个完整的符号表,将每个符号使用绑定到与其匹配的可能定义。

计算这样一个符号表的过程对于许多语言来说都很困难,对于 Java 来说也非常困难(但不像 C++ 那么糟糕)。必须有人对如何在(本地)作用域、继承、重载、隐式转换等情况下查找标识符的规则进行编码,并且 Java 参考手册用了很大一部分内容试图解释这一点。您不想自己做这件事。

您真正需要的是一个完整的 Java 前端,对于您想要检查的每个方法都有 AST 和相应的符号表。我想,你可以从(Sun?)Java 编译器的接口(我个人不知道如何做到这一点)、Jikes 编译器、Eclipse Java AST(?)模块以及诸如此类的工具中获得这一点。作为我们的 Java 前端。另一种方法是处理类文件,其中包含 JVM 形式的方法调用,其优点是 JVM 指令都是利用符号表构建的。

如果您想计算 m1 调用 mA 调用 mQ 调用 .... mZ,您需要一个愿意立即读取整个源代码库的工具。编译器不会为您执行此操作,但您可以使用 Eclipse 或我们的前端来执行此操作。

If you want to know which specific method mB (of all the ones named "mB" throughout your vast array of classes) is invoked by m1, you need more than just the AST. You need a full symbol table, that binds each symbol use to the possible definitions that match it.

The process of computing such a symbol table is difficult for many languages and very hard for Java (but not nearly as bad as it is for C++). Somebody has to encode the rules of how an identifier is looked up in the face of (local) scopes, inheritance, overloads, implied casts, etc, and the Java reference manual devotes a significant portion of its content trying to explain that. You don't want to have to do this yourself.

What you really need is a full Java front end, that has both ASTs and the corresponding symbol tables, for each method you want to inspect. You can get this, I think, from interfaces to the (Sun?) Java compiler (I don't personally know how to do this), from the Jikes compiler, from the Eclipse Java AST (?) module, and from tools such as our Java Front End. Another approach is to process class files, which contain the method calls in JVM form, with the advavntage that the JVM instructions all have built with the benefit of a symbol table.

If you want to compute m1 calls mA calls mQ calls .... mZ, you need a tool that is willing to read in the entire source code base at once. The compilers won't do that for you, but you can use Eclipse or our front end to do that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文