Skip to content

SONARJAVA-7241: Improve S9358 to only raise when differing operands are simple and have the same type - #6402

Merged
romainbrenguier merged 2 commits into
masterfrom
romain/sonarjava-7241
Oct 26, 2026
Merged

romainbrenguier merged 2 commits into
masterfrom
romain/sonarjava-7241

Conversation

@romainbrenguier

@romainbrenguier romainbrenguier commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

S9358 (Conditional expressions should not duplicate operations in both branches) raised many issues where moving the condition inside the operation would hurt readability or change semantics.

The rule now only raises when the single differing argument (or array index) in both branches:

  • is a simple operand: identifier, literal, negative literal, or field access chain (e.g. this.x, a.b). Method invocations, lambdas, method references, casts, binary expressions, object creations... are no longer considered.
  • has the same type in both branches (when known), so the rewrite cannot introduce boxing/unboxing (possible NPE), widening, or a different overload resolution.

Ruling

Removed issues (all involving complex arguments: nested calls, lambdas, casts):

  • guava: RegularImmutableTable x2, TreeMultiset, MessageDigestHashFunction
  • eclipse-jetty: QuotedQualityCSV, MBeanContainer x2, CounterStatisticTest
  • sonarqube-6.5: ConditionEvaluator, RuleActivator, ValuesAction

Kept: JavaVersion (version[0] vs version[1]) and QualityGateConditionsUpdater (differing string literals).

🤖 Generated with Claude Code

Agent workflow

Tool link: https://github.com/SonarSource/languages-experimental-tooling/tree/romain/my-tickets/personal/romain-brenguier
PR created using uv run create_with_claude.py SONARJAVA-7241.txt

PR updated using uv run update_with_claude.py --prompt "Implement the action plan described in the document Can we either make sameType return a ternary value or rename it sameTypeOrUnknown?." -a "Can we either make sameType return a ternary value or rename it sameTypeOrUnknown?" -g "claude"

…simple and have the same type

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

SONARJAVA-7241

@github-actions

Copy link
Copy Markdown
Contributor

Ruling Diff Summary

Detected changes in 4 rule files: 14 issues removed, 0 issues added.

S9358 (java) on eclipse-jetty - 4 issues removed, 0 issues added

Removed jetty-http/src/main/java/org/eclipse/jetty/http/QuotedQualityCSV.java (line 129)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/QuotedQualityCSV.java)

Removed jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java (line 362)

(source file not found at this revision: jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java)

Removed jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java (line 373)

(source file not found at this revision: jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java)

Removed jetty-util/src/test/java/org/eclipse/jetty/util/statistic/CounterStatisticTest.java (line 91)

(source file not found at this revision: jetty-util/src/test/java/org/eclipse/jetty/util/statistic/CounterStatisticTest.java)
S9358 (java) on eclipse-jetty-similar-to-main - 3 issues removed, 0 issues added - deleted ruling file

Removed jetty-http/src/main/java/org/eclipse/jetty/http/QuotedQualityCSV.java (line 129)

(source file not found at this revision: jetty-http/src/main/java/org/eclipse/jetty/http/QuotedQualityCSV.java)

Removed jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java (line 362)

(source file not found at this revision: jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java)

Removed jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java (line 373)

(source file not found at this revision: jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java)
S9358 (java) on guava - 4 issues removed, 0 issues added - deleted ruling file

Removed src/com/google/common/collect/RegularImmutableTable.java (line 151)

       146 |     for (Cell<R, C, V> cell : cells) {
       147 |       rowSpaceBuilder.add(cell.getRowKey());
       148 |       columnSpaceBuilder.add(cell.getColumnKey());
       149 |     }
       150 | 
>>>    151 |     ImmutableSet<R> rowSpace = (rowComparator == null)
       152 |         ? ImmutableSet.copyOf(rowSpaceBuilder)
       153 |         : ImmutableSet.copyOf(
       154 |             Ordering.from(rowComparator).immutableSortedCopy(rowSpaceBuilder));
       155 |     ImmutableSet<C> columnSpace = (columnComparator == null)
       156 |         ? ImmutableSet.copyOf(columnSpaceBuilder)

