user3181223
user3181223

Reputation:

how get the fully qualified name of the java class

I have a class like below.

public class Login {
    private Keyword browser;
    private String page;
}

Keyword is a class in different package. I want to get the fully qualified name of the class Keyword while parsing the Login class using javaparser.

Upvotes: 4

Views: 6237

Answers (7)

Simon Baars
Simon Baars

Reputation: 2309

You can use the JavaParser Symbol Solver:

<dependency>
    <groupId>com.github.javaparser</groupId>
    <artifactId>javaparser-symbol-solver-core</artifactId>
    <version>3.14.5</version>
</dependency>

Then parse the code using the following configuration:

CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), 
                                                     new JavaParserTypeSolver(sourceRoot));
final ParserConfiguration config = new ParserConfiguration()
                .setStoreTokens(true)
                .setSymbolResolver(new JavaSymbolSolver(combinedTypeSolver));
SourceRoot root = new SourceRoot(Paths.get("/path/to/project/"));
root.parse("", config, (Path localPath, Path absolutePath, ParseResult<CompilationUnit> result) -> {
                // Do something with the CompilationUnit
                return Result.DONT_SAVE;
            });

We can now get the fully qualified identifier of any ReferenceType using:

ResolvedType type = referenceType.resolve();
String qualifiedName = type.getQualifiedName();

Upvotes: 5

Simon Baars
Simon Baars

Reputation: 2309

I wrote a method that can get the fully qualified name on basis of a ClassOrInterfaceDeclaration object (latest version of JavaParser):

    private static String getFullyQualifiedName(ClassOrInterfaceDeclaration c2) {
        String name = "";
        ClassOrInterfaceDeclaration parentClass = c2.getParentNode().isPresent() ? getClass(c2.getParentNode().get()): null;
        if(parentClass!=null) {
            name+=getFullyQualifiedName(parentClass)+".";
        } else {
            CompilationUnit u = getCompilationUnit(c2);
            if(u!=null && u.getPackageDeclaration().isPresent()) {
                name+=u.getPackageDeclaration().get().getNameAsString()+".";
            }
        }
        return name+c2.getNameAsString();
    }

    private static ClassOrInterfaceDeclaration getClass(Node n1) {
        while (!(n1 instanceof ClassOrInterfaceDeclaration)) {
            if(n1.getParentNode().isPresent()) {
                n1 = n1.getParentNode().get();
            } else return null;
        }
        return (ClassOrInterfaceDeclaration)n1;
    }

    private static CompilationUnit getCompilationUnit(Node n1) {
        while (!(n1 instanceof CompilationUnit)) {
            if(n1.getParentNode().isPresent()) {
                n1 = n1.getParentNode().get();
            } else return null;
        }
        return (CompilationUnit)n1;
    }

A much simpler version can be used if you obtain the ClassOrInterfaceType of the class:

    private static String getFullyQualifiedName(ClassOrInterfaceType e) {
        String name = "";
        if(e.getScope().isPresent())
            name+=getFullyQualifiedName(e.getScope().get())+".";
        return name+e.getNameAsString();
    }

I hope this is of help to anyone!

Upvotes: 1

Federico Tomassetti
Federico Tomassetti

Reputation: 2268

You cannot do that using JavaParser because JavaParser does not resolve symbols. To resolve the name Keyword to a class you need to do several things: * implements proper scope rules (you need to look for internal classes, then for other classes inside the same file, then to consider imports...) * it depends on the classpath used to compile: changing it the same class could be resolved differently

To do that a symbol resolver should be written: it is not trivial but doable. If you are interested in the subject you can read a post I just wrote How to build a symbol solver for Java, in Clojure. The post contains also a link to the code, freely available on GitHub.

Source: I am a JavaParser contributor

Upvotes: 4

nd.
nd.

Reputation: 8942

JavaParser does not resolve imports (this isn't usually considered its job, anyway). You have to manually step through the import statements and search if the Keyword belongs to them. Keep in mind that Java implicitly does a import java.lang.*, otherwise you won't resolve types such as String.

Spring Roo has a JavaParserUtils class containing a method getJavaType(CompilationUnitServices compilationUnitServices, ClassOrInterfaceDeclaration cid). The class is not designed for usage outside of Roo, but you can use as a template for solving your problem.

Upvotes: 0

Seelenvirtuose
Seelenvirtuose

Reputation: 20658

If you are using the visitors, it seems that you only get the start and end indexes inside the source file for having the type name. That will not get you the fully qualified name.

So you should implement the visit(ImportDeclaration, A) method also in your custom visitor. This method then must store the import declarations, so you can later - when the method visit(FieldDeclaration, A) gets called - refer to the imported packages and assemble the fully qualified name.

Upvotes: 0

user207421
user207421

Reputation: 311023

Nobody so far appears to have read the question, but if you're parsing the source code, either it is in the current package or it is imported by an import statement.

I would have expected a Java parser writer or user to know that.

Upvotes: 1

Robert vd S
Robert vd S

Reputation: 332

this might be a better solution for your problem,

using instance of.

use of "Instance of" in java

Upvotes: -2

Related Questions