eslint-plugin-no-jquery 2.4.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/Changelog.md +87 -11
  2. package/README.md +114 -98
  3. package/README.md.template +14 -3
  4. package/package.json +14 -12
  5. package/src/all-methods.js +2 -0
  6. package/src/index.js +174 -53
  7. package/src/rules/no-ajax-events.js +10 -12
  8. package/src/rules/no-and-self.js +1 -1
  9. package/src/rules/no-animate-toggle.js +4 -3
  10. package/src/rules/no-animate.js +1 -1
  11. package/src/rules/no-append-html.js +53 -0
  12. package/src/rules/no-class-state.js +1 -1
  13. package/src/rules/no-constructor-attributes.js +1 -1
  14. package/src/rules/no-deferred.js +1 -1
  15. package/src/rules/no-error.js +7 -1
  16. package/src/rules/no-escape-selector.js +14 -0
  17. package/src/rules/no-event-shorthand.js +7 -7
  18. package/src/rules/no-extend.js +1 -1
  19. package/src/rules/no-global-selector.js +1 -1
  20. package/src/rules/no-html.js +2 -1
  21. package/src/rules/no-is-array.js +1 -1
  22. package/src/rules/no-is-function.js +1 -1
  23. package/src/rules/no-jquery-constructor.js +31 -0
  24. package/src/rules/no-load-shorthand.js +2 -2
  25. package/src/rules/no-noop.js +1 -1
  26. package/src/rules/no-now.js +2 -2
  27. package/src/rules/no-on-ready.js +17 -2
  28. package/src/rules/no-other-methods.js +121 -0
  29. package/src/rules/no-other-utils.js +88 -0
  30. package/src/rules/no-parse-html-literal.js +18 -7
  31. package/src/rules/no-parse-json.js +1 -1
  32. package/src/rules/no-parse-xml.js +12 -1
  33. package/src/rules/no-proxy.js +19 -1
  34. package/src/rules/no-ready-shorthand.js +9 -1
  35. package/src/rules/no-ready.js +1 -1
  36. package/src/rules/no-size.js +2 -2
  37. package/src/rules/no-sizzle.js +2 -2
  38. package/src/rules/no-submit.js +2 -1
  39. package/src/rules/no-unique.js +1 -1
  40. package/src/rules/variable-pattern.js +4 -3
  41. package/src/utils.js +59 -25