Removed src/com/google/common/collect/RegularImmutableTable.java (line 155)

       150 | 
       151 |     ImmutableSet<R> rowSpace = (rowComparator == null)
       152 |         ? ImmutableSet.copyOf(rowSpaceBuilder)
       153 |         : ImmutableSet.copyOf(
       154 |             Ordering.from(rowComparator).immutableSortedCopy(rowSpaceBuilder));
>>>    155 |     ImmutableSet<C> columnSpace = (columnComparator == null)
       156 |         ? ImmutableSet.copyOf(columnSpaceBuilder)
       157 |         : ImmutableSet.copyOf(
       158 |             Ordering.from(columnComparator).immutableSortedCopy(columnSpaceBuilder));
       159 | 
       160 |     // use a dense table if more than half of the cells have values

Removed src/com/google/common/collect/TreeMultiset.java (line 91)

        86 |    *          the comparator that will be used to sort this multiset. A null value indicates that
        87 |    *          the elements' <i>natural ordering</i> should be used.
        88 |    */
        89 |   @SuppressWarnings("unchecked")
        90 |   public static <E> TreeMultiset<E> create(@Nullable Comparator<? super E> comparator) {
>>>     91 |     return (comparator == null)
        92 |         ? new TreeMultiset<E>((Comparator) Ordering.natural())
        93 |         : new TreeMultiset<E>(comparator);
        94 |   }
        95 | 
        96 |   /**

Removed src/com/google/common/hash/MessageDigestHashFunction.java (line 156)

       151 | 
       152 |     @Override
       153 |     public HashCode hash() {
       154 |       checkNotDone();
       155 |       done = true;
>>>    156 |       return (bytes == digest.getDigestLength())
       157 |           ? HashCode.fromBytesNoCopy(digest.digest())
       158 |           : HashCode.fromBytesNoCopy(Arrays.copyOf(digest.digest(), bytes));
       159 |     }
       160 |   }
       161 | }
S9358 (java) on sonarqube-6.5 - 3 issues removed, 0 issues added

Removed src/main/java/org/sonar/server/computation/task/projectanalysis/qualitygate/ConditionEvaluator.java (line 113)

(source file not found at this revision: src/main/java/org/sonar/server/computation/task/projectanalysis/qualitygate/ConditionEvaluator.java)

Removed src/main/java/org/sonar/server/qualityprofile/RuleActivator.java (line 200)

(source file not found at this revision: src/main/java/org/sonar/server/qualityprofile/RuleActivator.java)

Removed src/main/java/org/sonar/server/setting/ws/ValuesAction.java (line 247)

(source file not found at this revision: src/main/java/org/sonar/server/setting/ws/ValuesAction.java)

@romainbrenguier
romainbrenguier marked this pull request as ready for review October 26, 2026 12:25

private static boolean sameType(Type left, Type right) {
if (left.isUnknown() || right.isUnknown()) {
return true;

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.

Returning true could be challenged here.
If we have no information about the types, it would be less risky to return false.
I'm not sure how often type information is missing though so this is your call.

@romainbrenguier romainbrenguier Oct 26, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Renamed to sameTypeOrUnknown to be clearer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@sonarqube-next

Copy link
Copy Markdown
Contributor

@gitar-bot

gitar-bot Bot commented Oct 26, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

🟡 Medium risk · Restricting S9358 to simple, same-typed differing operands could suppress findings and alter reported issue counts in analyzed projects.

Narrows S9358 to raise only when the single differing operand in both branches is a simple identifier, literal, negative literal, or field access chain with the same type, avoiding readability and semantic regressions from complex arguments. No issues found.

Verification Rules 2/2 met Repos 4 inspected

Functional validation No results

Rules 2 passed 1 not applicable

✅ Internal artifact registries
✅ Repository license compliance

Broader impact Repos 4 inspected
Cross-repo 4 repositories inspected 0 open impacts

SonarSource/sonarlint-intellij Inspected
SonarSource/sonarlint-vscode Inspected
SonarSource/sonarlint-language-server Inspected
SonarSource/sonar-java-symbolic-execution Inspected

Auto-approval Not enabled

Set up

For more verification details, comment gitar display:verbose.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing compact verification results.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@romainbrenguier
romainbrenguier merged commit f5bb12d into master Oct 26, 2026
20 checks passed
@romainbrenguier
romainbrenguier deleted the romain/sonarjava-7241 branch October 26, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants