Skip to content

refactor: convert grails-shell-cli to Groovy - #16585

Open
borinquenkid wants to merge 26 commits into
refactor/java-to-groovy-grails-springfrom
refactor/java-to-groovy-grails-shell-cli
Open

borinquenkid wants to merge 26 commits into
refactor/java-to-groovy-grails-springfrom
refactor/java-to-groovy-grails-shell-cli

Conversation

@borinquenkid

Copy link
Copy Markdown
Member

What

Converts the remaining Java sources of grails-shell-cli to Groovy: 97 .java files removed, 97 .groovy files added (117 files changed, 4406 insertions(+), 4528 deletions(-)).

Why

The maintainers asked on #16351 for the Java-to-Groovy migration to land one Gradle project at a time as a stack of PRs, bottom-up in dependency order. #16572 did grails-data-hibernate7; this PR is 7 of 30 in the next stack (base: refactor/java-to-groovy-grails-spring). The end state of every file is taken from the 9.0.x-java-to-groovy branch, which already carries the regression fixes found by CI.

Commits:

  • 1d74655 fix: keep the Java-facing API of the converted grails-shell-cli classes
  • 60fe7bc refactor: convert grails-shell-cli to Groovy

Changed outside the converted sources

  • nothing

Java-facing API sweep

Every deleted .java was compared with its Groovy twin via javap -v -protected (class declaration, public/protected fields, constructors, methods incl. modifiers/throws/generics, interface default methods, nested class modifiers, and the annotations callers see). Result:

  • grails-shell-cli: 97 deleted .java, 4 difference(s) found and fixed in this PR (see the fix: commit), 0 left

See also the notes below. Remaining informational entries (widened visibility, e.g. Groovy property accessors): 20.

Verification

  • classes and testClasses (plus ast/cli/testFixtures source sets where present) of the converted project(s) and of their direct dependents compile: ['grails-profiles-base']
  • No test suites were run locally (the umbrella branch was verified; CI runs them). codeStyle, rat and a whole-repo build -PskipTests are run once on the tip of the stack.

