eslint-plugin-unicorn 7.0.0 → 8.0.2

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 (39) hide show
  1. package/index.js +26 -30
  2. package/package.json +5 -2
  3. package/readme.md +50 -47
  4. package/rules/catch-error-name.js +29 -6
  5. package/rules/custom-error-definition.js +1 -0
  6. package/rules/error-message.js +3 -0
  7. package/rules/escape-case.js +1 -0
  8. package/rules/explicit-length-check.js +4 -0
  9. package/rules/filename-case.js +2 -1
  10. package/rules/import-index.js +1 -0
  11. package/rules/new-for-builtins.js +1 -0
  12. package/rules/no-abusive-eslint-disable.js +2 -1
  13. package/rules/no-array-instanceof.js +1 -0
  14. package/rules/no-console-spaces.js +1 -0
  15. package/rules/no-fn-reference-in-iterator.js +20 -3
  16. package/rules/no-for-loop.js +327 -0
  17. package/rules/no-hex-escape.js +1 -1
  18. package/rules/no-new-buffer.js +1 -0
  19. package/rules/no-process-exit.js +1 -0
  20. package/rules/no-unreadable-array-destructuring.js +1 -0
  21. package/rules/no-unsafe-regex.js +1 -0
  22. package/rules/no-unused-properties.js +11 -2
  23. package/rules/no-zero-fractions.js +55 -0
  24. package/rules/number-literal-case.js +1 -0
  25. package/rules/prefer-add-event-listener.js +126 -11
  26. package/rules/prefer-exponentiation-operator.js +1 -0
  27. package/rules/prefer-includes.js +73 -0
  28. package/rules/prefer-node-append.js +1 -0
  29. package/rules/prefer-node-remove.js +88 -0
  30. package/rules/prefer-query-selector.js +1 -0
  31. package/rules/prefer-spread.js +1 -0
  32. package/rules/prefer-starts-ends-with.js +1 -0
  33. package/rules/prefer-text-content.js +31 -0
  34. package/rules/prefer-type-error.js +1 -0
  35. package/rules/prevent-abbreviations.js +737 -0
  36. package/rules/regex-shorthand.js +1 -0
  37. package/rules/throw-new-error.js +1 -0
  38. package/rules/utils/avoid-capture.js +77 -0
  39. package/rules/utils/resolve-variable-name.js +22 -0
package/index.js CHANGED
@@ -17,44 +17,40 @@ module.exports = {
17
17
  'unicorn'
18
18
  ],
