Open
Description
when looking for super type of a type we try to resolve the canonical name of that type.
the issue is that we are trying to resolve wildcard imports before checking in the current package first.
example of the issue:
package org.jboss.forge.grammar.java;
import java.net.http.*;
import java.util.*;
public class MockWildcardClass {
public List<String> getList(){
return new ArrayList<>();
}
public HttpRequest getHttpRequest(){
return new HttpRequest();
}
}
and in the same package:
package org.jboss.forge.grammar.java;
public class HttpRequest {
private String fakeField;
public String getFakeField() {
return fakeField;
}
public <T extends HttpRequest> T setFakeField(String fakeField) {
this.fakeField = fakeField;
return (T) this;
}
}
roaster resolves HttpRequest
as java.net.http.HttpRequest
even though it should be org.jboss.forge.grammar.java.HttpRequest
Metadata
Assignees
Labels
No labels
Activity
asafbennatan commentedon Dec 22, 2021
seems like this will be hard to solve , as far as i see roaster parses a single file this means we lose context of other files within the same package - this is also why the resolving of wildcard imports is incorrect since it tries to find the class by using ContextualClassLoader.loadClass. but this will only work for classes which are also in the runtime environment....
asafbennatan commentedon Dec 22, 2021
here is the solution i have implemented on my fork of jboss:
added an interface:
and
now JavaType implements ContextCapable.
and in resolveType we do:
wildcard imports check is later.
the usage of the library is done via:
should i create a pull request?
Fixes forge#223 - tries to resolve classes in current package before …
gastaldi commentedon Dec 22, 2021
@asafbennatan If I understand it correctly, this won't solve the problem because in your
ParsingContext
implementation you're storing in a Map every .java file that was already parsed previously, therefore you can get a different result if you forget to add the imported type to the Map.We had a similar use case for resolving types out of wildcard imports, which is why we introduced
org.jboss.forge.roaster.spi.WildcardImportResolver
SPI using the ServiceLoader feature. Can you check if that could work for you?asafbennatan commentedon Dec 22, 2021
@gastaldi my idea is that once you create the parsing context you should only parse using the parsingContext.parse - which parses the source and adds it to its internal map.
as for org.jboss.forge.roaster.spi.WildcardImportResolver - how should i test it with the service location feature ? - if i understand correctly you mean i have to implement WildcardImportResolver which will find the correct implementation? - this means in that implementation i will first check if that source was already loaded before ?
gastaldi commentedon Dec 22, 2021
I think the
Roaster.parse
method needs a context object parameter that can provide implementations ofWildcardImportResolver
s and other features. For example, you could have something like:gastaldi commentedon Dec 22, 2021
I think you'll need to resolve the current project directory sources and check if the type exists in the path.
asafbennatan commentedon Dec 22, 2021
hmm , will that work ? since i will need to parse the source code to actually know it contains the class I'm looking for (i think we cant just rely on the file name -right ? ) this means every time we run the resolver it will parse it - unless we cache the result .
IMHO its quite a lot of code for what should be the default implementation (because that's how java does it when it searches for the class) - IMHO accomplishing it should be easy- perhaps if ProjectImportResolver was provided by roaster - but this solution has the problem of working only for files and directory (and not for strings and input streams).
asafbennatan commentedon Dec 22, 2021
how about :
and Roaster.parse will be incharge of adding the parsed source into the parsingContext
gastaldi commentedon Dec 22, 2021
Right, now we'll need to define what's in the
ParsingContext
and how would it be used during the parsinggastaldi commentedon Dec 22, 2021
I like the idea of having a
ParsingContext
and building it (like addingImportResolvers
for example). That would provide a neat abstraction instead of having a default implementation storing parsed sources in memory. WDYT?asafbennatan commentedon Dec 22, 2021
@gastaldi
in general yes i think its a good idea.
you think we should use import resolvers to solve the 'same package' issue ?
i mean it would be straight forward if the javaSourceImpl would search for classes in the required order:
1..x. import rules which i dont remember
x+1.explicit imports(aka com.x.y.z.ClassName)
x+2.same package classes
x+3.wildcard import.
where if we are using import resolvers some1 looking the code of javaSourceImpl will see:
1..x. import rules which i dont remember
x+1.explicit imports(aka com.x.y.z.ClassName)
x+2.wildcard import. (containing the special resolver to fix the same package issue)
in addition there might be other locations where you would like to use context from other parsing instances ? ( though im not sure if there are actual or not ).
other then that - seems like a valid solution.
asafbennatan commentedon Dec 22, 2021
also keep in mind that even we if are solving it with import resolvers - the implementation for the import resolver will have to keep track of the previously parsed classes anyway
asafbennatan commentedon Dec 25, 2021
@gastaldi noted another issue with type resolution - java.lang classes are being resolved out of order - if there's specific import of my.package.Object or if in the same package it should have priority over java.lang.Object
Fixes forge#223 - tries to resolve classes in current package before …