codeconsole opened a new pull request, #15759:
URL: https://github.com/apache/grails-core/pull/15759

   ### Summary
   
   Adds an opt-in that compiles **every** controller and service with 
`@GrailsCompileStatic` automatically, without annotating each class. Two 
independent flags are exposed on the `grails` Gradle extension:
   
   ```groovy
   grails {
       compileStaticControllers = true   // every grails-app/controllers class
       compileStaticServices = true      // every grails-app/services class
   }
   ```
   
   Both default to `false`. This automates what the framework's own guidance 
already recommends doing per-class, while keeping it opt-in and reversible.
   
   ### Design
   
   The configuration rides the same path PR #15118 established for the `grails 
{ importJavaTime / starImports }` DSL, but the annotation is applied through an 
artefact-aware AST injector rather than a global `ImportCustomizer`, because 
static compilation is selective (controllers/services only), semantic (can fail 
the build), and must yield to an explicit per-class choice — none of which a 
blanket customizer can do.
   
   - **Config + transport (grails-gradle):** `GrailsExtension` gains 
`compileStaticControllers` / `compileStaticServices`. A new 
`GrailsCompileStaticArtefactsProvider` (a `CommandLineArgumentProvider`, 
modeled on the existing `GrailsAppBaseDirProvider`) publishes the enabled flags 
to the Groovy compiler worker JVM as `-D` system properties. The property names 
live in `grails.util.BuildSettings` alongside `APP_BASE_DIR`.
   - **Application (grails-core):** `CompileStaticArtefactInjector` (an 
`@AstTransformer` `GrailsArtefactClassInjector` for `Controller`/`Service`) 
reads the `@Artefact` type, checks the corresponding flag, and applies 
`@GrailsCompileStatic` via a new 
`GrailsASTUtils.addGrailsCompileStaticAnnotation(ClassNode)` helper. That 
helper reproduces `@GrailsCompileStatic` (i.e. `@CompileStatic` carrying the 
Grails type-checking extensions) and registers the static-compile transform via 
`ClassNode.addTransform`, the same mechanism the existing 
`addCompileStaticAnnotation` uses so a late-added annotation still fires.
   
   ### Opt-out always wins
   
   A class that declares its own `@CompileDynamic` (or `@GrailsCompileStatic` / 
`@CompileStatic` / `@GrailsTypeChecked` / `@TypeChecked`) keeps that setting; 
the opt-in never overrides an explicit choice:
   
   ```groovy
   @CompileDynamic
   class LegacyController {
       // compiled dynamically even when grails.compileStaticControllers is 
enabled
   }
   ```
   
   When both flags are unset (the default), the injector is fully inert.
   
   ### Tests
   
   - `CompileStaticArtefactInjectorSpec` — controller/service compiled 
statically when the flag is on (a type error fails compilation), dynamically 
when off, and `@CompileDynamic` opted out even when on; services unaffected by 
the controllers flag.
   - `GrailsASTUtilsSpec` — `addGrailsCompileStaticAnnotation` applies 
`@CompileStatic` with the full Grails extension list; 
`hasStaticCompilationAnnotation` detects every opt-out annotation; the 
extension list stays in sync with `@GrailsCompileStatic`.
   - `GrailsCompileStaticArtefactsProviderSpec` + `GrailsExtensionSpec` — flags 
default to false, are settable, and are published as the expected `-D` system 
properties (read lazily).
   
   Full `grails-core` suite (374 tests) and the `grails-gradle` plugins/model 
suites pass; checkstyle + codenarc clean on the changed modules.
   
   ### Docs
   
   Documented under the GrailsCompileStatic guide section and the Grails 8 
"what's new" page (public DSL only).
   


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