Copilot commented on code in PR #3392:
URL: https://github.com/apache/maven-surefire/pull/3392#discussion_r3610057338


##########
maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java:
##########
@@ -184,6 +186,15 @@ File createArgsFile(
                         .append('"')
                         .append(NL);
 
+                // Check for module-info-patch.args generated by 
maven-compiler-plugin 4.x
+                File patchArgs = findModuleInfoPatchArgs(patchFile);
+                if (patchArgs != null) {
+                    // Use --add-exports directives from module-info-patch.args
+                    appendModuleInfoPatchArgs(args, patchArgs, moduleName);
+                }

Review Comment:
   The inline comment says only "--add-exports" directives are used from 
module-info-patch.args, but appendModuleInfoPatchArgs() also forwards other 
directives (e.g., --add-opens) and additionally injects --add-reads. This makes 
the comment misleading when reading the control flow.



##########
maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java:
##########
@@ -224,4 +238,73 @@ File createArgsFile(
             return surefireArgs;
         }
     }
+
+    /**
+     * Searches for module-info-patch.args generated by maven-compiler-plugin 
4.x.
+     * The file is expected at {@code 
target/test-classes/META-INF/maven/module-info-patch.args}
+     * or within a module subdirectory at
+     * {@code 
target/test-classes/<module>/META-INF/maven/module-info-patch.args}.
+     *
+     * @param patchFile the test classes directory (may be the module 
subdirectory)
+     * @return the module-info-patch.args file, or null if not found
+     */
+    @Nullable
+    private static File findModuleInfoPatchArgs(File patchFile) {
+        // Direct location: 
target/test-classes/<module>/META-INF/maven/module-info-patch.args
+        File argsFile = new File(patchFile, 
"META-INF/maven/module-info-patch.args");
+        if (argsFile.isFile()) {
+            return argsFile;
+        }
+        // Parent location: 
target/test-classes/META-INF/maven/module-info-patch.args
+        File parent = patchFile.getParentFile();
+        if (parent != null) {
+            argsFile = new File(parent, 
"META-INF/maven/module-info-patch.args");
+            if (argsFile.isFile()) {
+                return argsFile;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Reads the module-info-patch.args file and appends its --add-exports and 
--add-opens
+     * directives to the args builder. The --add-reads directive is handled by 
surefire itself
+     * (always adds ALL-UNNAMED) to avoid referencing modules that may be on 
the classpath
+     * rather than the module-path.

Review Comment:
   The Javadoc for appendModuleInfoPatchArgs() states that it appends only 
"--add-exports" and "--add-opens" directives, but the implementation currently 
appends any non-empty, non-comment line except --add-reads/--add-modules. 
Either the implementation should be restricted, or the Javadoc should describe 
the broader behavior.



##########
maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java:
##########
@@ -1457,6 +1476,43 @@ private ResolvePathResultWrapper 
findModuleDescriptor(File jdkHome, File buildPa
         }
     }
 
+    /**
+     * Whether the main build output uses the Maven 4 Module Source Hierarchy 
layout:
+     * no module-info.class at the root of the build output directory, but at 
least one
+     * immediate subdirectory containing one ({@code 
target/classes/<module>/}).
+     * A classic modular build (module-info.class at the root) is never 
nested, even if
+     * a subdirectory happens to share the module's name.
+     *
+     * @param buildPath the build output directory (e.g., target/classes)
+     * @return {@code true} for the nested module source hierarchy layout
+     */
+    private static boolean isNestedModuleLayout(File buildPath) {
+        return buildPath != null
+                && buildPath.isDirectory()
+                && !new File(buildPath, "module-info.class").exists()
+                && findNestedModuleDescriptor(buildPath) != null;
+    }
+
+    /**
+     * Searches for a module-info.class in immediate subdirectories of the 
given directory.
+     * This supports Maven 4 Module Source Hierarchy where compiled classes 
are placed
+     * in {@code target/classes/<module>/} instead of directly in {@code 
target/classes/}.
+     *
+     * @param buildPath the build output directory (e.g., target/classes)
+     * @return the subdirectory containing module-info.class, or null if not 
found
+     */
+    private static File findNestedModuleDescriptor(File buildPath) {
+        File[] subdirs = buildPath.listFiles(File::isDirectory);
+        if (subdirs != null) {
+            for (File subdir : subdirs) {
+                if (new File(subdir, "module-info.class").exists()) {
+                    return subdir;
+                }
+            }
+        }
+        return null;
+    }

Review Comment:
   findNestedModuleDescriptor() relies on File.listFiles() iteration order to 
pick the first nested module directory. If multiple nested module directories 
exist (even unintentionally), the chosen module becomes filesystem-order 
dependent, which can make module detection and test scanning non-deterministic.



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