SONARJAVA-6741 Implement new rule S9149: Static methods should not hide methods from superclasses - #5911
SONARJAVA-6741 Implement new rule S9149: Static methods should not hide methods from superclasses#5911romainbrenguier wants to merge 3 commits into
Conversation
Detect static methods in subclasses that hide static methods from superclasses by having the same name and parameter types. This catches a common source of confusion where developers expect polymorphic behavior but get compile-time binding instead.
| Symbol.TypeSymbol owner = (Symbol.TypeSymbol) methodSymbol.owner(); | ||
| Type superClass = owner.superClass(); | ||
| while (superClass != null) { | ||
| if (checkHiding(methodTree, methodSymbol, superClass)) { | ||
| return; | ||
| } | ||
| superClass = superClass.symbol().superClass(); | ||
| } |
There was a problem hiding this comment.
💡 Quality: Redundant hierarchy walk: lookupSymbols already returns inherited members
Symbol.TypeSymbol.lookupSymbols(name) returns symbols accessible from the type including inherited members (per the API javadoc, contrasted with memberSymbols() which does not). Therefore calling it on the immediate superclass already covers the whole ancestor chain, and the surrounding while (superClass != null) loop that re-invokes checkHiding on every ancestor is redundant work. Consider dropping the loop and calling checkHiding once on owner.superClass(), which also simplifies the code.
lookupSymbols already resolves inherited static methods, so a single check on the direct superclass suffices.:
Type superClass = owner.superClass();
if (superClass != null) {
checkHiding(methodTree, methodSymbol, superClass);
}
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
|
❌ Ruling needs updating. A fix PR has been created: #5912 Please review and merge it into your branch. |
Ruling Diff SummaryDetected changes in 2 rule files: 0 issues removed, 70 issues added. S9149 (
|
Remove ChildF and ChildG test cases that caused compilation errors (static/instance method mixing is a Java compile error, not a valid hiding scenario). Add S9149 to the Sonar way quality profile. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CI failed: Integration test failures occurred due to mismatched ruling baselines and missing test output directories introduced by the new S9149 rule changes.OverviewTwo integration test failures were found across jobs: one due to an empty or missing actual output directory during the autoscan integration test, and another due to a diff mismatch in the ruling QA integration test caused by the new rule S9149 implementation. FailuresAutoscan Diff Comparison Failure (confidence: high)
Ruling QA Integration Test Mismatch (confidence: high)
Summary
Code Review 👍 Approved with suggestions 1 resolved / 2 findingsImplements rule S9149 to detect static methods in subclasses that hide superclass static methods. Consider removing the redundant hierarchy walk since lookupSymbols already returns inherited members. 💡 Quality: Redundant hierarchy walk: lookupSymbols already returns inherited members📄 java-checks/src/main/java/org/sonar/java/checks/StaticMethodHidingCheck.java:44-51 📄 java-checks/src/main/java/org/sonar/java/checks/StaticMethodHidingCheck.java:55
lookupSymbols already resolves inherited static methods, so a single check on the direct superclass suffices.✅ 1 resolved✅ Quality: S9149 not added to Sonar_way profile; rule inactive by default
🤖 Prompt for agentsImplementation Status ✅ 1 / 1 issues implemented✅ SONARJAVA-6741 — 1 / 1 objectivesThe PR successfully implements the new rule S9149 ("Static methods should not hide methods from superclasses") along with its test cases, metadata, documentation, and ruling configuration. ✅ 1 complete
Tip Comment OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
|




Detect static methods in subclasses that hide static methods from superclasses by having the same name and parameter types. This catches a common source of confusion where developers expect polymorphic behavior but get compile-time binding instead.