jamesfredley commented on code in PR #15557:
URL: https://github.com/apache/grails-core/pull/15557#discussion_r3178549030


##########
grails-views-gson/src/test/groovy/grails/plugin/json/view/JsonViewTemplateResolverSpec.groovy:
##########
@@ -64,6 +71,8 @@ class JsonViewTemplateResolverSpec extends Specification {
     }
 
 
+    // Skip on Groovy 5+ - mocking final methods 
(GrailsWebRequest.getRequest()) not supported without special configuration
+    @IgnoreIf({ instance.isGroovy5OrLater() })

Review Comment:
   Spock 2.4 + Mockito with `mock-maker-inline` does support mocking final 
methods, you're right. The `@IgnoreIf` here was applied because the project's 
current test stack does not have `mock-maker-inline` wired in - the 
resources/mockito-extensions/org.mockito.plugins.MockMaker file is not on the 
classpath, so Spock's default JDK proxy mock-maker hits the final 
`GrailsWebRequest.getRequest()` call and throws. Adding mockito-inline as a 
test runtime dependency in `grails-views-gson/build.gradle` (or rewriting the 
test against `MockHttpServletRequest` instead of `Mock(GrailsWebRequest)`) 
would re-enable this spec on Groovy 5. I'd prefer to leave that change to a 
separate PR scoped to the testing-stack upgrade rather than bundle it into the 
Groovy 5 / Spring Boot 4 sweep, since it changes the mocking strategy for the 
file. Leaving this thread open.



##########
grails-gsp/core/src/test/groovy/org/grails/gsp/GspCompileStaticSpec.groovy:
##########
@@ -86,6 +93,10 @@ class GspCompileStaticSpec extends Specification {
         compileStatic << [true, false]
     }
 
+    // Note: In Groovy 5, the g.message() syntax with g. prefix fails static 
type checking
+    // because the type checking extension doesn't properly resolve the 'g' 
taglib property.

Review Comment:
   Confirmed - GROOVY-6362 (the original `g.taglib()` from `@CompileStatic` 
support, fixed in 2.5.0) and GROOVY-11817 (the claimed regression fix) are the 
right tickets to anchor on. I tested `g.message(code: 'foo')` from inside a 
`@CompileStatic` GSP class against 5.0.6-SNAPSHOT build #23 and the type-check 
extension still doesn't resolve the `g` taglib namespace, so this is a 
regression in 5.0.6 that GROOVY-11817 did not fully restore. I'll file a new 
Groovy ticket against `GROOVY_5_0_X` referencing both 6362 and 11817, with a 
standalone reproducer (the same shape as the disabled tests in 
`GspCompileStaticSpec`). Leaving the `@IgnoreIf` and inline note here as a 
known regression until the upstream ticket lands - will re-enable the tests 
when the fix is in a snapshot. Will update this thread when the Groovy ticket 
is filed.



