eslint-plugin-unicorn 22.0.0 → 23.0.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 (61) hide show
  1. package/index.js +4 -0
  2. package/package.json +20 -9
  3. package/readme.md +6 -0
  4. package/rules/better-regex.js +8 -4
  5. package/rules/catch-error-name.js +6 -5
  6. package/rules/consistent-function-scoping.js +13 -13
  7. package/rules/custom-error-definition.js +4 -3
  8. package/rules/error-message.js +11 -3
  9. package/rules/escape-case.js +8 -3
  10. package/rules/expiring-todo-comments.js +24 -23
  11. package/rules/explicit-length-check.js +20 -10
  12. package/rules/filename-case.js +6 -4
  13. package/rules/import-index.js +8 -2
  14. package/rules/import-style.js +6 -5
  15. package/rules/no-abusive-eslint-disable.js +10 -2
  16. package/rules/no-array-instanceof.js +7 -3
  17. package/rules/no-console-spaces.js +19 -17
  18. package/rules/no-fn-reference-in-iterator.js +7 -6
  19. package/rules/no-for-loop.js +10 -6
  20. package/rules/no-hex-escape.js +7 -1
  21. package/rules/no-keyword-prefix.js +4 -3
  22. package/rules/no-nested-ternary.js +24 -27
  23. package/rules/no-new-buffer.js +9 -2
  24. package/rules/no-null.js +6 -5
  25. package/rules/no-object-as-default-parameter.js +4 -3
  26. package/rules/no-process-exit.js +8 -3
  27. package/rules/no-reduce.js +5 -4
  28. package/rules/no-unreadable-array-destructuring.js +8 -3
  29. package/rules/no-unsafe-regex.js +8 -4
  30. package/rules/no-unused-properties.js +8 -2
  31. package/rules/no-useless-undefined.js +4 -3
  32. package/rules/no-zero-fractions.js +8 -3
  33. package/rules/number-literal-case.js +14 -12
  34. package/rules/numeric-separators-style.js +153 -0
  35. package/rules/prefer-add-event-listener.js +12 -5
  36. package/rules/prefer-array-find.js +11 -11
  37. package/rules/prefer-dataset.js +8 -2
  38. package/rules/prefer-event-key.js +9 -2
  39. package/rules/prefer-flat-map.js +12 -11
  40. package/rules/prefer-includes.js +7 -3
  41. package/rules/prefer-math-trunc.js +92 -0
  42. package/rules/prefer-negative-index.js +9 -2
  43. package/rules/prefer-node-append.js +7 -3
  44. package/rules/prefer-node-remove.js +8 -7
  45. package/rules/prefer-number-properties.js +12 -6
  46. package/rules/prefer-optional-catch-binding.js +5 -4
  47. package/rules/prefer-query-selector.js +12 -2
  48. package/rules/prefer-reflect-apply.js +10 -4
  49. package/rules/prefer-replace-all.js +8 -4
  50. package/rules/prefer-set-has.js +11 -9
  51. package/rules/prefer-spread.js +8 -2
  52. package/rules/prefer-starts-ends-with.js +5 -4
  53. package/rules/prefer-string-slice.js +11 -3
  54. package/rules/prefer-ternary.js +269 -0
  55. package/rules/prefer-text-content.js +7 -3
  56. package/rules/prefer-type-error.js +8 -2
  57. package/rules/prevent-abbreviations.js +15 -0
  58. package/rules/string-content.js +7 -6
  59. package/rules/throw-new-error.js +5 -3
  60. package/rules/utils/cartesian-product-samples.js +2 -2
  61. package/rules/utils/method-selector.js +1 -1
