Copilot commented on code in PR #2140:
URL: https://github.com/apache/groovy/pull/2140#discussion_r2921432290


##########
subprojects/groovy-console/src/main/groovy/groovy/console/ui/Console.groovy:
##########
@@ -378,6 +378,13 @@ class Console implements CaretListener, HyperlinkListener, 
ComponentListener, Fo
         } catch (ClassNotFoundException ignore) {
         }
 
+        // listen for Maven resolver events if the Maven console plugin is on 
the classpath
+        try {
+            def mavenPluginClass = 
Class.forName('groovy.console.ui.ConsoleMavenPlugin')
+            mavenPluginClass.getConstructor().newInstance().addListener(this)
+        } catch (ClassNotFoundException ignore) {

Review Comment:
   The Maven console plugin is loaded reflectively but the code only catches 
`ClassNotFoundException`. If the class exists but fails to instantiate (e.g. 
constructor/initializer throws, missing dependencies, 
`ReflectiveOperationException`), Console startup will fail. Consider catching 
broader reflection exceptions here (similar to how optional integrations are 
typically guarded) and either ignoring or reporting a concise message.
   ```suggestion
           } catch (ReflectiveOperationException ignore) {
   ```



##########
versions.properties:
##########
@@ -48,6 +48,8 @@ junit5Platform=1.14.3
 log4j=1.2.17
 log4j2=2.25.3
 logback=1.5.27
+mavenResolverProvider=4.0.0-rc-5
+mavenResolverSupplier=2.0.16

Review Comment:
   The PR description says "Just a placeholder at the moment", but this PR 
introduces a new Maven-based Grape engine subproject plus CLI/console/test 
changes. Please update the PR description to reflect the implemented scope and 
any remaining TODOs so reviewers know what's intended for this change set.



##########
src/main/java/groovy/grape/Grape.java:
##########
@@ -119,9 +121,12 @@ public static void setDisableChecksums(boolean 
disableChecksums) {
     public static synchronized GrapeEngine getInstance() {
         if (instance == null) {
             try {
-                // by default use GrapeIvy
+                String grapeClass = System.getProperty("groovy.grape.impl");
+                if (grapeClass == null) {
+                    grapeClass = "groovy.grape.GrapeIvy"; // by default use 
GrapeIvy
+                }
                 // TODO: META-INF/services resolver?
-                instance = (GrapeEngine) 
Class.forName("groovy.grape.GrapeIvy").getDeclaredConstructor().newInstance();
+                instance = (GrapeEngine) 
Class.forName(grapeClass).getDeclaredConstructor().newInstance();
             } catch (ReflectiveOperationException ignore) {
             }

Review Comment:
   `getInstance()` now instantiates the engine from the `groovy.grape.impl` 
system property, but any `ReflectiveOperationException` is silently swallowed, 
leaving `instance` as `null` and effectively disabling Grapes with no 
diagnostics. Consider falling back to the default engine (GrapeIvy) and/or 
throwing an `IllegalStateException` (or at least logging to stderr) so 
misconfiguration is discoverable.



##########
src/main/groovy/groovy/grape/GrapeUtil.groovy:
##########
@@ -0,0 +1,175 @@
+/*
+ *  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.
+ */
+package groovy.grape
+
+import groovy.transform.CompileStatic
+import org.apache.groovy.plugin.GroovyRunner
+import org.apache.groovy.plugin.GroovyRunnerRegistry
+import org.codehaus.groovy.reflection.CachedClass
+import org.codehaus.groovy.reflection.ClassInfo
+import org.codehaus.groovy.runtime.m12n.ExtensionModuleScanner
+import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl
+
+import java.util.jar.JarFile
+import java.util.zip.ZipEntry
+import java.util.zip.ZipException
+import java.util.zip.ZipFile
+
+/**
+ * Utility methods shared between GrapeIvy and GrapeMaven implementations.
+ */
+@CompileStatic
+class GrapeUtil {
+
+    private static final String METAINF_PREFIX = 'META-INF/services/'
+    private static final String RUNNER_PROVIDER_CONFIG = GroovyRunner.name
+
+    /**
+     * Adds a URI to a classloader's classpath via reflection.
+     */
+    static void addURL(ClassLoader loader, URI uri) {
+        // Dynamic invocation needed as addURL is not part of ClassLoader 
interface
+        loader.metaClass.invokeMethod(loader, 'addURL', uri.toURL())
+    }

Review Comment:
   `GrapeUtil` is `@CompileStatic` but `addURL` uses 
`loader.metaClass.invokeMethod(...)`, which relies on Groovy's dynamic 
metaClass property and is likely to fail static compilation. Consider marking 
`addURL` as `@CompileDynamic` (as the old Ivy implementation did) or using a 
statically-compilable reflective call (e.g., via `InvokerHelper`/reflection) to 
invoke `addURL`.



##########
src/test/groovy/org/codehaus/groovy/runtime/m12n/ExtensionModuleHelperForTests.groovy:
##########
@@ -53,7 +53,8 @@ final class ExtensionModuleHelperForTests {
         def ant = new AntBuilder()
         def allowed = [
             'Picked up JAVA_TOOL_OPTIONS: .*',
-            'Picked up _JAVA_OPTIONS: .*'
+            'Picked up _JAVA_OPTIONS: .*',
+            '(?s)SLF4J\\(W\\): Class path contains multiple SLF4J 
providers\\..*SLF4J\\(I\\): Actual provider is of type \\[[^\\n]+\\]'
         ]

Review Comment:
   This test now whitelists the SLF4J "multiple providers" warning rather than 
preventing the duplicate providers from appearing on the forked classpath. If 
possible, prefer fixing the underlying classpath/provider selection (so 
warnings don't leak into user output) instead of accepting the warning as 
normal.



##########
subprojects/groovy-grape-maven/build.gradle:
##########
@@ -0,0 +1,28 @@
+/*
+ *  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.
+ */
+plugins {
+    id 'org.apache.groovy-library'
+}
+
+dependencies {
+    api rootProject
+    implementation 
"org.apache.maven:maven-resolver-provider:${versions.mavenResolverProvider}"
+    implementation 
"org.apache.maven.resolver:maven-resolver-supplier-mvn4:${versions.mavenResolverSupplier}"
+    runtimeOnly "org.slf4j:slf4j-simple:${versions.slf4j}"

Review Comment:
   Declaring `slf4j-simple` as `runtimeOnly` makes this library bring its own 
SLF4J provider, which can cause "multiple SLF4J providers" warnings and 
override an application's chosen logging backend. Consider making the backend a 
test-only dependency (e.g. `testRuntimeOnly`) or leaving provider selection to 
the consuming application.
   ```suggestion
       testRuntimeOnly "org.slf4j:slf4j-simple:${versions.slf4j}"
   ```



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