SONARJAVA-6489: Implement rule S8909 - Quarkus CacheKeyGenerator should be instantiable#5699
SONARJAVA-6489: Implement rule S8909 - Quarkus CacheKeyGenerator should be instantiable#5699romainbrenguier wants to merge 6 commits into
Conversation
This commit contains partial work that failed to complete. Continuing with SA-CI and PR creation.
- Fixed CacheKeyGeneratorInstantiableCheck implementation to properly detect issues - Added mock-up CacheKeyGenerator interface for testing instead of external dependency - Moved test sample to compiling sources with proper mock-ups - Test now passes successfully Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Generated HTML and JSON rule metadata from RSPEC - Added S8909 to Sonar way profile - Rule detects non-instantiable CacheKeyGenerator implementations Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Comment: <details open> <summary><b>Code Review</b> <kbd>⚠️ Changes requested</kbd> <kbd>1 resolved / 3 findings</kbd></summary> Implements rule S8909 for Quarkus CacheKeyGenerator instantiability, but introduces a redundant dependency conflict and incorrectly evaluates implicit package-private constructors as public. <details> <summary>⚠️ <b>Quality:</b> Redundant quarkus-cache dependency conflicts with local mock interface</summary> <kbd>📄 <a href="https://github.com/SonarSource/sonar-java/pull/5699/files#diff-65b481d7948308268695c9b6ced91981e76b2f17492fa537fa94e0e1acc6057dR189-R194">java-checks-test-sources/default/pom.xml:189-194</a></kbd> <kbd>📄 <a href="https://github.com/SonarSource/sonar-java/pull/5699/files#diff-8eba708ee0e692d479690a9177582d8d3295836ae8036bddc835e583fd5f26c9R8-R9">java-checks-test-sources/default/src/main/java/io/quarkus/cache/CacheKeyGenerator.java:8-9</a></kbd> The PR adds the real `io.quarkus:quarkus-cache:3.2.0.Final` dependency in pom.xml AND also adds a hand-written mock `io/quarkus/cache/CacheKeyGenerator.java` with the same fully-qualified name. The PR description states the mock was created "avoiding external dependency", which directly contradicts also adding the dependency. Having both a local source file and a jar that define `io.quarkus.cache.CacheKeyGenerator` on the same compile path is at best redundant and can cause type-resolution ambiguity / duplicate-type issues in the test-sources module. Pick one approach: either rely on the real dependency and delete the mock, or keep the mock and drop the new dependency from pom.xml (consistent with the stated intent). Note the real Quarkus `CacheKeyGenerator` also declares a default `boolean generationGroup()` method, so the mock is not a faithful copy. </details> <details> <summary>💡 <b>Edge Case:</b> Implicit constructor of package-private class treated as public</summary> <kbd>📄 <a href="https://github.com/SonarSource/sonar-java/pull/5699/files#diff-163bcab034b13aa1549ddbee8f2fe2cde6ae0fa4bc77bce4da28044ef134cdf5R86-R98">java-checks/src/main/java/org/sonar/java/checks/quarkus/CacheKeyGeneratorInstantiableCheck.java:86-98</a></kbd> <kbd>📄 <a href="https://github.com/SonarSource/sonar-java/pull/5699/files#diff-163bcab034b13aa1549ddbee8f2fe2cde6ae0fa4bc77bce4da28044ef134cdf5R49-R51">java-checks/src/main/java/org/sonar/java/checks/quarkus/CacheKeyGeneratorInstantiableCheck.java:49-51</a></kbd> `hasPublicNoArgsConstructor` returns true when the no-arg constructor's `declaration() == null` (implicit default constructor), regardless of visibility. An implicit default constructor inherits the class's access level, so for a package-private (or private nested) class implementing `CacheKeyGenerator` the implicit constructor is NOT public. The issue message explicitly tells users to add a "public no-args constructor", yet such a class is reported compliant — an inconsistency that can produce a false negative if Quarkus requires a public constructor for non-CDI instantiation. Consider also checking the effective visibility of the implicit constructor (e.g. require the class itself to be public), or align the message with the actual check. Also note records/enums implementing the interface are not covered since `nodesToVisit()` only registers `Tree.Kind.CLASS`. </details> <details> <summary><kbd>✅ 1 resolved</kbd></summary> <details> <summary>✅ <b>Quality:</b> Missing S8909 rule metadata (HTML + JSON) breaks build</summary> > <kbd>📄 java-checks/src/main/java/org/sonar/java/checks/quarkus/CacheKeyGeneratorInstantiableCheck.java:30</kbd> > The new rule `CacheKeyGeneratorInstantiableCheck` is annotated with `@Rule(key = "S8909")` and is auto-registered via `CheckListGenerator`, but no metadata files exist for it. `GeneratedCheckListTest` asserts that both `org/sonar/l10n/java/rules/java/S8909.html` and `S8909.json` exist for every registered rule (see GeneratedCheckListTest.java:137-142), and a Glob confirms neither file is present. Without these the rule has no description, no severity/type/profile assignment, and the test suite (hence the build) will fail. Add `S8909.html` (rule description) and `S8909.json` (metadata: title, type, status, tags, remediation, default severity, and SonarWay profile membership) under `java-checks/src/main/resources/org/sonar/l10n/java/rules/java/`. </details> </details> <details> <summary>🤖 <b>Prompt for agents</b></summary> ```` Code Review: Implements rule S8909 for Quarkus CacheKeyGenerator instantiability, but introduces a redundant dependency conflict and incorrectly evaluates implicit package-private constructors as public. 1.⚠️ Quality: Redundant quarkus-cache dependency conflicts with local mock interface Files: java-checks-test-sources/default/pom.xml:189-194, java-checks-test-sources/default/src/main/java/io/quarkus/cache/CacheKeyGenerator.java:8-9 The PR adds the real `io.quarkus:quarkus-cache:3.2.0.Final` dependency in pom.xml AND also adds a hand-written mock `io/quarkus/cache/CacheKeyGenerator.java` with the same fully-qualified name. The PR description states the mock was created "avoiding external dependency", which directly contradicts also adding the dependency. Having both a local source file and a jar that define `io.quarkus.cache.CacheKeyGenerator` on the same compile path is at best redundant and can cause type-resolution ambiguity / duplicate-type issues in the test-sources module. Pick one approach: either rely on the real dependency and delete the mock, or keep the mock and drop the new dependency from pom.xml (consistent with the stated intent). Note the real Quarkus `CacheKeyGenerator` also declares a default `boolean generationGroup()` method, so the mock is not a faithful copy. 2. 💡 Edge Case: Implicit constructor of package-private class treated as public Files: java-checks/src/main/java/org/sonar/java/checks/quarkus/CacheKeyGeneratorInstantiableCheck.java:86-98, java-checks/src/main/java/org/sonar/java/checks/quarkus/CacheKeyGeneratorInstantiableCheck.java:49-51 `hasPublicNoArgsConstructor` returns true when the no-arg constructor's `declaration() == null` (implicit default constructor), regardless of visibility. An implicit default constructor inherits the class's access level, so for a package-private (or private nested) class implementing `CacheKeyGenerator` the implicit constructor is NOT public. The issue message explicitly tells users to add a "public no-args constructor", yet such a class is reported compliant — an inconsistency that can produce a false negative if Quarkus requires a public constructor for non-CDI instantiation. Consider also checking the effective visibility of the implicit constructor (e.g. require the class itself to be public), or align the message with the actual check. Also note records/enums implementing the interface are not covered since `nodesToVisit()` only registers `Tree.Kind.CLASS`. ```` </details> </details> <details> <summary><b>Options</b> </summary> <kbd>Auto-apply is off</kbd> → Gitar will not commit updates to this branch.<br><kbd>Display: compact</kbd> → Showing less information.<br><kbd>Unblock</kbd> → Override a blocking verdict and allow merging. Comment with these commands to change: <table> <tr> <td><kbd>Auto-apply</kbd></td> <td><kbd>Compact</kbd></td> <td><kbd>Unblock</kbd></td> </tr> <tr> <td> ``` gitar auto-apply:on ``` </td> <td> ``` gitar display:verbose ``` </td> <td> ``` gitar unblock ``` </td> </tr> </table> </details> <sub>Was this helpful? React with 👍 / 👎 | [Gitar](https://gitar.ai)</sub>
- Fix Noncompliant marker length in CacheKeyGeneratorInstantiableCheckSample (50 carets -> 45 carets to match class name)
Add expected autoscan diff for new rule S8909 (3 false positives in autoscan mode) and update S6813 false negatives count (65 -> 68). Update test to expect 11 rules causing FPs instead of 10. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Code Review ✅ Approved 3 resolved / 3 findingsImplements rule S8909 to detect non-instantiable Quarkus CacheKeyGenerator classes. The build metadata, dependency conflicts, and package-private constructor false positives have all been resolved. ✅ 3 resolved✅ Quality: Missing S8909 rule metadata (HTML + JSON) breaks build
✅ Quality: Redundant quarkus-cache dependency conflicts with local mock interface
✅ Edge Case: Implicit constructor of package-private class treated as public
OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change:
Was this helpful? React with 👍 / 👎 | Gitar |
|




Summary
Implements rule S8909 to detect Quarkus
CacheKeyGeneratorimplementations that cannot be instantiated by the CDI container.Changes
CacheKeyGeneratorInstantiableCheckto detect classes implementingCacheKeyGeneratorthat:@ApplicationScoped,@Dependent, etc.)CacheKeyGeneratorinterface for testing (avoiding external dependency)Test Coverage
The rule detects:
The rule correctly ignores:
🤖 Generated with Claude Code