Skip to content

Commit 1d557ed

Browse files
authored
New rule: no-done-fail (#334)
Fixes #332
1 parent 0e41a53 commit 1d557ed

File tree

7 files changed

+112
-1
lines changed

7 files changed

+112
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ Where rules are included in the configs `recommended`, `slim`, `all` or `depreca
107107
* [`no-jquery/no-data`](docs/rules/no-data.md) `all`
108108
* [`no-jquery/no-deferred`](docs/rules/no-deferred.md) `all`
109109
* [`no-jquery/no-delegate`](docs/rules/no-delegate.md) `3.0`, `all`
110+
* [`no-jquery/no-done-fail`](docs/rules/no-done-fail.md) `all`
110111
* [`no-jquery/no-each`](docs/rules/no-each.md)
111112
* [`no-jquery/no-each-collection`](docs/rules/no-each-collection.md) `all`
112113
* [`no-jquery/no-each-util`](docs/rules/no-each-util.md) `all`

docs/rules/no-done-fail.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[//]: # (This file is generated by eslint-docgen. Do not edit it directly.)
2+
3+
# no-done-fail
4+
5+
Disallows the [`.done`](https://api.jquery.com/deferred.done/)/[`.fail`](https://api.jquery.com/deferred.fail/) methods. Prefer `.then`.
6+
7+
📋 This rule is enabled in `plugin:no-jquery/all`.
8+
9+
## Rule details
10+
11+
❌ Examples of **incorrect** code:
12+
```js
13+
promise.done( callback );
14+
promise.fail( callback );
15+
```
16+
17+
✔️ Examples of **correct** code:
18+
```js
19+
promise.then( doneCallback, failCallback );
20+
done();
21+
fail();
22+
```
23+
24+
## Resources
25+
26+
* [Rule source](/src/rules/no-done-fail.js)
27+
* [Test source](/tests/rules/no-done-fail.js)

src/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module.exports = {
2525
'no-deferred': require( './rules/no-deferred' ),
2626
'no-delegate': require( './rules/no-delegate' ),
2727
'no-die': require( './rules/no-die' ),
28+
'no-done-fail': require( './rules/no-done-fail' ),
2829
'no-each': require( './rules/no-each' ),
2930
'no-each-collection': require( './rules/no-each-collection' ),
3031
'no-each-util': require( './rules/no-each-util' ),
@@ -333,8 +334,10 @@ module.exports = {
333334
'no-jquery/no-filter': 'warn',
334335
'no-jquery/no-prop': 'warn',
335336
'no-jquery/no-sub': 'warn',
336-
'no-jquery/no-text': 'warn'
337+
'no-jquery/no-text': 'warn',
337338

339+
// Other methods
340+
'no-jquery/no-done-fail': 'warn'
338341
}
339342
}
340343
}

src/rules/no-done-fail.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
const utils = require( '../utils.js' );
4+
5+
module.exports = utils.createUniversalMethodRule(
6+
[ 'done', 'fail' ],
7+
( node ) => node === true ?
8+
'Prefer `.then`' :
9+
`Prefer .then to .${ node.callee.property.name }`,
10+
( method ) => `[\`.${ method }\`](https://api.jquery.com/deferred.${ method }/)`
11+
);

src/utils.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,47 @@ function createCollectionOrUtilMethodRule( methods, message, options ) {
527527
} ), description, options.fixable, options.deprecated );
528528
}
529529

530+
/**
531+
* Create a rule for a method on any object
532+
*
533+
* @param {string|string[]} methods Method or list of method names
534+
* @param {string|Function} message Message to report. See createCollectionMethodRule.
535+
* @param {Function} linkGenerator Function to generate a markdown link
536+
* @param {Object} [options] Options. See createCollectionMethodRule.
537+
* for a given function name.
538+
* @return {Object} Rule
539+
*/
540+
function createUniversalMethodRule( methods, message, linkGenerator, options ) {
541+
options = options || {};
542+
543+
options.mode = 'util';
544+
545+
methods = Array.isArray( methods ) ? methods : [ methods ];
546+
547+
let description = 'Disallows the ' + methods.map( linkGenerator ).join( '/' ) + ' ' +
548+
( methods.length > 1 ? 'methods' : 'method' ) + '.';
549+
550+
description += messageSuffix( message );
551+
552+
return createRule( ( context ) => ( {
553+
'CallExpression:exit': ( node ) => {
554+
if ( node.callee.type !== 'MemberExpression' ) {
555+
return;
556+
}
557+
const name = node.callee.property.name;
558+
if ( !methods.includes( name ) ) {
559+
return;
560+
}
561+
562+
context.report( {
563+
node,
564+
message: messageToPlainString( message, node, name, options ),
565+
fix: options.fix && options.fix.bind( this, node, context )
566+
} );
567+
}
568+
} ), description, options.fixable, options.deprecated );
569+
}
570+
530571
function eventShorthandFixer( node, context, fixer ) {
531572
const name = node.callee.property.name;
532573
if ( node.callee.parent.arguments.length ) {
@@ -580,6 +621,7 @@ module.exports = {
580621
createUtilMethodRule,
581622
createUtilPropertyRule,
582623
createCollectionOrUtilMethodRule,
624+
createUniversalMethodRule,
583625
eventShorthandFixer,
584626
jQueryCollectionLink,
585627
jQueryGlobalLink,

test-self/all/methods.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,9 @@ $x.wrap();
239239
$x.wrapAll();
240240
// eslint-disable-next-line self/no-wrap
241241
$x.wrapInner();
242+
243+
// Other methods
244+
// eslint-disable-next-line self/no-done-fail
245+
promise.done();
246+
// eslint-disable-next-line self/no-done-fail
247+
promise.fail();

tests/rules/no-done-fail.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
const rule = require( '../../src/rules/no-done-fail' );
4+
const RuleTester = require( '../../tools/rule-tester' );
5+
6+
const error = ( method ) => `Prefer .then to .${ method }`;
7+
8+
const ruleTester = new RuleTester();
9+
ruleTester.run( 'no-done-fail', rule, {
10+
valid: [ 'promise.then( doneCallback, failCallback )', 'done()', 'fail()' ],
11+
invalid: [
12+
{
13+
code: 'promise.done( callback )',
14+
errors: [ error( 'done' ) ]
15+
},
16+
{
17+
code: 'promise.fail( callback )',
18+
errors: [ error( 'fail' ) ]
19+
}
20+
]
21+
} );

0 commit comments

Comments
 (0)