19
19
  rules: {
20
- 'unicorn/catch-error-name': [
21
- 'error',
22
- {
23
- name: 'error'
24
- }
25
- ],
20
+ 'unicorn/catch-error-name': 'error',
21
+ 'unicorn/custom-error-definition': 'off',
22
+ 'unicorn/error-message': 'error',
23
+ 'unicorn/escape-case': 'error',
26
24
  'unicorn/explicit-length-check': 'error',
27
- 'unicorn/filename-case': [
28
- 'error',
29
- {
30
- case: 'kebabCase'
31
- }
32
- ],
25
+ 'unicorn/filename-case': 'error',
26
+ 'unicorn/import-index': 'error',
27
+ 'unicorn/new-for-builtins': 'error',
33
28
  'unicorn/no-abusive-eslint-disable': 'error',
34
- 'unicorn/no-process-exit': 'error',
35
- 'unicorn/throw-new-error': 'error',
36
- 'unicorn/number-literal-case': 'error',
37
- 'unicorn/escape-case': 'error',
38
29
  'unicorn/no-array-instanceof': 'error',
39
- 'unicorn/no-new-buffer': 'error',
40
- 'unicorn/no-hex-escape': 'error',
41
- 'unicorn/custom-error-definition': 'off',
42
- 'unicorn/prefer-starts-ends-with': 'error',
43
- 'unicorn/prefer-type-error': 'error',
30
+ 'unicorn/no-console-spaces': 'error',
44
31
  'unicorn/no-fn-reference-in-iterator': 'off',
45
- 'unicorn/import-index': 'error',
46
- 'unicorn/new-for-builtins': 'error',
47
- 'unicorn/regex-shorthand': 'error',
48
- 'unicorn/prefer-spread': 'error',
49
- 'unicorn/error-message': 'error',
32
+ 'unicorn/no-for-loop': 'error',
33
+ 'unicorn/no-hex-escape': 'error',
34
+ 'unicorn/no-new-buffer': 'error',
35
+ 'unicorn/no-process-exit': 'error',
36
+ 'unicorn/no-unreadable-array-destructuring': 'error',
50
37
  'unicorn/no-unsafe-regex': 'off',
38
+ 'unicorn/no-unused-properties': 'off',
39
+ 'unicorn/no-zero-fractions': 'error',
40
+ 'unicorn/number-literal-case': 'error',
51
41
  'unicorn/prefer-add-event-listener': 'error',
52
42
  'unicorn/prefer-exponentiation-operator': 'error',
53
- 'unicorn/no-console-spaces': 'error',
54
- 'unicorn/no-unreadable-array-destructuring': 'error',
55
- 'unicorn/no-unused-properties': 'off',
43
+ 'unicorn/prefer-includes': 'error',
56
44
  'unicorn/prefer-node-append': 'error',
57
- 'unicorn/prefer-query-selector': 'error'
45
+ 'unicorn/prefer-node-remove': 'error',
46
+ 'unicorn/prefer-query-selector': 'error',
47
+ 'unicorn/prefer-spread': 'error',
48
+ 'unicorn/prefer-starts-ends-with': 'error',
49
+ 'unicorn/prefer-text-content': 'error',
50
+ 'unicorn/prefer-type-error': 'error',
51
+ 'unicorn/prevent-abbreviations': 'error',
52
+ 'unicorn/regex-shorthand': 'error',
53
+ 'unicorn/throw-new-error': 'error'
58
54
  }
59
55
  }
60
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-unicorn",
3
- "version": "7.0.0",
3
+ "version": "8.0.2",
4
4
  "description": "Various awesome ESLint rules",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/eslint-plugin-unicorn",
@@ -35,9 +35,12 @@
35
35
  "eslint-ast-utils": "^1.0.0",
36
36
  "import-modules": "^1.1.0",
37
37
  "lodash.camelcase": "^4.1.1",
38
+ "lodash.defaultsdeep": "^4.6.0",
38
39
  "lodash.kebabcase": "^4.0.1",
39
40
  "lodash.snakecase": "^4.0.1",
41
+ "lodash.topairs": "^4.3.0",
40
42
  "lodash.upperfirst": "^4.2.0",
43
+ "reserved-words": "^0.1.2",
41
44
  "safe-regex": "^2.0.1"
42
45
  },
43
46
  "devDependencies": {
@@ -53,7 +56,7 @@
53
56
  "nyc": "^13.1.0",
54
57
  "pify": "^4.0.1",
55
58
  "tempy": "^0.2.1",
56
- "xo": "^0.23.0"
59
+ "xo": "^0.24.0"
57
60
  },
58
61
  "peerDependencies": {
59
62
  "eslint": ">=5.0.0"
package/readme.md CHANGED
@@ -35,43 +35,40 @@ Configure it in `package.json`.
35
35
  "unicorn"
36
36
  ],
