eslint 6.3.0 → 6.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +11 -10
  3. package/bin/eslint.js +38 -12
  4. package/lib/cli-engine/cascading-config-array-factory.js +2 -1
  5. package/lib/cli-engine/cli-engine.js +11 -11
  6. package/lib/cli-engine/config-array/config-array.js +0 -4
  7. package/lib/cli-engine/config-array/config-dependency.js +2 -0
  8. package/lib/cli-engine/config-array/override-tester.js +4 -2
  9. package/lib/cli-engine/config-array-factory.js +7 -1
  10. package/lib/cli-engine/file-enumerator.js +5 -3
  11. package/lib/cli-engine/formatters/html.js +1 -0
  12. package/lib/cli-engine/ignored-paths.js +4 -3
  13. package/lib/cli-engine/lint-result-cache.js +0 -1
  14. package/lib/cli.js +13 -12
  15. package/lib/init/autoconfig.js +1 -11
  16. package/lib/init/config-file.js +0 -1
  17. package/lib/init/config-initializer.js +0 -1
  18. package/lib/init/config-rule.js +3 -7
  19. package/lib/init/npm-utils.js +1 -6
  20. package/lib/linter/code-path-analysis/code-path-analyzer.js +24 -38
  21. package/lib/linter/code-path-analysis/code-path-segment.js +17 -25
  22. package/lib/linter/code-path-analysis/code-path-state.js +40 -81
  23. package/lib/linter/code-path-analysis/code-path.js +10 -11
  24. package/lib/linter/code-path-analysis/debug-helpers.js +9 -13
  25. package/lib/linter/code-path-analysis/fork-context.js +23 -34
  26. package/lib/linter/code-path-analysis/id-generator.js +2 -2
  27. package/lib/linter/linter.js +121 -96
  28. package/lib/linter/node-event-generator.js +3 -2
  29. package/lib/options.js +6 -0
  30. package/lib/rule-tester/rule-tester.js +7 -10
  31. package/lib/rules/accessor-pairs.js +59 -19
  32. package/lib/rules/array-bracket-newline.js +12 -15
  33. package/lib/rules/array-bracket-spacing.js +12 -12
  34. package/lib/rules/array-callback-return.js +6 -11
  35. package/lib/rules/array-element-newline.js +5 -8
  36. package/lib/rules/arrow-parens.js +0 -1
  37. package/lib/rules/block-scoped-var.js +3 -3
  38. package/lib/rules/block-spacing.js +4 -4
  39. package/lib/rules/capitalized-comments.js +2 -9
  40. package/lib/rules/class-methods-use-this.js +3 -3
  41. package/lib/rules/comma-dangle.js +15 -23
  42. package/lib/rules/comma-spacing.js +1 -1
  43. package/lib/rules/computed-property-spacing.js +28 -11
  44. package/lib/rules/consistent-return.js +4 -5
  45. package/lib/rules/consistent-this.js +5 -5
  46. package/lib/rules/constructor-super.js +14 -16
  47. package/lib/rules/curly.js +3 -5
  48. package/lib/rules/default-param-last.js +62 -0
  49. package/lib/rules/dot-location.js +11 -12
  50. package/lib/rules/eqeqeq.js +7 -19
  51. package/lib/rules/func-names.js +6 -6
  52. package/lib/rules/function-call-argument-newline.js +5 -5
  53. package/lib/rules/generator-star-spacing.js +4 -9
  54. package/lib/rules/getter-return.js +4 -7
  55. package/lib/rules/indent-legacy.js +1 -1
  56. package/lib/rules/indent.js +46 -8
  57. package/lib/rules/index.js +3 -0
  58. package/lib/rules/init-declarations.js +2 -2
  59. package/lib/rules/jsx-quotes.js +1 -1
  60. package/lib/rules/keyword-spacing.js +32 -56
  61. package/lib/rules/lines-around-directive.js +1 -1
  62. package/lib/rules/max-len.js +0 -5
  63. package/lib/rules/max-statements-per-line.js +3 -7
  64. package/lib/rules/multiline-ternary.js +3 -3
  65. package/lib/rules/new-parens.js +5 -1
  66. package/lib/rules/newline-after-var.js +6 -7
  67. package/lib/rules/newline-before-return.js +8 -9
  68. package/lib/rules/newline-per-chained-call.js +2 -4
  69. package/lib/rules/no-class-assign.js +2 -2
  70. package/lib/rules/no-compare-neg-zero.js +1 -2
  71. package/lib/rules/no-confusing-arrow.js +2 -2
  72. package/lib/rules/no-console.js +4 -8
  73. package/lib/rules/no-const-assign.js +1 -1
  74. package/lib/rules/no-dupe-args.js +1 -1
  75. package/lib/rules/no-dupe-class-members.js +3 -4
  76. package/lib/rules/no-dupe-keys.js +6 -5
  77. package/lib/rules/no-duplicate-imports.js +14 -18
  78. package/lib/rules/no-else-return.js +0 -8
  79. package/lib/rules/no-empty-function.js +2 -4
  80. package/lib/rules/no-eval.js +10 -18
  81. package/lib/rules/no-ex-assign.js +1 -1
  82. package/lib/rules/no-extra-bind.js +12 -13
  83. package/lib/rules/no-extra-boolean-cast.js +1 -3
  84. package/lib/rules/no-extra-label.js +13 -10
  85. package/lib/rules/no-extra-parens.js +32 -17
  86. package/lib/rules/no-extra-semi.js +5 -6
  87. package/lib/rules/no-fallthrough.js +6 -6
  88. package/lib/rules/no-func-assign.js +3 -3
  89. package/lib/rules/no-global-assign.js +4 -4
  90. package/lib/rules/no-implicit-coercion.js +10 -10
  91. package/lib/rules/no-implied-eval.js +0 -1
  92. package/lib/rules/no-import-assign.js +238 -0
  93. package/lib/rules/no-invalid-this.js +1 -3
  94. package/lib/rules/no-labels.js +3 -6
  95. package/lib/rules/no-lone-blocks.js +7 -2
  96. package/lib/rules/no-loop-func.js +6 -11
  97. package/lib/rules/no-magic-numbers.js +6 -6
  98. package/lib/rules/no-misleading-character-class.js +14 -7
  99. package/lib/rules/no-mixed-operators.js +13 -22
  100. package/lib/rules/no-mixed-requires.js +0 -1
  101. package/lib/rules/no-multi-spaces.js +1 -1
  102. package/lib/rules/no-native-reassign.js +4 -4
  103. package/lib/rules/no-obj-calls.js +29 -9
  104. package/lib/rules/no-octal-escape.js +14 -8
  105. package/lib/rules/no-param-reassign.js +28 -7
  106. package/lib/rules/no-redeclare.js +1 -1
  107. package/lib/rules/no-regex-spaces.js +105 -45
  108. package/lib/rules/no-restricted-imports.js +11 -11
  109. package/lib/rules/no-self-assign.js +18 -18
  110. package/lib/rules/no-sequences.js +5 -5
  111. package/lib/rules/no-shadow.js +1 -4
  112. package/lib/rules/no-tabs.js +8 -2
  113. package/lib/rules/no-this-before-super.js +12 -13
  114. package/lib/rules/no-trailing-spaces.js +19 -7
  115. package/lib/rules/no-undef-init.js +7 -1
  116. package/lib/rules/no-unmodified-loop-condition.js +16 -29
  117. package/lib/rules/no-unneeded-ternary.js +3 -3
  118. package/lib/rules/no-unreachable.js +7 -7
  119. package/lib/rules/no-unsafe-finally.js +4 -7
  120. package/lib/rules/no-unsafe-negation.js +34 -19
  121. package/lib/rules/no-unused-expressions.js +11 -7
  122. package/lib/rules/no-unused-labels.js +3 -6
  123. package/lib/rules/no-unused-vars.js +22 -29
  124. package/lib/rules/no-use-before-define.js +10 -15
  125. package/lib/rules/no-useless-call.js +4 -4
  126. package/lib/rules/no-useless-concat.js +4 -4
  127. package/lib/rules/no-useless-constructor.js +14 -22
  128. package/lib/rules/no-useless-escape.js +3 -5
  129. package/lib/rules/no-useless-rename.js +32 -20
  130. package/lib/rules/no-useless-return.js +11 -17
  131. package/lib/rules/no-var.js +12 -25
  132. package/lib/rules/no-warning-comments.js +0 -1
  133. package/lib/rules/no-whitespace-before-property.js +3 -3
  134. package/lib/rules/object-curly-newline.js +7 -10
  135. package/lib/rules/object-curly-spacing.js +14 -15
  136. package/lib/rules/object-shorthand.js +36 -10
  137. package/lib/rules/one-var-declaration-per-line.js +2 -2
  138. package/lib/rules/operator-assignment.js +22 -1
  139. package/lib/rules/padded-blocks.js +1 -1
  140. package/lib/rules/padding-line-between-statements.js +0 -16
  141. package/lib/rules/prefer-arrow-callback.js +6 -6
  142. package/lib/rules/prefer-const.js +13 -21
  143. package/lib/rules/prefer-destructuring.js +1 -7
  144. package/lib/rules/prefer-named-capture-group.js +3 -16
  145. package/lib/rules/prefer-numeric-literals.js +35 -3
  146. package/lib/rules/prefer-object-spread.js +7 -7
  147. package/lib/rules/prefer-regex-literals.js +125 -0
  148. package/lib/rules/prefer-rest-params.js +3 -6
  149. package/lib/rules/prefer-spread.js +4 -4
  150. package/lib/rules/prefer-template.js +5 -6
  151. package/lib/rules/quote-props.js +1 -1
  152. package/lib/rules/quotes.js +11 -6
  153. package/lib/rules/radix.js +5 -10
  154. package/lib/rules/require-await.js +2 -5
  155. package/lib/rules/require-yield.js +2 -2
  156. package/lib/rules/rest-spread-spacing.js +1 -1
  157. package/lib/rules/sort-imports.js +3 -4
  158. package/lib/rules/sort-keys.js +1 -3
  159. package/lib/rules/space-before-blocks.js +1 -2
  160. package/lib/rules/space-before-function-paren.js +12 -1
  161. package/lib/rules/space-in-parens.js +81 -75
  162. package/lib/rules/space-infix-ops.js +5 -5
  163. package/lib/rules/spaced-comment.js +15 -18
  164. package/lib/rules/strict.js +2 -4
  165. package/lib/rules/symbol-description.js +1 -2
  166. package/lib/rules/template-curly-spacing.js +2 -2
  167. package/lib/rules/use-isnan.js +104 -6
  168. package/lib/rules/utils/ast-utils.js +53 -81
  169. package/lib/rules/utils/fix-tracker.js +0 -6
  170. package/lib/rules/utils/lazy-loading-rule-map.js +0 -1
  171. package/lib/rules/vars-on-top.js +11 -11
  172. package/lib/shared/config-ops.js +2 -2
  173. package/lib/shared/logging.js +2 -0
  174. package/lib/shared/runtime-info.js +163 -0
  175. package/lib/shared/traverser.js +2 -0
  176. package/lib/source-code/source-code.js +11 -12
  177. package/lib/source-code/token-store/backward-token-comment-cursor.js +5 -5
  178. package/lib/source-code/token-store/backward-token-cursor.js +5 -5
  179. package/lib/source-code/token-store/cursors.js +17 -19
  180. package/lib/source-code/token-store/decorative-cursor.js +1 -1
  181. package/lib/source-code/token-store/filter-cursor.js +2 -2
  182. package/lib/source-code/token-store/forward-token-comment-cursor.js +5 -5
  183. package/lib/source-code/token-store/forward-token-cursor.js +5 -5
  184. package/lib/source-code/token-store/index.js +86 -92
  185. package/lib/source-code/token-store/limit-cursor.js +2 -2
  186. package/lib/source-code/token-store/padded-token-cursor.js +7 -7
  187. package/lib/source-code/token-store/skip-cursor.js +2 -2
  188. package/lib/source-code/token-store/utils.js +9 -13
  189. package/package.json +8 -5
