Reputation:
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
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
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
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
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
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
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
Reputation: 332
this might be a better solution for your problem,
using instance of.
Upvotes: -2