[JEP 511] Module Import Declarations#4905
Conversation
… and ClassLoaderTypeSolver
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #4905 +/- ##
===============================================
+ Coverage 58.368% 58.394% +0.026%
- Complexity 2534 2555 +21
===============================================
Files 681 681
Lines 39302 39490 +188
Branches 7134 7163 +29
===============================================
+ Hits 22940 23060 +120
- Misses 13448 13493 +45
- Partials 2914 2937 +23
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
|
I realised while reviewing #4902 that I forgot the validator and printer support for this. I'm closing this for now and will re-open it once that's done. |
| continue; | ||
| } | ||
| try { | ||
| /* This code is equivalent to the snippet below, but is done with reflection to maintain compatibility |
There was a problem hiding this comment.
Can you isolate this code in a class that could be called, for example, ModuleLayerHelper?
| @@ -68,17 +121,24 @@ protected boolean filterName(String name) { | |||
| @Override | |||
| public SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveTypeInModule(String qualifiedModuleName, String simpleTypeName) { | |||
There was a problem hiding this comment.
Is it really necessary to create a new method to handle this particular case?
There was a problem hiding this comment.
A new method may not be the only solution, but we do need to keep track of the fact that we want to solve the type in a module, as well as the name of the module. This is not information that is currently tracked with the regular solveType methods. Since we know exactly when solving a type in a module is needed (that only being when handling module imports), I think a separate method is a much cleaner approach than trying to modify the already complex solveType structure/API to record the information we need, while also greatly reducing the risk of introducing new bugs into existing resolution logic.
There was a problem hiding this comment.
A new method may not be the only solution, but we do need to keep track of the fact that we want to solve the type in a module, as well as the name of the module. This is not information that is currently tracked with the regular
solveTypemethods. Since we know exactly when solving a type in a module is needed (that only being when handling module imports), I think a separate method is a much cleaner approach than trying to modify the already complexsolveTypestructure/API to record the information we need, while also greatly reducing the risk of introducing new bugs into existing resolution logic.
I do understand the concerns raised. I was thinking of scanning all modules for the class declaration, but that wouldn't be very efficient.
|
|
||
| HashSet<Object> moduleLayers = new HashSet<>(); | ||
| try { | ||
| /* This code is equivalent to the snippet below, but is done with reflection to maintain compatibility with |
There was a problem hiding this comment.
Probably to be declared in a ‘ModuleLayerHelper’ class.
|
|
||
| return SymbolReference.unsolved(); | ||
| } | ||
|
|
There was a problem hiding this comment.
To make the PRs easier to read, would it be possible to isolate the JP test cases in a single commit, and also isolate the code generated by JP, which is specific to printers, the features of the symbol resolver, and the tests which are specific to symbol resolvers?
| } | ||
| } | ||
|
|
||
| private void registerModuleInfo() { |
There was a problem hiding this comment.
This code could be externalised into a helper class until the Javassist project offers this functionality.
Perhaps we could either report an issue or make a contribution to the project.
There was a problem hiding this comment.
I think creating an issue is a good idea just to get an idea of whether this is something they would be interested in. The implementation here is very specific to what we need, so a more general approach would require some thought and could lead to some questions about attribute handling in javassist in general, which may be beyond the scope of what they want to do. I'll collect my thoughts on the issue and ask them about it
| * } | ||
| */ | ||
| Set<Object> modulesSet = (Set<Object>) moduleLayer.getClass().getMethod("modules").invoke(moduleLayer); | ||
| Set<Object> modulesSet = (Set<Object>) |
| } | ||
|
|
||
| @Test | ||
| void testJavaModuleImportFromSource() { |
|
|
||
| @BeforeEach | ||
| void setup() throws IOException { | ||
| Path pathToJar = adaptPath("src/test/resources/modules/moduletest/com-github-javaparser-testmodule.jar"); |
There was a problem hiding this comment.
Can you delete the directory "moduletest" from the path?
|
Thank you for this PR. I have a few comments and I have noted that you have other points to consider. |
|
I opened #4910 with the changes requested here. I could not reopen this PR since I force pushed changes |
Fixes #4848
This PR adds parser support for module import statements, as well as support for resolving types from modules.
Changes to ImportDeclaration/CompilationUnit
Constructors and an
addImportmethod with an option to specify whether this is a module import or not (indicated by the value of the newisModulefield in ImportDeclaration) were added. The old versions of these constructors and this method without theisModuleparameter were kept to avoid breaking user code.JarTypeSolver
Javassist does not provide much support for handling modules, so I ended up parsing the module attribute manually. This is a bit cumbersome, but does work and I hope the comments explain what is happening sufficiently well.
ClassLoaderTypeSolver
I couldn't figure out a way to do this without using Java 9+ types and methods, so I used a lot of reflection for the implementation to maintain compatibility with Java 8 (although this will always fail if JavaParser is run with Java 8). I also couldn't figure out a good way to get to a list of modules loaded by a classloader (the mechanisms I could find that looked promising were all JDK-internal or blocked for security reasons). The solution as it is presented here requires users to provide a list of module layers that the typesolver will use to find modules. This is done automatically for the ReflectionTypeSolver.