package/src/utils.js CHANGED
@@ -26,7 +26,7 @@ function traverse( context, node, variableTest, constructorTest ) {
26
26
  return false;
27
27
  } else {
28
28
  if (
29
- nonCollectionReturningMethods.indexOf( name ) !== -1 ||
29
+ nonCollectionReturningMethods.includes( name ) ||
30
30
  collectionReturningPlugins[ name ] === 'never'
31
31
  ) {
32
32
  // e.g. $foo.toArray()
@@ -35,7 +35,7 @@ function traverse( context, node, variableTest, constructorTest ) {
35
35
 
36
36
  if (
37
37
  (
38
- nonCollectionReturningAccessors.indexOf( name ) !== -1 ||
38
+ nonCollectionReturningAccessors.includes( name ) ||
39
39
  collectionReturningPlugins[ name ] === 'accessor'
40
40
  ) &&
41
41
  node.arguments.length === 0
@@ -46,7 +46,7 @@ function traverse( context, node, variableTest, constructorTest ) {
46
46
 
47
47
  if (
48
48
  (
49
- nonCollectionReturningValueAccessors.indexOf( name ) !== -1 ||
49
+ nonCollectionReturningValueAccessors.includes( name ) ||
50
50
  collectionReturningPlugins[ name ] === 'valueAccessor'
51
51
  ) &&
52
52
  (
@@ -97,7 +97,7 @@ function traverse( context, node, variableTest, constructorTest ) {
97
97
  }
98
98
 
99
99
  if (
100
- allKnownMethods.indexOf( name ) === -1 &&
100
+ !allKnownMethods.includes( name ) &&
101
101
  !( name in collectionReturningPlugins )
102
102
  ) {
103
103
  // The method is not core jQuery, so we don't know if it returns
@@ -113,7 +113,7 @@ function traverse( context, node, variableTest, constructorTest ) {
113
113
 
114
114
  break;
115
115
  case 'MemberExpression':
116
- if ( node.property && node.parent.type !== 'CallExpression' ) {
116
+ if ( node.property && !( node.parent.type === 'CallExpression' && node.parent.callee === node ) ) {
117
117
  if ( node.property.type === 'Identifier' ) {
118
118
  if ( node.computed ) {
119
119
  // e.g. foo[bar] can't be determined, returns false
@@ -132,7 +132,7 @@ function traverse( context, node, variableTest, constructorTest ) {
132
132
  node = node.object;
133
133
  break;
134
134
  case 'Identifier':
135
- if ( node.parent && node.parent.type === 'CallExpression' ) {
135
+ if ( node.parent && node.parent.type === 'CallExpression' && node.parent.callee === node ) {
136
136
  return constructorTest( node );
137
137
  } else {
138
138
  return variableTest( node ) || constructorTest( node );
@@ -141,13 +141,15 @@ function traverse( context, node, variableTest, constructorTest ) {
141
141
  return false;
142
142
  }
143
143
  }
144
+ /* istanbul ignore next */
145
+ throw new Error( 'Invalid node' );
144
146
  }
145
147
 
146
148
  function isjQueryConstructor( context, name ) {
147
149
  const constructorAliases =
148
150
  ( context.settings && context.settings[ 'no-jquery' ] && context.settings[ 'no-jquery' ].constructorAliases ) ||
149
151
  [ '$', 'jQuery' ];
150
- return constructorAliases.indexOf( name ) !== -1;
152
+ return constructorAliases.includes( name );
151
153
  }
152
154
 
153
155
  // Traverses from a node up to its root parent to determine if it
@@ -193,9 +195,10 @@ function isjQuery( context, node ) {
193
195
  * @param {string} [fixable] Fixable mode, e.g. 'code'
194
196
  * @param {string[]|boolean} [deprecated] Rule is deprecated.
195
197
  * If a string list, the replacedBy rules.
198
+ * @param {Array} schema Schema
196
199
  * @return {Object} Rule
197
200
  */
198
- function createRule( create, description, fixable, deprecated ) {
201
+ function createRule( create, description, fixable, deprecated, schema ) {
199
202
  return {
200
203
  meta: {
201
204
  type: 'suggestion',
@@ -205,7 +208,7 @@ function createRule( create, description, fixable, deprecated ) {
205
208
  replacedBy: Array.isArray( deprecated ) ? deprecated : undefined
206
209
  },
207
210
  fixable: fixable,
208
- schema: []
211
+ schema: schema || []
209
212
  },
210
213
  create: create
211
214
  };
@@ -296,6 +299,8 @@ function jQueryGlobalLink( name ) {
296
299
  * @param {Function} [options.fix] Fixing function. First argument is `node`.
297
300
  * @param {string[]|boolean} [options.deprecated] Rule is deprecated.
298
301
  * If a string list, the replacedBy rules.
302
+ * @param {boolean} [options.getAndSetOptions] Create options to enabled getting and setting
303
+ * separately.
299
304
  * @return {Object} Rule
300
305
  */
301
306
  function createCollectionMethodRule( methods, message, options ) {
@@ -310,30 +315,59 @@ function createCollectionMethodRule( methods, message, options ) {
310
315
 
311
316
  description += messageSuffix( message );
312
317
 
318
+ let schema = [];
319
+ if ( options.getAndSetOptions ) {
320
+ schema = [
321
+ {
322
+ type: 'object',
323
+ properties: {
324
+ allowGetOrSet: {
325
+ enum: [ 'none', 'get', 'set' ]
326
+ }
327
+ },
328
+ additionalProperties: false
329
+ }
330
+ ];
331
+
332
+ // TODO: nonCollectionReturningValueAccessors have 1 argument in getter mode
333
+ description += '\n\nUsing this method only as a getter or a setter can be allowed using the `allowGetOrSet` option:\n' +
334
+ '* `"none"` (default) the method can\'t be used at all\n' +
335
+ '* `"get"` the method can only be used as a getter i.e. with no arguments\n' +
336
+ '* `"set"` the method can only be used as a setter i.e. with arguments';
337
+ }
338
+
313
339
  return createRule( function ( context ) {
314
340
  return {
315
- CallExpression: function ( node ) {
341
+ 'CallExpression:exit': function ( node ) {
316
342
  if ( node.callee.type !== 'MemberExpression' ) {
317
343
  return;
318
344
  }
319
345
  const name = node.callee.property.name;
320
346
  if (
321
- methods.indexOf( name ) === -1 ||
347
+ !methods.includes( name ) ||
322
348
  isjQueryConstructor( context, node.callee.object.name )
323
349
  ) {
324
350
  return;
325
351
  }
352
+ const allowGetOrSet = ( context.options[ 0 ] && context.options[ 0 ].allowGetOrSet ) || 'none';
353
+ // TODO: nonCollectionReturningValueAccessors have 1 argument in getter mode
354
+ if (
355
+ ( allowGetOrSet === 'get' && !node.arguments.length ) ||
356
+ ( allowGetOrSet === 'set' && node.arguments.length )
357
+ ) {
358
+ return;
359
+ }
326
360
 
327
361
  if ( isjQuery( context, node.callee ) ) {
328
362
  context.report( {
329
363
  node: node,
330
364
  message: messageToPlainString( message, node, name, options ),
331
- fix: options.fix && options.fix.bind( this, node )
365
+ fix: options.fix && options.fix.bind( this, node, context )
332
366
  } );
333
367
  }
334
368
  }
335
369
  };
336
- }, description, options.fixable, options.deprecated );
370
+ }, description, options.fixable, options.deprecated, schema );
337
371
  }
338
372
 
339
373
  /**
@@ -355,7 +389,7 @@ function createCollectionPropertyRule( property, message, options ) {
355
389
 
356
390
  return createRule( function ( context ) {
357
391
  return {
358
- MemberExpression: function ( node ) {
392
+ 'MemberExpression:exit': function ( node ) {
359
393
  const name = node.property.name;
360
394
  if (
361
395
  name !== property ||
@@ -367,7 +401,7 @@ function createCollectionPropertyRule( property, message, options ) {
367
401
  context.report( {
368
402
  node: node,
369
403
  message: messageToPlainString( message, node, name, options ),
370
- fix: options.fix && options.fix.bind( this, node )
404
+ fix: options.fix && options.fix.bind( this, node, context )
371
405
  } );
372
406
  }
373
407
  }
@@ -397,13 +431,13 @@ function createUtilMethodRule( methods, message, options ) {
397
431
 
398
432
  return createRule( function ( context ) {
399
433
  return {
400
- CallExpression: function ( node ) {
434
+ 'CallExpression:exit': function ( node ) {
401
435
  if ( node.callee.type !== 'MemberExpression' ) {
402
436
  return;
403
437
  }
404
438
  const name = node.callee.property.name;
405
439
  if (
406
- methods.indexOf( name ) === -1 ||
440
+ !methods.includes( name ) ||
407
441
  !isjQueryConstructor( context, node.callee.object.name )
408
442
  ) {
409
443
  return;
@@ -412,7 +446,7 @@ function createUtilMethodRule( methods, message, options ) {
412
446
  context.report( {
413
447
  node: node,
414
448
  message: messageToPlainString( message, node, name, options ),
415
- fix: options.fix && options.fix.bind( this, node )
449
+ fix: options.fix && options.fix.bind( this, node, context )
416
450
  } );
417
451
  }
418
452
  };
@@ -438,7 +472,7 @@ function createUtilPropertyRule( property, message, options ) {
438
472
 
439
473
  return createRule( function ( context ) {
440
474
  return {
441
- MemberExpression: function ( node ) {
475
+ 'MemberExpression:exit': function ( node ) {
442
476
  if ( !isjQueryConstructor( context, node.object.name ) ) {
443
477
  return;
444
478
  }
@@ -450,7 +484,7 @@ function createUtilPropertyRule( property, message, options ) {
450
484
  context.report( {
451
485
  node: node,
452
486
  message: messageToPlainString( message, node, name, options ),
453
- fix: options.fix && options.fix.bind( this, node )
487
+ fix: options.fix && options.fix.bind( this, node, context )
454
488
  } );
455
489
  }
456
490
  };
@@ -482,19 +516,19 @@ function createCollectionOrUtilMethodRule( methods, message, options ) {
482
516
 
483
517
  return createRule( function ( context ) {
484
518
  return {
485
- CallExpression: function ( node ) {
519
+ 'CallExpression:exit': function ( node ) {
486
520
  if ( node.callee.type !== 'MemberExpression' ) {
487
521
  return;
488
522
  }
489
523
  const name = node.callee.property.name;
490
- if ( methods.indexOf( name ) === -1 ) {
524
+ if ( !methods.includes( name ) ) {
491
525
  return;
492
526
  }
493
527
  if ( isjQuery( context, node.callee ) ) {
494
528
  context.report( {
495
529
  node: node,
496
530
  message: messageToPlainString( message, node, name, options ),
497
- fix: options.fix && options.fix.bind( this, node )
531
+ fix: options.fix && options.fix.bind( this, node, context )
498
532
  } );
499
533
  }
500
534
  }
@@ -502,7 +536,7 @@ function createCollectionOrUtilMethodRule( methods, message, options ) {
502
536
  }, description, options.fixable, options.deprecated );
503
537
  }
504
538
 
505
- function eventShorthandFixer( node, fixer ) {
539
+ function eventShorthandFixer( node, context, fixer ) {
506
540
  const name = node.callee.property.name;
507
541
  if ( node.callee.parent.arguments.length ) {
508
542
  return [
@@ -512,7 +546,7 @@ function eventShorthandFixer( node, fixer ) {
512
546
  } else {
513
547
  return [
514
548
  fixer.replaceText( node.callee.property, 'trigger' ),
515
- fixer.insertTextBeforeRange( [ node.end - 1 ], JSON.stringify( name ) )
549
+ fixer.insertTextBeforeRange( [ node.range[ 1 ] - 1 ], JSON.stringify( name ) )
516
550
  ];
517
551
  }
518
552
  }