gnodet-bot commented on code in PR #1170:
URL: 
https://github.com/apache/maven-compiler-plugin/pull/1170#discussion_r4236696088


##########
src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java:
##########
@@ -398,6 +399,72 @@ private List<File> 
getCompileClasspathElements(MavenProject project, List<File>
         return list;
     }
 
+    /**
+     * Replaces exploded multi-release project outputs with the versioned 
directory containing their module descriptor.
+     * The Java module system does not apply multi-release JAR lookup rules to 
directories, so a descriptor under
+     * {@code META-INF/versions/<N>} is otherwise invisible when another 
reactor project is compiled before packaging.
+     *
+     * @param artifacts compile path entries, including this project's own 
output directories
+     * @param projectOutputDirectories this project's outputs, which are 
already arranged for multi-release compilation
+     */
+    private void resolveMultiReleaseDependencies(Collection<File> artifacts, 
List<File> projectOutputDirectories) {
+        String release = getRelease();
+        if (release == null) {
+            release = getSource();
+        }
+        if (release == null) {
+            release = getTarget();
+        }
+        int releaseVersion =
+                getJavaMajorVersion(release != null ? release : 
System.getProperty("java.specification.version"));
+        List<File> resolved = new ArrayList<>(artifacts.size());
+        for (File artifact : artifacts) {
+            if (!projectOutputDirectories.contains(artifact)) {
+                File moduleDirectory = findModuleDirectory(artifact, 
releaseVersion);
+                if (moduleDirectory != null) {
+                    artifact = moduleDirectory;
+                }
+            }
+            resolved.add(artifact);
+        }
+        artifacts.clear();
+        artifacts.addAll(resolved);

Review Comment:
   ⚠️ **Critical — module path entries lose their exported classes**
   
   `findModuleDirectory` replaces `module-a/target/classes` with 
`module-a/target/classes/META-INF/versions/9/` on the module path. That 
versioned directory contains only `module-info.class`; the actual package 
classes (e.g. `sample/a/Api.class`) live in `target/classes/`. Once the 
replacement happens, any downstream module that imports classes from `module-a` 
will fail to compile — javac can resolve the module descriptor (satisfying 
`requires`), but cannot see the exported types.
   
   The IT masks this because `module-b` only has a `module-info.java` with a 
bare `requires` declaration and no source file that uses `module-a`'s API. The 
described fix — also adding `--patch-module 
<module-name>=<original-classes-dir>` for each affected dependency — is the 
correct approach, mirroring what the existing `multiReleaseOutput` logic at 
line 321–328 does for the project's own output.
   
   Without this fix, the approach is incomplete: it solves module descriptor 
resolution but breaks class resolution for any real downstream consumer.



##########
src/it/MCOMPILER-1137/module-b/src/main/java9/module-info.java:
##########
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+module org.apache.maven.plugins.compiler.it.moduleb {
+    requires org.apache.maven.plugins.compiler.it.modulea;
+}

Review Comment:
   ⚠️ **IT doesn't test the critical scenario: actual class imports from the 
reactor dependency**
   
   `module-b` only declares `requires 
org.apache.maven.plugins.compiler.it.modulea` but never uses any class from 
`module-a` in Java source. The path-replacement bug (see main finding) would 
only manifest if a downstream module compiled source files that import exported 
types. Adding a `module-b/src/main/java9/UseApi.java` like:
   
   ```java
   package sample.b;
   import sample.a.Api;
   public class UseApi { public static void demo() { Api.value(); } }
   ```
   
   would turn this IT into an actual regression test for the scenario described 
in the PR title.



##########
src/it/MCOMPILER-1137/invoker.properties:
##########
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+invoker.goals=clean compile

Review Comment:
   ⚠️ **Missing `invoker.java.version` guard**
   
   This IT exercises module-path compilation with `release=9`. Without 
`invoker.java.version = 9+`, it will be attempted (and fail) on JDK 8. All 
other module-path ITs in this plugin set this property — e.g. 
`MCOMPILER-321_pathexceptions/invoker.properties` line 18.
   
   ```suggestion
   invoker.goals=clean compile
   invoker.java.version = 9+
   ```



##########
src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java:
##########
@@ -398,6 +399,72 @@ private List<File> 
getCompileClasspathElements(MavenProject project, List<File>
         return list;
     }
 
+    /**
+     * Replaces exploded multi-release project outputs with the versioned 
directory containing their module descriptor.
+     * The Java module system does not apply multi-release JAR lookup rules to 
directories, so a descriptor under
+     * {@code META-INF/versions/<N>} is otherwise invisible when another 
reactor project is compiled before packaging.
+     *
+     * @param artifacts compile path entries, including this project's own 
output directories
+     * @param projectOutputDirectories this project's outputs, which are 
already arranged for multi-release compilation
+     */
+    private void resolveMultiReleaseDependencies(Collection<File> artifacts, 
List<File> projectOutputDirectories) {

Review Comment:
   💡 **API design: `Collection<File>` parameter is mutated in-place**
   
   `resolveMultiReleaseDependencies(Collection<File> artifacts, ...)` takes a 
`Collection<File>` and calls `artifacts.clear(); artifacts.addAll(resolved)`. 
This is only safe because `getCompileClasspathElements()` returns a fresh 
`ArrayList`. Accepting `Collection<File>` on the signature implies callers can 
pass any collection (e.g. an unmodifiable view), but it silently requires 
mutability. Consider either accepting `List<File>` (closer to the actual 
contract) or returning `List<File>` and letting the caller reassign, making the 
intent explicit.



##########
src/it/MCOMPILER-1137/invoker.properties:
##########
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+invoker.goals=clean compile

Review Comment:
   💡 **No `verify.groovy` script**
   
   `MCOMPILER-328_multiReleaseOutput` has a verify script that asserts expected 
class files exist under `META-INF/versions/`. This IT should do the same: at 
minimum verify that 
`module-b/target/classes/META-INF/versions/9/module-info.class` exists and that 
`module-a`'s versioned descriptors were produced. Without this, the IT only 
checks that `mvn compile` exits 0 — not that the right artifacts were generated.



-- 
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