JS-1971: Extend S8785 coverage#7452
Conversation
This comment has been minimized.
This comment has been minimized.
e8a2986 to
e1b6f54
Compare
| function visitRaisingSuiteCallback( | ||
| context: Rule.RuleContext, | ||
| parserServices: Rule.RuleContext['sourceCode']['parserServices'], | ||
| raisingSuiteCallback: RaisingSuiteCallback, | ||
| ): void { | ||
| const { callback, byReference } = raisingSuiteCallback; | ||
| const asyncSuiteOutcome = callback.async | ||
| ? analyzeAsyncSuiteCallback(context, parserServices, callback) | ||
| : undefined; | ||
|
|
||
| if (asyncSuiteOutcome?.kind === 'noTopLevelAwait') { | ||
| // Async callback, no top-level await: remove the misleading async keyword. | ||
| reportRemoveAsync(context, callback, !byReference); | ||
| } | ||
|
|
There was a problem hiding this comment.
💡 Edge Case: Referenced async callback may be reported once per suite
getRaisingSuiteCallback now resolves a callback passed by reference (an identifier) to its function-like declaration and returns it as byReference. When the same async function is shared across multiple suite registrations (e.g. describe('a', register); describe('b', register);), each CallExpression visit resolves to the identical declaration node, and visitRaisingSuiteCallback will call reportRemoveAsync/reportUnawaitedAsyncHelperCalls on that same declaration for every referencing suite. Since the report helper does not deduplicate and ESLint core does not dedupe identical descriptors, this emits duplicate issues at the same location on the shared declaration. Consider deduplicating reports on referenced declarations (e.g. track already-reported declaration nodes in the rule's per-file state) so a shared helper is flagged only once. This is an edge case (multiple suites sharing one referenced callback), hence minor.
Was this helpful? React with 👍 / 👎
| "code": { | ||
| "impacts": { | ||
| "MAINTAINABILITY": "MEDIUM" | ||
| "MAINTAINABILITY": "LOW" |
There was a problem hiding this comment.
💡 Quality: Unrelated S6582 severity change bundled in S8785 PR
This PR is titled "Extend S8785 coverage" yet also changes S6582.json, downgrading its impact from MAINTAINABILITY MEDIUM to LOW and defaultSeverity from Major to Minor. This behavioral metadata change for an unrelated rule is easy to miss during review and complicates rollback/bisection if it turns out to be unintended. If this is an intentional RSPEC metadata sync it is fine to keep, but it would be cleaner to split it into a separate commit/PR or note it explicitly in the description.
Was this helpful? React with 👍 / 👎
Ruling Report✅ No changes to ruling expected issues in this PR |
nathsou
left a comment
There was a problem hiding this comment.
Reviewed the S8785 extension logic (async-analysis.ts, call-to-declaration.ts, rule.ts). Found a real false-negative gap, an overlapping-secondaries bug, a false-negative from a bare-name check, a reuse opportunity, and a minor efficiency note. Details inline.
e1b6f54 to
a769bd1
Compare
| function findNextTopLevelAwaitAfter( | ||
| sourceCode: Rule.RuleContext['sourceCode'], | ||
| body: estree.BlockStatement, | ||
| afterNode: estree.Node, | ||
| ): estree.Node | undefined { | ||
| const afterEnd = sourceCode.getRange(afterNode)[1]; | ||
| for (const stmt of body.body) { | ||
| if ( | ||
| stmt.type === 'ExpressionStatement' && | ||
| stmt.expression.type === 'AwaitExpression' && | ||
| sourceCode.getRange(stmt)[0] >= afterEnd | ||
| ) { | ||
| return stmt.expression; | ||
| } | ||
| } |
There was a problem hiding this comment.
💡 Edge Case: Secondary-location overlap cap misses nested awaited helpers
findNextTopLevelAwaitAfter (rule.ts:433-449) only scans the direct statements of body.body for the next awaited expression, but reportUnawaitedAsyncHelperCalls descends into nested blocks (if/try/loops) to find awaited helper calls, and findTestsRegisteredAfter likewise descends into nested blocks when collecting dropped tests.
Consequently, if an awaited helper call lives inside a nested block and the following awaited helper is also nested (not a top-level statement of the describe body), findNextTopLevelAwaitAfter returns undefined, so the beforeNode cap becomes Infinity. The first helper's report then collects dropped tests all the way to the end of the callback, overlapping with the second helper's secondaries — the exact duplication this commit aims to prevent.
This is an uncommon shape (awaited helpers nested inside conditionals/loops), so severity is minor. If desired, findNextTopLevelAwaitAfter could walk the same node set (descending into non-function children) used by the other helpers so the cap is consistent.
Was this helpful? React with 👍 / 👎
| // Block body: seed the stack with direct statement children. | ||
| // Concise-body arrow (`() => expr`): seed with the qexpression itself so it falls through the | ||
| // while loop below. The expression is identified inside the loop by `current === body`. |
There was a problem hiding this comment.
💡 Quality: Typo 'qexpression' in reportUnawaitedAsyncHelperCalls comment
The comment at rule.ts:363 reads "seed with the qexpression itself" — 'qexpression' should be 'expression'. Minor wording cleanup in a newly added comment.
Fix typo 'qexpression' -> 'expression'.:
// Concise-body arrow (`() => expr`): seed with the expression itself so it falls through the
Was this helpful? React with 👍 / 👎
|
Code Review 👍 Approved with suggestions 2 resolved / 6 findingsExtends S8785 coverage to async helper functions with improved analysis modularity and metadata updates. Consider isolating the unrelated S6582 severity change and addressing the potential reporting duplication of referenced async callbacks. 💡 Edge Case: Referenced async callback may be reported once per suite📄 packages/analysis/src/jsts/rules/S8785/rule.ts:120-134 📄 packages/analysis/src/jsts/rules/S8785/rule.ts:242-256
💡 Quality: Unrelated S6582 severity change bundled in S8785 PR📄 sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6582.json:5 📄 sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6582.json:18 This PR is titled "Extend S8785 coverage" yet also changes S6582.json, downgrading its impact from MAINTAINABILITY MEDIUM to LOW and defaultSeverity from Major to Minor. This behavioral metadata change for an unrelated rule is easy to miss during review and complicates rollback/bisection if it turns out to be unintended. If this is an intentional RSPEC metadata sync it is fine to keep, but it would be cleaner to split it into a separate commit/PR or note it explicitly in the description. 💡 Edge Case: Secondary-location overlap cap misses nested awaited helpers📄 packages/analysis/src/jsts/rules/S8785/rule.ts:433-447 📄 packages/analysis/src/jsts/rules/S8785/rule.ts:384-396 📄 packages/analysis/src/jsts/rules/S8785/rule.ts:517-525 📄 packages/analysis/src/jsts/rules/S8785/async-analysis.ts:118-132
Consequently, if an awaited helper call lives inside a nested block and the following awaited helper is also nested (not a top-level statement of the describe body), This is an uncommon shape (awaited helpers nested inside conditionals/loops), so severity is minor. If desired, 💡 Quality: Typo 'qexpression' in reportUnawaitedAsyncHelperCalls comment📄 packages/analysis/src/jsts/rules/S8785/rule.ts:362-364 The comment at rule.ts:363 reads "seed with the qexpression itself" — 'qexpression' should be 'expression'. Minor wording cleanup in a newly added comment. Fix typo 'qexpression' -> 'expression'.✅ 2 resolved✅ Performance: Type checker resolves signature for every call statement in suite
✅ Edge Case: reportUnawaitedAsyncHelperCalls reads callback.body.type without null guard
🤖 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 |





Summary by Gitar
asynchelper functions that silently drop tests when called within test suites.async-analysis.tsandcall-to-declaration.tsfor improved maintainability.rule.tsto orchestrate detection of both top-levelawaitand unawaitedasynchelper calls.S5914andS6582rule metadata (titles, severity, and quick-fix indicators).This will update automatically on new commits.