37
37
  "rules": {
38
- "unicorn/catch-error-name": [
39
- "error",
40
- {
41
- "name": "error"
42
- }
43
- ],
44
- "unicorn/explicit-length-check": "error",
45
- "unicorn/filename-case": [
46
- "error",
47
- {
48
- "case": "kebabCase"
49
- }
50
- ],
51
- "unicorn/no-abusive-eslint-disable": "error",
52
- "unicorn/no-process-exit": "error",
53
- "unicorn/throw-new-error": "error",
54
- "unicorn/number-literal-case": "error",
55
- "unicorn/escape-case": "error",
56
- "unicorn/no-array-instanceof": "error",
57
- "unicorn/no-new-buffer": "error",
58
- "unicorn/no-hex-escape": "error",
38
+ "unicorn/catch-error-name": "error",
59
39
  "unicorn/custom-error-definition": "off",
60
- "unicorn/prefer-starts-ends-with": "error",
61
- "unicorn/prefer-type-error": "error",
62
- "unicorn/no-fn-reference-in-iterator": "off",
40
+ "unicorn/error-message": "error",
41
+ "unicorn/escape-case": "error",
42
+ "unicorn/explicit-length-check": "error",
43
+ "unicorn/filename-case": "error",
63
44
  "unicorn/import-index": "error",
64
45
  "unicorn/new-for-builtins": "error",
65
- "unicorn/regex-shorthand": "error",
66
- "unicorn/prefer-spread": "error",
67
- "unicorn/error-message": "error",
68
- "unicorn/no-unsafe-regex": "off",
69
- "unicorn/prefer-add-event-listener": "error",
46
+ "unicorn/no-abusive-eslint-disable": "error",
47
+ "unicorn/no-array-instanceof": "error",
70
48
  "unicorn/no-console-spaces": "error",
49
+ "unicorn/no-fn-reference-in-iterator": "off",
50
+ "unicorn/no-for-loop": "error",
51
+ "unicorn/no-hex-escape": "error",
52
+ "unicorn/no-new-buffer": "error",
53
+ "unicorn/no-process-exit": "error",
71
54
  "unicorn/no-unreadable-array-destructuring": "error",
55
+ "unicorn/no-unsafe-regex": "off",
72
56
  "unicorn/no-unused-properties": "off",
57
+ "unicorn/no-zero-fractions": "error",
58
+ "unicorn/number-literal-case": "error",
59
+ "unicorn/prefer-add-event-listener": "error",
60
+ "unicorn/prefer-exponentiation-operator": "error",
61
+ "unicorn/prefer-includes": "error",
73
62
  "unicorn/prefer-node-append": "error",
74
- "unicorn/prefer-query-selector": "error"
63
+ "unicorn/prefer-node-remove": "error",
64
+ "unicorn/prefer-query-selector": "error",
65
+ "unicorn/prefer-spread": "error",
66
+ "unicorn/prefer-starts-ends-with": "error",
67
+ "unicorn/prefer-text-content": "error",
68
+ "unicorn/prefer-type-error": "error",
69
+ "unicorn/prevent-abbreviations": "error",
70
+ "unicorn/regex-shorthand": "error",
71
+ "unicorn/throw-new-error": "error"
75
72
  }
76
73
  }
77
74
  }
@@ -81,33 +78,39 @@ Configure it in `package.json`.
81
78
  ## Rules
82
79
 
83
80
  - [catch-error-name](docs/rules/catch-error-name.md) - Enforce a specific parameter name in catch clauses.
81
+ - [custom-error-definition](docs/rules/custom-error-definition.md) - Enforce correct `Error` subclassing. *(fixable)*
82
+ - [error-message](docs/rules/error-message.md) - Enforce passing a `message` value when throwing a built-in error.
83
+ - [escape-case](docs/rules/escape-case.md) - Require escape sequences to use uppercase values. *(fixable)*
84
84
  - [explicit-length-check](docs/rules/explicit-length-check.md) - Enforce explicitly comparing the `length` property of a value. *(partly fixable)*
85
85
  - [filename-case](docs/rules/filename-case.md) - Enforce a case style for filenames.
86
+ - [import-index](docs/rules/import-index.md) - Enforce importing index files with `.`. *(fixable)*
87
+ - [new-for-builtins](docs/rules/new-for-builtins.md) - Enforce the use of `new` for all builtins, except `String`, `Number`, `Boolean` and `Symbol`. *(fixable)*
86
88
  - [no-abusive-eslint-disable](docs/rules/no-abusive-eslint-disable.md) - Enforce specifying rules to disable in `eslint-disable` comments.
87
- - [no-process-exit](docs/rules/no-process-exit.md) - Disallow `process.exit()`.
88
- - [throw-new-error](docs/rules/throw-new-error.md) - Require `new` when throwing an error. *(fixable)*
89
- - [number-literal-case](docs/rules/number-literal-case.md) - Enforce lowercase identifier and uppercase value for number literals. *(fixable)*
90
- - [escape-case](docs/rules/escape-case.md) - Require escape sequences to use uppercase values. *(fixable)*
91
89
  - [no-array-instanceof](docs/rules/no-array-instanceof.md) - Require `Array.isArray()` instead of `instanceof Array`. *(fixable)*
