Синтаксический анализатор вызова метода Java? - PullRequest
3 голосов
/ 27 октября 2010

Мне нужно разобрать некоторые вызовы вызова метода, включая всю сигнатуру, из некоторых классов Java, например,

public class MyClass {
    public void myMthod() {
        // ... some code here
        result = someInstance.someOtherMethod(param1, param2);
        // ... some other code here
    }
}

В результате я хотел бы получить что-то вроде:

serviceName = someInstance
methodName = someOtherMethod
arguments = {
   argument = java.lang.String,
   argument = boolean
}
result = java.lang.Long

Каков был бы самый быстрый способ достичь этого?Я думал об использовании парсера RegEx.Проблема в том, что существует несколько шаблонов, например,

a)
result = someInstance.someOtherMethod(getSomething(), param);

b)
result = 
    getSomeInstance().someOtherMethod(param);

c)
result = getSomeInstance()
            .someOtherMethod(
                    getSomethingElse(), null, param);

. Любая помощь будет принята с благодарностью!Спасибо!

Ответы [ 2 ]

7 голосов
/ 27 октября 2010

Не используйте регулярные выражения!Используйте инструменты, которые понимают Java.

Используйте либо:

  • Анализатор исходного кода (например, javaparser )
  • Анализ байтового кода (например, ASM )
  • Аспект ( AspectJ )

Как в анализаторе исходного кода, так и в ASM вы напишите посетитель, который сканирует вызовы методов.


Для javaparser: прочитайте эту страницу , расширьте VoidVisitorAdapter и переопределите

public void visit(MethodCallExpr n, A arg)

Пример кода:

public static void main(final String[] args) throws Exception{
    parseCompilationUnit(new File("src/main/java/foo/bar/Phleem.java"));
}

public static void parseCompilationUnit(final File sourceFile)
    throws ParseException, IOException{
    final CompilationUnit cu = JavaParser.parse(sourceFile);
    cu.accept(new VoidVisitorAdapter<Void>(){

        @Override
        public void visit(final MethodCallExpr n, final Void arg){
            System.out.println(n);
            super.visit(n, arg);
        }
    }, null);
}

Проблема здесь в том, что у вас есть только имена объектов, а не типы объектов, поэтому вам также придется сохранять локальную Карту переменной / поля для ввода, и именно здесь все становится беспорядочно.Возможно, ASM - более легкий выбор, в конце концов.


Для ASM: прочитайте эту страницу руководства , чтобы начать

0 голосов
/ 27 октября 2010

Реально вы не можете разобрать типичный язык программирования, такой как Java, с регулярными выражениями; вам нужен полный парсер. В вашем случае вам нужен синтаксический анализатор, который способен анализировать произвольные подстроки (в данном случае, нетерминалы вызова функций) языка, и их гораздо сложнее найти.

Вы также не сказали, как намеревались найти (и разграничить) интересующие вас вызовы, прежде чем решили позвонить им. Вероятно, вам понадобятся данные таблицы символов Java, чтобы просто выбрать нужные имена методов; oherwise, как вы узнаете, что "someService" разрешает фактический класс обслуживания, который вас интересует, а не просто какой-то произвольный класс, имеющий случайное имя?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...