package/index.js CHANGED
@@ -49,6 +49,8 @@ module.exports = {
49
49
  'unicorn/no-useless-undefined': 'error',
50
50
  'unicorn/no-zero-fractions': 'error',
51
51
  'unicorn/number-literal-case': 'error',
52
+ // TODO: Enable this by default when it's shipping in a Node.js LTS version.
53
+ 'unicorn/numeric-separators-style': 'off',
52
54
  'unicorn/prefer-add-event-listener': 'error',
53
55
  'unicorn/prefer-array-find': 'error',
54
56
  'unicorn/prefer-dataset': 'error',
@@ -56,6 +58,7 @@ module.exports = {
56
58
  // TODO: Enable this by default when targeting Node.js 12.
57
59
  'unicorn/prefer-flat-map': 'off',
58
60
  'unicorn/prefer-includes': 'error',
61
+ 'unicorn/prefer-math-trunc': 'error',
59
62
  'unicorn/prefer-modern-dom-apis': 'error',
60
63
  'unicorn/prefer-negative-index': 'error',
61
64
  'unicorn/prefer-node-append': 'error',
@@ -70,6 +73,7 @@ module.exports = {
70
73
  'unicorn/prefer-spread': 'error',
71
74
  'unicorn/prefer-starts-ends-with': 'error',
72
75
  'unicorn/prefer-string-slice': 'error',
76
+ 'unicorn/prefer-ternary': 'error',
73
77
  'unicorn/prefer-text-content': 'error',
74
78
  'unicorn/prefer-trim-start-end': 'error',
75
79
  'unicorn/prefer-type-error': 'error',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-unicorn",
3
- "version": "22.0.0",
3
+ "version": "23.0.0",
4
4
  "description": "Various awesome ESLint rules",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/eslint-plugin-unicorn",
@@ -51,25 +51,25 @@
51
51
  "@ava/babel": "^1.0.1",
52
52
  "@babel/code-frame": "7.10.4",
53
53
  "@lubien/fixture-beta-package": "^1.0.0-beta.1",
54
- "@typescript-eslint/parser": "^4.1.0",
55
- "ava": "^3.12.1",
54
+ "@typescript-eslint/parser": "^4.4.1",
55
+ "ava": "^3.13.0",
56
56
  "babel-eslint": "^10.1.0",
57
57
  "chalk": "^4.1.0",
58
- "eslint": "^7.8.0",
58
+ "eslint": "^7.11.0",
59
59
  "eslint-ava-rule-tester": "^4.0.0",
60
60
  "eslint-plugin-eslint-plugin": "^2.3.0",
61
61
  "execa": "^4.0.3",
62
62
  "listr": "^0.14.3",
63
- "mem": "6.1.1",
63
+ "mem": "8.0.0",
64
64
  "nyc": "^15.1.0",
65
65
  "outdent": "^0.7.1",
66
66
  "pify": "^5.0.0",
67
- "typescript": "^4.0.2",
68
- "vue-eslint-parser": "^7.1.0",
67
+ "typescript": "^4.0.3",
68
+ "vue-eslint-parser": "^7.1.1",
69
69
  "xo": "^0.33.1"
70
70
  },
71
71
  "peerDependencies": {
72
- "eslint": ">=7.8.0"
72
+ "eslint": ">=7.11.0"
73
73
  },
74
74
  "ava": {
75
75
  "babel": true,
@@ -93,6 +93,9 @@
93
93
  "extends": [
94
94
  "plugin:eslint-plugin/all"
95
95
  ],
96
+ "ignores": [
97
+ "test/integration/{fixtures,unicorn}/**"
98
+ ],
96
99
  "overrides": [
97
100
  {
98
101
  "files": "rules/utils/*.js",
@@ -110,7 +113,15 @@
110
113
  ],
111
114
  "rules": {
112
115
  "strict": "error",
113
- "unicorn/no-null": "error"
116
+ "unicorn/no-null": "error",
117
+ "unicorn/prevent-abbreviations": [
118
+ "error",
119
+ {
120
+ "replacements": {
121
+ "fn": false
122
+ }
123
+ }
124
+ ]
114
125
  }
115
126
  }
116
127
  }
package/readme.md CHANGED
@@ -65,12 +65,14 @@ Configure it in `package.json`.
65
65
  "unicorn/no-useless-undefined": "error",
66
66
  "unicorn/no-zero-fractions": "error",
67
67
  "unicorn/number-literal-case": "error",
68
+ "unicorn/numeric-separators-style": "off",
68
69
  "unicorn/prefer-add-event-listener": "error",
69
70
  "unicorn/prefer-array-find": "error",
70
71
  "unicorn/prefer-dataset": "error",
71
72
  "unicorn/prefer-event-key": "error",
72
73
  "unicorn/prefer-flat-map": "error",
73
74
  "unicorn/prefer-includes": "error",
75
+ "unicorn/prefer-math-trunc": "error",
74
76
  "unicorn/prefer-modern-dom-apis": "error",
75
77
  "unicorn/prefer-negative-index": "error",
76
78
  "unicorn/prefer-node-append": "error",
@@ -84,6 +86,7 @@ Configure it in `package.json`.
84
86
  "unicorn/prefer-spread": "error",
85
87
  "unicorn/prefer-starts-ends-with": "error",
86
88
  "unicorn/prefer-string-slice": "error",
89
+ "unicorn/prefer-ternary": "off",
87
90
  "unicorn/prefer-text-content": "error",
88
91
  "unicorn/prefer-trim-start-end": "error",
89
92
  "unicorn/prefer-type-error": "error",
@@ -128,12 +131,14 @@ Configure it in `package.json`.
128
131
  - [no-useless-undefined](docs/rules/no-useless-undefined.md) - Disallow useless `undefined`. *(fixable)*
129
132
  - [no-zero-fractions](docs/rules/no-zero-fractions.md) - Disallow number literals with zero fractions or dangling dots. *(fixable)*
130
133
  - [number-literal-case](docs/rules/number-literal-case.md) - Enforce proper case for numeric literals. *(fixable)*
134
+ - [numeric-separators-style](docs/rules/numeric-separators-style.md) - Enforce the style of numeric separators by correctly grouping digits. *(fixable)*
131
135
  - [prefer-add-event-listener](docs/rules/prefer-add-event-listener.md) - Prefer `.addEventListener()` and `.removeEventListener()` over `on`-functions. *(partly fixable)*
132
136
  - [prefer-array-find](docs/rules/prefer-array-find.md) - Prefer `.find(…)` over the first element from `.filter(…)`. *(partly fixable)*
133
137
  - [prefer-dataset](docs/rules/prefer-dataset.md) - Prefer using `.dataset` on DOM elements over `.setAttribute(…)`. *(fixable)*
134
138
  - [prefer-event-key](docs/rules/prefer-event-key.md) - Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. *(partly fixable)*
135
139
  - [prefer-flat-map](docs/rules/prefer-flat-map.md) - Prefer `.flatMap(…)` over `.map(…).flat()`. *(fixable)*
136
140
  - [prefer-includes](docs/rules/prefer-includes.md) - Prefer `.includes()` over `.indexOf()` when checking for existence or non-existence. *(fixable)*
141
+ - [prefer-math-trunc](docs/rules/prefer-math-trunc.md) - Enforce the use of `Math.trunc` instead of bitwise operators. *(partly fixable)*
137
142
  - [prefer-modern-dom-apis](docs/rules/prefer-modern-dom-apis.md) - Prefer `.before()` over `.insertBefore()`, `.replaceWith()` over `.replaceChild()`, prefer one of `.before()`, `.after()`, `.append()` or `.prepend()` over `insertAdjacentText()` and `insertAdjacentElement()`. *(fixable)*
138
143
  - [prefer-negative-index](docs/rules/prefer-negative-index.md) - Prefer negative index over `.length - index` for `{String,Array,TypedArray}#slice()` and `Array#splice()`. *(fixable)*
139
144
  - [prefer-node-append](docs/rules/prefer-node-append.md) - Prefer `Node#append()` over `Node#appendChild()`. *(fixable)*
@@ -147,6 +152,7 @@ Configure it in `package.json`.
147
152
  - [prefer-spread](docs/rules/prefer-spread.md) - Prefer the spread operator over `Array.from()`. *(fixable)*
148
153
  - [prefer-starts-ends-with](docs/rules/prefer-starts-ends-with.md) - Prefer `String#startsWith()` & `String#endsWith()` over more complex alternatives. *(partly fixable)*
149
154
  - [prefer-string-slice](docs/rules/prefer-string-slice.md) - Prefer `String#slice()` over `String#substr()` and `String#substring()`. *(partly fixable)*
155
+ - [prefer-ternary](docs/rules/prefer-ternary.md) - Prefer ternary expressions over simple `if-else` statements. *(fixable)*
150
156
  - [prefer-text-content](docs/rules/prefer-text-content.md) - Prefer `.textContent` over `.innerText`. *(fixable)*
151
157
  - [prefer-trim-start-end](docs/rules/prefer-trim-start-end.md) - Prefer `String#trimStart()` / `String#trimEnd()` over `String#trimLeft()` / `String#trimRight()`. *(fixable)*
152
158
  - [prefer-type-error](docs/rules/prefer-type-error.md) - Enforce throwing `TypeError` in type checking conditions. *(fixable)*
@@ -4,7 +4,10 @@ const {optimize} = require('regexp-tree');
4
4
  const getDocumentationUrl = require('./utils/get-documentation-url');
5
5
  const quoteString = require('./utils/quote-string');
6
6
 
7
- const message = '{{original}} can be optimized to {{optimized}}';
7
+ const MESSAGE_ID = 'better-regex';
8
+ const messages = {
9
+ [MESSAGE_ID]: '{{original}} can be optimized to {{optimized}}.'
10
+ };
8
11
 
9
12
  const create = context => {
10
13
  const {sortCharacterClasses} = context.options[0] || {};
@@ -37,7 +40,7 @@ const create = context => {
37
40
 
38
41
  context.report({
39
42
  node,
40
- message,
43
+ messageId: MESSAGE_ID,
41
44
  data: {
42
45
  original,
43
46
  optimized
@@ -64,7 +67,7 @@ const create = context => {
64
67
  if (oldPattern !== newPattern) {
65
68
  context.report({
66
69
  node,
67
- message,
70
+ messageId: MESSAGE_ID,
68
71
  data: {
69
72
  original: oldPattern,
70
73
  optimized: newPattern
@@ -99,6 +102,7 @@ module.exports = {
99
102
  url: getDocumentationUrl(__filename)
100
103
  },
101
104
  fixable: 'code',
102
- schema
105
+ schema,
106
+ messages
103
107
  }
104
108
  };
@@ -5,7 +5,10 @@ const getDocumentationUrl = require('./utils/get-documentation-url');
5
5
  const renameVariable = require('./utils/rename-variable');
6
6
  const methodSelector = require('./utils/method-selector');
7
7
 
8
- const ERROR_MESSAGE_ID = 'error';
8
+ const MESSAGE_ID = 'catch-error-name';
9
+ const messages = {
10
+ [MESSAGE_ID]: 'The catch parameter `{{originalName}}` should be named `{{fixedName}}`.'
11
+ };
9
12
 
10
13
  const promiseMethodSelector = (method, argumentsLength, argumentIndex) => [
11
14
  methodSelector({
@@ -78,7 +81,7 @@ const create = context => {
78
81
 
79
82
  context.report({
80
83
  node,
81
- messageId: ERROR_MESSAGE_ID,
84
+ messageId: MESSAGE_ID,
82
85
  data: {
83
86
  originalName,
84
87
  fixedName
@@ -124,8 +127,6 @@ module.exports = {
124
127
  },
125
128
  fixable: 'code',
126
129
  schema,
127
- messages: {
128
- [ERROR_MESSAGE_ID]: 'The catch parameter `{{originalName}}` should be named `{{fixedName}}`.'
129
- }
130
+ messages
130
131
  }
131
132
  };
@@ -4,6 +4,9 @@ const getDocumentationUrl = require('./utils/get-documentation-url');
4
4
  const getReferences = require('./utils/get-references');
5
5
 
6
6
  const MESSAGE_ID = 'consistent-function-scoping';
7
+ const messages = {
8
+ [MESSAGE_ID]: 'Move {{functionNameWithKind}} to the outer scope.'
9
+ };
7
10
 
8
11
  const isSameScope = (scope1, scope2) =>
9
12
  scope1 && scope2 && (scope1 === scope2 || scope1.block === scope2.block);
@@ -153,17 +156,21 @@ const create = context => {
153
156
  const {scopeManager} = sourceCode;
154
157
 
155
158
  const functions = [];
156
- let hasJsx = false;
157
159
 
158
160
  return {
159
- 'ArrowFunctionExpression, FunctionDeclaration': node => functions.push(node),
161
+ ':function': () => {
162
+ functions.push(false);
163
+ },
160
164
  JSXElement: () => {
161
165
  // Turn off this rule if we see a JSX element because scope
162
166
  // references does not include JSXElement nodes.
163
- hasJsx = true;
167
+ if (functions.length > 0) {
168
+ functions[functions.length - 1] = true;
169
+ }
164
170
  },
165
- ':matches(ArrowFunctionExpression, FunctionDeclaration):exit': node => {
166
- if (!hasJsx && !checkNode(node, scopeManager)) {
171
+ ':function:exit': node => {
172
+ const currentFunctionHasJsx = functions.pop();
173
+ if (!currentFunctionHasJsx && !checkNode(node, scopeManager)) {
167
174
  context.report({
168
175
  node,
169
176
  loc: getFunctionHeadLocation(node, sourceCode),
@@ -173,11 +180,6 @@ const create = context => {
173
180
  }
174
181
  });
175
182
  }
176
-
177
- functions.pop();
178
- if (functions.length === 0) {
179
- hasJsx = false;
180
- }
181
183
  }
182
184
  };
183
185
  };
@@ -189,8 +191,6 @@ module.exports = {
189
191
  docs: {
190
192
  url: getDocumentationUrl(__filename)
191
193
  },
192
- messages: {
193
- [MESSAGE_ID]: 'Move {{functionNameWithKind}} to the outer scope.'
194
- }
194
+ messages
195
195
  }
196
196
  };
@@ -3,6 +3,9 @@ const {upperFirst} = require('lodash');
3
3
  const getDocumentationUrl = require('./utils/get-documentation-url');
4
4
 
5
5
  const MESSAGE_ID_INVALID_EXPORT = 'invalidExport';
6
+ const messages = {
7
+ [MESSAGE_ID_INVALID_EXPORT]: 'Exported error name should match error class'
8
+ };
6
9
 
7
10
  const nameRegexp = /^(?:[A-Z][\da-z]*)*Error$/;
8
11
 
@@ -212,8 +215,6 @@ module.exports = {
212
215
  url: getDocumentationUrl(__filename)
213
216
  },
214
217
  fixable: 'code',
215
- messages: {
216
- [MESSAGE_ID_INVALID_EXPORT]: 'Exported error name should match error class'
217
- }
218
+ messages
218
219
  }
219
220
  };
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
2
  const getDocumentationUrl = require('./utils/get-documentation-url');
3
3
 
4
+ const MESSAGE_ID_MISSING_MESSAGE = 'constructorMissingMessage';
5
+ const MESSAGE_ID_EMPTY_MESSAGE = 'emptyMessage';
6
+ const messages = {
7
+ [MESSAGE_ID_MISSING_MESSAGE]: 'Pass a message to the error constructor.',
8
+ [MESSAGE_ID_EMPTY_MESSAGE]: 'Error message should not be an empty string.'
9
+ };
10
+
4
11
  const errorConstructors = new Set([
5
12
  'Error',
6
13
  'EvalError',
@@ -55,14 +62,14 @@ const reportError = (expressionNode, context) => {
55
62
  if (expressionNode.arguments.length === 0) {
56
63
  context.report({
57
64
  node: expressionNode.parent,
58
- message: 'Pass a message to the error constructor.'
65
+ messageId: MESSAGE_ID_MISSING_MESSAGE
59
66
  });
60
67
  }
61
68
 
62
69
  if (isEmptyMessageString(expressionNode)) {
63
70
  context.report({
64
71
  node: expressionNode.parent,
65
- message: 'Error message should not be an empty string.'
72
+ messageId: MESSAGE_ID_EMPTY_MESSAGE
66
73
  });
67
74
  }
68
75
  }
@@ -99,6 +106,7 @@ module.exports = {
99
106
  type: 'problem',
100
107
  docs: {
101
108
  url: getDocumentationUrl(__filename)
102
- }
109
+ },
110
+ messages
103
111
  }
104
112
  };
@@ -2,9 +2,13 @@
2
2
  const getDocumentationUrl = require('./utils/get-documentation-url');
3
3
  const replaceTemplateElement = require('./utils/replace-template-element');
4
4
 
5
+ const MESSAGE_ID = 'escape-case';
6
+ const messages = {
7
+ [MESSAGE_ID]: 'Use uppercase characters for the value of the escape sequence.'
8
+ };
9
+
5
10
  const escapeWithLowercase = /(?<=(?:^|[^\\])(?:\\\\)*\\)(?<data>x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|u{[\dA-Fa-f]+})/g;
6
11
  const escapePatternWithLowercase = /(?<=(?:^|[^\\])(?:\\\\)*\\)(?<data>x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|u{[\dA-Fa-f]+}|c[a-z])/g;
7
- const message = 'Use uppercase characters for the value of the escape sequence.';
8
12
 
9
13
  const create = context => {
10
14
  const check = ({node, original, regex = escapeWithLowercase, fix}) => {
@@ -13,7 +17,7 @@ const create = context => {
13
17
  if (fixed !== original) {
14
18
  context.report({
15
19
  node,
16
- message,
20
+ messageId: MESSAGE_ID,
17
21
  fix: fixer => fix ? fix(fixer, fixed) : fixer.replaceText(node, fixed)
18
22
  });
19
23
  }
@@ -54,6 +58,7 @@ module.exports = {
54
58
  docs: {
55
59
  url: getDocumentationUrl(__filename)
56
60
  },
57
- fixable: 'code'
61
+ fixable: 'code',
62
+ messages
58
63
  }
59
64
  };
@@ -18,6 +18,29 @@ const MESSAGE_ID_VERSION_MATCHES = 'unicorn/versionMatches';
18
18
  const MESSAGE_ID_ENGINE_MATCHES = 'unicorn/engineMatches';
19
19
  const MESSAGE_ID_REMOVE_WHITESPACE = 'unicorn/removeWhitespaces';
20
20
  const MESSAGE_ID_MISSING_AT_SYMBOL = 'unicorn/missingAtSymbol';
21
+ const messages = {
22
+ [MESSAGE_ID_AVOID_MULTIPLE_DATES]:
23
+ 'Avoid using multiple expiration dates in TODO: {{expirationDates}}. {{message}}',
24
+ [MESSAGE_ID_EXPIRED_TODO]:
25
+ 'There is a TODO that is past due date: {{expirationDate}}. {{message}}',
26
+ [MESSAGE_ID_REACHED_PACKAGE_VERSION]:
27
+ 'There is a TODO that is past due package version: {{comparison}}. {{message}}',
28
+ [MESSAGE_ID_AVOID_MULTIPLE_PACKAGE_VERSIONS]:
29
+ 'Avoid using multiple package versions in TODO: {{versions}}. {{message}}',
30
+ [MESSAGE_ID_HAVE_PACKAGE]:
31
+ 'There is a TODO that is deprecated since you installed: {{package}}. {{message}}',
32
+ [MESSAGE_ID_DONT_HAVE_PACKAGE]:
33
+ 'There is a TODO that is deprecated since you uninstalled: {{package}}. {{message}}',
34
+ [MESSAGE_ID_VERSION_MATCHES]:
35
+ 'There is a TODO match for package version: {{comparison}}. {{message}}',
36
+ [MESSAGE_ID_ENGINE_MATCHES]:
37
+ 'There is a TODO match for Node.js version: {{comparison}}. {{message}}',
38
+ [MESSAGE_ID_REMOVE_WHITESPACE]:
39
+ 'Avoid using whitespace on TODO argument. On \'{{original}}\' use \'{{fix}}\'. {{message}}',
40
+ [MESSAGE_ID_MISSING_AT_SYMBOL]:
41
+ 'Missing \'@\' on TODO argument. On \'{{original}}\' use \'{{fix}}\'. {{message}}',
42
+ ...baseRule.meta.messages
43
+ };
21
44
 
22
45
  const packageResult = readPkgUp.sync();
23
46
  const hasPackage = Boolean(packageResult);
@@ -509,29 +532,7 @@ module.exports = {
509
532
  docs: {
510
533
  url: getDocumentationUrl(__filename)
511
534
  },
512
- messages: {
513
- [MESSAGE_ID_AVOID_MULTIPLE_DATES]:
514
- 'Avoid using multiple expiration dates in TODO: {{expirationDates}}. {{message}}',
515
- [MESSAGE_ID_EXPIRED_TODO]:
516
- 'There is a TODO that is past due date: {{expirationDate}}. {{message}}',
517
- [MESSAGE_ID_REACHED_PACKAGE_VERSION]:
518
- 'There is a TODO that is past due package version: {{comparison}}. {{message}}',
519
- [MESSAGE_ID_AVOID_MULTIPLE_PACKAGE_VERSIONS]:
520
- 'Avoid using multiple package versions in TODO: {{versions}}. {{message}}',
521
- [MESSAGE_ID_HAVE_PACKAGE]:
522
- 'There is a TODO that is deprecated since you installed: {{package}}. {{message}}',
523
- [MESSAGE_ID_DONT_HAVE_PACKAGE]:
524
- 'There is a TODO that is deprecated since you uninstalled: {{package}}. {{message}}',
525
- [MESSAGE_ID_VERSION_MATCHES]:
526
- 'There is a TODO match for package version: {{comparison}}. {{message}}',
527
- [MESSAGE_ID_ENGINE_MATCHES]:
528
- 'There is a TODO match for Node.js version: {{comparison}}. {{message}}',
529
- [MESSAGE_ID_REMOVE_WHITESPACE]:
530
- 'Avoid using whitespace on TODO argument. On \'{{original}}\' use \'{{fix}}\'. {{message}}',
531
- [MESSAGE_ID_MISSING_AT_SYMBOL]:
532
- 'Missing \'@\' on TODO argument. On \'{{original}}\' use \'{{fix}}\'. {{message}}',
533
- ...baseRule.meta.messages
534
- },
535
+ messages,
535
536
  schema
536
537
  }
537
538
  };
@@ -1,16 +1,24 @@
1
1
  'use strict';
2
2
  const getDocumentationUrl = require('./utils/get-documentation-url');
3
3
 
4
+ const messages = {
5
+ compareToValue: '`length` property should be compared to a value.',
6
+ zeroEqual: 'Zero `.length` should be compared with `=== 0`.',
7
+ nonZeroEqual: 'Non-zero `.length` should be compared with `!== 0`.',
8
+ nonZeroGreater: 'Non-zero `.length` should be compared with `> 0`.',
9
+ nonZeroGreaterEqual: 'Non-zero `.length` should be compared with `>= 1`.'
10
+ };
11
+
4
12
  const operatorTypes = {
5
13
  gt: ['>'],
6
14
  gte: ['>='],
7
15
  ne: ['!==', '!=']
8
16
  };
9
17
 
10
- function reportError(context, node, message, fixDetails) {
18
+ function reportError(context, node, messageId, fixDetails) {
11
19
  context.report({
12
20
  node,
13
- message,
21
+ messageId,
14
22
  fix: fixDetails && (fixer => {
15
23
  return fixer.replaceText(
16
24
  node,
@@ -25,7 +33,7 @@ function checkZeroType(context, node) {
25
33
  reportError(
26
34
  context,
27
35
  node,
28
- 'Zero `.length` should be compared with `=== 0`.',
36
+ 'zeroEqual',
29
37
  {
30
38
  node: node.left,
31
39
  operator: '===',
@@ -35,7 +43,7 @@ function checkZeroType(context, node) {
35
43
  }
36
44
  }
37
45
 
38
- function checkNonZeroType(context, node, type) {
46
+ function checkNonZeroType(context, node, type = 'greater-than') {
39
47
  const {value} = node.right;
40
48
  const {operator} = node;
41
49
 
@@ -48,7 +56,7 @@ function checkNonZeroType(context, node, type) {
48
56
  reportError(
49
57
  context,
50
58
  node,
51
- 'Non-zero `.length` should be compared with `> 0`.',
59
+ 'nonZeroGreater',
52
60
  {
53
61
  node: node.left,
54
62
  operator: '>',
@@ -66,7 +74,7 @@ function checkNonZeroType(context, node, type) {
66
74
  reportError(
67
75
  context,
68
76
  node,
69
- 'Non-zero `.length` should be compared with `>= 1`.',
77
+ 'nonZeroGreaterEqual',
70
78
  {
71
79
  node: node.left,
72
80
  operator: '>=',
@@ -84,7 +92,7 @@ function checkNonZeroType(context, node, type) {
84
92
  reportError(
85
93
  context,
86
94
  node,
87
- 'Non-zero `.length` should be compared with `!== 0`.',
95
+ 'nonZeroEqual',
88
96
  {
89
97
  node: node.left,
90
98
  operator: '!==',
@@ -134,7 +142,7 @@ function checkExpression(context, node) {
134
142
  node.property.name === 'length' &&
135
143
  !node.computed
136
144
  ) {
137
- reportError(context, node, '`length` property should be compared to a value.');
145
+ reportError(context, node, 'compareToValue');
138
146
  }
139
147
  }
140
148
 
@@ -154,7 +162,8 @@ const schema = [
154
162
  type: 'object',
155
163
  properties: {
156
164
  'non-zero': {
157
- enum: ['not-equal', 'greater-than', 'greater-than-or-equal']
165
+ enum: ['not-equal', 'greater-than', 'greater-than-or-equal'],
166
+ default: 'greater-than'
158
167
  }
159
168
  }
160
169
  }
@@ -168,6 +177,7 @@ module.exports = {
168
177
  url: getDocumentationUrl(__filename)
169
178
  },
170
179
  fixable: 'code',
171
- schema
180
+ schema,
181
+ messages
172
182
  }
173
183
  };
@@ -4,6 +4,11 @@ const {camelCase, kebabCase, snakeCase, upperFirst} = require('lodash');
4
4
  const getDocumentationUrl = require('./utils/get-documentation-url');
5
5
  const cartesianProductSamples = require('./utils/cartesian-product-samples');
6
6
 
7
+ const messages = {
8
+ renameToCase: 'Filename is not in {{chosenCases}}. Rename it to {{renamedFilenames}}.',
9
+ renameToCases: 'Filename is not in {{chosenCases}}. Rename it to {{renamedFilenames}}.'
10
+ };
11
+
7
12
  const pascalCase = string => upperFirst(camelCase(string));
8
13
  const numberRegex = /\d+/;
9
14
  const PLACEHOLDER = '\uFFFF\uFFFF\uFFFF';
@@ -246,9 +251,6 @@ module.exports = {
246
251
  url: getDocumentationUrl(__filename)
247
252
  },
248
253
  schema,
249
- messages: {
250
- renameToCase: 'Filename is not in {{chosenCases}}. Rename it to {{renamedFilenames}}.',
251
- renameToCases: 'Filename is not in {{chosenCases}}. Rename it to {{renamedFilenames}}.'
252
- }
254
+ messages
253
255
  }
254
256
  };
@@ -1,6 +1,11 @@
1
1
  'use strict';
2
2
  const getDocumentationUrl = require('./utils/get-documentation-url');
3
3
 
4
+ const MESSAGE_ID = 'import-index';
5
+ const messages = {
6
+ [MESSAGE_ID]: 'Do not reference the index file directly..'
7
+ };
8
+
4
9
  const regexp = /^(?<package>@.*?\/.*?|[./]+?.*?)\/(?:\.|(?:index(?:\.js)?))?$/;
5
10
  const isImportingIndex = value => regexp.test(value);
6
11
  const normalize = value => value.replace(regexp, '$<package>');
@@ -9,7 +14,7 @@ const importIndex = (context, node, argument) => {
9
14
  if (argument && isImportingIndex(argument.value)) {
10
15
  context.report({
11
16
  node,
12
- message: 'Do not reference the index file directly.',
17
+ messageId: MESSAGE_ID,
13
18
  fix: fixer => fixer.replaceText(argument, `'${normalize(argument.value)}'`)
14
19
  });
15
20
  }
@@ -50,6 +55,7 @@ module.exports = {
50
55
  url: getDocumentationUrl(__filename)
51
56
  },
52
57
  schema,
53
- fixable: 'code'
58
+ fixable: 'code',
59
+ messages
54
60
  }
55
61
  };
@@ -3,6 +3,11 @@ const {defaultsDeep} = require('lodash');
3
3
  const {getStringIfConstant} = require('eslint-utils');
4
4
  const eslintTemplateVisitor = require('eslint-template-visitor');
5
5
 
6
+ const MESSAGE_ID = 'importStyle';
7
+ const messages = {
8
+ [MESSAGE_ID]: 'Use {{allowedStyles}} import for module `{{moduleName}}`.'
9
+ };
10
+
6
11
  const getDocumentationUrl = require('./utils/get-documentation-url');
7
12
 
8
13
  const getActualImportDeclarationStyles = importDeclaration => {
@@ -111,8 +116,6 @@ const joinOr = words => {
111
116
  .join(' ');
112
117
  };
113
118
 
114
- const MESSAGE_ID = 'importStyle';
115
-
116
119
  // Keep this alphabetically sorted for easier maintenance
117
120
  const defaultStyles = {
118
121
  chalk: {
@@ -364,9 +367,7 @@ module.exports = {
364
367
  docs: {
365
368
  url: getDocumentationUrl(__filename)
366
369
  },
367
- messages: {
368
- [MESSAGE_ID]: 'Use {{allowedStyles}} import for module `{{moduleName}}`.'
369
- },
370
+ messages,
370
371
  schema
371
372
  }
372
373
  };
@@ -1,6 +1,11 @@
1
1
  'use strict';
2
2
  const getDocumentationUrl = require('./utils/get-documentation-url');
3
3
 
4
+ const MESSAGE_ID = 'no-abusive-eslint-disable';
5
+ const messages = {
6
+ [MESSAGE_ID]: 'Specify the rules you want to disable.'
7
+ };
8
+
4
9
  const disableRegex = /^eslint-disable(?:-next-line|-line)?(?<ruleId>$|(?:\s+(?:@(?:[\w-]+\/){1,2})?[\w-]+)?)/;
5
10
 
6
11
  const create = context => ({
@@ -14,6 +19,8 @@ const create = context => ({
14
19
  !result.groups.ruleId // But it did not specify any rules
15
20
  ) {
16
21
  context.report({
22
+ // Can't set it at the given location as the warning
23
+ // will be ignored due to the disable comment
17
24
  loc: {
18
25
  start: {
19
26
  ...comment.loc.start,
@@ -21,7 +28,7 @@ const create = context => ({
21
28
  },
22
29
  end: comment.loc.end
23
30
  },
24
- message: 'Specify the rules you want to disable.'
31
+ messageId: MESSAGE_ID
25
32
  });
26
33
  }
27
34
  }
@@ -34,6 +41,7 @@ module.exports = {
34
41
  type: 'suggestion',
35
42
  docs: {
36
43
  url: getDocumentationUrl(__filename)
37
- }
44
+ },
45
+ messages
38
46
  }
39
47
  };
@@ -1,7 +1,10 @@
1
1
  'use strict';
2
2
  const getDocumentationUrl = require('./utils/get-documentation-url');
3
3
 
4
- const message = 'Use `Array.isArray()` instead of `instanceof Array`.';
4
+ const MESSAGE_ID = 'no-array-instanceof';
5
+ const messages = {
6
+ [MESSAGE_ID]: 'Use `Array.isArray()` instead of `instanceof Array`.'
7
+ };
5
8
  const selector = [
6
9
  'BinaryExpression',
7
10
  '[operator="instanceof"]',
@@ -15,7 +18,7 @@ const create = context => {
15
18
  return {
16
19
  [selector]: node => context.report({
17
20
  node,
18
- message,
21
+ messageId: MESSAGE_ID,
19
22
  fix: fixer => fixer.replaceText(
20
23
  node,
21
24
  `Array.isArray(${sourceCode.getText(node.left)})`
@@ -31,6 +34,7 @@ module.exports = {
31
34
  docs: {
32
35
  url: getDocumentationUrl(__filename)
33
36
  },
34
- fixable: 'code'
37
+ fixable: 'code',
38
+ messages
35
39
  }
36
40
  };