eslint 6.3.0 → 6.4.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 +33 -0
- package/README.md +2 -2
- package/lib/cli-engine/config-array/override-tester.js +2 -2
- package/lib/rules/accessor-pairs.js +51 -11
- package/lib/rules/computed-property-spacing.js +18 -1
- package/lib/rules/default-param-last.js +61 -0
- package/lib/rules/eqeqeq.js +7 -19
- package/lib/rules/indent.js +16 -6
- package/lib/rules/index.js +3 -0
- package/lib/rules/no-extra-boolean-cast.js +1 -1
- package/lib/rules/no-import-assign.js +238 -0
- package/lib/rules/no-lone-blocks.js +6 -1
- package/lib/rules/no-obj-calls.js +29 -9
- package/lib/rules/no-octal-escape.js +14 -8
- package/lib/rules/no-self-assign.js +6 -5
- package/lib/rules/no-sequences.js +2 -2
- package/lib/rules/no-unsafe-negation.js +2 -10
- package/lib/rules/object-curly-spacing.js +1 -1
- package/lib/rules/object-shorthand.js +35 -9
- package/lib/rules/prefer-regex-literals.js +125 -0
- package/lib/rules/quotes.js +6 -0
- package/lib/rules/space-before-function-paren.js +12 -1
- package/lib/rules/space-in-parens.js +77 -71
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
v6.4.0 - September 13, 2019
|
2
|
+
|
3
|
+
* [`e915fff`](https://github.com/eslint/eslint/commit/e915fffb6089a23ff1cae926cc607f9b87dc1819) Docs: Improve examples and clarify default option (#12067) (Yuping Zuo)
|
4
|
+
* [`540296f`](https://github.com/eslint/eslint/commit/540296fcecd232a09dc873a5a22f5839b59b7842) Update: enforceForClassMembers option to accessor-pairs (fixes #12063) (#12192) (Milos Djermanovic)
|
5
|
+
* [`d3c2334`](https://github.com/eslint/eslint/commit/d3c2334646eae9287d5be9e457d041e445efb512) Update: flag nested block with declaration as error (#12193) (David Waller)
|
6
|
+
* [`b2498d2`](https://github.com/eslint/eslint/commit/b2498d284b9c30ed1543429c2f45d9014e12fe22) Update: Fix handling of property names in no-self-assign (#12105) (Milos Djermanovic)
|
7
|
+
* [`1ee61b0`](https://github.com/eslint/eslint/commit/1ee61b06715fcc750be2c923034a1e59ba663287) Update: enforceForClassMembers computed-property-spacing (fixes #12049) (#12214) (Milos Djermanovic)
|
8
|
+
* [`520c922`](https://github.com/eslint/eslint/commit/520c92270eed6e90c1a796e8af275980f01705e0) Docs: Added naming convention details to plugin usage (#12202) (Henrique Barcelos)
|
9
|
+
* [`f826eab`](https://github.com/eslint/eslint/commit/f826eabbeecddb047f58f4e7308a14c18148d369) Fix: Allow line comment exception in object-curly-spacing (fixes #11902) (#12216) (Milos Djermanovic)
|
10
|
+
* [`db2a29b`](https://github.com/eslint/eslint/commit/db2a29beb0fa28183f65bf9e659c66c03a8918b5) Update: indentation of comment followed by semicolon (fixes #12232) (#12243) (Kai Cataldo)
|
11
|
+
* [`ae17d1c`](https://github.com/eslint/eslint/commit/ae17d1ca59dd466aa64da0680ec2453c2dc3b80d) Fix: no-sequences is reporting incorrect locations (#12241) (Milos Djermanovic)
|
12
|
+
* [`365331a`](https://github.com/eslint/eslint/commit/365331a42e22af5a77ac9cfa9673d6a8f653eb5a) Fix: object-shorthand providing invalid fixes for typescript (#12260) (Brad Zacher)
|
13
|
+
* [`1c921c6`](https://github.com/eslint/eslint/commit/1c921c6dfd7ddfb0308c8103e53d32c1241475f0) New: add no-import-assign (fixes #12237) (#12252) (Toru Nagashima)
|
14
|
+
* [`3be04fd`](https://github.com/eslint/eslint/commit/3be04fd6a4e7b3f5a5ecb845a29cf29b71fe2dfb) New: Add prefer-regex-literals rule (fixes #12238) (#12254) (Milos Djermanovic)
|
15
|
+
* [`37c0fde`](https://github.com/eslint/eslint/commit/37c0fdeb87b92a0b779b125adf45535b79b65757) Update: Report global Atomics calls in no-obj-calls (fixes #12234) (#12258) (Milos Djermanovic)
|
16
|
+
* [`985c9e5`](https://github.com/eslint/eslint/commit/985c9e5eba351965a8a1491a41dbdcc78154b8f4) Fix: space-before-function-paren autofix removes comments (fixes #12259) (#12264) (Milos Djermanovic)
|
17
|
+
* [`01da7d0`](https://github.com/eslint/eslint/commit/01da7d04c4e5a7376cf241ec02db7971726a1bf9) Fix: eqeqeq rule reports incorrect locations (#12265) (Milos Djermanovic)
|
18
|
+
* [`319e4d8`](https://github.com/eslint/eslint/commit/319e4d8386ea846928f0f906c251b46043a53491) Docs: adding finally example (#12256) (Jens Melgaard)
|
19
|
+
* [`d52328f`](https://github.com/eslint/eslint/commit/d52328f012f3704c7d1ce39427e63f80531c7979) Docs: fix no-sequences `with` examples (#12239) (Milos Djermanovic)
|
20
|
+
* [`a41fdc0`](https://github.com/eslint/eslint/commit/a41fdc07404a7675d14183fab245fb8f49dcb858) Fix: Remove autofixer for no-unsafe-negation (#12157) (Milos Djermanovic)
|
21
|
+
* [`e38f5fd`](https://github.com/eslint/eslint/commit/e38f5fdfc786363a3eae642f1a69a8725600aa61) Update: fix no-octal-escape false negatives after \0 (#12079) (Milos Djermanovic)
|
22
|
+
* [`9418fbe`](https://github.com/eslint/eslint/commit/9418fbe0eb31cace3debe27b620709628df2fad7) Sponsors: Sync README with website (ESLint Jenkins)
|
23
|
+
* [`acc5ec5`](https://github.com/eslint/eslint/commit/acc5ec5082aed466a29899f651e6767b39155aec) Sponsors: Sync README with website (ESLint Jenkins)
|
24
|
+
* [`460c5ad`](https://github.com/eslint/eslint/commit/460c5ad176eaf39ff579cd96b3bcbe0539093f8f) Sponsors: Sync README with website (ESLint Jenkins)
|
25
|
+
* [`0313441`](https://github.com/eslint/eslint/commit/0313441d016c8aa0674c135f9da67a676e766ec5) New: add rule default-param-last (fixes #11361) (#12188) (Chiawen Chen)
|
26
|
+
* [`7621f5d`](https://github.com/eslint/eslint/commit/7621f5d2aa7d87e798b75ca47d6889c280597e99) Update: add more specific linting messages to space-in-parens (#11121) (Che Fisher)
|
27
|
+
* [`21eb904`](https://github.com/eslint/eslint/commit/21eb9044135c01b6c12188517bba840614483fc6) Fix: basePath of OverrideTester (fixes #12032) (#12205) (Toru Nagashima)
|
28
|
+
* [`86e5e65`](https://github.com/eslint/eslint/commit/86e5e657ea3fbf12b10524abcbc197afd215a060) Sponsors: Sync README with website (ESLint Jenkins)
|
29
|
+
* [`2b1a13f`](https://github.com/eslint/eslint/commit/2b1a13fa0de8360586857f3ced8da514c971297d) Fix: no-extra-boolean-cast reports wrong negation node (fixes #11324) (#12197) (Milos Djermanovic)
|
30
|
+
* [`ba8c2aa`](https://github.com/eslint/eslint/commit/ba8c2aa0154561fbeca33db0343cb39a7fbd9b4f) Sponsors: Sync README with website (ESLint Jenkins)
|
31
|
+
* [`a0a9746`](https://github.com/eslint/eslint/commit/a0a9746724ccd22c721ddc1b25c566aa9acea154) Docs: Fix link in no-irregular-whitespace.md (#12196) (Timo Tijhof)
|
32
|
+
* [`e10eeba`](https://github.com/eslint/eslint/commit/e10eebab4abd193dee697c4de7fb2d95bbab2d8c) Fix: quotes autofix produces syntax error with octal escape sequences (#12118) (Milos Djermanovic)
|
33
|
+
|
1
34
|
v6.3.0 - August 30, 2019
|
2
35
|
|
3
36
|
* [`0acdefb`](https://github.com/eslint/eslint/commit/0acdefb97f35bb09db2910540c70dc377a01ad62) Chore: refactor code (#12113) (James George)
|
package/README.md
CHANGED
@@ -262,9 +262,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
|
|
262
262
|
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
|
263
263
|
<!--sponsorsstart-->
|
264
264
|
<h3>Gold Sponsors</h3>
|
265
|
-
<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/d1b37c4/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/
|
265
|
+
<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/d1b37c4/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
|
266
266
|
<p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
|
267
|
-
<p><a href="https://
|
267
|
+
<p><a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://moneypug.co.uk/"><img src="https://images.opencollective.com/moneypug/45f8d53/logo.png" alt="MONEYPUG" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
|
268
268
|
<!--sponsorsend-->
|
269
269
|
|
270
270
|
## <a name="technology-sponsors"></a>Technology Sponsors
|
@@ -125,10 +125,10 @@ class OverrideTester {
|
|
125
125
|
*/
|
126
126
|
static and(a, b) {
|
127
127
|
if (!b) {
|
128
|
-
return a;
|
128
|
+
return a && new OverrideTester(a.patterns, a.basePath);
|
129
129
|
}
|
130
130
|
if (!a) {
|
131
|
-
return b;
|
131
|
+
return new OverrideTester(b.patterns, b.basePath);
|
132
132
|
}
|
133
133
|
|
134
134
|
assert.strictEqual(a.basePath, b.basePath);
|
@@ -152,7 +152,7 @@ module.exports = {
|
|
152
152
|
type: "suggestion",
|
153
153
|
|
154
154
|
docs: {
|
155
|
-
description: "enforce getter and setter pairs in objects",
|
155
|
+
description: "enforce getter and setter pairs in objects and classes",
|
156
156
|
category: "Best Practices",
|
157
157
|
recommended: false,
|
158
158
|
url: "https://eslint.org/docs/rules/accessor-pairs"
|
@@ -168,6 +168,10 @@ module.exports = {
|
|
168
168
|
setWithoutGet: {
|
169
169
|
type: "boolean",
|
170
170
|
default: true
|
171
|
+
},
|
172
|
+
enforceForClassMembers: {
|
173
|
+
type: "boolean",
|
174
|
+
default: false
|
171
175
|
}
|
172
176
|
},
|
173
177
|
additionalProperties: false
|
@@ -177,13 +181,16 @@ module.exports = {
|
|
177
181
|
missingGetterInPropertyDescriptor: "Getter is not present in property descriptor.",
|
178
182
|
missingSetterInPropertyDescriptor: "Setter is not present in property descriptor.",
|
179
183
|
missingGetterInObjectLiteral: "Getter is not present for {{ name }}.",
|
180
|
-
missingSetterInObjectLiteral: "Setter is not present for {{ name }}."
|
184
|
+
missingSetterInObjectLiteral: "Setter is not present for {{ name }}.",
|
185
|
+
missingGetterInClass: "Getter is not present for class {{ name }}.",
|
186
|
+
missingSetterInClass: "Setter is not present for class {{ name }}."
|
181
187
|
}
|
182
188
|
},
|
183
189
|
create(context) {
|
184
190
|
const config = context.options[0] || {};
|
185
191
|
const checkGetWithoutSet = config.getWithoutSet === true;
|
186
192
|
const checkSetWithoutGet = config.setWithoutGet !== false;
|
193
|
+
const enforceForClassMembers = config.enforceForClassMembers === true;
|
187
194
|
const sourceCode = context.getSourceCode();
|
188
195
|
|
189
196
|
/**
|
@@ -201,6 +208,13 @@ module.exports = {
|
|
201
208
|
loc: astUtils.getFunctionHeadLoc(node.value, sourceCode),
|
202
209
|
data: { name: astUtils.getFunctionNameWithKind(node.value) }
|
203
210
|
});
|
211
|
+
} else if (node.type === "MethodDefinition") {
|
212
|
+
context.report({
|
213
|
+
node,
|
214
|
+
messageId: `${messageKind}InClass`,
|
215
|
+
loc: astUtils.getFunctionHeadLoc(node.value, sourceCode),
|
216
|
+
data: { name: astUtils.getFunctionNameWithKind(node.value) }
|
217
|
+
});
|
204
218
|
} else {
|
205
219
|
context.report({
|
206
220
|
node,
|
@@ -313,15 +327,41 @@ module.exports = {
|
|
313
327
|
}
|
314
328
|
}
|
315
329
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
330
|
+
/**
|
331
|
+
* Checks the given object expression as an object literal and as a possible property descriptor.
|
332
|
+
* @param {ASTNode} node `ObjectExpression` node to check.
|
333
|
+
* @returns {void}
|
334
|
+
* @private
|
335
|
+
*/
|
336
|
+
function checkObjectExpression(node) {
|
337
|
+
checkObjectLiteral(node);
|
338
|
+
if (isPropertyDescriptor(node)) {
|
339
|
+
checkPropertyDescriptor(node);
|
324
340
|
}
|
325
|
-
}
|
341
|
+
}
|
342
|
+
|
343
|
+
/**
|
344
|
+
* Checks the given class body.
|
345
|
+
* @param {ASTNode} node `ClassBody` node to check.
|
346
|
+
* @returns {void}
|
347
|
+
* @private
|
348
|
+
*/
|
349
|
+
function checkClassBody(node) {
|
350
|
+
const methodDefinitions = node.body.filter(m => m.type === "MethodDefinition");
|
351
|
+
|
352
|
+
checkList(methodDefinitions.filter(m => m.static));
|
353
|
+
checkList(methodDefinitions.filter(m => !m.static));
|
354
|
+
}
|
355
|
+
|
356
|
+
const listeners = {};
|
357
|
+
|
358
|
+
if (checkSetWithoutGet || checkGetWithoutSet) {
|
359
|
+
listeners.ObjectExpression = checkObjectExpression;
|
360
|
+
if (enforceForClassMembers) {
|
361
|
+
listeners.ClassBody = checkClassBody;
|
362
|
+
}
|
363
|
+
}
|
364
|
+
|
365
|
+
return listeners;
|
326
366
|
}
|
327
367
|
};
|
@@ -26,6 +26,16 @@ module.exports = {
|
|
26
26
|
schema: [
|
27
27
|
{
|
28
28
|
enum: ["always", "never"]
|
29
|
+
},
|
30
|
+
{
|
31
|
+
type: "object",
|
32
|
+
properties: {
|
33
|
+
enforceForClassMembers: {
|
34
|
+
type: "boolean",
|
35
|
+
default: false
|
36
|
+
}
|
37
|
+
},
|
38
|
+
additionalProperties: false
|
29
39
|
}
|
30
40
|
],
|
31
41
|
|
@@ -41,6 +51,7 @@ module.exports = {
|
|
41
51
|
create(context) {
|
42
52
|
const sourceCode = context.getSourceCode();
|
43
53
|
const propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never"
|
54
|
+
const enforceForClassMembers = context.options[1] && context.options[1].enforceForClassMembers;
|
44
55
|
|
45
56
|
//--------------------------------------------------------------------------
|
46
57
|
// Helpers
|
@@ -178,10 +189,16 @@ module.exports = {
|
|
178
189
|
// Public
|
179
190
|
//--------------------------------------------------------------------------
|
180
191
|
|
181
|
-
|
192
|
+
const listeners = {
|
182
193
|
Property: checkSpacing("key"),
|
183
194
|
MemberExpression: checkSpacing("property")
|
184
195
|
};
|
185
196
|
|
197
|
+
if (enforceForClassMembers) {
|
198
|
+
listeners.MethodDefinition = checkSpacing("key");
|
199
|
+
}
|
200
|
+
|
201
|
+
return listeners;
|
202
|
+
|
186
203
|
}
|
187
204
|
};
|
@@ -0,0 +1,61 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview enforce default parameters to be last
|
3
|
+
* @author Chiawen Chen
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
module.exports = {
|
9
|
+
meta: {
|
10
|
+
type: "suggestion",
|
11
|
+
|
12
|
+
docs: {
|
13
|
+
description: "enforce default parameters to be last",
|
14
|
+
category: "Best Practices",
|
15
|
+
recommended: false,
|
16
|
+
url: "https://eslint.org/docs/rules/default-param-last"
|
17
|
+
},
|
18
|
+
|
19
|
+
schema: [],
|
20
|
+
|
21
|
+
messages: {
|
22
|
+
shouldBeLast: "Default parameters should be last."
|
23
|
+
}
|
24
|
+
},
|
25
|
+
|
26
|
+
create(context) {
|
27
|
+
|
28
|
+
/**
|
29
|
+
* @param {ASTNode} node function node
|
30
|
+
* @returns {void}
|
31
|
+
*/
|
32
|
+
function handleFunction(node) {
|
33
|
+
let hasSeenPlainParam = false;
|
34
|
+
|
35
|
+
for (let i = node.params.length - 1; i >= 0; i -= 1) {
|
36
|
+
const param = node.params[i];
|
37
|
+
|
38
|
+
if (
|
39
|
+
param.type !== "AssignmentPattern" &&
|
40
|
+
param.type !== "RestElement"
|
41
|
+
) {
|
42
|
+
hasSeenPlainParam = true;
|
43
|
+
continue;
|
44
|
+
}
|
45
|
+
|
46
|
+
if (hasSeenPlainParam && param.type === "AssignmentPattern") {
|
47
|
+
context.report({
|
48
|
+
node: param,
|
49
|
+
messageId: "shouldBeLast"
|
50
|
+
});
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
return {
|
56
|
+
FunctionDeclaration: handleFunction,
|
57
|
+
FunctionExpression: handleFunction,
|
58
|
+
ArrowFunctionExpression: handleFunction
|
59
|
+
};
|
60
|
+
}
|
61
|
+
};
|
package/lib/rules/eqeqeq.js
CHANGED
@@ -116,18 +116,6 @@ module.exports = {
|
|
116
116
|
return astUtils.isNullLiteral(node.right) || astUtils.isNullLiteral(node.left);
|
117
117
|
}
|
118
118
|
|
119
|
-
/**
|
120
|
-
* Gets the location (line and column) of the binary expression's operator
|
121
|
-
* @param {ASTNode} node The binary expression node to check
|
122
|
-
* @returns {Object} { line, column } location of operator
|
123
|
-
* @private
|
124
|
-
*/
|
125
|
-
function getOperatorLocation(node) {
|
126
|
-
const opToken = sourceCode.getTokenAfter(node.left);
|
127
|
-
|
128
|
-
return { line: opToken.loc.start.line, column: opToken.loc.start.column };
|
129
|
-
}
|
130
|
-
|
131
119
|
/**
|
132
120
|
* Reports a message for this rule.
|
133
121
|
* @param {ASTNode} node The binary expression node that was checked
|
@@ -136,21 +124,21 @@ module.exports = {
|
|
136
124
|
* @private
|
137
125
|
*/
|
138
126
|
function report(node, expectedOperator) {
|
127
|
+
const operatorToken = sourceCode.getFirstTokenBetween(
|
128
|
+
node.left,
|
129
|
+
node.right,
|
130
|
+
token => token.value === node.operator
|
131
|
+
);
|
132
|
+
|
139
133
|
context.report({
|
140
134
|
node,
|
141
|
-
loc:
|
135
|
+
loc: operatorToken.loc,
|
142
136
|
messageId: "unexpected",
|
143
137
|
data: { expectedOperator, actualOperator: node.operator },
|
144
138
|
fix(fixer) {
|
145
139
|
|
146
140
|
// If the comparison is a `typeof` comparison or both sides are literals with the same type, then it's safe to fix.
|
147
141
|
if (isTypeOfBinary(node) || areLiteralsAndSameType(node)) {
|
148
|
-
const operatorToken = sourceCode.getFirstTokenBetween(
|
149
|
-
node.left,
|
150
|
-
node.right,
|
151
|
-
token => token.value === node.operator
|
152
|
-
);
|
153
|
-
|
154
142
|
return fixer.replaceText(operatorToken, expectedOperator);
|
155
143
|
}
|
156
144
|
return null;
|
package/lib/rules/indent.js
CHANGED
@@ -1588,18 +1588,23 @@ module.exports = {
|
|
1588
1588
|
return;
|
1589
1589
|
}
|
1590
1590
|
|
1591
|
-
// If the token matches the expected expected indentation, don't report it.
|
1592
|
-
if (validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine))) {
|
1593
|
-
return;
|
1594
|
-
}
|
1595
|
-
|
1596
1591
|
if (astUtils.isCommentToken(firstTokenOfLine)) {
|
1597
1592
|
const tokenBefore = precedingTokens.get(firstTokenOfLine);
|
1598
1593
|
const tokenAfter = tokenBefore ? sourceCode.getTokenAfter(tokenBefore) : sourceCode.ast.tokens[0];
|
1599
|
-
|
1600
1594
|
const mayAlignWithBefore = tokenBefore && !hasBlankLinesBetween(tokenBefore, firstTokenOfLine);
|
1601
1595
|
const mayAlignWithAfter = tokenAfter && !hasBlankLinesBetween(firstTokenOfLine, tokenAfter);
|
1602
1596
|
|
1597
|
+
/*
|
1598
|
+
* If a comment precedes a line that begins with a semicolon token, align to that token, i.e.
|
1599
|
+
*
|
1600
|
+
* let foo
|
1601
|
+
* // comment
|
1602
|
+
* ;(async () => {})()
|
1603
|
+
*/
|
1604
|
+
if (tokenAfter && astUtils.isSemicolonToken(tokenAfter) && !astUtils.isTokenOnSameLine(firstTokenOfLine, tokenAfter)) {
|
1605
|
+
offsets.setDesiredOffset(firstTokenOfLine, tokenAfter, 0);
|
1606
|
+
}
|
1607
|
+
|
1603
1608
|
// If a comment matches the expected indentation of the token immediately before or after, don't report it.
|
1604
1609
|
if (
|
1605
1610
|
mayAlignWithBefore && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenBefore)) ||
|
@@ -1609,6 +1614,11 @@ module.exports = {
|
|
1609
1614
|
}
|
1610
1615
|
}
|
1611
1616
|
|
1617
|
+
// If the token matches the expected indentation, don't report it.
|
1618
|
+
if (validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine))) {
|
1619
|
+
return;
|
1620
|
+
}
|
1621
|
+
|
1612
1622
|
// Otherwise, report the token/comment.
|
1613
1623
|
report(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine));
|
1614
1624
|
});
|
package/lib/rules/index.js
CHANGED
@@ -37,6 +37,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
37
37
|
"constructor-super": () => require("./constructor-super"),
|
38
38
|
curly: () => require("./curly"),
|
39
39
|
"default-case": () => require("./default-case"),
|
40
|
+
"default-param-last": () => require("./default-param-last"),
|
40
41
|
"dot-location": () => require("./dot-location"),
|
41
42
|
"dot-notation": () => require("./dot-notation"),
|
42
43
|
"eol-last": () => require("./eol-last"),
|
@@ -131,6 +132,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
131
132
|
"no-implicit-coercion": () => require("./no-implicit-coercion"),
|
132
133
|
"no-implicit-globals": () => require("./no-implicit-globals"),
|
133
134
|
"no-implied-eval": () => require("./no-implied-eval"),
|
135
|
+
"no-import-assign": () => require("./no-import-assign"),
|
134
136
|
"no-inline-comments": () => require("./no-inline-comments"),
|
135
137
|
"no-inner-declarations": () => require("./no-inner-declarations"),
|
136
138
|
"no-invalid-regexp": () => require("./no-invalid-regexp"),
|
@@ -241,6 +243,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
241
243
|
"prefer-object-spread": () => require("./prefer-object-spread"),
|
242
244
|
"prefer-promise-reject-errors": () => require("./prefer-promise-reject-errors"),
|
243
245
|
"prefer-reflect": () => require("./prefer-reflect"),
|
246
|
+
"prefer-regex-literals": () => require("./prefer-regex-literals"),
|
244
247
|
"prefer-rest-params": () => require("./prefer-rest-params"),
|
245
248
|
"prefer-spread": () => require("./prefer-spread"),
|
246
249
|
"prefer-template": () => require("./prefer-template"),
|
@@ -0,0 +1,238 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to flag updates of imported bindings.
|
3
|
+
* @author Toru Nagashima <https://github.com/mysticatea>
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Helpers
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const { findVariable, getPropertyName } = require("eslint-utils");
|
13
|
+
|
14
|
+
const MutationMethods = {
|
15
|
+
Object: new Set([
|
16
|
+
"assign", "defineProperties", "defineProperty", "freeze",
|
17
|
+
"setPrototypeOf"
|
18
|
+
]),
|
19
|
+
Reflect: new Set([
|
20
|
+
"defineProperty", "deleteProperty", "set", "setPrototypeOf"
|
21
|
+
])
|
22
|
+
};
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Check if a given node is LHS of an assignment node.
|
26
|
+
* @param {ASTNode} node The node to check.
|
27
|
+
* @returns {boolean} `true` if the node is LHS.
|
28
|
+
*/
|
29
|
+
function isAssignmentLeft(node) {
|
30
|
+
const { parent } = node;
|
31
|
+
|
32
|
+
return (
|
33
|
+
(
|
34
|
+
parent.type === "AssignmentExpression" &&
|
35
|
+
parent.left === node
|
36
|
+
) ||
|
37
|
+
|
38
|
+
// Destructuring assignments
|
39
|
+
parent.type === "ArrayPattern" ||
|
40
|
+
(
|
41
|
+
parent.type === "Property" &&
|
42
|
+
parent.value === node &&
|
43
|
+
parent.parent.type === "ObjectPattern"
|
44
|
+
) ||
|
45
|
+
parent.type === "RestElement" ||
|
46
|
+
(
|
47
|
+
parent.type === "AssignmentPattern" &&
|
48
|
+
parent.left === node
|
49
|
+
)
|
50
|
+
);
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Check if a given node is the operand of mutation unary operator.
|
55
|
+
* @param {ASTNode} node The node to check.
|
56
|
+
* @returns {boolean} `true` if the node is the operand of mutation unary operator.
|
57
|
+
*/
|
58
|
+
function isOperandOfMutationUnaryOperator(node) {
|
59
|
+
const { parent } = node;
|
60
|
+
|
61
|
+
return (
|
62
|
+
(
|
63
|
+
parent.type === "UpdateExpression" &&
|
64
|
+
parent.argument === node
|
65
|
+
) ||
|
66
|
+
(
|
67
|
+
parent.type === "UnaryExpression" &&
|
68
|
+
parent.operator === "delete" &&
|
69
|
+
parent.argument === node
|
70
|
+
)
|
71
|
+
);
|
72
|
+
}
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Check if a given node is the iteration variable of `for-in`/`for-of` syntax.
|
76
|
+
* @param {ASTNode} node The node to check.
|
77
|
+
* @returns {boolean} `true` if the node is the iteration variable.
|
78
|
+
*/
|
79
|
+
function isIterationVariable(node) {
|
80
|
+
const { parent } = node;
|
81
|
+
|
82
|
+
return (
|
83
|
+
(
|
84
|
+
parent.type === "ForInStatement" &&
|
85
|
+
parent.left === node
|
86
|
+
) ||
|
87
|
+
(
|
88
|
+
parent.type === "ForOfStatement" &&
|
89
|
+
parent.left === node
|
90
|
+
)
|
91
|
+
);
|
92
|
+
}
|
93
|
+
|
94
|
+
/**
|
95
|
+
* Check if a given node is the iteration variable of `for-in`/`for-of` syntax.
|
96
|
+
* @param {ASTNode} node The node to check.
|
97
|
+
* @param {Scope} scope A `escope.Scope` object to find variable (whichever).
|
98
|
+
* @returns {boolean} `true` if the node is the iteration variable.
|
99
|
+
*/
|
100
|
+
function isArgumentOfWellKnownMutationFunction(node, scope) {
|
101
|
+
const { parent } = node;
|
102
|
+
|
103
|
+
if (
|
104
|
+
parent.type === "CallExpression" &&
|
105
|
+
parent.arguments[0] === node &&
|
106
|
+
parent.callee.type === "MemberExpression" &&
|
107
|
+
parent.callee.object.type === "Identifier"
|
108
|
+
) {
|
109
|
+
const { callee } = parent;
|
110
|
+
const { object } = callee;
|
111
|
+
|
112
|
+
if (Object.keys(MutationMethods).includes(object.name)) {
|
113
|
+
const variable = findVariable(scope, object);
|
114
|
+
|
115
|
+
return (
|
116
|
+
variable !== null &&
|
117
|
+
variable.scope.type === "global" &&
|
118
|
+
MutationMethods[object.name].has(getPropertyName(callee, scope))
|
119
|
+
);
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
return false;
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* Check if the identifier node is placed at to update members.
|
128
|
+
* @param {ASTNode} id The Identifier node to check.
|
129
|
+
* @param {Scope} scope A `escope.Scope` object to find variable (whichever).
|
130
|
+
* @returns {boolean} `true` if the member of `id` was updated.
|
131
|
+
*/
|
132
|
+
function isMemberWrite(id, scope) {
|
133
|
+
const { parent } = id;
|
134
|
+
|
135
|
+
return (
|
136
|
+
(
|
137
|
+
parent.type === "MemberExpression" &&
|
138
|
+
parent.object === id &&
|
139
|
+
(
|
140
|
+
isAssignmentLeft(parent) ||
|
141
|
+
isOperandOfMutationUnaryOperator(parent) ||
|
142
|
+
isIterationVariable(parent)
|
143
|
+
)
|
144
|
+
) ||
|
145
|
+
isArgumentOfWellKnownMutationFunction(id, scope)
|
146
|
+
);
|
147
|
+
}
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Get the mutation node.
|
151
|
+
* @param {ASTNode} id The Identifier node to get.
|
152
|
+
* @returns {ASTNode} The mutation node.
|
153
|
+
*/
|
154
|
+
function getWriteNode(id) {
|
155
|
+
let node = id.parent;
|
156
|
+
|
157
|
+
while (
|
158
|
+
node &&
|
159
|
+
node.type !== "AssignmentExpression" &&
|
160
|
+
node.type !== "UpdateExpression" &&
|
161
|
+
node.type !== "UnaryExpression" &&
|
162
|
+
node.type !== "CallExpression" &&
|
163
|
+
node.type !== "ForInStatement" &&
|
164
|
+
node.type !== "ForOfStatement"
|
165
|
+
) {
|
166
|
+
node = node.parent;
|
167
|
+
}
|
168
|
+
|
169
|
+
return node || id;
|
170
|
+
}
|
171
|
+
|
172
|
+
//------------------------------------------------------------------------------
|
173
|
+
// Rule Definition
|
174
|
+
//------------------------------------------------------------------------------
|
175
|
+
|
176
|
+
module.exports = {
|
177
|
+
meta: {
|
178
|
+
type: "problem",
|
179
|
+
|
180
|
+
docs: {
|
181
|
+
description: "disallow assigning to imported bindings",
|
182
|
+
category: "Possible Errors",
|
183
|
+
recommended: false,
|
184
|
+
url: "https://eslint.org/docs/rules/no-import-assign"
|
185
|
+
},
|
186
|
+
|
187
|
+
schema: [],
|
188
|
+
|
189
|
+
messages: {
|
190
|
+
readonly: "'{{name}}' is read-only.",
|
191
|
+
readonlyMember: "The members of '{{name}}' are read-only."
|
192
|
+
}
|
193
|
+
},
|
194
|
+
|
195
|
+
create(context) {
|
196
|
+
return {
|
197
|
+
ImportDeclaration(node) {
|
198
|
+
const scope = context.getScope();
|
199
|
+
|
200
|
+
for (const variable of context.getDeclaredVariables(node)) {
|
201
|
+
const shouldCheckMembers = variable.defs.some(
|
202
|
+
d => d.node.type === "ImportNamespaceSpecifier"
|
203
|
+
);
|
204
|
+
let prevIdNode = null;
|
205
|
+
|
206
|
+
for (const reference of variable.references) {
|
207
|
+
const idNode = reference.identifier;
|
208
|
+
|
209
|
+
/*
|
210
|
+
* AssignmentPattern (e.g. `[a = 0] = b`) makes two write
|
211
|
+
* references for the same identifier. This should skip
|
212
|
+
* the one of the two in order to prevent redundant reports.
|
213
|
+
*/
|
214
|
+
if (idNode === prevIdNode) {
|
215
|
+
continue;
|
216
|
+
}
|
217
|
+
prevIdNode = idNode;
|
218
|
+
|
219
|
+
if (reference.isWrite()) {
|
220
|
+
context.report({
|
221
|
+
node: getWriteNode(idNode),
|
222
|
+
messageId: "readonly",
|
223
|
+
data: { name: idNode.name }
|
224
|
+
});
|
225
|
+
} else if (shouldCheckMembers && isMemberWrite(idNode, scope)) {
|
226
|
+
context.report({
|
227
|
+
node: getWriteNode(idNode),
|
228
|
+
messageId: "readonlyMember",
|
229
|
+
data: { name: idNode.name }
|
230
|
+
});
|
231
|
+
}
|
232
|
+
}
|
233
|
+
}
|
234
|
+
}
|
235
|
+
};
|
236
|
+
|
237
|
+
}
|
238
|
+
};
|