eslint 4.7.2 → 4.11.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 +123 -0
- package/README.md +34 -19
- package/conf/default-cli-options.js +7 -4
- package/conf/eslint-recommended.js +2 -0
- package/lib/ast-utils.js +83 -42
- package/lib/cli-engine.js +53 -17
- package/lib/cli.js +17 -9
- package/lib/code-path-analysis/code-path-analyzer.js +8 -4
- package/lib/code-path-analysis/code-path-segment.js +43 -41
- package/lib/code-path-analysis/code-path-state.js +7 -2
- package/lib/config/autoconfig.js +14 -12
- package/lib/config/config-file.js +8 -51
- package/lib/config/config-initializer.js +10 -6
- package/lib/config/config-ops.js +21 -21
- package/lib/config/config-rule.js +24 -24
- package/lib/config/config-validator.js +38 -36
- package/lib/config/plugins.js +8 -35
- package/lib/config.js +12 -8
- package/lib/formatters/html-template-message.html +1 -1
- package/lib/formatters/html-template-page.html +3 -1
- package/lib/formatters/html.js +2 -1
- package/lib/formatters/junit.js +21 -15
- package/lib/formatters/tap.js +5 -3
- package/lib/ignored-paths.js +5 -3
- package/lib/linter.js +42 -42
- package/lib/logging.js +2 -2
- package/lib/options.js +12 -0
- package/lib/rules/.eslintrc.yml +2 -2
- package/lib/rules/array-bracket-newline.js +39 -25
- package/lib/rules/array-bracket-spacing.js +28 -28
- package/lib/rules/array-callback-return.js +13 -9
- package/lib/rules/array-element-newline.js +8 -8
- package/lib/rules/arrow-body-style.js +12 -6
- package/lib/rules/arrow-parens.js +4 -2
- package/lib/rules/block-spacing.js +1 -1
- package/lib/rules/brace-style.js +14 -14
- package/lib/rules/callback-return.js +2 -1
- package/lib/rules/capitalized-comments.js +2 -1
- package/lib/rules/comma-style.js +3 -1
- package/lib/rules/computed-property-spacing.js +22 -22
- package/lib/rules/consistent-return.js +4 -4
- package/lib/rules/consistent-this.js +4 -2
- package/lib/rules/curly.js +13 -9
- package/lib/rules/dot-notation.js +56 -35
- package/lib/rules/func-call-spacing.js +4 -2
- package/lib/rules/generator-star-spacing.js +3 -3
- package/lib/rules/getter-return.js +2 -1
- package/lib/rules/indent-legacy.js +25 -14
- package/lib/rules/indent.js +101 -91
- package/lib/rules/key-spacing.js +5 -3
- package/lib/rules/lines-around-comment.js +33 -4
- package/lib/rules/lines-around-directive.js +16 -12
- package/lib/rules/lines-between-class-members.js +91 -0
- package/lib/rules/max-len.js +2 -3
- package/lib/rules/max-statements-per-line.js +5 -3
- package/lib/rules/multiline-comment-style.js +294 -0
- package/lib/rules/new-cap.js +2 -1
- package/lib/rules/newline-after-var.js +8 -6
- package/lib/rules/newline-before-return.js +13 -9
- package/lib/rules/no-alert.js +7 -15
- package/lib/rules/no-await-in-loop.js +17 -9
- package/lib/rules/no-bitwise.js +5 -3
- package/lib/rules/no-catch-shadow.js +4 -2
- package/lib/rules/no-console.js +2 -1
- package/lib/rules/no-constant-condition.js +2 -2
- package/lib/rules/no-control-regex.js +2 -1
- package/lib/rules/no-else-return.js +60 -19
- package/lib/rules/no-empty-character-class.js +11 -11
- package/lib/rules/no-extra-parens.js +22 -11
- package/lib/rules/no-extra-semi.js +5 -3
- package/lib/rules/no-global-assign.js +4 -2
- package/lib/rules/no-implicit-coercion.js +6 -6
- package/lib/rules/no-implied-eval.js +2 -1
- package/lib/rules/no-label-var.js +4 -2
- package/lib/rules/no-lone-blocks.js +3 -3
- package/lib/rules/no-lonely-if.js +2 -1
- package/lib/rules/no-loop-func.js +10 -7
- package/lib/rules/no-mixed-requires.js +8 -4
- package/lib/rules/no-native-reassign.js +4 -2
- package/lib/rules/no-param-reassign.js +4 -2
- package/lib/rules/no-regex-spaces.js +1 -1
- package/lib/rules/no-restricted-imports.js +86 -17
- package/lib/rules/no-restricted-modules.js +84 -15
- package/lib/rules/no-restricted-properties.js +10 -10
- package/lib/rules/no-return-await.js +6 -6
- package/lib/rules/no-self-assign.js +4 -2
- package/lib/rules/no-sequences.js +6 -4
- package/lib/rules/no-trailing-spaces.js +14 -8
- package/lib/rules/no-unneeded-ternary.js +3 -1
- package/lib/rules/no-unreachable.js +4 -2
- package/lib/rules/no-unused-labels.js +2 -1
- package/lib/rules/no-use-before-define.js +13 -11
- package/lib/rules/no-useless-call.js +1 -25
- package/lib/rules/no-useless-computed-key.js +2 -1
- package/lib/rules/no-useless-escape.js +31 -23
- package/lib/rules/no-useless-return.js +14 -8
- package/lib/rules/no-var.js +11 -0
- package/lib/rules/no-whitespace-before-property.js +4 -2
- package/lib/rules/object-curly-newline.js +9 -2
- package/lib/rules/object-curly-spacing.js +20 -20
- package/lib/rules/object-shorthand.js +47 -35
- package/lib/rules/operator-assignment.js +9 -9
- package/lib/rules/operator-linebreak.js +15 -11
- package/lib/rules/padding-line-between-statements.js +6 -4
- package/lib/rules/prefer-arrow-callback.js +12 -10
- package/lib/rules/prefer-const.js +18 -10
- package/lib/rules/prefer-destructuring.js +4 -2
- package/lib/rules/prefer-numeric-literals.js +4 -2
- package/lib/rules/prefer-promise-reject-errors.js +16 -16
- package/lib/rules/prefer-rest-params.js +4 -2
- package/lib/rules/prefer-spread.js +1 -25
- package/lib/rules/prefer-template.js +33 -29
- package/lib/rules/quote-props.js +8 -8
- package/lib/rules/require-jsdoc.js +11 -18
- package/lib/rules/semi-style.js +44 -19
- package/lib/rules/semi.js +5 -3
- package/lib/rules/sort-imports.js +11 -6
- package/lib/rules/space-unary-ops.js +67 -69
- package/lib/rules/strict.js +8 -8
- package/lib/rules/valid-jsdoc.js +39 -33
- package/lib/rules/valid-typeof.js +4 -4
- package/lib/rules/wrap-iife.js +4 -4
- package/lib/rules/yoda.js +9 -7
- package/lib/testers/rule-tester.js +63 -40
- package/lib/token-store/backward-token-cursor.js +5 -3
- package/lib/token-store/forward-token-cursor.js +5 -3
- package/lib/token-store/utils.js +8 -4
- package/lib/util/apply-disable-directives.js +56 -27
- package/lib/util/glob.js +1 -1
- package/lib/util/naming.js +112 -0
- package/lib/util/node-event-generator.js +13 -27
- package/lib/util/safe-emitter.js +54 -0
- package/lib/util/source-code-fixer.js +4 -2
- package/lib/util/source-code.js +70 -65
- package/messages/no-config-found.txt +1 -1
- package/package.json +8 -8
- package/lib/internal-rules/.eslintrc.yml +0 -3
- package/lib/internal-rules/internal-consistent-docs-description.js +0 -130
- package/lib/internal-rules/internal-no-invalid-meta.js +0 -188
@@ -12,11 +12,11 @@ const astUtils = require("../ast-utils");
|
|
12
12
|
//------------------------------------------------------------------------------
|
13
13
|
|
14
14
|
/**
|
15
|
-
* Returns the union of two sets.
|
16
|
-
* @param {Set} setA The first set
|
17
|
-
* @param {Set} setB The second set
|
18
|
-
* @returns {Set} The union of the two sets
|
19
|
-
*/
|
15
|
+
* Returns the union of two sets.
|
16
|
+
* @param {Set} setA The first set
|
17
|
+
* @param {Set} setB The second set
|
18
|
+
* @returns {Set} The union of the two sets
|
19
|
+
*/
|
20
20
|
function union(setA, setB) {
|
21
21
|
return new Set(function *() {
|
22
22
|
yield* setA;
|
@@ -29,22 +29,22 @@ const REGEX_GENERAL_ESCAPES = new Set("\\bcdDfnrsStvwWxu0123456789]");
|
|
29
29
|
const REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()B"));
|
30
30
|
|
31
31
|
/**
|
32
|
-
* Parses a regular expression into a list of characters with character class info.
|
33
|
-
* @param {string} regExpText The raw text used to create the regular expression
|
34
|
-
* @returns {Object[]} A list of characters, each with info on escaping and whether they're in a character class.
|
35
|
-
* @example
|
36
|
-
*
|
37
|
-
* parseRegExp('a\\b[cd-]')
|
38
|
-
*
|
39
|
-
* returns:
|
40
|
-
* [
|
41
|
-
* {text: 'a', index: 0, escaped: false, inCharClass: false, startsCharClass: false, endsCharClass: false},
|
42
|
-
* {text: 'b', index: 2, escaped: true, inCharClass: false, startsCharClass: false, endsCharClass: false},
|
43
|
-
* {text: 'c', index: 4, escaped: false, inCharClass: true, startsCharClass: true, endsCharClass: false},
|
44
|
-
* {text: 'd', index: 5, escaped: false, inCharClass: true, startsCharClass: false, endsCharClass: false},
|
45
|
-
* {text: '-', index: 6, escaped: false, inCharClass: true, startsCharClass: false, endsCharClass: false}
|
46
|
-
* ]
|
47
|
-
*/
|
32
|
+
* Parses a regular expression into a list of characters with character class info.
|
33
|
+
* @param {string} regExpText The raw text used to create the regular expression
|
34
|
+
* @returns {Object[]} A list of characters, each with info on escaping and whether they're in a character class.
|
35
|
+
* @example
|
36
|
+
*
|
37
|
+
* parseRegExp('a\\b[cd-]')
|
38
|
+
*
|
39
|
+
* returns:
|
40
|
+
* [
|
41
|
+
* {text: 'a', index: 0, escaped: false, inCharClass: false, startsCharClass: false, endsCharClass: false},
|
42
|
+
* {text: 'b', index: 2, escaped: true, inCharClass: false, startsCharClass: false, endsCharClass: false},
|
43
|
+
* {text: 'c', index: 4, escaped: false, inCharClass: true, startsCharClass: true, endsCharClass: false},
|
44
|
+
* {text: 'd', index: 5, escaped: false, inCharClass: true, startsCharClass: false, endsCharClass: false},
|
45
|
+
* {text: '-', index: 6, escaped: false, inCharClass: true, startsCharClass: false, endsCharClass: false}
|
46
|
+
* ]
|
47
|
+
*/
|
48
48
|
function parseRegExp(regExpText) {
|
49
49
|
const charList = [];
|
50
50
|
|
@@ -63,7 +63,14 @@ function parseRegExp(regExpText) {
|
|
63
63
|
return Object.assign(state, { inCharClass: false, startingCharClass: false });
|
64
64
|
}
|
65
65
|
}
|
66
|
-
charList.push({
|
66
|
+
charList.push({
|
67
|
+
text: char,
|
68
|
+
index,
|
69
|
+
escaped: state.escapeNextChar,
|
70
|
+
inCharClass: state.inCharClass,
|
71
|
+
startsCharClass: state.startingCharClass,
|
72
|
+
endsCharClass: false
|
73
|
+
});
|
67
74
|
return Object.assign(state, { escapeNextChar: false, startingCharClass: false });
|
68
75
|
}, { escapeNextChar: false, inCharClass: false, startingCharClass: false });
|
69
76
|
|
@@ -123,7 +130,8 @@ module.exports = {
|
|
123
130
|
isUnnecessaryEscape = match.input[match.index + 2] !== "{";
|
124
131
|
} else if (escapedChar === "{") {
|
125
132
|
|
126
|
-
/*
|
133
|
+
/*
|
134
|
+
* Warn if `\{` is not preceded by `$`. If preceded by `$`, escaping
|
127
135
|
* is necessary and the rule should not warn. If preceded by `/$`, the rule
|
128
136
|
* will warn for the `/$` instead, as it is the first unnecessarily escaped character.
|
129
137
|
*/
|
@@ -222,10 +222,12 @@ module.exports = {
|
|
222
222
|
fix(fixer) {
|
223
223
|
if (isRemovable(node)) {
|
224
224
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
225
|
+
/*
|
226
|
+
* Extend the replacement range to include the
|
227
|
+
* entire function to avoid conflicting with
|
228
|
+
* no-else-return.
|
229
|
+
* https://github.com/eslint/eslint/issues/8026
|
230
|
+
*/
|
229
231
|
return new FixTracker(fixer, context.getSourceCode())
|
230
232
|
.retainEnclosingFunction(node)
|
231
233
|
.remove(node);
|
@@ -238,8 +240,10 @@ module.exports = {
|
|
238
240
|
scopeInfo = scopeInfo.upper;
|
239
241
|
},
|
240
242
|
|
241
|
-
|
242
|
-
|
243
|
+
/*
|
244
|
+
* Initializes segments.
|
245
|
+
* NOTE: This event is notified for only reachable segments.
|
246
|
+
*/
|
243
247
|
onCodePathSegmentStart(segment) {
|
244
248
|
const info = {
|
245
249
|
uselessReturns: getUselessReturns([], segment.allPrevSegments),
|
@@ -270,8 +274,10 @@ module.exports = {
|
|
270
274
|
scopeInfo.uselessReturns.push(node);
|
271
275
|
},
|
272
276
|
|
273
|
-
|
274
|
-
|
277
|
+
/*
|
278
|
+
* Registers for all statement nodes except FunctionDeclaration, BlockStatement, BreakStatement.
|
279
|
+
* Removes return statements of the current segments from the useless return statement list.
|
280
|
+
*/
|
275
281
|
ClassDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed,
|
276
282
|
ContinueStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
|
277
283
|
DebuggerStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
|
package/lib/rules/no-var.js
CHANGED
@@ -15,6 +15,15 @@ const astUtils = require("../ast-utils");
|
|
15
15
|
// Helpers
|
16
16
|
//------------------------------------------------------------------------------
|
17
17
|
|
18
|
+
/**
|
19
|
+
* Check whether a given variable is a global variable or not.
|
20
|
+
* @param {eslint-scope.Variable} variable The variable to check.
|
21
|
+
* @returns {boolean} `true` if the variable is a global variable.
|
22
|
+
*/
|
23
|
+
function isGlobal(variable) {
|
24
|
+
return Boolean(variable.scope) && variable.scope.type === "global";
|
25
|
+
}
|
26
|
+
|
18
27
|
/**
|
19
28
|
* Finds the nearest function scope or global scope walking up the scope
|
20
29
|
* hierarchy.
|
@@ -203,6 +212,7 @@ module.exports = {
|
|
203
212
|
* Checks whether it can fix a given variable declaration or not.
|
204
213
|
* It cannot fix if the following cases:
|
205
214
|
*
|
215
|
+
* - A variable is a global variable.
|
206
216
|
* - A variable is declared on a SwitchCase node.
|
207
217
|
* - A variable is redeclared.
|
208
218
|
* - A variable is used from outside the scope.
|
@@ -256,6 +266,7 @@ module.exports = {
|
|
256
266
|
|
257
267
|
if (node.parent.type === "SwitchCase" ||
|
258
268
|
node.declarations.some(hasSelfReferenceInTDZ) ||
|
269
|
+
variables.some(isGlobal) ||
|
259
270
|
variables.some(isRedeclared) ||
|
260
271
|
variables.some(isUsedFromOutsideOf(scopeNode))
|
261
272
|
) {
|
@@ -53,8 +53,10 @@ module.exports = {
|
|
53
53
|
fix(fixer) {
|
54
54
|
if (!node.computed && astUtils.isDecimalInteger(node.object)) {
|
55
55
|
|
56
|
-
|
57
|
-
|
56
|
+
/*
|
57
|
+
* If the object is a number literal, fixing it to something like 5.toString() would cause a SyntaxError.
|
58
|
+
* Don't fix this case.
|
59
|
+
*/
|
58
60
|
return null;
|
59
61
|
}
|
60
62
|
return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], replacementText);
|
@@ -131,8 +131,15 @@ module.exports = {
|
|
131
131
|
*/
|
132
132
|
function check(node) {
|
133
133
|
const options = normalizedOptions[node.type];
|
134
|
-
const openBrace = sourceCode.getFirstToken(node);
|
135
|
-
|
134
|
+
const openBrace = sourceCode.getFirstToken(node, token => token.value === "{");
|
135
|
+
let closeBrace;
|
136
|
+
|
137
|
+
if (node.typeAnnotation) {
|
138
|
+
closeBrace = sourceCode.getTokenBefore(node.typeAnnotation);
|
139
|
+
} else {
|
140
|
+
closeBrace = sourceCode.getLastToken(node);
|
141
|
+
}
|
142
|
+
|
136
143
|
let first = sourceCode.getTokenAfter(openBrace, { includeComments: true });
|
137
144
|
let last = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
|
138
145
|
const needsLinebreaks = (
|
@@ -65,11 +65,11 @@ module.exports = {
|
|
65
65
|
//--------------------------------------------------------------------------
|
66
66
|
|
67
67
|
/**
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
* Reports that there shouldn't be a space after the first token
|
69
|
+
* @param {ASTNode} node - The node to report in the event of an error.
|
70
|
+
* @param {Token} token - The token to use for the report.
|
71
|
+
* @returns {void}
|
72
|
+
*/
|
73
73
|
function reportNoBeginningSpace(node, token) {
|
74
74
|
context.report({
|
75
75
|
node,
|
@@ -87,11 +87,11 @@ module.exports = {
|
|
87
87
|
}
|
88
88
|
|
89
89
|
/**
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
90
|
+
* Reports that there shouldn't be a space before the last token
|
91
|
+
* @param {ASTNode} node - The node to report in the event of an error.
|
92
|
+
* @param {Token} token - The token to use for the report.
|
93
|
+
* @returns {void}
|
94
|
+
*/
|
95
95
|
function reportNoEndingSpace(node, token) {
|
96
96
|
context.report({
|
97
97
|
node,
|
@@ -109,11 +109,11 @@ module.exports = {
|
|
109
109
|
}
|
110
110
|
|
111
111
|
/**
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
112
|
+
* Reports that there should be a space after the first token
|
113
|
+
* @param {ASTNode} node - The node to report in the event of an error.
|
114
|
+
* @param {Token} token - The token to use for the report.
|
115
|
+
* @returns {void}
|
116
|
+
*/
|
117
117
|
function reportRequiredBeginningSpace(node, token) {
|
118
118
|
context.report({
|
119
119
|
node,
|
@@ -129,11 +129,11 @@ module.exports = {
|
|
129
129
|
}
|
130
130
|
|
131
131
|
/**
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
132
|
+
* Reports that there should be a space before the last token
|
133
|
+
* @param {ASTNode} node - The node to report in the event of an error.
|
134
|
+
* @param {Token} token - The token to use for the report.
|
135
|
+
* @returns {void}
|
136
|
+
*/
|
137
137
|
function reportRequiredEndingSpace(node, token) {
|
138
138
|
context.report({
|
139
139
|
node,
|
@@ -127,16 +127,17 @@ module.exports = {
|
|
127
127
|
* @param {ASTNode} property Property AST node
|
128
128
|
* @returns {boolean} True if the property can have a shorthand form
|
129
129
|
* @private
|
130
|
-
|
130
|
+
*
|
131
|
+
*/
|
131
132
|
function canHaveShorthand(property) {
|
132
133
|
return (property.kind !== "set" && property.kind !== "get" && property.type !== "SpreadProperty" && property.type !== "ExperimentalSpreadProperty");
|
133
134
|
}
|
134
135
|
|
135
136
|
/**
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
137
|
+
* Checks whether a node is a string literal.
|
138
|
+
* @param {ASTNode} node - Any AST node.
|
139
|
+
* @returns {boolean} `true` if it is a string literal.
|
140
|
+
*/
|
140
141
|
function isStringLiteral(node) {
|
141
142
|
return node.type === "Literal" && typeof node.value === "string";
|
142
143
|
}
|
@@ -146,7 +147,8 @@ module.exports = {
|
|
146
147
|
* @param {ASTNode} property Property AST node
|
147
148
|
* @returns {boolean} True if the property is considered shorthand, false if not.
|
148
149
|
* @private
|
149
|
-
|
150
|
+
*
|
151
|
+
*/
|
150
152
|
function isShorthand(property) {
|
151
153
|
|
152
154
|
// property.method is true when `{a(){}}`.
|
@@ -158,7 +160,8 @@ module.exports = {
|
|
158
160
|
* @param {ASTNode} property Property AST node
|
159
161
|
* @returns {boolean} True if the key and value are named equally, false if not.
|
160
162
|
* @private
|
161
|
-
|
163
|
+
*
|
164
|
+
*/
|
162
165
|
function isRedundant(property) {
|
163
166
|
const value = property.value;
|
164
167
|
|
@@ -177,7 +180,8 @@ module.exports = {
|
|
177
180
|
* @param {ASTNode} node Property AST node
|
178
181
|
* @param {boolean} checkRedundancy Whether to check longform redundancy
|
179
182
|
* @returns {void}
|
180
|
-
|
183
|
+
*
|
184
|
+
*/
|
181
185
|
function checkConsistency(node, checkRedundancy) {
|
182
186
|
|
183
187
|
// We are excluding getters/setters and spread properties as they are considered neither longform nor shorthand.
|
@@ -187,8 +191,10 @@ module.exports = {
|
|
187
191
|
if (properties.length > 0) {
|
188
192
|
const shorthandProperties = properties.filter(isShorthand);
|
189
193
|
|
190
|
-
|
191
|
-
|
194
|
+
/*
|
195
|
+
* If we do not have an equal number of longform properties as
|
196
|
+
* shorthand properties, we are using the annotations inconsistently
|
197
|
+
*/
|
192
198
|
if (shorthandProperties.length !== properties.length) {
|
193
199
|
|
194
200
|
// We have at least 1 shorthand property
|
@@ -196,8 +202,10 @@ module.exports = {
|
|
196
202
|
context.report({ node, message: "Unexpected mix of shorthand and non-shorthand properties." });
|
197
203
|
} else if (checkRedundancy) {
|
198
204
|
|
199
|
-
|
200
|
-
|
205
|
+
/*
|
206
|
+
* If all properties of the object contain a method or value with a name matching it's key,
|
207
|
+
* all the keys are redundant.
|
208
|
+
*/
|
201
209
|
const canAlwaysUseShorthand = properties.every(isRedundant);
|
202
210
|
|
203
211
|
if (canAlwaysUseShorthand) {
|
@@ -209,14 +217,18 @@ module.exports = {
|
|
209
217
|
}
|
210
218
|
|
211
219
|
/**
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
220
|
+
* Fixes a FunctionExpression node by making it into a shorthand property.
|
221
|
+
* @param {SourceCodeFixer} fixer The fixer object
|
222
|
+
* @param {ASTNode} node A `Property` node that has a `FunctionExpression` or `ArrowFunctionExpression` as its value
|
223
|
+
* @returns {Object} A fix for this node
|
224
|
+
*/
|
217
225
|
function makeFunctionShorthand(fixer, node) {
|
218
|
-
const firstKeyToken = node.computed
|
219
|
-
|
226
|
+
const firstKeyToken = node.computed
|
227
|
+
? sourceCode.getFirstToken(node, astUtils.isOpeningBracketToken)
|
228
|
+
: sourceCode.getFirstToken(node.key);
|
229
|
+
const lastKeyToken = node.computed
|
230
|
+
? sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isClosingBracketToken)
|
231
|
+
: sourceCode.getLastToken(node.key);
|
220
232
|
const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]);
|
221
233
|
let keyPrefix = "";
|
222
234
|
|
@@ -249,11 +261,11 @@ module.exports = {
|
|
249
261
|
}
|
250
262
|
|
251
263
|
/**
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
264
|
+
* Fixes a FunctionExpression node by making it into a longform property.
|
265
|
+
* @param {SourceCodeFixer} fixer The fixer object
|
266
|
+
* @param {ASTNode} node A `Property` node that has a `FunctionExpression` as its value
|
267
|
+
* @returns {Object} A fix for this node
|
268
|
+
*/
|
257
269
|
function makeFunctionLongform(fixer, node) {
|
258
270
|
const firstKeyToken = node.computed ? sourceCode.getTokens(node).find(token => token.value === "[") : sourceCode.getFirstToken(node.key);
|
259
271
|
const lastKeyToken = node.computed ? sourceCode.getTokensBetween(node.key, node.value).find(token => token.value === "]") : sourceCode.getLastToken(node.key);
|
@@ -284,10 +296,10 @@ module.exports = {
|
|
284
296
|
const argumentsIdentifiers = new WeakSet();
|
285
297
|
|
286
298
|
/**
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
299
|
+
* Enters a function. This creates a new lexical identifier scope, so a new Set of arrow functions is pushed onto the stack.
|
300
|
+
* Also, this marks all `arguments` identifiers so that they can be detected later.
|
301
|
+
* @returns {void}
|
302
|
+
*/
|
291
303
|
function enterFunction() {
|
292
304
|
lexicalScopeStack.unshift(new Set());
|
293
305
|
context.getScope().variables.filter(variable => variable.name === "arguments").forEach(variable => {
|
@@ -296,18 +308,18 @@ module.exports = {
|
|
296
308
|
}
|
297
309
|
|
298
310
|
/**
|
299
|
-
|
300
|
-
|
301
|
-
|
311
|
+
* Exits a function. This pops the current set of arrow functions off the lexical scope stack.
|
312
|
+
* @returns {void}
|
313
|
+
*/
|
302
314
|
function exitFunction() {
|
303
315
|
lexicalScopeStack.shift();
|
304
316
|
}
|
305
317
|
|
306
318
|
/**
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
319
|
+
* Marks the current function as having a lexical keyword. This implies that all arrow functions
|
320
|
+
* in the current lexical scope contain a reference to this lexical keyword.
|
321
|
+
* @returns {void}
|
322
|
+
*/
|
311
323
|
function reportLexicalIdentifier() {
|
312
324
|
lexicalScopeStack[0].forEach(arrowFunction => arrowsWithLexicalIdentifiers.add(arrowFunction));
|
313
325
|
}
|
@@ -77,11 +77,11 @@ function same(a, b) {
|
|
77
77
|
}
|
78
78
|
|
79
79
|
/**
|
80
|
-
* Determines if the left side of a node can be safely fixed (i.e. if it activates the same getters/setters and)
|
81
|
-
* toString calls regardless of whether assignment shorthand is used)
|
82
|
-
* @param {ASTNode} node The node on the left side of the expression
|
83
|
-
* @returns {boolean} `true` if the node can be fixed
|
84
|
-
*/
|
80
|
+
* Determines if the left side of a node can be safely fixed (i.e. if it activates the same getters/setters and)
|
81
|
+
* toString calls regardless of whether assignment shorthand is used)
|
82
|
+
* @param {ASTNode} node The node on the left side of the expression
|
83
|
+
* @returns {boolean} `true` if the node can be fixed
|
84
|
+
*/
|
85
85
|
function canBeFixed(node) {
|
86
86
|
return node.type === "Identifier" ||
|
87
87
|
node.type === "MemberExpression" && node.object.type === "Identifier" && (!node.computed || node.property.type === "Literal");
|
@@ -109,10 +109,10 @@ module.exports = {
|
|
109
109
|
const sourceCode = context.getSourceCode();
|
110
110
|
|
111
111
|
/**
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
112
|
+
* Returns the operator token of an AssignmentExpression or BinaryExpression
|
113
|
+
* @param {ASTNode} node An AssignmentExpression or BinaryExpression node
|
114
|
+
* @returns {Token} The operator token in the node
|
115
|
+
*/
|
116
116
|
function getOperatorToken(node) {
|
117
117
|
return sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
|
118
118
|
}
|
@@ -69,11 +69,11 @@ module.exports = {
|
|
69
69
|
//--------------------------------------------------------------------------
|
70
70
|
|
71
71
|
/**
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
72
|
+
* Gets a fixer function to fix rule issues
|
73
|
+
* @param {Token} operatorToken The operator token of an expression
|
74
|
+
* @param {string} desiredStyle The style for the rule. One of 'before', 'after', 'none'
|
75
|
+
* @returns {Function} A fixer function
|
76
|
+
*/
|
77
77
|
function getFixer(operatorToken, desiredStyle) {
|
78
78
|
return fixer => {
|
79
79
|
const tokenBefore = sourceCode.getTokenBefore(operatorToken);
|
@@ -87,7 +87,9 @@ module.exports = {
|
|
87
87
|
if (hasLinebreakBefore !== hasLinebreakAfter && desiredStyle !== "none") {
|
88
88
|
|
89
89
|
// If there is a comment before and after the operator, don't do a fix.
|
90
|
-
if (sourceCode.getTokenBefore(operatorToken, { includeComments: true }) !== tokenBefore &&
|
90
|
+
if (sourceCode.getTokenBefore(operatorToken, { includeComments: true }) !== tokenBefore &&
|
91
|
+
sourceCode.getTokenAfter(operatorToken, { includeComments: true }) !== tokenAfter) {
|
92
|
+
|
91
93
|
return null;
|
92
94
|
}
|
93
95
|
|
@@ -133,11 +135,13 @@ module.exports = {
|
|
133
135
|
*/
|
134
136
|
function validateNode(node, leftSide) {
|
135
137
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
/*
|
139
|
+
* When the left part of a binary expression is a single expression wrapped in
|
140
|
+
* parentheses (ex: `(a) + b`), leftToken will be the last token of the expression
|
141
|
+
* and operatorToken will be the closing parenthesis.
|
142
|
+
* The leftToken should be the last closing parenthesis, and the operatorToken
|
143
|
+
* should be the token right after that.
|
144
|
+
*/
|
141
145
|
const operatorToken = sourceCode.getTokenAfter(leftSide, astUtils.isNotClosingParenToken);
|
142
146
|
const leftToken = sourceCode.getTokenBefore(operatorToken);
|
143
147
|
const rightToken = sourceCode.getTokenAfter(operatorToken);
|
@@ -85,8 +85,10 @@ function isBlockLikeStatement(sourceCode, node) {
|
|
85
85
|
return true;
|
86
86
|
}
|
87
87
|
|
88
|
-
|
89
|
-
|
88
|
+
/*
|
89
|
+
* IIFE is a block-like statement specially from
|
90
|
+
* JSCS#disallowPaddingNewLinesAfterBlocks.
|
91
|
+
*/
|
90
92
|
if (isIIFEStatement(node)) {
|
91
93
|
return true;
|
92
94
|
}
|
@@ -205,14 +207,14 @@ function verifyForAny() {
|
|
205
207
|
* blank lines automatically.
|
206
208
|
*
|
207
209
|
* @param {RuleContext} context The rule context to report.
|
208
|
-
* @param {ASTNode}
|
210
|
+
* @param {ASTNode} _ Unused. The previous node to check.
|
209
211
|
* @param {ASTNode} nextNode The next node to check.
|
210
212
|
* @param {Array<Token[]>} paddingLines The array of token pairs that blank
|
211
213
|
* lines exist between the pair.
|
212
214
|
* @returns {void}
|
213
215
|
* @private
|
214
216
|
*/
|
215
|
-
function verifyForNever(context,
|
217
|
+
function verifyForNever(context, _, nextNode, paddingLines) {
|
216
218
|
if (paddingLines.length === 0) {
|
217
219
|
return;
|
218
220
|
}
|
@@ -115,12 +115,12 @@ function getCallbackInfo(node) {
|
|
115
115
|
}
|
116
116
|
|
117
117
|
/**
|
118
|
-
* Checks whether a simple list of parameters contains any duplicates. This does not handle complex
|
119
|
-
parameter lists (e.g. with destructuring), since complex parameter lists are a SyntaxError with duplicate
|
120
|
-
parameter names anyway. Instead, it always returns `false` for complex parameter lists.
|
121
|
-
* @param {ASTNode[]} paramsList The list of parameters for a function
|
122
|
-
* @returns {boolean} `true` if the list of parameters contains any duplicates
|
123
|
-
*/
|
118
|
+
* Checks whether a simple list of parameters contains any duplicates. This does not handle complex
|
119
|
+
* parameter lists (e.g. with destructuring), since complex parameter lists are a SyntaxError with duplicate
|
120
|
+
* parameter names anyway. Instead, it always returns `false` for complex parameter lists.
|
121
|
+
* @param {ASTNode[]} paramsList The list of parameters for a function
|
122
|
+
* @returns {boolean} `true` if the list of parameters contains any duplicates
|
123
|
+
*/
|
124
124
|
function hasDuplicateParams(paramsList) {
|
125
125
|
return paramsList.every(param => param.type === "Identifier") && paramsList.length !== new Set(paramsList.map(param => param.name)).size;
|
126
126
|
}
|
@@ -265,10 +265,12 @@ module.exports = {
|
|
265
265
|
fix(fixer) {
|
266
266
|
if ((!callbackInfo.isLexicalThis && scopeInfo.this) || hasDuplicateParams(node.params)) {
|
267
267
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
268
|
+
/*
|
269
|
+
* If the callback function does not have .bind(this) and contains a reference to `this`, there
|
270
|
+
* is no way to determine what `this` should be, so don't perform any fixes.
|
271
|
+
* If the callback function has duplicates in its list of parameters (possible in sloppy mode),
|
272
|
+
* don't replace it with an arrow function, because this is a SyntaxError with arrow functions.
|
273
|
+
*/
|
272
274
|
return null;
|
273
275
|
}
|
274
276
|
|
@@ -112,8 +112,10 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) {
|
|
112
112
|
}
|
113
113
|
}
|
114
114
|
|
115
|
-
|
116
|
-
|
115
|
+
/*
|
116
|
+
* If the assignment is from a different scope, ignore it.
|
117
|
+
* If the assignment cannot change to a declaration, ignore it.
|
118
|
+
*/
|
117
119
|
const shouldBeConst = (
|
118
120
|
writer !== null &&
|
119
121
|
writer.from === variable.scope &&
|
@@ -179,8 +181,10 @@ function groupByDestructuring(variables, ignoreReadBeforeAssign) {
|
|
179
181
|
const reference = references[j];
|
180
182
|
const id = reference.identifier;
|
181
183
|
|
182
|
-
|
183
|
-
|
184
|
+
/*
|
185
|
+
* Avoid counting a reference twice or more for default values of
|
186
|
+
* destructuring.
|
187
|
+
*/
|
184
188
|
if (id === prevId) {
|
185
189
|
continue;
|
186
190
|
}
|
@@ -274,17 +278,21 @@ module.exports = {
|
|
274
278
|
const varDeclParent = findUp(nodes[0], "VariableDeclaration", parentNode => parentNode.type.endsWith("Statement"));
|
275
279
|
const shouldFix = varDeclParent &&
|
276
280
|
|
277
|
-
|
278
|
-
|
279
|
-
|
281
|
+
/*
|
282
|
+
* If there are multiple variable declarations, like {let a = 1, b = 2}, then
|
283
|
+
* do not attempt to fix if one of the declarations should be `const`. It's
|
284
|
+
* too hard to know how the developer would want to automatically resolve the issue.
|
285
|
+
*/
|
280
286
|
varDeclParent.declarations.length === 1 &&
|
281
287
|
|
282
288
|
// Don't do a fix unless the variable is initialized (or it's in a for-in or for-of loop)
|
283
289
|
(varDeclParent.parent.type === "ForInStatement" || varDeclParent.parent.type === "ForOfStatement" || varDeclParent.declarations[0].init) &&
|
284
290
|
|
285
|
-
|
286
|
-
|
287
|
-
|
291
|
+
/*
|
292
|
+
* If options.destucturing is "all", then this warning will not occur unless
|
293
|
+
* every assignment in the destructuring should be const. In that case, it's safe
|
294
|
+
* to apply the fix.
|
295
|
+
*/
|
288
296
|
nodesToReport.length === nodes.length;
|
289
297
|
|
290
298
|
nodesToReport.forEach(node => {
|
@@ -18,8 +18,10 @@ module.exports = {
|
|
18
18
|
schema: [
|
19
19
|
{
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
/*
|
22
|
+
* old support {array: Boolean, object: Boolean}
|
23
|
+
* new support {VariableDeclarator: {}, AssignmentExpression: {}}
|
24
|
+
*/
|
23
25
|
oneOf: [
|
24
26
|
{
|
25
27
|
type: "object",
|