92
- - [no-new-buffer](docs/rules/no-new-buffer.md) - Enforce the use of `Buffer.from()` and `Buffer.alloc()` instead of the deprecated `new Buffer()`. *(fixable)*
93
- - [no-hex-escape](docs/rules/no-hex-escape.md) - Enforce the use of unicode escapes instead of hexadecimal escapes. *(fixable)*
94
- - [custom-error-definition](docs/rules/custom-error-definition.md) - Enforce correct `Error` subclassing. *(fixable)*
95
- - [prefer-starts-ends-with](docs/rules/prefer-starts-ends-with.md) - Prefer `String#startsWith` & `String#endsWith` over more complex alternatives.
96
- - [prefer-type-error](docs/rules/prefer-type-error.md) - Enforce throwing `TypeError` in type checking conditions. *(fixable)*
90
+ - [no-console-spaces](docs/rules/no-console-spaces.md) - Do not use leading/trailing space between `console.log` parameters. *(fixable)*
97
91
  - [no-fn-reference-in-iterator](docs/rules/no-fn-reference-in-iterator.md) - Prevents passing a function reference directly to iterator methods. *(fixable)*
98
- - [import-index](docs/rules/import-index.md) - Enforce importing index files with `.`. *(fixable)*
99
- - [new-for-builtins](docs/rules/new-for-builtins.md) - Enforce the use of `new` for all builtins, except `String`, `Number` and `Boolean`. *(fixable)*
100
- - [regex-shorthand](docs/rules/regex-shorthand.md) - Enforce the use of regex shorthands to improve readability. *(fixable)*
101
- - [prefer-spread](docs/rules/prefer-spread.md) - Prefer the spread operator over `Array.from()`. *(fixable)*
102
- - [error-message](docs/rules/error-message.md) - Enforce passing a `message` value when throwing a built-in error.
92
+ - [no-for-loop](docs/rules/no-for-loop.md) - Do not use a `for` loop that can be replaced with a `for-of` loop. *(fixable)*
93
+ - [no-hex-escape](docs/rules/no-hex-escape.md) - Enforce the use of unicode escapes instead of hexadecimal escapes. *(fixable)*
94
+ - [no-new-buffer](docs/rules/no-new-buffer.md) - Enforce the use of `Buffer.from()` and `Buffer.alloc()` instead of the deprecated `new Buffer()`. *(fixable)*
95
+ - [no-process-exit](docs/rules/no-process-exit.md) - Disallow `process.exit()`.
96
+ - [no-unreadable-array-destructuring](docs/rules/no-unreadable-array-destructuring.md) - Disallow unreadable array destructuring.
103
97
  - [no-unsafe-regex](docs/rules/no-unsafe-regex.md) - Disallow unsafe regular expressions.
98
+ - [no-unused-properties](docs/rules/no-unused-properties.md) - Disallow unused object properties.
99
+ - [no-zero-fractions](docs/rules/no-zero-fractions.md) - Disallow number literals with zero fractions or dangling dots. *(fixable)*
100
+ - [number-literal-case](docs/rules/number-literal-case.md) - Enforce lowercase identifier and uppercase value for number literals. *(fixable)*
104
101
  - [prefer-add-event-listener](docs/rules/prefer-add-event-listener.md) - Prefer `addEventListener` over `on`-functions. *(fixable)*
105
102
  - [prefer-exponentiation-operator](docs/rules/prefer-exponentiation-operator.md) - Prefer the exponentiation operator over `Math.pow()` *(fixable)*