@@ -29,7 +29,7 @@ module.exports = {
29
29
 
30
30
  /**
31
31
  * Reports a reference if is non initializer and writable.
32
- * @param {References} references - Collection of reference to check.
32
+ * @param {References} references Collection of reference to check.
33
33
  * @returns {void}
34
34
  */
35
35
  function checkReference(references) {
@@ -40,7 +40,7 @@ module.exports = {
40
40
 
41
41
  /**
42
42
  * Finds and reports references that are non initializer and writable.
43
- * @param {Variable} variable - A variable to check.
43
+ * @param {Variable} variable A variable to check.
44
44
  * @returns {void}
45
45
  */
46
46
  function checkVariable(variable) {
@@ -51,7 +51,7 @@ module.exports = {
51
51
 
52
52
  /**
53
53
  * Checks parameters of a given function node.
54
- * @param {ASTNode} node - A function node to check.
54
+ * @param {ASTNode} node A function node to check.
55
55
  * @returns {void}
56
56
  */
57
57
  function checkForFunction(node) {
@@ -41,9 +41,9 @@ module.exports = {
41
41
 
42
42
  /**
43
43
  * Reports write references.
44
- * @param {Reference} reference - A reference to check.
45
- * @param {int} index - The index of the reference in the references.
46
- * @param {Reference[]} references - The array that the reference belongs to.
44
+ * @param {Reference} reference A reference to check.
45
+ * @param {int} index The index of the reference in the references.
46
+ * @param {Reference[]} references The array that the reference belongs to.
47
47
  * @returns {void}
48
48
  */
49
49
  function checkReference(reference, index, references) {
@@ -68,7 +68,7 @@ module.exports = {
68
68
 
69
69
  /**
70
70
  * Reports write references if a given variable is read-only builtin.
71
- * @param {Variable} variable - A variable to check.
71
+ * @param {Variable} variable A variable to check.
72
72
  * @returns {void}
73
73
  */
74
74
  function checkVariable(variable) {
@@ -16,7 +16,7 @@ const ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"];
16
16
 
17
17
  /**
18
18
  * Parses and normalizes an option object.
19
- * @param {Object} options - An option object to parse.
19
+ * @param {Object} options An option object to parse.
20
20
  * @returns {Object} The parsed and normalized option object.
21
21
  */
22
22
  function parseOptions(options) {
@@ -30,7 +30,7 @@ function parseOptions(options) {
30
30
 
31
31
  /**
32
32
  * Checks whether or not a node is a double logical nigating.
33
- * @param {ASTNode} node - An UnaryExpression node to check.
33
+ * @param {ASTNode} node An UnaryExpression node to check.
34
34
  * @returns {boolean} Whether or not the node is a double logical nigating.
35
35
  */
36
36
  function isDoubleLogicalNegating(node) {
@@ -43,7 +43,7 @@ function isDoubleLogicalNegating(node) {
43
43
 
44
44
  /**
45
45
  * Checks whether or not a node is a binary negating of `.indexOf()` method calling.
46
- * @param {ASTNode} node - An UnaryExpression node to check.
46
+ * @param {ASTNode} node An UnaryExpression node to check.
47
47
  * @returns {boolean} Whether or not the node is a binary negating of `.indexOf()` method calling.
48
48
  */
49
49
  function isBinaryNegatingOfIndexOf(node) {
@@ -58,7 +58,7 @@ function isBinaryNegatingOfIndexOf(node) {
58
58
 
59
59
  /**
60
60
  * Checks whether or not a node is a multiplying by one.
61
- * @param {BinaryExpression} node - A BinaryExpression node to check.
61
+ * @param {BinaryExpression} node A BinaryExpression node to check.
62
62
  * @returns {boolean} Whether or not the node is a multiplying by one.
63
63
  */
64
64
  function isMultiplyByOne(node) {
@@ -118,7 +118,7 @@ function isEmptyString(node) {
118
118
 
119
119
  /**
120
120
  * Checks whether or not a node is a concatenating with an empty string.
121
- * @param {ASTNode} node - A BinaryExpression node to check.
121
+ * @param {ASTNode} node A BinaryExpression node to check.
122
122
  * @returns {boolean} Whether or not the node is a concatenating with an empty string.
123
123
  */
124
124
  function isConcatWithEmptyString(node) {
@@ -130,7 +130,7 @@ function isConcatWithEmptyString(node) {
130
130
 
131
131
  /**
132
132
  * Checks whether or not a node is appended with an empty string.
133
- * @param {ASTNode} node - An AssignmentExpression node to check.
133
+ * @param {ASTNode} node An AssignmentExpression node to check.
134
134
  * @returns {boolean} Whether or not the node is appended with an empty string.
135
135
  */
136
136
  function isAppendEmptyString(node) {
@@ -139,7 +139,7 @@ function isAppendEmptyString(node) {
139
139
 
140
140
  /**
141
141
  * Returns the operand that is not an empty string from a flagged BinaryExpression.
142
- * @param {ASTNode} node - The flagged BinaryExpression node to check.
142
+ * @param {ASTNode} node The flagged BinaryExpression node to check.
143
143
  * @returns {ASTNode} The operand that is not an empty string from a flagged BinaryExpression.
144
144
  */
145
145
  function getNonEmptyOperand(node) {
@@ -196,9 +196,9 @@ module.exports = {
196
196
 
197
197
  /**
198
198
  * Reports an error and autofixes the node
199
- * @param {ASTNode} node - An ast node to report the error on.
200
- * @param {string} recommendation - The recommended code for the issue
201
- * @param {bool} shouldFix - Whether this report should fix the node
199
+ * @param {ASTNode} node An ast node to report the error on.
200
+ * @param {string} recommendation The recommended code for the issue
201
+ * @param {bool} shouldFix Whether this report should fix the node
202
202
  * @returns {void}
203
203
  */
204
204
  function report(node, recommendation, shouldFix) {
@@ -64,7 +64,6 @@ module.exports = {
64
64
  * Determines if a node represents a call to a potentially implied eval.
65
65
  *
66
66
  * This checks the callee name and that there's an argument, but not the type of the argument.
67
- *
68
67
  * @param {ASTNode} node The CallExpression to check.
69
68
  * @returns {boolean} True if the node matches, false if not.
70
69
  * @private
@@ -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
+ };
@@ -38,7 +38,6 @@ module.exports = {
38
38
  *
39
39
  * The return value has a flag that whether or not `this` keyword is valid.
40
40
  * The flag is initialized when got at the first time.
41
- *
42
41
  * @returns {{valid: boolean}}
43
42
  * an object which has a flag that whether or not `this` keyword is valid.
44
43
  */
@@ -61,8 +60,7 @@ module.exports = {
61
60
  * The checking context is not initialized yet.
62
61
  * Because most functions don't have `this` keyword.
63
62
  * When `this` keyword was found, the checking context is initialized.
64
- *
65
- * @param {ASTNode} node - A function node that was entered.
63
+ * @param {ASTNode} node A function node that was entered.
66
64
  * @returns {void}
67
65
  */
68
66
  function enterFunction(node) {
@@ -51,8 +51,7 @@ module.exports = {
51
51
 
52
52
  /**
53
53
  * Gets the kind of a given node.
54
- *
55
- * @param {ASTNode} node - A node to get.
54
+ * @param {ASTNode} node A node to get.
56
55
  * @returns {string} The kind of the node.
57
56
  */
58
57
  function getBodyKind(node) {
@@ -67,8 +66,7 @@ module.exports = {
67
66
 
68
67
  /**
69
68
  * Checks whether the label of a given kind is allowed or not.
70
- *
71
- * @param {string} kind - A kind to check.
69
+ * @param {string} kind A kind to check.
72
70
  * @returns {boolean} `true` if the kind is allowed.
73
71
  */
74
72
  function isAllowed(kind) {
@@ -81,8 +79,7 @@ module.exports = {
81
79
 
82
80
  /**
83
81
  * Checks whether a given name is a label of a loop or not.
84
- *
85
- * @param {string} label - A name of a label to check.
82
+ * @param {string} label A name of a label to check.
86
83
  * @returns {boolean} `true` if the name is a label of a loop.
87
84
  */
88
85
  function getKind(label) {
@@ -31,7 +31,7 @@ module.exports = {
31
31
 
32
32
  /**
33
33
  * Reports a node as invalid.
34
- * @param {ASTNode} node - The node to be reported.
34
+ * @param {ASTNode} node The node to be reported.
35
35
  * @returns {void}
36
36
  */
37
37
  function report(node) {
@@ -79,7 +79,7 @@ module.exports = {
79
79
  }
80
80
  };
81
81
 
82
- // ES6: report blocks without block-level bindings
82
+ // ES6: report blocks without block-level bindings, or that's only child of another block
83
83
  if (context.parserOptions.ecmaVersion >= 6) {
84
84
  ruleDef = {
85
85
  BlockStatement(node) {
@@ -91,6 +91,11 @@ module.exports = {
91
91
  if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) {
92
92
  loneBlocks.pop();
93
93
  report(node);
94
+ } else if (
95
+ node.parent.type === "BlockStatement" &&
96
+ node.parent.body.length === 1
97
+ ) {
98
+ report(node);
94
99
  }
95
100
  }
96
101
  };
@@ -14,8 +14,7 @@
14
14
  *
15
15
  * We don't need to check nested functions, so this ignores those.
16
16
  * `Scope.through` contains references of nested functions.
17
- *
18
- * @param {ASTNode} node - An AST node to get.
17
+ * @param {ASTNode} node An AST node to get.
19
18
  * @returns {ASTNode|null} The containing loop node of the specified node, or
20
19
  * `null`.
21
20
  */
@@ -63,9 +62,8 @@ function getContainingLoopNode(node) {
63
62
  /**
64
63
  * Gets the containing loop node of a given node.
65
64
  * If the loop was nested, this returns the most outer loop.
66
- *
67
- * @param {ASTNode} node - A node to get. This is a loop node.
68
- * @param {ASTNode|null} excludedNode - A node that the result node should not
65
+ * @param {ASTNode} node A node to get. This is a loop node.
66
+ * @param {ASTNode|null} excludedNode A node that the result node should not
69
67
  * include.
70
68
  * @returns {ASTNode} The most outer loop node.
71
69
  */
@@ -85,9 +83,8 @@ function getTopLoopNode(node, excludedNode) {
85
83
  /**
86
84
  * Checks whether a given reference which refers to an upper scope's variable is
87
85
  * safe or not.
88
- *
89
- * @param {ASTNode} loopNode - A containing loop node.
90
- * @param {eslint-scope.Reference} reference - A reference to check.
86
+ * @param {ASTNode} loopNode A containing loop node.
87
+ * @param {eslint-scope.Reference} reference A reference to check.
91
88
  * @returns {boolean} `true` if the reference is safe or not.
92
89
  */
93
90
  function isSafe(loopNode, reference) {
@@ -131,8 +128,7 @@ function isSafe(loopNode, reference) {
131
128
  * It's safeafe if the reference matches one of the following condition.
132
129
  * - is readonly.
133
130
  * - doesn't exist inside a local function and after the border.
134
- *
135
- * @param {eslint-scope.Reference} upperRef - A reference to check.
131
+ * @param {eslint-scope.Reference} upperRef A reference to check.
136
132
  * @returns {boolean} `true` if the reference is safe.
137
133
  */
138
134
  function isSafeReference(upperRef) {
@@ -177,7 +173,6 @@ module.exports = {
177
173
  *
178
174
  * - has a loop node in ancestors.
179
175
  * - has any references which refers to an unsafe variable.
180
- *
181
176
  * @param {ASTNode} node The AST node to check.
182
177
  * @returns {boolean} Whether or not the node is within a loop.
183
178
  */
@@ -61,7 +61,7 @@ module.exports = {
61
61
 
62
62
  /**
63
63
  * Returns whether the node is number literal
64
- * @param {Node} node - the node literal being evaluated
64
+ * @param {Node} node the node literal being evaluated
65
65
  * @returns {boolean} true if the node is a number literal
66
66
  */
67
67
  function isNumber(node) {
@@ -70,7 +70,7 @@ module.exports = {
70
70
 
71
71
  /**
72
72
  * Returns whether the number should be ignored
73
- * @param {number} num - the number
73
+ * @param {number} num the number
74
74
  * @returns {boolean} true if the number should be ignored
75
75
  */
76
76
  function shouldIgnoreNumber(num) {
@@ -79,8 +79,8 @@ module.exports = {
79
79
 
80
80
  /**
81
81
  * Returns whether the number should be ignored when used as a radix within parseInt() or Number.parseInt()
82
- * @param {ASTNode} parent - the non-"UnaryExpression" parent
83
- * @param {ASTNode} node - the node literal being evaluated
82
+ * @param {ASTNode} parent the non-"UnaryExpression" parent
83
+ * @param {ASTNode} node the node literal being evaluated
84
84
  * @returns {boolean} true if the number should be ignored
85
85
  */
86
86
  function shouldIgnoreParseInt(parent, node) {
@@ -93,7 +93,7 @@ module.exports = {
93
93
 
94
94
  /**
95
95
  * Returns whether the number should be ignored when used to define a JSX prop
96
- * @param {ASTNode} parent - the non-"UnaryExpression" parent
96
+ * @param {ASTNode} parent the non-"UnaryExpression" parent
97
97
  * @returns {boolean} true if the number should be ignored
98
98
  */
99
99
  function shouldIgnoreJSXNumbers(parent) {
@@ -102,7 +102,7 @@ module.exports = {
102
102
 
103
103
  /**
104
104
  * Returns whether the number should be ignored when used as an array index with enabled 'ignoreArrayIndexes' option.
105
- * @param {ASTNode} parent - the non-"UnaryExpression" parent.
105
+ * @param {ASTNode} parent the non-"UnaryExpression" parent.
106
106
  * @returns {boolean} true if the number should be ignored
107
107
  */
108
108
  function shouldIgnoreArrayIndexes(parent) {
@@ -16,7 +16,6 @@ const { isCombiningCharacter, isEmojiModifier, isRegionalIndicatorSymbol, isSurr
16
16
  *
17
17
  * CharacterClassRange syntax can steal a part of character sequence,
18
18
  * so this function reverts CharacterClassRange syntax and restore the sequence.
19
- *
20
19
  * @param {regexpp.AST.CharacterClassElement[]} nodes The node list to iterate character sequences.
21
20
  * @returns {IterableIterator<number[]>} The list of character sequences.
22
21
  */
@@ -131,12 +130,6 @@ module.exports = {
131
130
  * @returns {void}
132
131
  */
133
132
  function verify(node, pattern, flags) {
134
- const patternNode = parser.parsePattern(
135
- pattern,
136
- 0,
137
- pattern.length,
138
- flags.includes("u")
139
- );
140
133
  const has = {
141
134
  surrogatePairWithoutUFlag: false,
142
135
  combiningClass: false,
@@ -145,6 +138,20 @@ module.exports = {
145
138
  regionalIndicatorSymbol: false,
146
139
  zwj: false
147
140
  };
141
+ let patternNode;
142
+
143
+ try {
144
+ patternNode = parser.parsePattern(
145
+ pattern,
146
+ 0,
147
+ pattern.length,
148
+ flags.includes("u")
149
+ );
150
+ } catch (e) {
151
+
152
+ // Ignore regular expressions with syntax errors
153
+ return;
154
+ }
148
155
 
149
156
  visitRegExpAST(patternNode, {
150
157
  onCharacterClassEnter(ccNode) {