daniellansun commented on PR #3235:
URL: https://github.com/apache/groovy/pull/3235#issuecomment-6768672082

   The module declaration is not a class (JLS §7.3, §7.7), and the per-class 
pipeline is what we needed to reuse. `visitModuleDeclaration` builds a 
`ModuleInfoNode` for the directives, then a carrier `ClassNode` named 
`module-info` (`ACC_ABSTRACT | ACC_INTERFACE`) so resolution, annotation 
checking, and class writing already have a class to visit. The declaration 
itself has no field on `ClassNode`. Groovy's `ModuleNode` is the source unit, 
so it is the wrong place to hang a JPMS module. 
`putNodeMetaData(ModuleInfoNode.class, declaration)` is how 
`ModuleInfoVerifier` and `AsmClassGenerator.emitModuleInfo` find the 
directives; emission then writes a real `ACC_MODULE` class 
(`module-info.class`, JVMS §4.7.25) and does not write the interface. 
Annotations are also copied onto the carrier so `ExtendedVerifier` can check 
`ElementType.MODULE`.
   
   That does affect the joint compiler, and the stub generator is wrong for 
this carrier today.
   
   `JavaAwareCompilationUnit` runs `JavaStubGenerator.generateClass` at 
`CONVERSION` for every non-private top-level class once any `.java` file is in 
the compile. The carrier is that kind of class. The generator never reads node 
metadata. It already special-cases a class named `package-info` and emits only 
a package statement; it has no such case for `module-info`. 
`generateStubContent` therefore prints a type, approximately:
   
   ```java
   interface module-info {
   }
   ```
   
   into `module-info.java` (`createJavaStubFile` uses the class name). Two 
problems follow. `module-info` is not a Java identifier, and JLS §7.3 makes 
`module-info.java` a modular compilation unit: javac requires a module 
declaration there, not a type. Joint compilation of `module-info.groovy` 
together with any `.java` file fails at javac. Compiling the `.groovy` file 
alone does not generate stubs, and ordinary Groovy classes in a joint compile 
do not carry this metadata, so they are unaffected.
   
   Metadata is not dropped inside this compilation unit. The stub generator 
reads the same primary `ClassNode` it was given; `emitModuleInfo` still sees 
`ModuleInfoNode.of` later. The failure is that the stubber never looks at the 
key, so it treats the carrier as an interface. A copy that does not call 
`copyNodeMetaData` (for example `ClassNode.getPlainNodeReference`) would also 
lose the declaration and then really emit an interface class file.
   
   What should change: `JavaStubGenerator.generateClass` should skip a class 
for which `ModuleInfoNode.of(classNode)` is non-null, the same way it refuses 
to emit a type for `package-info`. Sibling `.java` files in this joint compiler 
are compiled from the classpath, not as a module-source-path compile, so javac 
does not need a `module-info.java` stub to compile them. Groovy still writes 
`module-info.class` at class generation. If we would rather have javac own the 
descriptor, the stub has to be the JLS §7.7 declaration transcribed from 
`ModuleInfoNode`, and Groovy must not write `module-info.class` as well. Either 
fix is a special case in the stub generator; leaving the carrier as an ordinary 
interface is what breaks the joint compile.
   
   
   I will skip that carrier in `JavaStubGenerator.generateClass`, the same way 
`package-info` is special-cased, and add a joint-compilation test.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to