How to get the final package name?

I have a code

private static class MyVisitor extends VoidVisitorAdapter<Object> { @Override public void visit(MethodCallExpr exp, Object arg) { System.out.println("Scope: " + exp.getScope()); System.out.println("Method: " + exp.getName()); if(exp.getArgs() != null) for(Expression e : exp.getArgs()) { System.out.println("\tArgument: " + e.toString()); } System.out.println(); } } 

AND

 CompilationUnit cu = JavaParser.parse(new File("Test.java")); for(TypeDeclaration type : cu.getTypes()) { for(BodyDeclaration dec : type.getMembers()) { if(dec instanceof MethodDeclaration) { MethodDeclaration mdec = (MethodDeclaration) dec; BlockStmt block = mdec.getBody(); for(Statement stmt : block.getStmts()) { MyVisitor visitor = new MyVisitor(); s.accept(visitor, null); } } } } 

I have two problems:

  • How to convert an expression to an expression? I want to check that method call. I tried to check that they are incompatible types: if(stmt instanceof MethodCallExp) but got an error. I have entered the code that I am using now. Is this the only way to check?
  • System.out.println("Scope: " + exp.getScope()); the name of the object / package / package + class will be displayed. But how to get its type? For example, for the code System.out.println("Hello world"); Must be issued

Type: java.io.PrintStream

+5
source share
2 answers
  • There is no 1: 1 relationship between statements and expressions. For instance. ExpressionStmt contains only one expression, but WhileStmt contains an Expression condition and a body containing another expression.
  • Type information contained in the FieldAccessExpr field attribute returned by the call to getScope (). JavaParser doesn't seem to provide an easy way to get a type. Using the Node hierarchy and their types, you can use the appropriate Reflection classes to achieve your goal. For your example, this would mean finding the top scope (the type will be NameExpr) and getting a class object (recognizing that System is short for java.lang.System), for the next Node (type will be FieldAccessExpr) you will get a Class Field and then can get the type :
     Class.forName("java.lang.System").getField("out").getType(); 
    In the above code example, you pass the visitor to each statement in the body of the method. If you create a visitor outside the cycle, he will be able to remember the information specified in previous statements. Thus, you can add a field to the visitor to store variable declarations:
     final HashMap varNameToType = new HashMap(); 
    You can store the variable declarations like below. When you get to a method call, you can use the scope to try and get the type via the map. If the map doesn't contain the Type, you may need to use Reflection, since the variable may be part of the JDK classes. I'm not suggesting that this covers all cases. Eg when you access a field of your parent class, you wouldn't have any information about that field at your position in the code - you may need to look at different compilation units for that.
 @Override public void visit( final VariableDeclarationExpr n, final Object arg) { final Type varType = n.getType(); n.getVars().forEach(vd -> varNameToType.put(vd.getId().getName(),varType) ); } 
0
source

If you don’t need to embed JavaParser , you may be able to solve this in the way the Android JavaParser tools do. EcjParserTest.java . He uses Lombok under the hood.

On line 380 he compares the output in the test, similar to the one you want [ExpressionStatement], type: void, resolved method: println java.io.PrintStream .

I didn't have a deeper look, but it looks like a promising starting point

0
source

All Articles