Skip to content

Add proxy package test coverage and fix IntelliJ inspections in grails-datamapping-core - #16155

Open
borinquenkid wants to merge 5 commits into
8.1.xfrom
chore/lint-proxy-package
Open

Add proxy package test coverage and fix IntelliJ inspections in grails-datamapping-core#16155
borinquenkid wants to merge 5 commits into
8.1.xfrom
chore/lint-proxy-package

Conversation

@borinquenkid

Copy link
Copy Markdown
Member

Summary

  • Adds unit test coverage for GroovyProxyFactory and ProxyInstanceMetaClass in grails-datamapping-core, which previously had none in this module despite implementing the core Groovy-based proxy contract used outside Hibernate/Neo4j.
  • Fixes IntelliJ inspection warnings in both classes: methods with no instance-state dependency marked static, replaces deprecated Class.newInstance() with getDeclaredConstructor().newInstance(), makes never-reassigned fields final, suppresses the unchecked-generics warning inherent to MetaClass.getTheClass()'s raw return type, and fills in missing Javadoc tag descriptions.

Test plan

  • ./gradlew :grails-datamapping-core:test --tests "org.grails.datastore.gorm.proxy.*" — 29 tests pass
  • ./gradlew :grails-datamapping-core:test — full module suite passes
  • ./gradlew :grails-datamapping-core:codeStyle — no Checkstyle/CodeNarc violations

🤖 Generated with Claude Code

borinquenkid and others added 3 commits August 15, 2026 18:29
GroovyProxyFactory and ProxyInstanceMetaClass had no tests in this
module despite implementing the core Groovy-based proxy contract used
outside Hibernate/Neo4j. Also picks up a CodeNarc auto-fix replacing a
fully-qualified @CompileDynamic annotation with an import.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mark instance-state-free helper methods static and replace the
deprecated Class.newInstance() with getDeclaredConstructor().newInstance().

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Make the never-reassigned session/key fields final, suppress the
unchecked-generics warning inherent to MetaClass.getTheClass()'s raw
Class return type, fill in missing Javadoc tag descriptions on
invokeMethod, and switch to switch-expressions for getProperty/
setProperty/getAttribute.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 15, 2026 23:54

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.

Pull request overview

This PR improves grails-datamapping-core’s Groovy proxy support by adding missing unit coverage for the proxy implementation and applying a set of code adjustments aimed at addressing IntelliJ inspection warnings.

Changes:

  • Added new Spock specs covering GroovyProxyFactory and ProxyInstanceMetaClass behavior (lazy resolution, proxy metadata, delegation paths).
  • Refactored ProxyInstanceMetaClass (final fields, Javadoc tag descriptions, switch expressions, warning suppression) to reduce inspection noise and modernize code.
  • Refactored GroovyProxyFactory to replace deprecated instantiation and adjust helper methods/annotations (with a potential API-compatibility concern noted in comments).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/proxy/ProxyInstanceMetaClassSpec.groovy Adds focused unit coverage for proxy metaclass behavior (method/property/attribute resolution semantics).
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactorySpec.groovy Adds unit coverage for proxy factory creation/unwrap/identifier/initialization paths.
grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/ProxyInstanceMetaClass.java Cleans up implementation details (final fields, switch refactor, warning suppression, Javadoc completeness).
grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy Updates proxy factory internals (constructor instantiation, annotation import usage) and changes helper methods to static (flagged).
Suppressed comments (2)

grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy:128

  • Same concern here: making a protected method static breaks subclasses that might override it to customize proxy metaClass installation. Consider keeping it non-static and suppressing IntelliJ’s “method may be static” inspection instead.
    @CompileDynamic
    protected static void setMetaClassDynamic(Object proxy, MetaClass proxyMc) {
        proxy.setMetaClass(proxyMc)
    }

grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy:170

  • Making this protected method static is also a potential breaking change for subclasses (cannot be overridden). If the goal is just to satisfy IntelliJ’s inspection, keep it as an instance method and suppress GrMethodMayBeStatic on the method.
    protected static MetaClass unwrapHandleMetaClass(MetaClass mc) {
        if (mc instanceof HandleMetaClass) {
            return ((HandleMetaClass) mc).getAdaptee()
        }
        return mc
    }

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@bito-code-review

Copy link
Copy Markdown

The concern regarding the conversion of protected instance methods to static is valid. In Groovy, changing an instance method to static breaks binary compatibility for any subclasses that override these methods, as static methods are not polymorphic and cannot be overridden.

If these changes were made solely to satisfy static analysis inspections, it is recommended to revert them to instance methods and suppress the inspection, consistent with existing patterns in the repository.

grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy

@CompileDynamic
    protected Serializable getIdDynamic(obj) {
        if (obj.respondsTo('getId')) {
            return (Serializable)obj.invokeMethod('getId', null)
        }

@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 53.1846%. Comparing base (df424da) to head (55d4b81).

Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##                8.1.x     #16155        +/-   ##
==================================================
+ Coverage     53.1444%   53.1846%   +0.0402%     
- Complexity      19371      19406        +35     
==================================================
  Files            2080       2080                
  Lines           99000      98991         -9     
  Branches        17363      17355         -8     
==================================================
+ Hits            52613      52648        +35     
+ Misses          38828      38792        -36     
+ Partials         7559       7551         -8     
Files with missing lines Coverage Δ
...ils/datastore/gorm/proxy/GroovyProxyFactory.groovy 80.4348% <100.0000%> (+36.9565%) ⬆️
...s/datastore/gorm/proxy/ProxyInstanceMetaClass.java 100.0000% <100.0000%> (+52.7273%) ⬆️

... and 4 files with indirect coverage changes

🚀 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 and others added 2 commits August 15, 2026 19:36
Making protected getIdDynamic/setMetaClassDynamic/unwrapHandleMetaClass
static would silently break binary compatibility for any subclass
overriding them, since static methods aren't polymorphic. Suppress the
IntelliJ inspection instead, matching the existing
@SuppressWarnings('GrMethodMayBeStatic') convention used elsewhere in
the repo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cover the previously-untested target property/attribute cases in
getProperty/getAttribute, the already-initiated branch of the
class/domainClass ternary, and the remaining argument-shape branches
of the setMetaClass special case in invokeMethod/setProperty. File is
now fully line- and branch-covered.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@borinquenkid borinquenkid added this to the grails:8.1.0-M1 milestone Aug 16, 2026
@borinquenkid
borinquenkid requested review from jdaugherty and a lite review from Copilot August 16, 2026 01:06

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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/proxy/ProxyInstanceMetaClassSpec.groovy:103

  • The test name says the call “delegates” for getTarget/initialize, but ProxyInstanceMetaClass.invokeMethod returns getProxyTarget() directly for those method names (no delegate.invokeMethod call). Removing the unused delegate stub and renaming the test avoids misleading future readers.
    void "invokeMethod resolves the target and delegates for getTarget/initialize"() {
        given:
        ProxyInstanceMetaClass metaClass = newMetaClass()
        session.retrieve(ProxyInstanceTestTarget, 11L) >> target
        delegate.invokeMethod(target, methodName, [] as Object[]) >> target

@testlens-app

testlens-app Bot commented Aug 16, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

⚠️ TestLens detected flakiness ⚠️

Test Summary

CI / Build Grails-Core (macOS JDK 21) > :grails-wrapper:test

Test Runs Flakiness
GrailsUpdaterSpec > remote wrapper rejects HTTP redirect responses ❌ ✅ 0% 🟢

🏷️ Commit: 55d4b81
▶️ Tests: 23735 executed
⚪️ Checks: 78/78 completed


Learn more about TestLens at testlens.app.

@borinquenkid borinquenkid moved this to In Progress in Apache Grails Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants