2

I'm trying to code rfc metric (Response for a Class), it counts the Method declarations + Method Calls.

Method declarations works fine, but I got a problem at counting method calls using JavaParser API.

Here is my code:

public class MethodPrinter {

    public static void main(String[] args) throws Exception {
        // creates an input stream for the file to be parsed
        FileInputStream in = new FileInputStream("D://test.java");
        CompilationUnit cu;
        try {
            // parse the file
            cu = JavaParser.parse(in);
        } finally {
            in.close();
        }
        // visit and print the methods names
        MethodVisitor MV =new MethodVisitor();

        cu.accept(new VoidVisitorAdapter<Void>(){
            @Override
            public void visit(final MethodCallExpr n, final Void arg){
                System.out.println("method call :"+n);
                super.visit(n, arg);

            }
        }, null);
    }
}

test.java

package test;
import java.util.*;

public class ClassA 
{
  private int test;
  private ClassB classB = new ClassB();
  public void doSomething(int t){

    System.out.println ( toString());
    int i= doSomethingBasedOnClassBBV(classB.toString());
  }
  protected void doSomethingBasedOnClassB(){
    System.out.println (classB.toString());
  }
}

public class ClassB 
{
  private ClassA classA = new ClassA();
  public void doSomethingBasedOneClassA(){
    System.out.println (classA.toString());
  }

  private String toString(){
    return "classB";
  }
  private String toString(){
    return "classB";
  }
  public void doSomethingBasedOneClassA(){
    System.out.println (classA.toString());
  }
  protected void doSomethingBasedOnClassB(){
    System.out.println (classB.toString());
  }
}

the result of that code:

*method call :System.out.println(toString())

method call :toString()

method call :doSomethingBasedOnClassBBV(classB.toString())

method call :classB.toString()

method call :System.out.println(classB.toString())

method call :classB.toString()

method call :System.out.println(classA.toString())

method call :classA.toString()

method call :System.out.println(classA.toString())

method call :classA.toString()

method call :System.out.println(classB.toString())

method call :classB.toString()*

indeed, that code inspects method calls, but in my case I don't want it to count libraries method calls like System.out.println(toString()), I want it to count only toString().

If you got a better code, or another API to use... any help is welcomed, thank you in advance.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
GSDa
  • 193
  • 2
  • 4
  • 21

1 Answers1

0

You cannot easily resolve your issue using exclusively a parser, because you need to resolve the method call and find out if it is a call to a method part of the standard library.

You can easily do that using JavaSymbolSolver, which is a library created to complement JavaParser. In practice you call:

JavaParserFacade.solveMethodAsUsage(myMethodCallExpr)

And you get back a MethodDeclaration which tells you also the type on which that method was defined. Once you have the type you can look at the package and check if it starts with java or javax and exclude it.

Federico Tomassetti
  • 2,100
  • 1
  • 19
  • 26
  • This a classic example of why Life After Parsing is important when building any kind of static analysis tools. See http://www.semdesigns.com/Products/DMS/LifeAfterParsing.html – Ira Baxter Nov 13 '16 at 19:08