google / google/compile-testing
[BUG] InMemoryJavaFileManager.uriForJavaFileObject() breaks when supplied with a Locations.ModuleLocationHandler
- Dominant language
- Java
- Stars
- 722
- Forks
- 129
- Avg merge
- 11m
- Merged PRs (30d)
- 4
Description
In `InMemoryJavaFileManager` the method `uriForJavaFileObject()` is defined as such:
private static URI uriForJavaFileObject(Location location, String className, Kind kind) {
return URI.create(
"mem:///" + location.getName() + '/' + className.replace('.', '/') + kind.extension);
}
**EXPECTED:**
This method works for any `Location` object.
**ACTUAL:**
This breaks when using modules.
When the `JavacTask` runs `validate()` on the arguments in `JavacTaskImpl.prepareCompiler()`, if a module has been found, the CLASS_OUTPUT location will be determined by asking the `JavaFileManager` for the location for that module
fm.getLocationForModule(StandardLocation.CLASS_OUTPUT, moduleName)
This will lead to `Locations.OutputLocationHandler.getLocationForModule(moduleName)` being called, which returns a `Location` of type `Locations.ModuleLocationHandler` with the name set to `location.getName() + "[" + name + "]"` eg. `"CLASS_OUTPUT[foo]"` if the module name is "foo".
@Override
Location getLocationForModule(String name) {
if (moduleTable == null) {
moduleTable = new ModuleTable();
}
ModuleLocationHandler l = moduleTable.get(name);
if (l == null) {
Path out = outputDir.resolve(name);
l = new ModuleLocationHandler(this, location.getName() + "[" + name + "]",
name, Collections.singletonList(out), true);
moduleTable.add(l);
}
return l;
}
The `validate()` method will then call `getJavaFileForInput()` using this location, which calls the `InMemoryJavaFileManager.uriForJavaFileObject()` method.
Due to location.getName returning `"CLASS_OUTPUT[foo]"`, URL.create will throw the following exception:
java.lang.IllegalArgumentException: Illegal character in path
It gives index 19, which is the square opening bracket `[` in `mem:///CLASS_OUTPUT[test]/...`.
This makes it not possible to directly use `location.getName()` in the `uriForJavaFileObject()` method for any given `Location` object, without encoding this name in some form, before passing it along to `URL.create()`
**SOLUTION**:
Encode the location name in some way, so that illegal URI characters won't be passed along to the `URL.create()` method.
**VERSIONS USED:**
compile-testing: 0.19
JDK: AZUL-17 version 17.0.4.1
Contributor guide
Assessment
This issue has not been assessed yet.