Hello,
i am trying to find the fully qualified name of interface main.MyInterface<E> that is being implemented in class main.MyClass<E>.
package main;
public class MyClass<E> implements MyInterface<E> { }
package main;
public class MyInterface<E> { }
for (ClassOrInterfaceType type : classDeclaration.getImplementedTypes()) {
ResolvedReferenceType rrt = type.resolve(); // exception gets thrown here
if (rrt != null) {
String interfaceName = rrt.getQualifiedName();
// do other stuff with it
}
}
Sadly, this yields me an exception:
Symbol resolution not configured: to configure consider setting a SymbolResolver in the ParserConfiguration
at com.github.javaparser.ast.Node.lambda$getSymbolResolver$5(Node.java:682)
at java.base/java.util.Optional.map(Optional.java:254)
at com.github.javaparser.ast.Node.getSymbolResolver(Node.java:679)
at com.github.javaparser.ast.type.ClassOrInterfaceType.resolve(ClassOrInterfaceType.java:292)
I am setting a SymbolSolver before I start running .resolve():
CombinedTypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver());
// optionally some more external libraries added (required for what I am doing)
CombinedTypeSolver finalTypeSolver = new CombinedTypeSolver(typeSolver);
if (path.endsWith(".jar")) {
finalTypeSolver.add(new JarTypeSolver(path));
} else if (path.endsWith("src")){
finalTypeSolver.add(new JavaParserTypeSolver(path));
}
JavaSymbolSolver symbolSolver = new JavaSymbolSolver(finalTypeSolver);
JavaParser.getStaticConfiguration().setSymbolResolver(symbolSolver);
I also double checked without the generic types and it always yields the same exception. Same issue with extending from classes.
Am I doing something wrong or why does this not work as intended?
I just updated to the 3.7.1 (from 3.6.23) and now the exception is now this:
java.lang.IllegalStateException: No data of this type found. Use containsData to check for this first.
at com.github.javaparser.ast.Node.getData(Node.java:457)
at com.github.javaparser.ast.Node.lambda$getSymbolResolver$5(Node.java:699)
at java.base/java.util.Optional.map(Optional.java:254)
at com.github.javaparser.ast.Node.getSymbolResolver(Node.java:698)
at com.github.javaparser.ast.type.ClassOrInterfaceType.resolve(ClassOrInterfaceType.java:292)
Since this did work before and only started to fail recently, I double checked what I did differently. And it turns out that I previously was using a path to a source folder (JavaParserTypeSolver). Now I am trying to read a JAR file and therefore use the JarTypeSolver, but it does not seem to work with that one. Whats going on here?
So apparently .resolve() is the problem.
The old fashioned way works:
ResolvedType rt = JavaParserFacade.get(typeSolver).convertToUsage(type);
if (rt.isReferenceType()) {
System.out.println(rt.asReferenceType().getQualifiedName());
}
It is still weird that it works when checking raw source files and it does not work when checking a JAR file. Is this intended behaviour?
Maybe @ftomassetti knows.
I am using the com.github.javaparser.utils.SourceZip class to read the JAR file.
Are you setting the symbol solver _before_ parsing?
the problem seems to be that typesolver is not injected in the nodes
Yes, since my file is ruff spaghetti code, I am very confident that I setup the SymbolSolver before reading any of the source code file. The file looks like this:
```
TypeSolver combinedTypeSolver = null;
if (pathToJar.endsWith(".jar")) {
try {
combinedTypeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JarTypeSolver(pathToJar));
} catch (IOException e) {
e.printStackTrace();
return "Something went wrong while trying to read your JAR file!";
}
} else if (pathToJar.endsWith("src")){
combinedTypeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), new JavaParserTypeSolver(pathToJar));
}
JavaSymbolSolver symbolSolver = new JavaSymbolSolver(combinedTypeSolver);
JavaParser.getStaticConfiguration().setSymbolResolver(symbolSolver);
Map<String, CompilationUnit> files = new HashMap<>();
if (pathToJar.endsWith(".jar")) {
SourceZip sourceZip = new SourceZip(Paths.get(pathToJar), new ParserConfiguration().setTabSize(4));
List<Pair<Path, ParseResult<CompilationUnit>>> cuList;
try {
cuList = sourceZip.parse();
} catch (IOException e) {
e.printStackTrace();
return "";
}
for (Pair<Path, ParseResult<CompilationUnit>> pair : cuList) {
Optional<CompilationUnit> optional = pair.b.getResult();
if (optional.isPresent()) {
Optional<ClassOrInterfaceDeclaration> optionalNode = optional.get().findFirst(ClassOrInterfaceDeclaration.class);
if (optionalNode.isPresent()) {
String name = QualifiedNameGenerator.getFullyQualifiedName(optionalNode.get());
files.put(name, optional.get());
}
}
}
} else {
if (!pathToJar.endsWith("src")) {
pathToJar = pathToJar + File.separator + "src";
}
if (!Files.exists(Paths.get(pathToJar))) {
return "No folder '" + pathToJar + "' found!";
}
if (!Files.isDirectory(Paths.get(pathToJar))) {
return "The path '" + pathToJar + "' is not a folder!";
}
List<File> sourceFiles = new ArrayList<>();
findSourceFiles(pathToJar, sourceFiles);
for (File file : sourceFiles) {
CompilationUnit cu;
try {
cu = JavaParser.parse(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
return "Unable to parse file! Exiting...";
}
Optional<ClassOrInterfaceDeclaration> optionalNode = cu.findFirst(ClassOrInterfaceDeclaration.class);
if (optionalNode.isPresent()) {
String name = QualifiedNameGenerator.getFullyQualifiedName(optionalNode.get());
files.put(name, cu);
}
}
}
// MORE CODE INBETWEEN
HashMap<String, ArrayList<String>> classAndTheirInterfaces = new HashMap<>();
for (String key : files.keySet()) {
CompilationUnit cu = files.get(key);
for (ClassOrInterfaceDeclaration c : cu.findAll(ClassOrInterfaceDeclaration.class)) {
if (c.getImplementedTypes().size() > 0) {
ArrayList<String> interfacesOfThisClass = new ArrayList<>();
for (ClassOrInterfaceType type : c.getImplementedTypes()) {
ResolvedReferenceType rrt = type.resolve(); // THIS FAILS
ResolvedType rt = JavaParserFacade.get(combinedTypeSolver).convertToUsage(type); // THIS WORKS
if (rt.isReferenceType()) {
interfacesOfThisClass.add("\"" + rt.asReferenceType().getQualifiedName() + "\"");
}
}
classAndTheirInterfaces.put(QualifiedNameGenerator.getFullyQualifiedName(c), interfacesOfThisClass);
}
}
}```
I should really get into streams. The code is embarrassing :D
I probably should explain it a little bit, so that it might be more helpful when it comes to help figure out what went wrong.
The input is a path to a folder containing source files or a JAR file.
The first part is where I define the TypeSolver by adding the path to the JAR file or folder.
Then I have two ways to read the source files. One for the folder, where I just scan it for .java files and parse them one-by-one with JavaParser.parse(File). And one for the JAR file, where I use the SourceZip class to read the .java entires.
I save the ComputationUnits of each file in a Map for later use where the key is the qualified name of the file/first class in the file.
Once the source files are read and ASTs have been generated, I try to find the Interface class that is being implemented on another class. If I use ResolvedType rt = JavaParserFacade.get(combinedTypeSolver).convertToUsage(type); it always works.
If I use ResolvedReferenceType rrt = type.resolve(); it throws me the exception. But only if I read the source files from a JAR file with SourceZip.
So the issue is either SourceZip or JarTypeSolver.
I know this is a complex issue (and I probably could have made a better job at preseting it), but did you have the time to read into it yet? @ftomassetti
Sorry, I'm busy trying to get JDK12 support in, and @ftomassetti is drowning in work.
Can it be that SourceZip gets a configuration where you don't set the symbol solver?
No problem.
Ah, indeed. SourceZip has its own ParserConfiguration and requires the TypeSolver to be set. I thought it would always just take the statically set TypeSolver, but I guess SourceZip is older than the newest .resolve() functionality.
new SourceZip(Paths.get(path), new ParserConfiguration().setSymbolResolver(symbolSolver));
Nah, the static configuration is for the static methods. Every instance gets its own configuration.
It's kind of confusing, so the plan is to remove all the static methods soon.
I have the same problem, except I am not using SourceZip. Below is the method that sets the symbol resolver:
private void setSymbolSolver() {
final String sourceDirectory = getAnnotatedClassSourceInformation().getSourceDirectory();
final ReflectionTypeSolver standardLibraryTypeSolver = new ReflectionTypeSolver();
final JavaParserTypeSolver processedProjectTypeSolver = new JavaParserTypeSolver(sourceDirectory);
final CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(
standardLibraryTypeSolver,
processedProjectTypeSolver
);
final ClassLoader processedProjectClassLoader = getClass().getClassLoader();
final URLClassLoader processedProjectURLClassLoader = (URLClassLoader) processedProjectClassLoader;
final URL[] processedProjectDependencyLocations = processedProjectURLClassLoader.getURLs();
try {
for (final URL processedProjectDependencyLocation : processedProjectDependencyLocations) {
final Path dependencyLocationPath = Paths.get(processedProjectDependencyLocation.toURI());
if (dependencyLocationPath.endsWith(".jar")) {
final JavaParserTypeSolver dependencyTypeSolver = new JavaParserTypeSolver(dependencyLocationPath);
combinedTypeSolver.add(dependencyTypeSolver);
}
}
}
catch (final URISyntaxException e) {
throw new RuntimeException(e);
}
final JavaSymbolSolver javaSymbolSolver = new JavaSymbolSolver(combinedTypeSolver);
JavaParser.getStaticConfiguration().setSymbolResolver(javaSymbolSolver);
}
and here is the calling code:
@Override
public Visitable visit(
final ClassOrInterfaceType classOrInterfaceType,
final PrimitiveTypesCombination primitiveTypesCombination
) {
super.visit(classOrInterfaceType, primitiveTypesCombination);
ResolvedReferenceType resolvedClassOrInterfaceType = classOrInterfaceType.resolve();
...
}
I get the following exception:
Caused by: java.lang.IllegalStateException: No data of this type found. Use containsData to check for this first.
@TheeNinja the crucial part is how you do the parsing, which is not in your report.
All JavaParser.parse... methods use the static configuration.
new Javaparser(config).parse(..,..,..) uses the configuration from config.
The error simply means that the solver is not set in the configuration the parser is using.
@TheeNinja the crucial part is how you do the parsing, which is not in your report.
AllJavaParser.parse...methods use the static configuration.
new Javaparser(config).parse(..,..,..)uses the configuration from config.The error simply means that the solver is not set in the configuration the parser is using.
I am getting my "generic" compilation unit through final CompilationUnit genericClassCompilationUnit = JavaParser.parse(annotatedClassSourceCode);. I then get my "specialized" compilation unit through cloning the generic compilation unit (this will happen multiple times). final CompilationUnit specializedClassCompilationUnit = genericClassCompilationUnit.clone(); I then perform all the visiting on the specializedClassCompilationUnit. setSymbolResolver() is called before the generic compilation unit is parsed. Does cloning throw away the resolutions?
I do think it does not clone all data (the CloneVisitor has the answer.) This will need some thinking...
Oh yeah! Let's fix this one.
Hi everybody,
I am having the same problem to solve symbols with sources that are in jar file. I am using the javaparser/symbolsolver v.3.13.3 and the problem still continues. When the program executes the ".resolve()", it yelds a UnsolvedSymbolException, even loading the sources previously using JarTypeSolver.
Does anybody already have a solution?
Well, the solution for me was to set the SymbolSolver on the ParserConfiguration and pass it on to SourceZip (or another instance that consumes ParserConfiguration). Did you set it?
new SourceZip(Paths.get(path), new ParserConfiguration().setSymbolResolver(symbolSolver));
Sorry, but I think that I did not understand exactly how the SourceZip works.
Well, below there is a source code snippet:
CombinedTypeSolver typeSolver = new CombinedTypeSolver();
typeSolver.add(new ReflectionTypeSolver(false));
typeSolver.add(new JavaParserTypeSolver(new File(SOURCE_PATH)));
typeSolver.add(new JarTypeSolver(jarSourceFile));
JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);
StaticJavaParser.getConfiguration().setSymbolResolver(symbolSolver);
Where should I put the mentioned SourceZip code snippet in this code and how I use it later to ".resolve()"?
SourceZip is a class that allows you to read in all the source files from a JAR or ZIP file. I used it in my program to read in the source code. You probably use another class to help you parse the source code. So you have to provide the Configuration to that instead, not StaticJavaParser.
As far as I understood: The ParserConfiguration object gets passed into each Node, which then gets used by .resolve(). If you set the ParserConfiguration as static, then it probably wont be injected in your Node objects. Thus, you have to provide your SymbolSolver to the ParserConfiguration of the Class you use to parse your files. I dont know how you read in the source code to parse it, so you might want to provide that part.
I have use the JarTypeSolver class to read source codes inside jar files. If I am not mistaken, I have worked with this class and it has worked fine - using also a static parser - but it is not working now. The code below shows the part that I need use the ".resolve()" to solve the method called to get information about its package, class, etc.
new VoidVisitorAdapter<Object>() {
@Override
public void visit(MethodCallExpr methodCall, Object obj) {
super.visit(methodCall, obj);
// Identify the host class (source)
Node node = (Node) methodCall.getParentNode().get();
while(!(node instanceof ClassOrInterfaceDeclaration) &&
!(node instanceof EnumDeclaration)) {
node = node.getParentNode().get();
}
ClassInfo cSource = null;
if(node instanceof ClassOrInterfaceDeclaration) // its a class
cSource = new ClassInfo((ClassOrInterfaceDeclaration) node);
else // is a enum
cSource = new ClassInfo((EnumDeclaration) node);
//
// Identify the method called
ResolvedMethodDeclaration resmd = null;
// rejecting method call that can not have a ResolvedMethodDeclaration instance
try {
resmd = methodCall.resolve();
} catch (UnsolvedSymbolException e) {
if(log) toLog("WARNING: rejecting method call "+methodCall.getName()+" - UnsolvedSymbolException: "+e.getMessage());
}
...
... (etc.)
...
}
Are you using JavaParser.parse(...) on the source code you are parsing? How do you parse your code is important, because you have to provide that class the Configuration. Doesnt matter which TypeSolver you use if you put it on the wrong class/instance.
Sorry, I forgot to tell you how I call the parser in the code. See it now.
new VoidVisitorAdapter<Object>() {
@Override
public void visit(MethodCallExpr methodCall, Object obj) {
super.visit(methodCall, obj);
// Identify the host class (source)
Node node = (Node) methodCall.getParentNode().get();
while(!(node instanceof ClassOrInterfaceDeclaration) &&
!(node instanceof EnumDeclaration)) {
node = node.getParentNode().get();
}
ClassInfo cSource = null;
if(node instanceof ClassOrInterfaceDeclaration) // its a class
cSource = new ClassInfo((ClassOrInterfaceDeclaration) node);
else // is a enum
cSource = new ClassInfo((EnumDeclaration) node);
//
// Identify the method called
ResolvedMethodDeclaration resmd = null;
// rejecting method call that can not have a ResolvedMethodDeclaration instance
try {
resmd = methodCall.resolve();
} catch (UnsolvedSymbolException e) {
if(log) toLog("WARNING: rejecting method call "+methodCall.getName()+" - UnsolvedSymbolException: "+e.getMessage());
}
...
... (etc.)
...
}
}.visit(StaticJavaParser.parse(new File(completeFileName)), null);
Did you try StaticJavaParser.setConfiguration(ParserConfiguration parserConfiguration) yet? Instead of doing getConfiguration() =
Yes. Unfortunately it did not work.
Did you try
StaticJavaParser.setConfiguration(ParserConfiguration parserConfiguration)yet? Instead of doinggetConfiguration() =
Hm, then I have no idea. Maybe the developers can help you with this one. Maybe create a new issue since this seems to be a bit different from mine. And mine got already solved. Since then they changed some stuff, so maybe something broke along the way.
Ok, thank you very much.
Hm, then I have no idea. Maybe the developers can help you with this one. Maybe create a new issue since this seems to be a bit different from mine. And mine got already solved. Since then they changed some stuff, so maybe something broke along the way.
No Problem :)
I also meet this error。I resolved this problem finally。
because code has a complie error, when i fix this error, is work well。
if anyone meet this problem,review that