-
Notifications
You must be signed in to change notification settings - Fork 191
JS-1108 Fix false positives in S7739 for custom Promise/thenable implementations #6279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JS-1108 Fix false positives in S7739 for custom Promise/thenable implementations #6279
Conversation
Tests cover intentional thenable implementations that should not raise issues: - Prototype extension with then method (ReactPromise pattern) - RHS delegation with bind (ant-design, vuetify pattern) - RHS delegation directly to another object's then (jQuery readyList) - Deferred class with then method (jQuery.Deferred pattern) - Class/function named "Promise" with then method (polyfill pattern) - Object with both then AND catch methods (complete thenable implementation) Also includes true positive test cases that should continue to raise issues. Relates to JS-1108
Enhance the interceptReport decorator to recognize intentional Promise/thenable implementations that should not trigger the no-thenable rule. The fix adds checks for: - RHS delegation pattern: obj.then = promise.then or obj.then = promise.then.bind(promise) - Promise/Deferred class context: then defined in function/class named Promise or Deferred - Prototype extension: X.prototype.then assignments - Sibling thenable methods: objects with both then and catch/finally These patterns represent legitimate thenable implementations used in Promise polyfills (angular.js), Deferred patterns (jQuery), and objects made awaitable for Promise interoperability (ant-design, vuetify, React). The implementation follows the proposed approach from the Jira ticket, including the feedback to check for the 'then' property in isPrototypeThenAssignment. Relates to JS-1108
Extend the isDelegatingToPromiseThen() check to handle arrow function patterns like `result.then = (args) => promise.then(args)`. This pattern is used in ant-design's message components to make objects awaitable by delegating to an underlying Promise. The fix adds two new helper functions: - isArrowFunctionDelegatingToThen(): detects arrow functions whose body calls X.then() - isCallToThenMethod(): checks if a CallExpression calls .then() Also added a test case covering the arrow function delegation pattern.
Synced expected ruling files from actual results and removed orphaned expected files that no longer have corresponding actual ruling files. Ruling Status: PASS (rule-specific projects refined successfully) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Replace `!objectExpr || objectExpr.type !== 'ObjectExpression'` with the more concise optional chain expression `objectExpr?.type !== 'ObjectExpression'` in hasSiblingThenableMethods() to address S6582 (prefer-optional-chain).
Ruling ReportCode no longer flagged (8 issues)S7739ag-grid/src/ts/misc/simpleHttpRequest.ts:26 24 | private thenFunc: (result: any)=>void;
25 |
> 26 | public then(func: (result: any)=>void) {
27 | this.thenFunc = func;
28 | }angular.js/src/ng/animateRunner.js:128 126 | },
127 |
> 128 | then: function(resolveHandler, rejectHandler) {
129 | return this.getPromise().then(resolveHandler, rejectHandler);
130 | },angular.js/src/ng/q.js:320 318 |
319 | extend(Promise.prototype, {
> 320 | then: function(onFulfilled, onRejected, progressBack) {
321 | if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {
322 | return this;ant-design/components/message/hooks/useMessage.tsx:65 63 | }
64 | };
> 65 | result.then = (filled: ThenableArgument, rejected: ThenableArgument) =>
66 | closePromise.then(filled, rejected);
67 | result.promise = closePromise;ant-design/components/message/index.tsx:199 197 | }
198 | };
> 199 | result.then = (filled: ThenableArgument, rejected: ThenableArgument) =>
200 | closePromise.then(filled, rejected);
201 | result.promise = closePromise;jquery/src/core/ready.js:55 53 | } );
54 |
> 55 | jQuery.ready.then = readyList.then;
56 |
57 | // The ready event handler and self cleanup methodjquery/src/deferred.js:102 100 | } ).promise();
101 | },
> 102 | then: function( onFulfilled, onRejected, onProgress ) {
103 | var maxDepth = 0;
104 | function resolve( depth, deferred, handler, special ) {vuetify/packages/vuetify/src/components/VForm/VForm.tsx:37 35 |
36 | const ready = form.validate()
> 37 | e.then = ready.then.bind(ready)
38 | e.catch = ready.catch.bind(ready)
39 | e.finally = ready.finally.bind(ready) |
|
|
github-actions[bot] 2026-01-28T12:12:59Z addressed
The fix correctly identifies these as legitimate Promise/thenable implementations per the approved approach. |
francois-mora-sonarsource
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM




Summary
Fixes false positives in rule S7739 (no-thenable) that were incorrectly flagging legitimate Promise and thenable implementations. The rule now recognizes intentional thenable patterns used in Promise polyfills, Deferred patterns, and objects made awaitable for Promise interoperability.
Key Changes
obj.then = promise.thenandobj.then = promise.then.bind(promise)patterns used in ant-design, vuetify, and jQueryresult.then = (args) => promise.then(args)patterns used in ant-design's message componentsthenmethods defined in functions/classes named "Promise" or "Deferred" (polyfill and jQuery patterns)X.prototype.thenassignments (React Promise pattern)thenandcatch/finallymethods as complete thenable implementationsTesting
Relates to JS-1108