tags:

views:

48

answers:

2

Hi, I need to parse certain method invocation calls including the whole signature out of some Java classes, e.g.

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

As a result I would like to get something like:

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

What would be the fastest way to achieve this? I was thinking about using a RegEx parser. The problem there is there are several occurence patterns, e.g.

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

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

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

Any help would be really appreciated! Thanks!

+4  A: 

Don't use regex! Use tools that understand java.

Use either:

In both source parser and ASM, you will write a visitor that scans for method invocations.


For javaparser: Read this page, extend VoidVisitorAdapter and override

public void visit(MethodCallExpr n, A arg)

Sample Code:

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

The problem here is that you only have the object names, not the object types, so you will also have to keep a local Map of variable / field to type and that's where things get messy. Perhaps ASM is the easier choice, after all.


For ASM: read this tutorial page to get started

seanizer
Is there an API for javaparser somewhere? I could not find it. I would assume that VoidVisitorAdapter is only for methods which return "void"? I need a more generic solution as the methods could have any kind of return type.
Peter
no, the VoidVisitorAdapter just means that you don't need additional parameters when you are using the visitor. An api for javaparser? You probably mean an api description (javadocs)? No, I'm afraid not, and it's a rocky road.
seanizer
A: 

Realistically you can't parse a typical programming langauge like Java with regular expressions; you need a full parser. In your case, you need a parser that is capable of parsing arbitrary substrings (in this case, function call nonterminals) of the langauge, and those are much harder to find.

You also didn't say how you intended to find (and delimit) the calls of interest, before you decided to call them. You are likely to need Java symbol table data in order to just pick the method names you want; oherwise, how will you know that "someService" resolves the actual service class that you care about, and not just some arbitrary class that happens to have what appears to be the right name?

Ira Baxter