106
- - [no-console-spaces](docs/rules/no-console-spaces.md) - Do not use leading/trailing space between `console.log` parameters. *(fixable)*
107
- - [no-unreadable-array-destructuring](docs/rules/no-unreadable-array-destructuring.md) - Disallow unreadable array destructuring.
108
- - [no-unused-properties](docs/rules/no-unused-properties.md) - Disallow unused object properties.
103
+ - [prefer-includes](docs/rules/prefer-includes.md) - Prefer `.includes()` over `.indexOf()` when checking for existence or non-existence. *(fixable)*
109
104
  - [prefer-node-append](docs/rules/prefer-node-append.md) - Prefer `append` over `appendChild`. *(fixable)*
105
+ - [prefer-node-remove](docs/rules/prefer-node-remove.md) - Prefer `remove` over `parentNode.removeChild` and `parentElement.removeChild`. *(fixable)*
110
106
  - [prefer-query-selector](docs/rules/prefer-query-selector.md) - Prefer `querySelector` over `getElementById`, `querySelectorAll` over `getElementsByClassName` and `getElementsByTagName`. *(partly fixable)*
107
+ - [prefer-spread](docs/rules/prefer-spread.md) - Prefer the spread operator over `Array.from()`. *(fixable)*
108
+ - [prefer-starts-ends-with](docs/rules/prefer-starts-ends-with.md) - Prefer `String#startsWith` & `String#endsWith` over more complex alternatives.
109
+ - [prefer-text-content](docs/rules/prefer-text-content.md) - Prefer `textContent` over `innerText`. *(fixable)*
110
+ - [prefer-type-error](docs/rules/prefer-type-error.md) - Enforce throwing `TypeError` in type checking conditions. *(fixable)*
111
+ - [prevent-abbreviations](docs/rules/prevent-abbreviations.md) - Prevent abbreviations *(partly fixable)*
112
+ - [regex-shorthand](docs/rules/regex-shorthand.md) - Enforce the use of regex shorthands to improve readability. *(fixable)*
113
+ - [throw-new-error](docs/rules/throw-new-error.md) - Require `new` when throwing an error. *(fixable)*
111
114
 
112
115
 
113
116
  ## Recommended config
@@ -25,6 +25,7 @@ function isLintablePromiseCatch(node) {
25
25
  return arg0.type === 'FunctionExpression' || arg0.type === 'ArrowFunctionExpression';
26
26
  }
27
27
 
28
+ // TODO: Use `./utils/avoid-capture.js` instead
28
29
  function indexifyName(name, scope) {
29
30
  const variables = scope.variableScope.set;
30
31
 
@@ -42,6 +43,8 @@ const create = context => {
42
43
  caughtErrorsIgnorePattern: '^_$'
43
44
  }, context.options[0]);
44
45
 
46
+ const {scopeManager} = context.getSourceCode();
47
+
45
48
  const {name} = options;
46
49
  const caughtErrorsIgnorePattern = new RegExp(options.caughtErrorsIgnorePattern);
47
50
  const stack = [];
@@ -54,14 +57,31 @@ const create = context => {
54
57
  stack.push(stack.length > 0 || value);
55
58
  }
56
59
 
57
- function popAndReport(node) {
60
+ function popAndReport(node, scopeNode) {
58
61
  const value = stack.pop();
59
62
 
60
63
  if (value !== true && !caughtErrorsIgnorePattern.test(node.name)) {
61
- context.report({
64
+ const expectedName = value || name;
65
+ const problem = {
62
66
  node,
63
- message: `The catch parameter should be named \`${value || name}\`.`
64
- });
67
+ message: `The catch parameter should be named \`${expectedName}\`.`
68
+ };
69
+
70
+ if (node.type === 'Identifier') {
71
+ problem.fix = fixer => {
72
+ const fixings = [fixer.replaceText(node, expectedName)];
73
+
74
+ const scope = scopeManager.acquire(scopeNode);
75
+ const variable = scope.set.get(node.name);
76
+ for (const reference of variable.references) {
77
+ fixings.push(fixer.replaceText(reference.identifier, expectedName));
78
+ }
79
+
80
+ return fixings;
81
+ };
82
+ }
83
+
84
+ context.report(problem);
65
85
  }
66
86
  }
67
87
 
@@ -81,7 +101,8 @@ const create = context => {
81
101
  },
82
102
  'CallExpression:exit': node => {
83
103
  if (isLintablePromiseCatch(node)) {
84
- popAndReport(node.arguments[0].params[0]);
104
+ const callbackNode = node.arguments[0];
105
+ popAndReport(callbackNode.params[0], callbackNode);
85
106
  }
86
107
  },
87
108
  CatchClause: node => {
@@ -100,7 +121,7 @@ const create = context => {
100
121
  push(node.param.name === errName || errName);
101
122
  },
102
123
  'CatchClause:exit': node => {
103
- popAndReport(node.param);
124
+ popAndReport(node.param, node);
104
125
  }
105
126
  };
106
127
  };
