2010-10-27 54 views
3

我需要解析某些方法调用调用,包括某些Java类的整个签名,例如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); 

任何帮助将非常感激!谢谢!

+0

出于好奇,你的用例是什么? – lhballoti 2010-10-27 13:24:18

+0

我需要做一个静态的源代码分析:我需要找到某个服务类的所有方法调用来做一些接口合约验证。 – Peter 2010-10-27 13:39:57

回答

7

不要使用正则表达式!使用了解java的工具。

选其一:

  • 源代码解析器(例如javaparser
  • 字节代码分析(例如ASM
  • 一个方面(AspectJ

在这两种源解析器和ASM,您将编写一个访问器来扫描方法调用。


对于JavaParser类:阅读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); 
} 

这里的问题是,你只有对象名称,而不是对象类型,所以你还必须保留一个局部变量/字段的Map来输入,这就是事情变得混乱的地方。毕竟,ASM可能是更容易的选择。


对于ASM:读this tutorial page上手

+0

是否有javaparser的某个API?我找不到。我会假设VoidVisitorAdapter仅适用于返回“void”的方法?我需要更通用的解决方案,因为这些方法可能有任何返回类型。 – Peter 2010-10-27 13:42:29

+0

不,VoidVisitorAdapter只是意味着您在使用访问者时不需要额外的参数。 javaparser的API?你可能是指api描述(javadocs)?不,我不害怕,这是一条崎岖的道路。 – 2010-10-27 13:45:11

+0

这是javaparser的API http://static.javadoc.io/com.github.javaparser/javaparser-core/2.3.0/overview-summary.html – 2016-01-10 19:51:27

0

现实,你无法解析一个典型的编程的langauge像Java正则表达式;你需要一个完整的解析器。在你的情况下,你需要一个解析器,它能够解析语言的任意子字符串(在这种情况下,函数调用非终止符),而那些更难找到。

在您决定致电之前,您也没有说明您打算如何查找(并划定)感兴趣的电话。您可能需要Java符号表数据才能选择所需的方法名称;另外, 你怎么知道“someService”解决了你关心的实际服务类,而不仅仅是一些看起来是正确名称的任意类?