2010-10-27 2 views
3

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

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

Любая помощь была бы действительно оценена! Благодаря!

+0

Из любопытства, в чем ваш прецедент? – lhballoti

+0

Мне нужно сделать статический анализ исходного кода: мне нужно найти все вызовы методов определенного класса службы для выполнения проверки подлинности интерфейса. – Peter

ответ

7

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

можно использовать:

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

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


Для javaparser: Read this page, расширить 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: прочитать this tutorial page начать

+0

Есть ли API для javaparser где-нибудь? Я не мог найти его. Я бы предположил, что VoidVisitorAdapter предназначен только для методов, которые возвращают «void»?Мне нужно более общее решение, так как методы могут иметь какой-либо тип возврата. – Peter

+0

нет, VoidVisitorAdapter просто означает, что вам не нужны дополнительные параметры при использовании посетителя. Апи для javaparser? Вы, вероятно, имеете в виду описание api (javadocs)? Нет, я боюсь, что нет, и это скалистая дорога. –

+0

Это API для javaparser http://static.javadoc.io/com.github.javaparser/javaparser-core/2.3.0/overview-summary.html –

0

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

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