Получение информации о вызове метода из AST - PullRequest
4 голосов
/ 09 ноября 2011

Как я могу получить имена методов, вызываемых в каждом объявлении метода программы с использованием синтаксического анализатора AST (Abstract Syntax Tree)?До сих пор мне удалось получить все имена объявлений методов и все имена вызываемых методов, но я хочу знать, какой метод вызывает какой метод.Например, я хочу видеть, что метод m1 вызывает методы mA и mB, а метод m2 вызывает методы mC и mD и т. Д.

[ПРАВИТЬ 11/9/ 2011 IDB, расшифровав расширенный комментарий новичка в основной части исходного вопроса.Я надеюсь, что я расшифровал это правильно.Я надеюсь, что автор возвращается и пересматривает по мере необходимости]:

Моя проблема в том, что api MethodDeclaration (Eclipse) не имеет функции 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() ); }

Ответы [ 2 ]

3 голосов
/ 23 октября 2012

У меня была такая же проблема.Это было мое решение:

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);
            }

        });

Теперь можно попросить invocationsForMethods.keySet() получить все объявления методов для используемых AST, а invocationsForMethods.get(key) возвращает все вызовы методов для объявления, заданного какключ.

2 голосов
/ 10 ноября 2011

Если вы хотите знать, какой конкретный метод mB (из всех названных «mB» в вашем огромном массиве классов) вызывается m1, вам нужно больше, чем просто AST. Вам нужна полная таблица символов, которая связывает каждое использование символа с возможными определениями, которые ему соответствуют.

Процесс вычисления такой таблицы символов сложен для многих языков и очень сложен для Java (но не так плохо, как для C ++). Кто-то должен кодировать правила поиска идентификатора перед лицом (локальных) областей, наследования, перегрузок, подразумеваемых приведений и т. Д., И справочное руководство по Java посвящает значительную часть своего содержания, пытаясь объяснить это. Вы не хотите делать это самостоятельно.

Что вам действительно нужно, так это полноценный внешний интерфейс Java, который имеет как AST, так и соответствующие таблицы символов для каждого метода, который вы хотите проверить. Я думаю, вы можете получить это из интерфейсов к компилятору Java (Sun?) (Я лично не знаю, как это сделать), из компилятора Jikes, из модуля Eclipse Java AST (?) И из таких инструментов, как как наш интерфейс Java . Другой подход заключается в обработке файлов классов, содержащих вызовы методов в форме JVM, с преимуществом, которое все инструкции JVM создали с помощью таблицы символов.

Если вы хотите вычислить вызовы m1, вызовы mA, вызовы mQ .... mZ, вам нужен инструмент, который готов читать всю базу исходного кода сразу. Компиляторы не сделают этого за вас, но вы можете использовать Eclipse или наш интерфейс для этого.

...