google / google/compile-testing

[BUG] InMemoryJavaFileManager.uriForJavaFileObject() breaks when supplied with a Locations.ModuleLocationHandler

Open
#335 4 comments 0 reactions 0 assignees View on GitHub
P3 type=defect
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.