##########
grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/taglib/UrlMappingTagLib.groovy:
##########
@@ -184,14 +184,14 @@ class UrlMappingTagLib implements TagLibrary {
         // display previous link when not on firststep unless omitPrev is true
         if (currentstep > firststep && !attrs.boolean('omitPrev')) {
             linkParams.offset = offset - max
-            writer << callLink(appendClass((Map) linkTagAttrs.clone(), 
'prevLink')) {
+            writer << callLink(appendClass(new LinkedHashMap(linkTagAttrs), 
'prevLink')) {

Review Comment:
   This change came in via Mattias's commit c54de20008f (`fix: more Groovy 5 
compatibility changes`, 2026-01-15) along with several other Groovy 5 compat 
fixes in `MongoCodecSession`, `BsonPersistentEntityCodec`, 
`PersistentEntityCodec`, etc. The original `(Map) linkTagAttrs.clone()` form 
runs into a Groovy 5 `@CompileStatic` issue - `Map.clone()` is declared `Object 
clone()` on the JDK `Cloneable` contract, and Groovy 5's stricter STC dispatch 
on the cast result no longer routes through the `DefaultGroovyMethods` MOP path 
that Groovy 4 used (the same kind of dispatch tightening we saw in 
`File.asBoolean`). `new LinkedHashMap(linkTagAttrs)` is the explicit 
copy-constructor shape that survives unchanged. There's no upstream Groovy 
ticket I can point at for this one - the change has been on the branch since 
January and predates the audit. I can file a follow-up Groovy ticket with a 
standalone reproducer if you'd like to track it for upstream. Leaving this 
thread open pending that decis
 ion.



##########
grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/taglib/ValidationTagLib.groovy:
##########
@@ -317,7 +317,9 @@ class ValidationTagLib implements TagLibrary {
             }
             catch (NoSuchMessageException e) {
                 if (error instanceof MessageSourceResolvable) {
-                    text = ((MessageSourceResolvable) error).codes[0]
+                    MessageSourceResolvable resolvable = 
(MessageSourceResolvable) error

Review Comment:
   Agreed - reverted in commit ad634e0c09e. The `defaultMessage ?: codes[0]` 
tweak was a behavioural change (prefer the i18n `defaultMessage` over the raw 
error code in the catch path) that snuck in with the Groovy 5 sweep but is not 
Groovy-version conditional. Restored to the original single-line `text = 
((MessageSourceResolvable) error).codes[0]` shape. If we want the 
defaultMessage preference, that should be its own scoped change with its own 
tests.



##########
grails-scaffolding/grails-app/commands/scaffolding/CreateScaffoldServiceCommand.groovy:
##########
@@ -47,12 +47,12 @@ class CreateScaffoldServiceCommand implements 
GrailsApplicationCommand, CommandL
         final String domainClassName = args[0]
         if (!domainClassName) {
             error('No domain-class specified')
-            return FAILURE
+            return false

Review Comment:
   Agreed - reverted across all 9 scaffolding command files in commit 
ad634e0c09e (`CreateScaffoldControllerCommand`, `CreateScaffoldServiceCommand`, 
`GenerateAllCommand`, `GenerateAsyncControllerCommand`, 
`GenerateControllerCommand`, `GenerateScaffoldAllCommand`, 
`GenerateServiceCommand`, `GenerateViewsCommand`, `InstallTemplatesCommand`). 
The earlier inline-to-`true`/`false` rewrite (commit d2441fbcb5a) was driven by 
the GROOVY-11907 trait-static-fields bytecode bug that prevented all 
scaffolding commands from loading at the time. GROOVY-11907 is fixed in 5.0.5, 
and its indy=false follow-up GROOVY-11968 is fixed in 5.0.6 build #22, so the 
constants on the `CommandLineHelper` trait resolve cleanly again. The trait 
still defines `static final boolean SUCCESS = true` / `static final boolean 
FAILURE = false`, no other change needed. `./gradlew :grails-scaffolding:test` 
passes against 5.0.6-SNAPSHOT build #23.



##########
grails-scaffolding/src/main/groovy/grails/plugin/scaffolding/RestfulServiceController.groovy:
##########
@@ -82,7 +82,7 @@ class RestfulServiceController<T extends GormEntity<T>> 
extends RestfulControlle
 
     @Override
     protected Integer countResources() {
-        getService().count(params)
+        Math.toIntExact(getService().count(params))

Review Comment:
   This change is actually load-bearing for Groovy 5 / @CompileStatic 
compilation, not cosmetic. `RestfulServiceController.countResources()` 
overrides `RestfulController.countResources()` whose return type is `Integer`. 
`getService().count(params)` resolves to `GormStaticApi.count(params)` which 
returns `Number` (not `Integer`) on the new GORM 9.x interface. Under Groovy 4 
`@CompileStatic` the implicit `Number` -> `Integer` narrowing was tolerated; 
under Groovy 5 `@CompileStatic` the typer rejects the implicit narrowing and 
the file fails to compile (`Cannot return value of type Number on method 
returning type Integer`). `Math.toIntExact` is the standard JDK shape for that 
conversion (and correctly throws `ArithmeticException` on overflow rather than 
silently truncating like a plain `(int)` cast would, which matters for a count 
that exceeds `Integer.MAX_VALUE`). The change is from c54de20008f (`fix: more 
Groovy 5 compatibility changes` by @mattiasreichel, 2026-01-15) - I'll add an in
 line comment to that effect so it doesn't read as a drive-by improvement. 
Leaving the change in this PR rather than extracting since reverting it breaks 
`:grails-scaffolding:compileGroovy`.



##########
grails-test-examples/hibernate5/grails-hibernate-groovy-proxy/grails-app/domain/example/Customer.groovy:
##########
@@ -19,11 +19,9 @@
 
 package example
 
-import grails.compiler.GrailsCompileStatic
 import grails.persistence.Entity
 
 @Entity
-@GrailsCompileStatic

Review Comment:
   Removed in commit 83567f41930 (`fix: resolve Groovy 5 CI failures for 
CodeNarc, controller params, and bytecode`, 2026-04-06). At that time, applying 
`@GrailsCompileStatic` to this entity (which has both an explicit two-arg 
constructor `Customer(Long id, String name)` and a `static mapping = { id 
generator: 'assigned' }` closure) produced a runtime `VerifyError` in the 
static initialiser of the `mapping` closure on Groovy 5. The same VerifyError 
shape (`get long/double overflows locals`) was the symptom of GROOVY-11907 and 
its indy=false follow-up GROOVY-11968 - both of which are now fixed in 5.0.6 
build #22. I'll re-test restoring `@GrailsCompileStatic` on this entity against 
build #23. If it now compiles and the proxy regression spec still passes, I'll 
restore it in a follow-up commit and resolve this thread; if it still 
VerifyErrors, I'll add an inline comment with the actual mechanism (likely a 
separate Groovy bug) and link to the test that fails. Leaving the thread open 
until
  I confirm.



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