SONARJAVA-6787 Implement new rule S9351: "BigDecimal.compareTo()" should be used instead of "equals()" for numerical comparison - #5945
SONARJAVA-6787 Implement new rule S9351: "BigDecimal.compareTo()" should be used instead of "equals()" for numerical comparison#5945nathsou wants to merge 4 commits into
Conversation
| private static boolean isLoopInvariant(ExpressionTree arg, Tree loop) { | ||
| ExpressionTree expression = ExpressionUtils.skipParentheses(arg); | ||
| if (expression.is(Tree.Kind.IDENTIFIER)) { | ||
| Symbol symbol = ((IdentifierTree) expression).symbol(); | ||
| if (!symbol.isVariableSymbol()) { | ||
| return false; | ||
| } | ||
| if (symbol.owner().isTypeSymbol()) { | ||
| return symbol.isFinal(); | ||
| } | ||
| var collector = new DeclaredOrAssignedLocalsCollector(); | ||
| loop.accept(collector); | ||
| return !collector.names.contains(((IdentifierTree) expression).name()); | ||
| } | ||
| return ExpressionUtils.resolveAsConstant(expression) != null; |
There was a problem hiding this comment.
💡 Performance: Loop-invariance check re-traverses entire loop per matched call
In isLoopInvariant, for every identifier argument of every matched invocation inside a loop, a fresh DeclaredOrAssignedLocalsCollector traverses the whole loop subtree (loop.accept(collector)). For loops containing many matched invocations this is repeated O(matches) times over the loop body, which is wasteful on large loops. Consider computing the assigned/declared-locals set once per loop and caching it.
Was this helpful? React with 👍 / 👎
…uld be used instead of "equals()" for numerical comparison
9bf2e3a to
1fe33ca
Compare
…s and mark quickfix infeasible
Code Review 👍 Approved with suggestions 2 resolved / 3 findingsImplements rule S9351 to flag BigDecimal.equals() usage in favor of compareTo(), resolving incorrect receiver matching and metadata issues. Consider optimizing loop traversal performance in isLoopInvariant to avoid redundant subtree visits. 💡 Performance: Loop-invariance check re-traverses entire loop per matched call📄 java-checks/src/main/java/org/sonar/java/checks/CompilationOrPreparationInLoopCheck.java:152-166 In isLoopInvariant, for every identifier argument of every matched invocation inside a loop, a fresh DeclaredOrAssignedLocalsCollector traverses the whole loop subtree (loop.accept(collector)). For loops containing many matched invocations this is repeated O(matches) times over the loop body, which is wasteful on large loops. Consider computing the assigned/declared-locals set once per loop and caching it. ✅ 2 resolved✅ Quality: S9351.json declares quickfix "targeted" but no quick fix implemented
✅ Edge Case: BigDecimalEqualsCheck flags equals() on any receiver when arg is BigDecimal
🤖 Prompt for agentsOptionsAuto-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 |
|




Description
Implements rule S9351:
"BigDecimal.compareTo()\" should be used instead of \"equals()\" for numerical comparison.Implementation Summary
BigDecimalEqualsCheckwhich detects calls toBigDecimal.equals(Object)andObjects.equals(...)/com.google.common.base.Objects.equal(...)involvingBigDecimaloperands.equals(Object)method definitions overridingObject.equals(Object)where scale-sensitive comparison is required forhashCode()consistency.BigDecimalEqualsCheckTestandBigDecimalEqualsCheckSample.🤖 Generated with AI assistance.
Summary by Gitar
CompilationOrPreparationInLoopCheckto detect regex compilation or statement preparation inside loops// NOSONARexception rationale forBigDecimal.compareTo()usageThis will update automatically on new commits.