@@ -120,9 +141,11 @@ const schema = [{
120
141
  module.exports = {
121
142
  create,
122
143
  meta: {
144
+ type: 'suggestion',
123
145
  docs: {
124
146
  url: getDocsUrl(__filename)
125
147
  },
148
+ fixable: 'code',
126
149
  schema
127
150
  }
128
151
  };
@@ -134,6 +134,7 @@ const create = context => {
134
134
  module.exports = {
135
135
  create,
136
136
  meta: {
137
+ type: 'problem',
137
138
  docs: {
138
139
  url: getDocsUrl(__filename)
139
140
  },
@@ -17,6 +17,7 @@ const isReferenceAssigned = expression => {
17
17
  const assignedVariable = expression.left;
18
18
  return assignedVariable.type === 'Identifier' && assignedVariable.name;
19
19
  }
20
+
20
21
  return false;
21
22
  };
22
23
 
@@ -36,6 +37,7 @@ const findIdentifierValues = (identifierNode, context) => {
36
37
  referenceValues.push(expression.init);
37
38
  }
38
39
  }
40
+
39
41
  return referenceValues;
40
42
  };
41
43
 
@@ -90,6 +92,7 @@ const create = context => {
90
92
  module.exports = {
91
93
  create,
92
94
  meta: {
95
+ type: 'problem',
93
96
  docs: {
94
97
  url: getDocsUrl(__filename)
95
98
  }
@@ -55,6 +55,7 @@ const create = context => {
55
55
  module.exports = {
56
56
  create,
57
57
  meta: {
58
+ type: 'suggestion',
58
59
  docs: {
59
60
  url: getDocsUrl(__filename)
60
61
  },
@@ -56,6 +56,7 @@ function checkNonZeroType(context, node, type) {
56
56
  }
57
57
  );
58
58
  }
59
+
59
60
  break;
60
61
  case 'greater-than-or-equal':
61
62
  if (
@@ -73,6 +74,7 @@ function checkNonZeroType(context, node, type) {
73
74
  }
74
75
  );
75
76
  }
77
+
76
78
  break;
77
79
  case 'not-equal':
78
80
  if (
@@ -90,6 +92,7 @@ function checkNonZeroType(context, node, type) {
90
92
  }
91
93
  );
92
94
  }
95
+
93
96
  break;
94
97
  default:
95
98
  break;
@@ -159,6 +162,7 @@ const schema = [{
159
162
  module.exports = {
160
163
  create,
161
164
  meta: {
165
+ type: 'problem',
162
166
  docs: {
163
167
  url: getDocsUrl(__filename)
164
168
  },
@@ -70,7 +70,7 @@ function splitFilename(filename) {
70
70
  const create = context => {
71
71
  const options = context.options[0] || {};
72
72
 
73
- const chosenCase = cases[options.case || 'camelCase'];
73
+ const chosenCase = cases[options.case || 'kebabCase'];
74
74
  const filenameWithExt = context.getFilename();
75
75
 
76
76
  if (filenameWithExt === '<text>') {
@@ -117,6 +117,7 @@ const schema = [{
117
117
  module.exports = {
118
118
  create,
119
119
  meta: {
120
+ type: 'suggestion',
120
121
  docs: {
121
122
  url: getDocsUrl(__filename)
122
123
  },
@@ -25,6 +25,7 @@ const create = context => {
25
25
  module.exports = {
26
26
  create,
27
27
  meta: {
28
+ type: 'suggestion',
28
29
  docs: {
29
30
  url: getDocsUrl(__filename)
30
31
  },
@@ -66,6 +66,7 @@ const create = context => {
66
66
  module.exports = {
67
67
  create,
68
68
  meta: {
69
+ type: 'suggestion',
69
70
  docs: {
70
71
  url: getDocsUrl(__filename)
71
72
  },
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
  const getDocsUrl = require('./utils/get-docs-url');
3
3
 
4
- const disableRegex = /^eslint-disable(-next-line|-line)?($|(\s+(@[\w-]+\/[\w-]+\/)?[\w-]+)?)/;
4
+ const disableRegex = /^eslint-disable(-next-line|-line)?($|(\s+(@[\w-]+\/(?:[\w-]+\/)?)?[\w-]+)?)/;
5
5
 
6
6
  const create = context => ({
7
7
  Program: node => {
@@ -32,6 +32,7 @@ const create = context => ({
32
32
  module.exports = {
33
33
  create,
34
34
  meta: {
35
+ type: 'suggestion',
35
36
  docs: {
36
37
  url: getDocsUrl(__filename)
37
38
  }
@@ -19,6 +19,7 @@ const create = context => ({
19
19
  module.exports = {
20
20
  create,
21
21
  meta: {
22
+ type: 'suggestion',
22
23
  docs: {
23
24
  url: getDocsUrl(__filename)
24
25
  },
@@ -133,6 +133,7 @@ const create = context => {
133
133
  module.exports = {
134
134
  create,
135
135
  meta: {
136
+ type: 'suggestion',
136
137
  docs: {
137
138
  url: getDocsUrl(__filename)
138
139
  },
@@ -13,12 +13,20 @@ const iteratorMethods = new Map([
13
13
  ['reduceRight', 2]
14
14
  ]);
15
15
 
16
- const whitelist = new Set([
16
+ const functionWhitelist = new Set([
17
17
  'Boolean'
18
18
  ]);
19
19
 
20
+ const calleeBlacklist = [
21
+ 'Promise',
22
+ 'React.children',
23
+ '_',
24
+ 'Async',
25
+ 'async'
26
+ ];
27
+
20
28
  const isIteratorMethod = node => node.callee.property && iteratorMethods.has(node.callee.property.name);
21
- const hasFunctionArgument = node => node.arguments.length > 0 && (node.arguments[0].type === 'Identifier' || node.arguments[0].type === 'CallExpression') && !whitelist.has(node.arguments[0].name);
29
+ const hasFunctionArgument = node => node.arguments.length > 0 && (node.arguments[0].type === 'Identifier' || node.arguments[0].type === 'CallExpression') && !functionWhitelist.has(node.arguments[0].name);
22
30
 
23
31
  const getNumberOfArguments = node => node.callee.property && iteratorMethods.get(node.callee.property.name);
24
32
  const parseArgument = (context, arg) => arg.type === 'Identifier' ? arg.name : context.getSourceCode().getText(arg);
@@ -31,8 +39,16 @@ const fix = (context, node) => {
31
39
  return fixer => fixer.replaceText(arg, `${numberOfArgs === 1 ? argString : `(${argString})`} => ${parseArgument(context, arg)}(${argString})`);
32
40
  };
33
41
 
42
+ const toSelector = name => {
43
+ const splitted = name.split('.');
44
+ return `[callee.${'object.'.repeat(splitted.length)}name!="${splitted.shift()}"]`;
45
+ };
46
+
47
+ // Select all the call expressions except the ones present in the blacklist
48
+ const selector = `CallExpression${calleeBlacklist.map(toSelector).join('')}`;
49
+
34
50
  const create = context => ({
35
- 'CallExpression[callee.object.name!="Promise"]': node => {
51
+ [selector]: node => {
36
52
  if (isIteratorMethod(node) && hasFunctionArgument(node)) {
37
53
  const [arg] = node.arguments;
38
54
 
@@ -48,6 +64,7 @@ const create = context => ({
48
64
  module.exports = {
49
65
  create,
50
66
  meta: {
67
+ type: 'problem',
51
68
  docs: {
52
69
  url: getDocsUrl(__filename)
53
70
  },