Skip to content

JS-1308 Fix S3516 false positives when same return value has different semantic meanings#6588

Open
sonar-nigel[bot] wants to merge 4 commits intomasterfrom
fix/JS-1308-fix-fp-on-s3516-same-return-value-with-different-semantic-meanings-sonnet
Open

JS-1308 Fix S3516 false positives when same return value has different semantic meanings#6588
sonar-nigel[bot] wants to merge 4 commits intomasterfrom
fix/JS-1308-fix-fp-on-s3516-same-return-value-with-different-semantic-meanings-sonnet

Conversation

@sonar-nigel
Copy link
Contributor

@sonar-nigel sonar-nigel bot commented Mar 13, 2026

Rule S3516 raised false positives on functions that intentionally return the same literal value across branches where each return represents a distinct semantic outcome — for example, event handlers returning false for different propagation decisions, or status functions returning true for "skipped" vs "completed".

Root Cause

The rule flagged all literal invariant returns without checking whether the return branches performed meaningful work beforehand. Pure early-exit branches and side-effect branches were treated identically.

Fix

Two flags were added to FunctionContext:

  • hasSideEffectBranchWithReturn — set when a branch has both side effects and a return
  • hasReturnBranchWithoutSideEffect — set when a branch returns without side effects

Suppression now applies only when all branching returns are accompanied by side effects. A pure early-exit branch (returning the same literal with no side effect) still triggers the rule.

Behavior Preserved

  • The original noncompliant spec example continues to raise an issue
  • The Redux switch-case pattern (all branches have side effects) is correctly suppressed
  • Event handler and status function patterns with intentional same-value returns are no longer flagged

Validation

Reviewed 13 ruling entries across ace, TypeScript, redux, desktop, and mootools-core projects — all match expected behavior.

Relates to JS-1308

Vibe Bot and others added 4 commits March 13, 2026 17:15
Tests cover the scenario where a function returns the same literal value
across multiple branches but each branch performs a distinct side effect,
giving each return a different semantic meaning (e.g. "skipped" vs
"completed", "handled escape" vs "handled enter" vs "not handled").

The valid cases verify suppression when all return-containing branches have
side effects and no pure-return branch exists. The new invalid case verifies
that suppression does not apply when a pure-return guard branch is present
alongside a side-effect+return branch.

Relates to JS-1308
Rule S3516 raised false positives on functions that intentionally return
the same literal value across branches when each return represents a
different semantic outcome (e.g., event handlers using false for distinct
propagation decisions, or status functions using true for "skipped" vs
"completed"). The root cause was that the rule flagged all literal
invariant returns without distinguishing whether each return branch was
doing meaningful work.

Fix adds two flags to FunctionContext: hasSideEffectBranchWithReturn
(set when a branch has both side effects and a return) and
hasReturnBranchWithoutSideEffect (set when a branch has a return but no
side effects). Suppression now applies only when ALL branching returns
are accompanied by side effects, ensuring that pure early-exit branches
(no side effect before returning the same literal) still trigger the
rule. This preserves the original noncompliant spec example and the
Redux switch-case pattern while fixing the identified false positives.

Relates to JS-1308
Reviewed 13 ruling entries across ace, TypeScript, redux, desktop, and mootools-core
projects. Confirmed that the implementation correctly distinguishes between:
- Pure returns (should raise): Functions with at least one branch that returns
  the same value without side effects (suspicious code)
- Semantic returns (should not raise): Functions where ALL return paths perform
  meaningful side effects before returning the same value (intentional patterns
  like event handlers, status functions, and guards)

All 13 entries match expected behavior. No implementation changes needed.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Ticket: JS-1308

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions
Copy link
Contributor

Ruling Report

Code no longer flagged (4 issues)

S3516

ace/lib/ace/mode/html/saxparser.js:1766

  1764 | 	}
  1765 | 
> 1766 | 	function markup_declaration_open_state(buffer) {
  1767 | 		var chars = buffer.shift(2);
  1768 | 		if (chars === '--') {

ace/lib/ace/mode/html/saxparser.js:2007

  2005 | 	}
  2006 | 
> 2007 | 	function after_doctype_name_state(buffer) {
  2008 | 		var data = buffer.char();
  2009 | 		if (data === InputStream.EOF) {

custom-yaml/lambda-block-folded.yaml:111

   109 |             responseData.Key = key;
   110 |             console.log("LAMBDA FUNCTION BUCKET:",bucket,"KEY:",key);
>  111 |             (async function(){
   112 |               if (event.RequestType && event.RequestType == 'Create'){
   113 |                 params.Bucket = bucket;

mootools-core/Source/Slick/Slick.Parser.js:106

   104 | );
   105 | 
>  106 | function parser(
   107 | 	rawMatch,
   108 | 

@sonarqube-next
Copy link

@sonar-nigel sonar-nigel bot marked this pull request as ready for review March 13, 2026 18:01
@sonar-nigel sonar-nigel bot requested a review from a team March 13, 2026 18:01
@francois-mora-sonarsource
Copy link
Contributor

LGTM - fixes S3516 false positives when all branching returns are accompanied by side effects (e.g. guard-logging patterns, event handlers), by tracking whether any pure-return branch exists and suppressing only when none do — #6588

@sonar-nigel
Copy link
Contributor Author

sonar-nigel bot commented Mar 17, 2026

Thank you for the review and approval!

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.

1 participant