Annotation processors can write `CLASS_OUTPUT` resources beside source inputs
- Dominant language
- Java
- Stars
- 1.4k
- Forks
- 161
- PR merge metrics
- No merged PRs in 30d
Description
J2CL’s javac frontend configures `SOURCE_OUTPUT` when annotation processing is enabled, but does not configure `CLASS_OUTPUT`.
This affects annotation processors that use the standard API to create a class-output resource with an originating element:
```java
processingEnv
.getFiler()
.createResource(
StandardLocation.CLASS_OUTPUT,
"",
"META-INF/example/config.json",
originatingElement);
```
On JDK 18 and later, javac propagates the originating element’s source file to the `JavaFileManager` as an originating file. When `CLASS_OUTPUT` has not been configured, javac may use that source file as the sibling placement hint.
Observed with JDK 21.0.9:
- With only `SOURCE_OUTPUT` configured, the resource is written beside the originating source input.
- The directory portion of the requested resource name is lost because javac’s sibling fallback uses the basename.
- If the source path traverses a symlink, the write can cross that symlink and modify the underlying source tree.
- The file is not a declared J2CL action output, so cached action results can hide the side effect.
- Configuring `CLASS_OUTPUT` causes the complete resource path to be written beneath that output directory.
A minimal javac-only reproduction uses a processor containing the call above:
```text
javac -proc:only -s /tmp/generated-sources \
-processorpath processor.jar \
-processor ExampleProcessor \
path/to/Sample.java
```
Without `-d`, javac creates `Sample.json` beside `Sample.java`.
Adding a class-output directory:
```text
javac -proc:only \
-s /tmp/generated-sources \
-d /tmp/class-output \
-processorpath processor.jar \
-processor ExampleProcessor \
path/to/Sample.java
```
creates the intended resource at:
```text
/tmp/class-output/META-INF/example/config.json
```
The issue appears to have been introduced when annotation processing was enabled in `JavacParser` by commit a0a25d692efa2e32b21cba64f90a333e37d25b0d. Current J2CL still configures `SOURCE_OUTPUT` without configuring `CLASS_OUTPUT`.
### Expected behavior
All files created by annotation processors should remain under action-local output directories. Processing must not write beside source inputs.
### Local workaround
The local patch points `CLASS_OUTPUT` at J2CL’s existing action-local generated-source directory:
```diff
diff --git a/transpiler/java/com/google/j2cl/transpiler/frontend/javac/JavacParser.java b/transpiler/java/com/google/j2cl/transpiler/frontend/javac/JavacParser.java
--- a/transpiler/java/com/google/j2cl/transpiler/frontend/javac/JavacParser.java
+++ b/transpiler/java/com/google/j2cl/transpiler/frontend/javac/JavacParser.java
@@ -218,6 +218,8 @@
fileManager.setLocationFromPaths(StandardLocation.CLASS_PATH, classPath);
if (sourceGenPath != null) {
fileManager.setLocationFromPaths(
+ StandardLocation.CLASS_OUTPUT, ImmutableList.of(sourceGenPath));
+ fileManager.setLocationFromPaths(
StandardLocation.SOURCE_OUTPUT, ImmutableList.of(sourceGenPath));
}
```
This was validated with a cache-disabled J2CL action. The processor resource was written beneath `_sourcegen/META-INF/...`, and no file was created beside the source input.
A separate action-local class-output directory would also address the issue if keeping generated sources and class resources separate is preferred.
Contributor guide
Research direction
Start in transpiler/java/com/google/j2cl/transpiler/frontend/javac/JavacParser.java, where SOURCE_OUTPUT and CLASS_PATH are configured, and review the annotation-processing setup. Run the cache-disabled J2CL action described in the issue with a processor resource; done means the resource is written under an action-local output directory and nothing is created beside the source input.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100