eslint 4.10.0 → 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 +36 -22
- package/conf/default-cli-options.js +5 -3
- package/lib/ast-utils.js +81 -41
- package/lib/cli-engine.js +27 -12
- package/lib/code-path-analysis/code-path-analyzer.js +8 -4
- package/lib/code-path-analysis/code-path-segment.js +4 -2
- package/lib/code-path-analysis/code-path-state.js +4 -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/junit.js +21 -15
- package/lib/formatters/tap.js +5 -3
- package/lib/ignored-paths.js +4 -2
- package/lib/linter.js +16 -10
- package/lib/rules/.eslintrc.yml +2 -2
- package/lib/rules/array-bracket-newline.js +20 -20
- 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/brace-style.js +14 -14
- 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 +5 -5
- package/lib/rules/func-call-spacing.js +4 -2
- package/lib/rules/getter-return.js +2 -1
- package/lib/rules/indent-legacy.js +20 -12
- package/lib/rules/indent.js +77 -73
- package/lib/rules/key-spacing.js +5 -3
- package/lib/rules/lines-around-directive.js +16 -12
- package/lib/rules/max-statements-per-line.js +5 -3
- package/lib/rules/newline-after-var.js +8 -6
- package/lib/rules/newline-before-return.js +9 -7
- 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-else-return.js +17 -11
- package/lib/rules/no-empty-character-class.js +11 -11
- package/lib/rules/no-extra-parens.js +16 -8
- 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-loop-func.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-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 +13 -7
- package/lib/rules/no-unreachable.js +4 -2
- package/lib/rules/no-use-before-define.js +13 -11
- package/lib/rules/no-useless-call.js +1 -25
- package/lib/rules/no-useless-escape.js +23 -22
- package/lib/rules/no-useless-return.js +14 -8
- 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 +41 -33
- package/lib/rules/operator-assignment.js +9 -9
- package/lib/rules/operator-linebreak.js +12 -10
- package/lib/rules/padding-line-between-statements.js +4 -2
- 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/semi-style.js +44 -19
- package/lib/rules/semi.js +5 -3
- package/lib/rules/sort-imports.js +5 -3
- package/lib/rules/space-unary-ops.js +61 -61
- package/lib/rules/strict.js +8 -8
- 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 +43 -34
- 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/glob.js +1 -1
- package/lib/util/naming.js +112 -0
- package/lib/util/node-event-generator.js +10 -10
- package/lib/util/safe-emitter.js +1 -1
- package/lib/util/source-code-fixer.js +4 -2
- package/lib/util/source-code.js +2 -1
- package/package.json +6 -5
@@ -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,11 +217,11 @@ 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
226
|
const firstKeyToken = node.computed
|
219
227
|
? sourceCode.getFirstToken(node, astUtils.isOpeningBracketToken)
|
@@ -253,11 +261,11 @@ module.exports = {
|
|
253
261
|
}
|
254
262
|
|
255
263
|
/**
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
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
|
+
*/
|
261
269
|
function makeFunctionLongform(fixer, node) {
|
262
270
|
const firstKeyToken = node.computed ? sourceCode.getTokens(node).find(token => token.value === "[") : sourceCode.getFirstToken(node.key);
|
263
271
|
const lastKeyToken = node.computed ? sourceCode.getTokensBetween(node.key, node.value).find(token => token.value === "]") : sourceCode.getLastToken(node.key);
|
@@ -288,10 +296,10 @@ module.exports = {
|
|
288
296
|
const argumentsIdentifiers = new WeakSet();
|
289
297
|
|
290
298
|
/**
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
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
|
+
*/
|
295
303
|
function enterFunction() {
|
296
304
|
lexicalScopeStack.unshift(new Set());
|
297
305
|
context.getScope().variables.filter(variable => variable.name === "arguments").forEach(variable => {
|
@@ -300,18 +308,18 @@ module.exports = {
|
|
300
308
|
}
|
301
309
|
|
302
310
|
/**
|
303
|
-
|
304
|
-
|
305
|
-
|
311
|
+
* Exits a function. This pops the current set of arrow functions off the lexical scope stack.
|
312
|
+
* @returns {void}
|
313
|
+
*/
|
306
314
|
function exitFunction() {
|
307
315
|
lexicalScopeStack.shift();
|
308
316
|
}
|
309
317
|
|
310
318
|
/**
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
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
|
+
*/
|
315
323
|
function reportLexicalIdentifier() {
|
316
324
|
lexicalScopeStack[0].forEach(arrowFunction => arrowsWithLexicalIdentifiers.add(arrowFunction));
|
317
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);
|
@@ -135,11 +135,13 @@ module.exports = {
|
|
135
135
|
*/
|
136
136
|
function validateNode(node, leftSide) {
|
137
137
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
+
*/
|
143
145
|
const operatorToken = sourceCode.getTokenAfter(leftSide, astUtils.isNotClosingParenToken);
|
144
146
|
const leftToken = sourceCode.getTokenBefore(operatorToken);
|
145
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
|
}
|
@@ -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",
|
@@ -96,8 +96,10 @@ module.exports = {
|
|
96
96
|
|
97
97
|
if (+(newPrefix + node.arguments[0].value) !== parseInt(node.arguments[0].value, node.arguments[1].value)) {
|
98
98
|
|
99
|
-
|
100
|
-
|
99
|
+
/*
|
100
|
+
* If the newly-produced literal would be invalid, (e.g. 0b1234),
|
101
|
+
* or it would yield an incorrect parseInt result for some other reason, don't make a fix.
|
102
|
+
*/
|
101
103
|
return null;
|
102
104
|
}
|
103
105
|
return fixer.replaceText(node, prefixMap[node.arguments[1].value] + node.arguments[0].value);
|
@@ -38,10 +38,10 @@ module.exports = {
|
|
38
38
|
//----------------------------------------------------------------------
|
39
39
|
|
40
40
|
/**
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
* Checks the argument of a reject() or Promise.reject() CallExpression, and reports it if it can't be an Error
|
42
|
+
* @param {ASTNode} callExpression A CallExpression node which is used to reject a Promise
|
43
|
+
* @returns {void}
|
44
|
+
*/
|
45
45
|
function checkRejectCall(callExpression) {
|
46
46
|
if (!callExpression.arguments.length && ALLOW_EMPTY_REJECT) {
|
47
47
|
return;
|
@@ -59,10 +59,10 @@ module.exports = {
|
|
59
59
|
}
|
60
60
|
|
61
61
|
/**
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
* Determines whether a function call is a Promise.reject() call
|
63
|
+
* @param {ASTNode} node A CallExpression node
|
64
|
+
* @returns {boolean} `true` if the call is a Promise.reject() call
|
65
|
+
*/
|
66
66
|
function isPromiseRejectCall(node) {
|
67
67
|
return node.callee.type === "MemberExpression" &&
|
68
68
|
node.callee.object.type === "Identifier" && node.callee.object.name === "Promise" &&
|
@@ -96,14 +96,14 @@ module.exports = {
|
|
96
96
|
context.getDeclaredVariables(node.arguments[0])
|
97
97
|
|
98
98
|
/*
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
99
|
+
* Find the first variable that matches the second parameter's name.
|
100
|
+
* If the first parameter has the same name as the second parameter, then the variable will actually
|
101
|
+
* be "declared" when the first parameter is evaluated, but then it will be immediately overwritten
|
102
|
+
* by the second parameter. It's not possible for an expression with the variable to be evaluated before
|
103
|
+
* the variable is overwritten, because functions with duplicate parameters cannot have destructuring or
|
104
|
+
* default assignments in their parameter lists. Therefore, it's not necessary to explicitly account for
|
105
|
+
* this case.
|
106
|
+
*/
|
107
107
|
.find(variable => variable.name === node.arguments[0].params[1].name)
|
108
108
|
|
109
109
|
// Get the references to that variable.
|
@@ -22,8 +22,10 @@ function getVariableOfArguments(scope) {
|
|
22
22
|
|
23
23
|
if (variable.name === "arguments") {
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
/*
|
26
|
+
* If there was a parameter which is named "arguments", the implicit "arguments" is not defined.
|
27
|
+
* So does fast return with null.
|
28
|
+
*/
|
27
29
|
return (variable.identifiers.length === 0) ? variable : null;
|
28
30
|
}
|
29
31
|
}
|
@@ -28,30 +28,6 @@ function isVariadicApplyCalling(node) {
|
|
28
28
|
);
|
29
29
|
}
|
30
30
|
|
31
|
-
/**
|
32
|
-
* Checks whether or not the tokens of two given nodes are same.
|
33
|
-
* @param {ASTNode} left - A node 1 to compare.
|
34
|
-
* @param {ASTNode} right - A node 2 to compare.
|
35
|
-
* @param {SourceCode} sourceCode - The ESLint source code object.
|
36
|
-
* @returns {boolean} the source code for the given node.
|
37
|
-
*/
|
38
|
-
function equalTokens(left, right, sourceCode) {
|
39
|
-
const tokensL = sourceCode.getTokens(left);
|
40
|
-
const tokensR = sourceCode.getTokens(right);
|
41
|
-
|
42
|
-
if (tokensL.length !== tokensR.length) {
|
43
|
-
return false;
|
44
|
-
}
|
45
|
-
for (let i = 0; i < tokensL.length; ++i) {
|
46
|
-
if (tokensL[i].type !== tokensR[i].type ||
|
47
|
-
tokensL[i].value !== tokensR[i].value
|
48
|
-
) {
|
49
|
-
return false;
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
return true;
|
54
|
-
}
|
55
31
|
|
56
32
|
/**
|
57
33
|
* Checks whether or not `thisArg` is not changed by `.apply()`.
|
@@ -64,7 +40,7 @@ function isValidThisArg(expectedThis, thisArg, context) {
|
|
64
40
|
if (!expectedThis) {
|
65
41
|
return astUtils.isNullOrUndefined(thisArg);
|
66
42
|
}
|
67
|
-
return equalTokens(expectedThis, thisArg, context);
|
43
|
+
return astUtils.equalTokens(expectedThis, thisArg, context);
|
68
44
|
}
|
69
45
|
|
70
46
|
//------------------------------------------------------------------------------
|
@@ -37,10 +37,10 @@ function getTopConcatBinaryExpression(node) {
|
|
37
37
|
}
|
38
38
|
|
39
39
|
/**
|
40
|
-
* Checks whether or not a given binary expression has string literals.
|
41
|
-
* @param {ASTNode} node - A node to check.
|
42
|
-
* @returns {boolean} `true` if the node has string literals.
|
43
|
-
*/
|
40
|
+
* Checks whether or not a given binary expression has string literals.
|
41
|
+
* @param {ASTNode} node - A node to check.
|
42
|
+
* @returns {boolean} `true` if the node has string literals.
|
43
|
+
*/
|
44
44
|
function hasStringLiteral(node) {
|
45
45
|
if (isConcatenation(node)) {
|
46
46
|
|
@@ -65,10 +65,10 @@ function hasNonStringLiteral(node) {
|
|
65
65
|
}
|
66
66
|
|
67
67
|
/**
|
68
|
-
* Determines whether a given node will start with a template curly expression (`${}`) when being converted to a template literal.
|
69
|
-
* @param {ASTNode} node The node that will be fixed to a template literal
|
70
|
-
* @returns {boolean} `true` if the node will start with a template curly.
|
71
|
-
*/
|
68
|
+
* Determines whether a given node will start with a template curly expression (`${}`) when being converted to a template literal.
|
69
|
+
* @param {ASTNode} node The node that will be fixed to a template literal
|
70
|
+
* @returns {boolean} `true` if the node will start with a template curly.
|
71
|
+
*/
|
72
72
|
function startsWithTemplateCurly(node) {
|
73
73
|
if (node.type === "BinaryExpression") {
|
74
74
|
return startsWithTemplateCurly(node.left);
|
@@ -80,10 +80,10 @@ function startsWithTemplateCurly(node) {
|
|
80
80
|
}
|
81
81
|
|
82
82
|
/**
|
83
|
-
* Determines whether a given node end with a template curly expression (`${}`) when being converted to a template literal.
|
84
|
-
* @param {ASTNode} node The node that will be fixed to a template literal
|
85
|
-
* @returns {boolean} `true` if the node will end with a template curly.
|
86
|
-
*/
|
83
|
+
* Determines whether a given node end with a template curly expression (`${}`) when being converted to a template literal.
|
84
|
+
* @param {ASTNode} node The node that will be fixed to a template literal
|
85
|
+
* @returns {boolean} `true` if the node will end with a template curly.
|
86
|
+
*/
|
87
87
|
function endsWithTemplateCurly(node) {
|
88
88
|
if (node.type === "BinaryExpression") {
|
89
89
|
return startsWithTemplateCurly(node.right);
|
@@ -116,11 +116,11 @@ module.exports = {
|
|
116
116
|
let done = Object.create(null);
|
117
117
|
|
118
118
|
/**
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
119
|
+
* Gets the non-token text between two nodes, ignoring any other tokens that appear between the two tokens.
|
120
|
+
* @param {ASTNode} node1 The first node
|
121
|
+
* @param {ASTNode} node2 The second node
|
122
|
+
* @returns {string} The text between the nodes, excluding other tokens
|
123
|
+
*/
|
124
124
|
function getTextBetween(node1, node2) {
|
125
125
|
const allTokens = [node1].concat(sourceCode.getTokensBetween(node1, node2)).concat(node2);
|
126
126
|
const sourceText = sourceCode.getText();
|
@@ -129,19 +129,21 @@ module.exports = {
|
|
129
129
|
}
|
130
130
|
|
131
131
|
/**
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
132
|
+
* Returns a template literal form of the given node.
|
133
|
+
* @param {ASTNode} currentNode A node that should be converted to a template literal
|
134
|
+
* @param {string} textBeforeNode Text that should appear before the node
|
135
|
+
* @param {string} textAfterNode Text that should appear after the node
|
136
|
+
* @returns {string} A string form of this node, represented as a template literal
|
137
|
+
*/
|
138
138
|
function getTemplateLiteral(currentNode, textBeforeNode, textAfterNode) {
|
139
139
|
if (currentNode.type === "Literal" && typeof currentNode.value === "string") {
|
140
140
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
141
|
+
/*
|
142
|
+
* If the current node is a string literal, escape any instances of ${ or ` to prevent them from being interpreted
|
143
|
+
* as a template placeholder. However, if the code already contains a backslash before the ${ or `
|
144
|
+
* for some reason, don't add another backslash, because that would change the meaning of the code (it would cause
|
145
|
+
* an actual backslash character to appear before the dollar sign).
|
146
|
+
*/
|
145
147
|
return `\`${currentNode.raw.slice(1, -1).replace(/\\*(\${|`)/g, matched => {
|
146
148
|
if (matched.lastIndexOf("\\") % 2) {
|
147
149
|
return `\\${matched}`;
|
@@ -178,8 +180,10 @@ module.exports = {
|
|
178
180
|
getTemplateLiteral(currentNode.right, textBeforePlus + textAfterPlus, textAfterNode).slice(1);
|
179
181
|
}
|
180
182
|
|
181
|
-
|
182
|
-
|
183
|
+
/*
|
184
|
+
* Otherwise, these nodes should not be combined into a template curly, since there is nowhere to put
|
185
|
+
* the text between them.
|
186
|
+
*/
|
183
187
|
return `${getTemplateLiteral(currentNode.left, textBeforeNode, null)}${textBeforePlus}+${textAfterPlus}${getTemplateLiteral(currentNode.right, textAfterNode, null)}`;
|
184
188
|
}
|
185
189
|
|
package/lib/rules/quote-props.js
CHANGED
@@ -104,19 +104,19 @@ module.exports = {
|
|
104
104
|
}
|
105
105
|
|
106
106
|
/**
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
107
|
+
* Returns a string representation of a property node with quotes removed
|
108
|
+
* @param {ASTNode} key Key AST Node, which may or may not be quoted
|
109
|
+
* @returns {string} A replacement string for this property
|
110
|
+
*/
|
111
111
|
function getUnquotedKey(key) {
|
112
112
|
return key.type === "Identifier" ? key.name : key.value;
|
113
113
|
}
|
114
114
|
|
115
115
|
/**
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
116
|
+
* Returns a string representation of a property node with quotes added
|
117
|
+
* @param {ASTNode} key Key AST Node, which may or may not be quoted
|
118
|
+
* @returns {string} A replacement string for this property
|
119
|
+
*/
|
120
120
|
function getQuotedKey(key) {
|
121
121
|
if (key.type === "Literal" && typeof key.value === "string") {
|
122
122
|
|