eslint 6.3.0 → 6.6.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.
- package/CHANGELOG.md +126 -0
- package/README.md +11 -10
- package/bin/eslint.js +38 -12
- package/lib/cli-engine/cascading-config-array-factory.js +2 -1
- package/lib/cli-engine/cli-engine.js +11 -11
- package/lib/cli-engine/config-array/config-array.js +0 -4
- package/lib/cli-engine/config-array/config-dependency.js +2 -0
- package/lib/cli-engine/config-array/override-tester.js +4 -2
- package/lib/cli-engine/config-array-factory.js +7 -1
- package/lib/cli-engine/file-enumerator.js +5 -3
- package/lib/cli-engine/formatters/html.js +1 -0
- package/lib/cli-engine/ignored-paths.js +4 -3
- package/lib/cli-engine/lint-result-cache.js +0 -1
- package/lib/cli.js +13 -12
- package/lib/init/autoconfig.js +1 -11
- package/lib/init/config-file.js +0 -1
- package/lib/init/config-initializer.js +0 -1
- package/lib/init/config-rule.js +3 -7
- package/lib/init/npm-utils.js +1 -6
- package/lib/linter/code-path-analysis/code-path-analyzer.js +24 -38
- package/lib/linter/code-path-analysis/code-path-segment.js +17 -25
- package/lib/linter/code-path-analysis/code-path-state.js +40 -81
- package/lib/linter/code-path-analysis/code-path.js +10 -11
- package/lib/linter/code-path-analysis/debug-helpers.js +9 -13
- package/lib/linter/code-path-analysis/fork-context.js +23 -34
- package/lib/linter/code-path-analysis/id-generator.js +2 -2
- package/lib/linter/linter.js +121 -96
- package/lib/linter/node-event-generator.js +3 -2
- package/lib/options.js +6 -0
- package/lib/rule-tester/rule-tester.js +7 -10
- package/lib/rules/accessor-pairs.js +59 -19
- package/lib/rules/array-bracket-newline.js +12 -15
- package/lib/rules/array-bracket-spacing.js +12 -12
- package/lib/rules/array-callback-return.js +6 -11
- package/lib/rules/array-element-newline.js +5 -8
- package/lib/rules/arrow-parens.js +0 -1
- package/lib/rules/block-scoped-var.js +3 -3
- package/lib/rules/block-spacing.js +4 -4
- package/lib/rules/capitalized-comments.js +2 -9
- package/lib/rules/class-methods-use-this.js +3 -3
- package/lib/rules/comma-dangle.js +15 -23
- package/lib/rules/comma-spacing.js +1 -1
- package/lib/rules/computed-property-spacing.js +28 -11
- package/lib/rules/consistent-return.js +4 -5
- package/lib/rules/consistent-this.js +5 -5
- package/lib/rules/constructor-super.js +14 -16
- package/lib/rules/curly.js +3 -5
- package/lib/rules/default-param-last.js +62 -0
- package/lib/rules/dot-location.js +11 -12
- package/lib/rules/eqeqeq.js +7 -19
- package/lib/rules/func-names.js +6 -6
- package/lib/rules/function-call-argument-newline.js +5 -5
- package/lib/rules/generator-star-spacing.js +4 -9
- package/lib/rules/getter-return.js +4 -7
- package/lib/rules/indent-legacy.js +1 -1
- package/lib/rules/indent.js +46 -8
- package/lib/rules/index.js +3 -0
- package/lib/rules/init-declarations.js +2 -2
- package/lib/rules/jsx-quotes.js +1 -1
- package/lib/rules/keyword-spacing.js +32 -56
- package/lib/rules/lines-around-directive.js +1 -1
- package/lib/rules/max-len.js +0 -5
- package/lib/rules/max-statements-per-line.js +3 -7
- package/lib/rules/multiline-ternary.js +3 -3
- package/lib/rules/new-parens.js +5 -1
- package/lib/rules/newline-after-var.js +6 -7
- package/lib/rules/newline-before-return.js +8 -9
- package/lib/rules/newline-per-chained-call.js +2 -4
- package/lib/rules/no-class-assign.js +2 -2
- package/lib/rules/no-compare-neg-zero.js +1 -2
- package/lib/rules/no-confusing-arrow.js +2 -2
- package/lib/rules/no-console.js +4 -8
- package/lib/rules/no-const-assign.js +1 -1
- package/lib/rules/no-dupe-args.js +1 -1
- package/lib/rules/no-dupe-class-members.js +3 -4
- package/lib/rules/no-dupe-keys.js +6 -5
- package/lib/rules/no-duplicate-imports.js +14 -18
- package/lib/rules/no-else-return.js +0 -8
- package/lib/rules/no-empty-function.js +2 -4
- package/lib/rules/no-eval.js +10 -18
- package/lib/rules/no-ex-assign.js +1 -1
- package/lib/rules/no-extra-bind.js +12 -13
- package/lib/rules/no-extra-boolean-cast.js +1 -3
- package/lib/rules/no-extra-label.js +13 -10
- package/lib/rules/no-extra-parens.js +32 -17
- package/lib/rules/no-extra-semi.js +5 -6
- package/lib/rules/no-fallthrough.js +6 -6
- package/lib/rules/no-func-assign.js +3 -3
- package/lib/rules/no-global-assign.js +4 -4
- package/lib/rules/no-implicit-coercion.js +10 -10
- package/lib/rules/no-implied-eval.js +0 -1
- package/lib/rules/no-import-assign.js +238 -0
- package/lib/rules/no-invalid-this.js +1 -3
- package/lib/rules/no-labels.js +3 -6
- package/lib/rules/no-lone-blocks.js +7 -2
- package/lib/rules/no-loop-func.js +6 -11
- package/lib/rules/no-magic-numbers.js +6 -6
- package/lib/rules/no-misleading-character-class.js +14 -7
- package/lib/rules/no-mixed-operators.js +13 -22
- package/lib/rules/no-mixed-requires.js +0 -1
- package/lib/rules/no-multi-spaces.js +1 -1
- package/lib/rules/no-native-reassign.js +4 -4
- package/lib/rules/no-obj-calls.js +29 -9
- package/lib/rules/no-octal-escape.js +14 -8
- package/lib/rules/no-param-reassign.js +28 -7
- package/lib/rules/no-redeclare.js +1 -1
- package/lib/rules/no-regex-spaces.js +105 -45
- package/lib/rules/no-restricted-imports.js +11 -11
- package/lib/rules/no-self-assign.js +18 -18
- package/lib/rules/no-sequences.js +5 -5
- package/lib/rules/no-shadow.js +1 -4
- package/lib/rules/no-tabs.js +8 -2
- package/lib/rules/no-this-before-super.js +12 -13
- package/lib/rules/no-trailing-spaces.js +19 -7
- package/lib/rules/no-undef-init.js +7 -1
- package/lib/rules/no-unmodified-loop-condition.js +16 -29
- package/lib/rules/no-unneeded-ternary.js +3 -3
- package/lib/rules/no-unreachable.js +7 -7
- package/lib/rules/no-unsafe-finally.js +4 -7
- package/lib/rules/no-unsafe-negation.js +34 -19
- package/lib/rules/no-unused-expressions.js +11 -7
- package/lib/rules/no-unused-labels.js +3 -6
- package/lib/rules/no-unused-vars.js +22 -29
- package/lib/rules/no-use-before-define.js +10 -15
- package/lib/rules/no-useless-call.js +4 -4
- package/lib/rules/no-useless-concat.js +4 -4
- package/lib/rules/no-useless-constructor.js +14 -22
- package/lib/rules/no-useless-escape.js +3 -5
- package/lib/rules/no-useless-rename.js +32 -20
- package/lib/rules/no-useless-return.js +11 -17
- package/lib/rules/no-var.js +12 -25
- package/lib/rules/no-warning-comments.js +0 -1
- package/lib/rules/no-whitespace-before-property.js +3 -3
- package/lib/rules/object-curly-newline.js +7 -10
- package/lib/rules/object-curly-spacing.js +14 -15
- package/lib/rules/object-shorthand.js +36 -10
- package/lib/rules/one-var-declaration-per-line.js +2 -2
- package/lib/rules/operator-assignment.js +22 -1
- package/lib/rules/padded-blocks.js +1 -1
- package/lib/rules/padding-line-between-statements.js +0 -16
- package/lib/rules/prefer-arrow-callback.js +6 -6
- package/lib/rules/prefer-const.js +13 -21
- package/lib/rules/prefer-destructuring.js +1 -7
- package/lib/rules/prefer-named-capture-group.js +3 -16
- package/lib/rules/prefer-numeric-literals.js +35 -3
- package/lib/rules/prefer-object-spread.js +7 -7
- package/lib/rules/prefer-regex-literals.js +125 -0
- package/lib/rules/prefer-rest-params.js +3 -6
- package/lib/rules/prefer-spread.js +4 -4
- package/lib/rules/prefer-template.js +5 -6
- package/lib/rules/quote-props.js +1 -1
- package/lib/rules/quotes.js +11 -6
- package/lib/rules/radix.js +5 -10
- package/lib/rules/require-await.js +2 -5
- package/lib/rules/require-yield.js +2 -2
- package/lib/rules/rest-spread-spacing.js +1 -1
- package/lib/rules/sort-imports.js +3 -4
- package/lib/rules/sort-keys.js +1 -3
- package/lib/rules/space-before-blocks.js +1 -2
- package/lib/rules/space-before-function-paren.js +12 -1
- package/lib/rules/space-in-parens.js +81 -75
- package/lib/rules/space-infix-ops.js +5 -5
- package/lib/rules/spaced-comment.js +15 -18
- package/lib/rules/strict.js +2 -4
- package/lib/rules/symbol-description.js +1 -2
- package/lib/rules/template-curly-spacing.js +2 -2
- package/lib/rules/use-isnan.js +104 -6
- package/lib/rules/utils/ast-utils.js +53 -81
- package/lib/rules/utils/fix-tracker.js +0 -6
- package/lib/rules/utils/lazy-loading-rule-map.js +0 -1
- package/lib/rules/vars-on-top.js +11 -11
- package/lib/shared/config-ops.js +2 -2
- package/lib/shared/logging.js +2 -0
- package/lib/shared/runtime-info.js +163 -0
- package/lib/shared/traverser.js +2 -0
- package/lib/source-code/source-code.js +11 -12
- package/lib/source-code/token-store/backward-token-comment-cursor.js +5 -5
- package/lib/source-code/token-store/backward-token-cursor.js +5 -5
- package/lib/source-code/token-store/cursors.js +17 -19
- package/lib/source-code/token-store/decorative-cursor.js +1 -1
- package/lib/source-code/token-store/filter-cursor.js +2 -2
- package/lib/source-code/token-store/forward-token-comment-cursor.js +5 -5
- package/lib/source-code/token-store/forward-token-cursor.js +5 -5
- package/lib/source-code/token-store/index.js +86 -92
- package/lib/source-code/token-store/limit-cursor.js +2 -2
- package/lib/source-code/token-store/padded-token-cursor.js +7 -7
- package/lib/source-code/token-store/skip-cursor.js +2 -2
- package/lib/source-code/token-store/utils.js +9 -13
- package/package.json +8 -5
@@ -40,8 +40,7 @@ const TARGET_NODE_TYPE = /^(?:Binary|Logical|Conditional)Expression$/u;
|
|
40
40
|
|
41
41
|
/**
|
42
42
|
* Normalizes options.
|
43
|
-
*
|
44
|
-
* @param {Object|undefined} options - A options object to normalize.
|
43
|
+
* @param {Object|undefined} options A options object to normalize.
|
45
44
|
* @returns {Object} Normalized option object.
|
46
45
|
*/
|
47
46
|
function normalizeOptions(options = {}) {
|
@@ -57,10 +56,9 @@ function normalizeOptions(options = {}) {
|
|
57
56
|
|
58
57
|
/**
|
59
58
|
* Checks whether any group which includes both given operator exists or not.
|
60
|
-
*
|
61
|
-
* @param {
|
62
|
-
* @param {string}
|
63
|
-
* @param {string} right - Another operator.
|
59
|
+
* @param {Array.<string[]>} groups A list of groups to check.
|
60
|
+
* @param {string} left An operator.
|
61
|
+
* @param {string} right Another operator.
|
64
62
|
* @returns {boolean} `true` if such group existed.
|
65
63
|
*/
|
66
64
|
function includesBothInAGroup(groups, left, right) {
|
@@ -69,8 +67,7 @@ function includesBothInAGroup(groups, left, right) {
|
|
69
67
|
|
70
68
|
/**
|
71
69
|
* Checks whether the given node is a conditional expression and returns the test node else the left node.
|
72
|
-
*
|
73
|
-
* @param {ASTNode} node - A node which can be a BinaryExpression or a LogicalExpression node.
|
70
|
+
* @param {ASTNode} node A node which can be a BinaryExpression or a LogicalExpression node.
|
74
71
|
* This parent node can be BinaryExpression, LogicalExpression
|
75
72
|
* , or a ConditionalExpression node
|
76
73
|
* @returns {ASTNode} node the appropriate node(left or test).
|
@@ -124,8 +121,7 @@ module.exports = {
|
|
124
121
|
|
125
122
|
/**
|
126
123
|
* Checks whether a given node should be ignored by options or not.
|
127
|
-
*
|
128
|
-
* @param {ASTNode} node - A node to check. This is a BinaryExpression
|
124
|
+
* @param {ASTNode} node A node to check. This is a BinaryExpression
|
129
125
|
* node or a LogicalExpression node. This parent node is one of
|
130
126
|
* them, too.
|
131
127
|
* @returns {boolean} `true` if the node should be ignored.
|
@@ -146,8 +142,7 @@ module.exports = {
|
|
146
142
|
/**
|
147
143
|
* Checks whether the operator of a given node is mixed with parent
|
148
144
|
* node's operator or not.
|
149
|
-
*
|
150
|
-
* @param {ASTNode} node - A node to check. This is a BinaryExpression
|
145
|
+
* @param {ASTNode} node A node to check. This is a BinaryExpression
|
151
146
|
* node or a LogicalExpression node. This parent node is one of
|
152
147
|
* them, too.
|
153
148
|
* @returns {boolean} `true` if the node was mixed.
|
@@ -163,8 +158,7 @@ module.exports = {
|
|
163
158
|
/**
|
164
159
|
* Checks whether the operator of a given node is mixed with a
|
165
160
|
* conditional expression.
|
166
|
-
*
|
167
|
-
* @param {ASTNode} node - A node to check. This is a conditional
|
161
|
+
* @param {ASTNode} node A node to check. This is a conditional
|
168
162
|
* expression node
|
169
163
|
* @returns {boolean} `true` if the node was mixed.
|
170
164
|
*/
|
@@ -174,8 +168,7 @@ module.exports = {
|
|
174
168
|
|
175
169
|
/**
|
176
170
|
* Gets the operator token of a given node.
|
177
|
-
*
|
178
|
-
* @param {ASTNode} node - A node to check. This is a BinaryExpression
|
171
|
+
* @param {ASTNode} node A node to check. This is a BinaryExpression
|
179
172
|
* node or a LogicalExpression node.
|
180
173
|
* @returns {Token} The operator token of the node.
|
181
174
|
*/
|
@@ -186,8 +179,7 @@ module.exports = {
|
|
186
179
|
/**
|
187
180
|
* Reports both the operator of a given node and the operator of the
|
188
181
|
* parent node.
|
189
|
-
*
|
190
|
-
* @param {ASTNode} node - A node to check. This is a BinaryExpression
|
182
|
+
* @param {ASTNode} node A node to check. This is a BinaryExpression
|
191
183
|
* node or a LogicalExpression node. This parent node is one of
|
192
184
|
* them, too.
|
193
185
|
* @returns {void}
|
@@ -205,13 +197,13 @@ module.exports = {
|
|
205
197
|
|
206
198
|
context.report({
|
207
199
|
node: left,
|
208
|
-
loc: getOperatorToken(left).loc
|
200
|
+
loc: getOperatorToken(left).loc,
|
209
201
|
message,
|
210
202
|
data
|
211
203
|
});
|
212
204
|
context.report({
|
213
205
|
node: right,
|
214
|
-
loc: getOperatorToken(right).loc
|
206
|
+
loc: getOperatorToken(right).loc,
|
215
207
|
message,
|
216
208
|
data
|
217
209
|
});
|
@@ -220,8 +212,7 @@ module.exports = {
|
|
220
212
|
/**
|
221
213
|
* Checks between the operator of this node and the operator of the
|
222
214
|
* parent node.
|
223
|
-
*
|
224
|
-
* @param {ASTNode} node - A node to check.
|
215
|
+
* @param {ASTNode} node A node to check.
|
225
216
|
* @returns {void}
|
226
217
|
*/
|
227
218
|
function check(node) {
|
@@ -121,7 +121,7 @@ module.exports = {
|
|
121
121
|
|
122
122
|
context.report({
|
123
123
|
node: rightToken,
|
124
|
-
loc: rightToken.loc.start,
|
124
|
+
loc: { start: leftToken.loc.end, end: rightToken.loc.start },
|
125
125
|
message: "Multiple spaces found before '{{displayValue}}'.",
|
126
126
|
data: { displayValue },
|
127
127
|
fix: fixer => fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ")
|
@@ -46,9 +46,9 @@ module.exports = {
|
|
46
46
|
|
47
47
|
/**
|
48
48
|
* Reports write references.
|
49
|
-
* @param {Reference} reference
|
50
|
-
* @param {int} index
|
51
|
-
* @param {Reference[]} references
|
49
|
+
* @param {Reference} reference A reference to check.
|
50
|
+
* @param {int} index The index of the reference in the references.
|
51
|
+
* @param {Reference[]} references The array that the reference belongs to.
|
52
52
|
* @returns {void}
|
53
53
|
*/
|
54
54
|
function checkReference(reference, index, references) {
|
@@ -73,7 +73,7 @@ module.exports = {
|
|
73
73
|
|
74
74
|
/**
|
75
75
|
* Reports write references if a given variable is read-only builtin.
|
76
|
-
* @param {Variable} variable
|
76
|
+
* @param {Variable} variable A variable to check.
|
77
77
|
* @returns {void}
|
78
78
|
*/
|
79
79
|
function checkVariable(variable) {
|
@@ -5,6 +5,18 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const { CALL, ReferenceTracker } = require("eslint-utils");
|
13
|
+
|
14
|
+
//------------------------------------------------------------------------------
|
15
|
+
// Helpers
|
16
|
+
//------------------------------------------------------------------------------
|
17
|
+
|
18
|
+
const nonCallableGlobals = ["Atomics", "JSON", "Math", "Reflect"];
|
19
|
+
|
8
20
|
//------------------------------------------------------------------------------
|
9
21
|
// Rule Definition
|
10
22
|
//------------------------------------------------------------------------------
|
@@ -20,23 +32,31 @@ module.exports = {
|
|
20
32
|
url: "https://eslint.org/docs/rules/no-obj-calls"
|
21
33
|
},
|
22
34
|
|
23
|
-
schema: []
|
35
|
+
schema: [],
|
36
|
+
|
37
|
+
messages: {
|
38
|
+
unexpectedCall: "'{{name}}' is not a function."
|
39
|
+
}
|
24
40
|
},
|
25
41
|
|
26
42
|
create(context) {
|
27
43
|
|
28
44
|
return {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
45
|
+
Program() {
|
46
|
+
const scope = context.getScope();
|
47
|
+
const tracker = new ReferenceTracker(scope);
|
48
|
+
const traceMap = {};
|
49
|
+
|
50
|
+
for (const global of nonCallableGlobals) {
|
51
|
+
traceMap[global] = {
|
52
|
+
[CALL]: true
|
53
|
+
};
|
54
|
+
}
|
33
55
|
|
34
|
-
|
35
|
-
|
36
|
-
}
|
56
|
+
for (const { node } of tracker.iterateGlobalReferences(traceMap)) {
|
57
|
+
context.report({ node, messageId: "unexpectedCall", data: { name: node.callee.name } });
|
37
58
|
}
|
38
59
|
}
|
39
60
|
};
|
40
|
-
|
41
61
|
}
|
42
62
|
};
|
@@ -20,7 +20,11 @@ module.exports = {
|
|
20
20
|
url: "https://eslint.org/docs/rules/no-octal-escape"
|
21
21
|
},
|
22
22
|
|
23
|
-
schema: []
|
23
|
+
schema: [],
|
24
|
+
|
25
|
+
messages: {
|
26
|
+
octalEscapeSequence: "Don't use octal: '\\{{sequence}}'. Use '\\u....' instead."
|
27
|
+
}
|
24
28
|
},
|
25
29
|
|
26
30
|
create(context) {
|
@@ -32,15 +36,17 @@ module.exports = {
|
|
32
36
|
return;
|
33
37
|
}
|
34
38
|
|
35
|
-
|
39
|
+
// \0 represents a valid NULL character if it isn't followed by a digit.
|
40
|
+
const match = node.raw.match(
|
41
|
+
/^(?:[^\\]|\\.)*?\\([0-3][0-7]{1,2}|[4-7][0-7]|[1-7])/u
|
42
|
+
);
|
36
43
|
|
37
44
|
if (match) {
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
}
|
45
|
+
context.report({
|
46
|
+
node,
|
47
|
+
messageId: "octalEscapeSequence",
|
48
|
+
data: { sequence: match[1] }
|
49
|
+
});
|
44
50
|
}
|
45
51
|
}
|
46
52
|
|
@@ -45,6 +45,13 @@ module.exports = {
|
|
45
45
|
type: "string"
|
46
46
|
},
|
47
47
|
uniqueItems: true
|
48
|
+
},
|
49
|
+
ignorePropertyModificationsForRegex: {
|
50
|
+
type: "array",
|
51
|
+
items: {
|
52
|
+
type: "string"
|
53
|
+
},
|
54
|
+
uniqueItems: true
|
48
55
|
}
|
49
56
|
},
|
50
57
|
additionalProperties: false
|
@@ -57,10 +64,11 @@ module.exports = {
|
|
57
64
|
create(context) {
|
58
65
|
const props = context.options[0] && context.options[0].props;
|
59
66
|
const ignoredPropertyAssignmentsFor = context.options[0] && context.options[0].ignorePropertyModificationsFor || [];
|
67
|
+
const ignoredPropertyAssignmentsForRegex = context.options[0] && context.options[0].ignorePropertyModificationsForRegex || [];
|
60
68
|
|
61
69
|
/**
|
62
70
|
* Checks whether or not the reference modifies properties of its variable.
|
63
|
-
* @param {Reference} reference
|
71
|
+
* @param {Reference} reference A reference to check.
|
64
72
|
* @returns {boolean} Whether or not the reference modifies properties of its variable.
|
65
73
|
*/
|
66
74
|
function isModifyingProp(reference) {
|
@@ -136,11 +144,24 @@ module.exports = {
|
|
136
144
|
return false;
|
137
145
|
}
|
138
146
|
|
147
|
+
/**
|
148
|
+
* Tests that an identifier name matches any of the ignored property assignments.
|
149
|
+
* First we test strings in ignoredPropertyAssignmentsFor.
|
150
|
+
* Then we instantiate and test RegExp objects from ignoredPropertyAssignmentsForRegex strings.
|
151
|
+
* @param {string} identifierName A string that describes the name of an identifier to
|
152
|
+
* ignore property assignments for.
|
153
|
+
* @returns {boolean} Whether the string matches an ignored property assignment regular expression or not.
|
154
|
+
*/
|
155
|
+
function isIgnoredPropertyAssignment(identifierName) {
|
156
|
+
return ignoredPropertyAssignmentsFor.includes(identifierName) ||
|
157
|
+
ignoredPropertyAssignmentsForRegex.some(ignored => new RegExp(ignored, "u").test(identifierName));
|
158
|
+
}
|
159
|
+
|
139
160
|
/**
|
140
161
|
* Reports a reference if is non initializer and writable.
|
141
|
-
* @param {Reference} reference
|
142
|
-
* @param {int} index
|
143
|
-
* @param {Reference[]} references
|
162
|
+
* @param {Reference} reference A reference to check.
|
163
|
+
* @param {int} index The index of the reference in the references.
|
164
|
+
* @param {Reference[]} references The array that the reference belongs to.
|
144
165
|
* @returns {void}
|
145
166
|
*/
|
146
167
|
function checkReference(reference, index, references) {
|
@@ -157,7 +178,7 @@ module.exports = {
|
|
157
178
|
) {
|
158
179
|
if (reference.isWrite()) {
|
159
180
|
context.report({ node: identifier, message: "Assignment to function parameter '{{name}}'.", data: { name: identifier.name } });
|
160
|
-
} else if (props && isModifyingProp(reference) &&
|
181
|
+
} else if (props && isModifyingProp(reference) && !isIgnoredPropertyAssignment(identifier.name)) {
|
161
182
|
context.report({ node: identifier, message: "Assignment to property of function parameter '{{name}}'.", data: { name: identifier.name } });
|
162
183
|
}
|
163
184
|
}
|
@@ -165,7 +186,7 @@ module.exports = {
|
|
165
186
|
|
166
187
|
/**
|
167
188
|
* Finds and reports references that are non initializer and writable.
|
168
|
-
* @param {Variable} variable
|
189
|
+
* @param {Variable} variable A variable to check.
|
169
190
|
* @returns {void}
|
170
191
|
*/
|
171
192
|
function checkVariable(variable) {
|
@@ -176,7 +197,7 @@ module.exports = {
|
|
176
197
|
|
177
198
|
/**
|
178
199
|
* Checks parameters of a given function node.
|
179
|
-
* @param {ASTNode} node
|
200
|
+
* @param {ASTNode} node A function node to check.
|
180
201
|
* @returns {void}
|
181
202
|
*/
|
182
203
|
function checkForFunction(node) {
|
@@ -5,7 +5,29 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
8
12
|
const astUtils = require("./utils/ast-utils");
|
13
|
+
const regexpp = require("regexpp");
|
14
|
+
|
15
|
+
//------------------------------------------------------------------------------
|
16
|
+
// Helpers
|
17
|
+
//------------------------------------------------------------------------------
|
18
|
+
|
19
|
+
const regExpParser = new regexpp.RegExpParser();
|
20
|
+
const DOUBLE_SPACE = / {2}/u;
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Check if node is a string
|
24
|
+
* @param {ASTNode} node node to evaluate
|
25
|
+
* @returns {boolean} True if its a string
|
26
|
+
* @private
|
27
|
+
*/
|
28
|
+
function isString(node) {
|
29
|
+
return node && node.type === "Literal" && typeof node.value === "string";
|
30
|
+
}
|
9
31
|
|
10
32
|
//------------------------------------------------------------------------------
|
11
33
|
// Rule Definition
|
@@ -27,40 +49,69 @@ module.exports = {
|
|
27
49
|
},
|
28
50
|
|
29
51
|
create(context) {
|
30
|
-
const sourceCode = context.getSourceCode();
|
31
52
|
|
32
53
|
/**
|
33
|
-
* Validate regular
|
34
|
-
* @param {ASTNode}
|
35
|
-
* @param {string}
|
36
|
-
* @param {
|
37
|
-
*
|
54
|
+
* Validate regular expression
|
55
|
+
* @param {ASTNode} nodeToReport Node to report.
|
56
|
+
* @param {string} pattern Regular expression pattern to validate.
|
57
|
+
* @param {string} rawPattern Raw representation of the pattern in the source code.
|
58
|
+
* @param {number} rawPatternStartRange Start range of the pattern in the source code.
|
59
|
+
* @param {string} flags Regular expression flags.
|
38
60
|
* @returns {void}
|
39
61
|
* @private
|
40
62
|
*/
|
41
|
-
function checkRegex(
|
42
|
-
const multipleSpacesRegex = /( {2,})( [+*{?]|[^+*{?]|$)/u,
|
43
|
-
regexResults = multipleSpacesRegex.exec(value);
|
63
|
+
function checkRegex(nodeToReport, pattern, rawPattern, rawPatternStartRange, flags) {
|
44
64
|
|
45
|
-
if (
|
46
|
-
|
65
|
+
// Skip if there are no consecutive spaces in the source code, to avoid reporting e.g., RegExp(' \ ').
|
66
|
+
if (!DOUBLE_SPACE.test(rawPattern)) {
|
67
|
+
return;
|
68
|
+
}
|
47
69
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
70
|
+
const characterClassNodes = [];
|
71
|
+
let regExpAST;
|
72
|
+
|
73
|
+
try {
|
74
|
+
regExpAST = regExpParser.parsePattern(pattern, 0, pattern.length, flags.includes("u"));
|
75
|
+
} catch (e) {
|
76
|
+
|
77
|
+
// Ignore regular expressions with syntax errors
|
78
|
+
return;
|
79
|
+
}
|
80
|
+
|
81
|
+
regexpp.visitRegExpAST(regExpAST, {
|
82
|
+
onCharacterClassEnter(ccNode) {
|
83
|
+
characterClassNodes.push(ccNode);
|
84
|
+
}
|
85
|
+
});
|
86
|
+
|
87
|
+
const spacesPattern = /( {2,})(?: [+*{?]|[^+*{?]|$)/gu;
|
88
|
+
let match;
|
89
|
+
|
90
|
+
while ((match = spacesPattern.exec(pattern))) {
|
91
|
+
const { 1: { length }, index } = match;
|
92
|
+
|
93
|
+
// Report only consecutive spaces that are not in character classes.
|
94
|
+
if (
|
95
|
+
characterClassNodes.every(({ start, end }) => index < start || end <= index)
|
96
|
+
) {
|
97
|
+
context.report({
|
98
|
+
node: nodeToReport,
|
99
|
+
message: "Spaces are hard to count. Use {{{length}}}.",
|
100
|
+
data: { length },
|
101
|
+
fix(fixer) {
|
102
|
+
if (pattern !== rawPattern) {
|
103
|
+
return null;
|
104
|
+
}
|
105
|
+
return fixer.replaceTextRange(
|
106
|
+
[rawPatternStartRange + index, rawPatternStartRange + index + length],
|
107
|
+
` {${length}}`
|
108
|
+
);
|
109
|
+
}
|
110
|
+
});
|
111
|
+
|
112
|
+
// Report only the first occurence of consecutive spaces
|
113
|
+
return;
|
114
|
+
}
|
64
115
|
}
|
65
116
|
}
|
66
117
|
|
@@ -71,25 +122,22 @@ module.exports = {
|
|
71
122
|
* @private
|
72
123
|
*/
|
73
124
|
function checkLiteral(node) {
|
74
|
-
|
75
|
-
|
76
|
-
|
125
|
+
if (node.regex) {
|
126
|
+
const pattern = node.regex.pattern;
|
127
|
+
const rawPattern = node.raw.slice(1, node.raw.lastIndexOf("/"));
|
128
|
+
const rawPatternStartRange = node.range[0] + 1;
|
129
|
+
const flags = node.regex.flags;
|
77
130
|
|
78
|
-
|
79
|
-
|
131
|
+
checkRegex(
|
132
|
+
node,
|
133
|
+
pattern,
|
134
|
+
rawPattern,
|
135
|
+
rawPatternStartRange,
|
136
|
+
flags
|
137
|
+
);
|
80
138
|
}
|
81
139
|
}
|
82
140
|
|
83
|
-
/**
|
84
|
-
* Check if node is a string
|
85
|
-
* @param {ASTNode} node node to evaluate
|
86
|
-
* @returns {boolean} True if its a string
|
87
|
-
* @private
|
88
|
-
*/
|
89
|
-
function isString(node) {
|
90
|
-
return node && node.type === "Literal" && typeof node.value === "string";
|
91
|
-
}
|
92
|
-
|
93
141
|
/**
|
94
142
|
* Validate strings passed to the RegExp constructor
|
95
143
|
* @param {ASTNode} node node to validate
|
@@ -100,9 +148,22 @@ module.exports = {
|
|
100
148
|
const scope = context.getScope();
|
101
149
|
const regExpVar = astUtils.getVariableByName(scope, "RegExp");
|
102
150
|
const shadowed = regExpVar && regExpVar.defs.length > 0;
|
151
|
+
const patternNode = node.arguments[0];
|
152
|
+
const flagsNode = node.arguments[1];
|
103
153
|
|
104
|
-
if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(
|
105
|
-
|
154
|
+
if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(patternNode) && !shadowed) {
|
155
|
+
const pattern = patternNode.value;
|
156
|
+
const rawPattern = patternNode.raw.slice(1, -1);
|
157
|
+
const rawPatternStartRange = patternNode.range[0] + 1;
|
158
|
+
const flags = isString(flagsNode) ? flagsNode.value : "";
|
159
|
+
|
160
|
+
checkRegex(
|
161
|
+
node,
|
162
|
+
pattern,
|
163
|
+
rawPattern,
|
164
|
+
rawPatternStartRange,
|
165
|
+
flags
|
166
|
+
);
|
106
167
|
}
|
107
168
|
}
|
108
169
|
|
@@ -111,6 +172,5 @@ module.exports = {
|
|
111
172
|
CallExpression: checkFunction,
|
112
173
|
NewExpression: checkFunction
|
113
174
|
};
|
114
|
-
|
115
175
|
}
|
116
176
|
};
|
@@ -116,7 +116,7 @@ module.exports = {
|
|
116
116
|
|
117
117
|
/**
|
118
118
|
* Checks to see if "*" is being used to import everything.
|
119
|
-
* @param {Set.<string>} importNames
|
119
|
+
* @param {Set.<string>} importNames Set of import names that are being imported
|
120
120
|
* @returns {boolean} whether everything is imported or not
|
121
121
|
*/
|
122
122
|
function isEverythingImported(importNames) {
|
@@ -145,7 +145,7 @@ module.exports = {
|
|
145
145
|
|
146
146
|
/**
|
147
147
|
* Report a restricted path specifically for patterns.
|
148
|
-
* @param {node} node
|
148
|
+
* @param {node} node representing the restricted path reference
|
149
149
|
* @returns {void}
|
150
150
|
* @private
|
151
151
|
*/
|
@@ -163,8 +163,8 @@ module.exports = {
|
|
163
163
|
|
164
164
|
/**
|
165
165
|
* Report a restricted path specifically when using the '*' import.
|
166
|
-
* @param {string} importSource
|
167
|
-
* @param {node} node
|
166
|
+
* @param {string} importSource path of the import
|
167
|
+
* @param {node} node representing the restricted path reference
|
168
168
|
* @returns {void}
|
169
169
|
* @private
|
170
170
|
*/
|
@@ -185,8 +185,8 @@ module.exports = {
|
|
185
185
|
|
186
186
|
/**
|
187
187
|
* Check if the given importSource is restricted because '*' is being imported.
|
188
|
-
* @param {string} importSource
|
189
|
-
* @param {Set.<string>} importNames
|
188
|
+
* @param {string} importSource path of the import
|
189
|
+
* @param {Set.<string>} importNames Set of import names that are being imported
|
190
190
|
* @returns {boolean} whether the path is restricted
|
191
191
|
* @private
|
192
192
|
*/
|
@@ -198,8 +198,8 @@ module.exports = {
|
|
198
198
|
|
199
199
|
/**
|
200
200
|
* Check if the given importNames are restricted given a list of restrictedImportNames.
|
201
|
-
* @param {Set.<string>} importNames
|
202
|
-
* @param {string[]} restrictedImportNames
|
201
|
+
* @param {Set.<string>} importNames Set of import names that are being imported
|
202
|
+
* @param {string[]} restrictedImportNames array of import names that are restricted for this import
|
203
203
|
* @returns {boolean} whether the objectName is restricted
|
204
204
|
* @private
|
205
205
|
*/
|
@@ -211,8 +211,8 @@ module.exports = {
|
|
211
211
|
|
212
212
|
/**
|
213
213
|
* Check if the given importSource is a restricted path.
|
214
|
-
* @param {string} importSource
|
215
|
-
* @param {Set.<string>} importNames
|
214
|
+
* @param {string} importSource path of the import
|
215
|
+
* @param {Set.<string>} importNames Set of import names that are being imported
|
216
216
|
* @returns {boolean} whether the variable is a restricted path or not
|
217
217
|
* @private
|
218
218
|
*/
|
@@ -232,7 +232,7 @@ module.exports = {
|
|
232
232
|
|
233
233
|
/**
|
234
234
|
* Check if the given importSource is restricted by a pattern.
|
235
|
-
* @param {string} importSource
|
235
|
+
* @param {string} importSource path of the import
|
236
236
|
* @returns {boolean} whether the variable is a restricted pattern or not
|
237
237
|
* @private
|
238
238
|
*/
|