Notes

  • Informational sweep entries that are not regressions: Groovy enums gain MIN_VALUE/MAX_VALUE/next()/previous(), property accessors appear for formerly package-private members, nested static classes with implicit constructors become public (they were protected), and generic type parameters that Groovy erases in constructors/methods (descriptors identical).
  • Groovy gotchas that applied (see build: migrate remaining Java sources to Groovy #16351): static final without public creates a property; == calls equals(); Closure/SAM coercions; @CompileStatic with nested classes. All CI regression fixes found on the umbrella branch are included in the end state.

🤖 Generated with Claude Code

borinquenkid and others added 2 commits October 10, 2026 14:27
Converts the Java sources of grails-shell-cli to Groovy.
Part of the per-project split requested by the maintainers on #16351; end state taken from the
9.0.x-java-to-groovy branch (origin/9.0.x..e55fd9e).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The public fields of FetchAllTaskSelectorsBuildAction.AllTasksModel became Groovy properties (private field plus accessors) when declared without 'public'; keep them public fields as in the Java original.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@borinquenkid
borinquenkid requested review from jamesfredley and jdaugherty and a balanced review from Copilot October 11, 2026 01:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@codecov

codecov Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 24.04692% with 1295 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (refactor/java-to-groovy-grails-spring@587469c). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...cli/compiler/grape/MavenResolverGrapeEngine.groovy 11.3636% 113 Missing and 4 partials ⚠️
...g/grails/cli/command/archive/ArchiveCommand.groovy 0.0000% 90 Missing ⚠️
...groovy/org/grails/cli/command/CommandRunner.groovy 0.0000% 78 Missing ⚠️
.../grails/cli/command/archive/ResourceMatcher.groovy 0.0000% 73 Missing ⚠️
.../GrailsApplicationCompilerAutoConfiguration.groovy 0.0000% 58 Missing ⚠️
...org/grails/cli/compiler/maven/MavenSettings.groovy 38.2979% 54 Missing and 4 partials ⚠️
...piler/DependencyManagementBomTransformation.groovy 5.3571% 53 Missing ⚠️
...vy/org/grails/cli/command/install/Installer.groovy 0.0000% 44 Missing ⚠️
...grails/cli/compiler/dependencies/Dependency.groovy 22.0000% 39 Missing ⚠️
...rg/grails/cli/compiler/DependencyCustomizer.groovy 7.5000% 37 Missing ⚠️
... and 67 more
Additional details and impacted files

Impacted file tree graph

@@                            Coverage Diff                             @@
##             refactor/java-to-groovy-grails-spring     #16585   +/-   ##
==========================================================================
  Coverage                                         ?   62.8188%           
  Complexity                                       ?      29005           
==========================================================================
  Files                                            ?       2243           
  Lines                                            ?     110599           
  Branches                                         ?      20232           
==========================================================================
  Hits                                             ?      69477           
  Misses                                           ?      32083           
  Partials                                         ?       9039           
Files with missing lines Coverage Δ
...g/grails/cli/boot/SpringApplicationLauncher.groovy 89.4737% <100.0000%> (ø)
...ils/cli/compiler/GrailsBomAstTransformation.groovy 100.0000% <100.0000%> (ø)
...ils/cli/compiler/grape/GrapeEngineInstaller.groovy 100.0000% <100.0000%> (ø)
...cli/command/NoHelpCommandArgumentsException.groovy 0.0000% <0.0000%> (ø)
...g/grails/cli/command/NoSuchCommandException.groovy 0.0000% <0.0000%> (ø)
...ails/cli/compiler/CompilerAutoConfiguration.groovy 0.0000% <0.0000%> (ø)
...ls/cli/compiler/GroovyCompilerConfiguration.groovy 0.0000% <0.0000%> (ø)
.../SpringBootDependenciesDependencyManagement.groovy 85.7143% <83.3333%> (ø)
...ultRepositorySystemSessionAutoConfiguration.groovy 87.5000% <95.2381%> (ø)
...r/grape/DependencyResolutionFailedException.groovy 0.0000% <0.0000%> (ø)
... and 70 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@borinquenkid borinquenkid added this to the grails:9.0.0-M1 milestone Oct 11, 2026
borinquenkid and others added 16 commits October 15, 2026 21:46
…y on 20 files

Rebuilds these 20 grails-shell-cli files from the original .java content
with a minimal mechanical conversion (public removed from methods/class
decls, unnecessary groovy auto-imports dropped, safe double-quote ->
single-quote conversions, unnecessary .class literal references removed)
that deliberately keeps every semicolon, so git's default 50%
rename-similarity threshold recognizes each as a rename of its .java
predecessor instead of a delete+add, following the pattern proven on
DefaultCommandLine.groovy (#16576) and already applied to
grails-datastore-core and grails-spring.

Each file adds a scoped @SuppressWarnings('UnnecessarySemicolon') with
an explanatory TODO, to be removed by the stacked groovyism-cleanup PR.

Four small files (GrailsCompilerAutoConfiguration, SpringBatchCompiler-
AutoConfiguration, SpringIntegrationCompilerAutoConfiguration,
SpringBootCompilerAutoConfiguration) stayed below the 50% threshold with
semicolons alone, because their string-literal-dense bodies made the
double-quote -> single-quote conversion (CodeNarc's UnnecessaryGString)
proportionally too disruptive for their size; these also keep their
original double-quoted strings under a documented, targeted
@SuppressWarnings(['UnnecessarySemicolon', 'UnnecessaryGString'])
exception, matching the GormProperties/KeyValueMappingFactory precedent
in grails-datastore-core.

Four files with nested/inner classes (GrailsApplicationCompiler-
AutoConfiguration, ResourceMatcher, RunCommand,
FetchAllTaskSelectorsBuildAction) needed one more fix: CodeNarc's
@SuppressWarnings-on-class only suppresses UnnecessarySemicolon inside
that class's own body, never on the file's package/import statements,
which live outside any ClassNode. Moving a second
@SuppressWarnings('UnnecessarySemicolon') onto the package declaration
itself (a legal annotation target in Groovy, verified empirically)
clears those violations file-wide. RunCommand's now-redundant explicit
no-arg constructor and FetchAllTaskSelectorsBuildAction's missing
blank-line-after-opening-brace were two further small, real CodeNarc
findings fixed outright rather than suppressed.

Verified: compileGroovy/compileTestGroovy clean, codenarcMain clean,
and all 196 grails-shell-cli tests pass (0 failures, 0 errors, 2
pre-existing skips). All 20 files are now git-detected as R050+
renames against origin/10.0.x with git's default (no -M flag)
similarity detection.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ning

GlobalGrailsClassInjectorTransformationSpec's "a generated class missing from
a hand-authored imports file is reported" fails on every GitHub-hosted runner
(Ubuntu 21/25, macOS, Windows, Coverage) with an empty warning list, and
passes locally in isolation, paired with every other base.dir-touching spec,
and in the full suite at both local and CI fork counts. Static analysis rules
out base.dir leakage (grails-core ships its own hand-authored imports file,
so a leaked value would still warn), groovy.* property mutation, Spock
parallelism and Groovy version drift (6.0.0 pinned on both sides).

This inlines the compilation so the power assertion prints which branch of
AutoConfigurationImportsWriter.register ran on the runner: whether the sibling
was generated, whether the generated imports file was written (hand-authored
file not found) or not (hand-authored branch taken), the collector's warning
level and counts, and the directories involved.

REVERT THIS COMMIT once the CI log has been read.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The stage-2 rebuild from the .java original omitted @CompileStatic on
DefaultBeanConfiguration and DefaultRuntimeSpringConfiguration (the original
has none) and turned this.setParent(...) into setParent(...). Without
whole-class @CompileStatic a cold reflective call into setProperty() makes a
further dynamic self-call that fails with "MetaClass.initialize() because mc is
null", which broke BeanBuilder's property DSL: BeanBuilderTests
testAbstractBeanDefinition, testAbstractBeanDefinitionWithClass and
testInheritPropertiesFromAbstractBean failed with NPEs on PR #16581.

Restores the annotation, the explanatory comment and the this. qualifier;
similarity stays above the threshold (R073/R076). Verified with grails-spring
21/21, codenarc clean and grails-test-suite-uber BeanBuilderTests 33/33, the
suite that exercises these classes and that the earlier local check skipped.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… dropped by the rename-fix

The stage-2 rebuild from the .java original turned three reference-identity
comparisons into ==/!=. In Groovy those call equals(), so:
- PersistentList.set no longer marked the list dirty when an equal but
  different element replaced the old one,
- AbstractSession.isDirty could treat a changed instance as clean when it
  equals() its cached copy,
- Query.eq compared equality where the Java compared identity.
They are .is() again, as in stage 1.

KeyValueMappingFactory also lost its @CompileStatic (the original has none).
Restoring it dropped similarity under 50%, so its imports and package line
regain their semicolons under a package-level UnnecessarySemicolon suppression:
R065.

grails-datastore-core 949/949, codenarc clean.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…by the rename-fix

580bd5e rebuilt DefaultCommandLine from the .java original, which carries
no annotations, and so lost the @CompileStatic stage 1 had put on the class
and the @PackageScope on systemProperties, undeclaredOptions, declaredOptions
and remainingArgs. Without them the four fields became public Groovy
properties with generated accessors and the class fell back to dynamic
dispatch. Both are restored; similarity stays at R069.

grails-gradle-model: compile, codenarc and 432 tests pass.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…efactor/java-to-groovy-grails-datastore-core
@testlens-app

testlens-app Bot commented Oct 18, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 68b4680
▶️ Tests: 82575 executed
⚪️ Checks: 84/84 completed


Learn more about TestLens at testlens.app/docs.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants