eslint 8.39.0 → 8.47.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 (317) hide show
  1. package/README.md +10 -4
  2. package/conf/globals.js +6 -1
  3. package/lib/cli-engine/cli-engine.js +30 -19
  4. package/lib/cli.js +2 -28
  5. package/lib/config/default-config.js +1 -1
  6. package/lib/config/flat-config-schema.js +127 -35
  7. package/lib/eslint/eslint-helpers.js +11 -10
  8. package/lib/eslint/eslint.js +1 -1
  9. package/lib/eslint/flat-eslint.js +119 -161
  10. package/lib/linter/apply-disable-directives.js +11 -1
  11. package/lib/linter/code-path-analysis/debug-helpers.js +1 -1
  12. package/lib/linter/config-comment-parser.js +9 -2
  13. package/lib/linter/linter.js +20 -11
  14. package/lib/linter/report-translator.js +22 -21
  15. package/lib/rule-tester/flat-rule-tester.js +1 -2
  16. package/lib/rule-tester/rule-tester.js +1 -2
  17. package/lib/rules/accessor-pairs.js +35 -43
  18. package/lib/rules/array-bracket-newline.js +2 -2
  19. package/lib/rules/array-bracket-spacing.js +2 -2
  20. package/lib/rules/array-callback-return.js +2 -2
  21. package/lib/rules/array-element-newline.js +12 -6
  22. package/lib/rules/arrow-body-style.js +2 -2
  23. package/lib/rules/arrow-parens.js +2 -2
  24. package/lib/rules/arrow-spacing.js +2 -2
  25. package/lib/rules/block-scoped-var.js +17 -7
  26. package/lib/rules/block-spacing.js +2 -2
  27. package/lib/rules/brace-style.js +2 -2
  28. package/lib/rules/callback-return.js +2 -2
  29. package/lib/rules/camelcase.js +2 -2
  30. package/lib/rules/capitalized-comments.js +2 -2
  31. package/lib/rules/class-methods-use-this.js +2 -2
  32. package/lib/rules/comma-dangle.js +2 -2
  33. package/lib/rules/comma-spacing.js +2 -2
  34. package/lib/rules/comma-style.js +2 -2
  35. package/lib/rules/complexity.js +1 -1
  36. package/lib/rules/computed-property-spacing.js +2 -2
  37. package/lib/rules/consistent-return.js +3 -3
  38. package/lib/rules/consistent-this.js +2 -2
  39. package/lib/rules/constructor-super.js +1 -1
  40. package/lib/rules/curly.js +2 -2
  41. package/lib/rules/default-case-last.js +1 -1
  42. package/lib/rules/default-case.js +2 -2
  43. package/lib/rules/default-param-last.js +1 -1
  44. package/lib/rules/dot-location.js +2 -2
  45. package/lib/rules/dot-notation.js +3 -4
  46. package/lib/rules/eol-last.js +2 -2
  47. package/lib/rules/eqeqeq.js +2 -2
  48. package/lib/rules/for-direction.js +1 -1
  49. package/lib/rules/func-call-spacing.js +2 -2
  50. package/lib/rules/func-name-matching.js +1 -1
  51. package/lib/rules/func-names.js +2 -2
  52. package/lib/rules/func-style.js +1 -1
  53. package/lib/rules/function-call-argument-newline.js +2 -2
  54. package/lib/rules/function-paren-newline.js +2 -2
  55. package/lib/rules/generator-star-spacing.js +2 -2
  56. package/lib/rules/getter-return.js +2 -2
  57. package/lib/rules/global-require.js +2 -2
  58. package/lib/rules/grouped-accessor-pairs.js +35 -44
  59. package/lib/rules/guard-for-in.js +1 -1
  60. package/lib/rules/handle-callback-err.js +2 -2
  61. package/lib/rules/id-blacklist.js +2 -2
  62. package/lib/rules/id-denylist.js +2 -2
  63. package/lib/rules/id-length.js +3 -36
  64. package/lib/rules/id-match.js +2 -2
  65. package/lib/rules/implicit-arrow-linebreak.js +2 -2
  66. package/lib/rules/indent-legacy.js +2 -2
  67. package/lib/rules/indent.js +84 -88
  68. package/lib/rules/init-declarations.js +1 -1
  69. package/lib/rules/jsx-quotes.js +1 -1
  70. package/lib/rules/key-spacing.js +4 -10
  71. package/lib/rules/keyword-spacing.js +2 -2
  72. package/lib/rules/line-comment-position.js +2 -2
  73. package/lib/rules/linebreak-style.js +2 -2
  74. package/lib/rules/lines-around-comment.js +2 -2
  75. package/lib/rules/lines-around-directive.js +2 -2
  76. package/lib/rules/lines-between-class-members.js +2 -2
  77. package/lib/rules/logical-assignment-operators.js +7 -5
  78. package/lib/rules/max-classes-per-file.js +1 -1
  79. package/lib/rules/max-depth.js +1 -1
  80. package/lib/rules/max-len.js +19 -15
  81. package/lib/rules/max-lines-per-function.js +2 -2
  82. package/lib/rules/max-lines.js +2 -2
  83. package/lib/rules/max-nested-callbacks.js +1 -1
  84. package/lib/rules/max-params.js +2 -2
  85. package/lib/rules/max-statements-per-line.js +2 -2
  86. package/lib/rules/max-statements.js +1 -1
  87. package/lib/rules/multiline-comment-style.js +2 -2
  88. package/lib/rules/multiline-ternary.js +2 -2
  89. package/lib/rules/new-cap.js +2 -2
  90. package/lib/rules/new-parens.js +2 -2
  91. package/lib/rules/newline-after-var.js +2 -4
  92. package/lib/rules/newline-before-return.js +2 -2
  93. package/lib/rules/newline-per-chained-call.js +2 -2
  94. package/lib/rules/no-alert.js +2 -2
  95. package/lib/rules/no-array-constructor.js +1 -1
  96. package/lib/rules/no-async-promise-executor.js +2 -2
  97. package/lib/rules/no-await-in-loop.js +1 -1
  98. package/lib/rules/no-bitwise.js +1 -1
  99. package/lib/rules/no-buffer-constructor.js +1 -1
  100. package/lib/rules/no-caller.js +1 -1
  101. package/lib/rules/no-case-declarations.js +1 -1
  102. package/lib/rules/no-catch-shadow.js +2 -2
  103. package/lib/rules/no-class-assign.js +2 -2
  104. package/lib/rules/no-compare-neg-zero.js +1 -1
  105. package/lib/rules/no-cond-assign.js +2 -2
  106. package/lib/rules/no-confusing-arrow.js +2 -2
  107. package/lib/rules/no-console.js +2 -2
  108. package/lib/rules/no-const-assign.js +2 -2
  109. package/lib/rules/no-constant-binary-expression.js +2 -2
  110. package/lib/rules/no-constant-condition.js +2 -2
  111. package/lib/rules/no-constructor-return.js +1 -1
  112. package/lib/rules/no-continue.js +1 -1
  113. package/lib/rules/no-control-regex.js +16 -3
  114. package/lib/rules/no-debugger.js +1 -1
  115. package/lib/rules/no-delete-var.js +1 -1
  116. package/lib/rules/no-div-regex.js +2 -2
  117. package/lib/rules/no-dupe-args.js +2 -2
  118. package/lib/rules/no-dupe-class-members.js +1 -1
  119. package/lib/rules/no-dupe-else-if.js +2 -2
  120. package/lib/rules/no-dupe-keys.js +1 -1
  121. package/lib/rules/no-duplicate-case.js +2 -2
  122. package/lib/rules/no-duplicate-imports.js +1 -1
  123. package/lib/rules/no-else-return.js +2 -2
  124. package/lib/rules/no-empty-character-class.js +34 -13
  125. package/lib/rules/no-empty-function.js +2 -2
  126. package/lib/rules/no-empty-pattern.js +39 -4
  127. package/lib/rules/no-empty-static-block.js +2 -2
  128. package/lib/rules/no-empty.js +2 -2
  129. package/lib/rules/no-eq-null.js +1 -1
  130. package/lib/rules/no-eval.js +2 -2
  131. package/lib/rules/no-ex-assign.js +2 -2
  132. package/lib/rules/no-extend-native.js +2 -2
  133. package/lib/rules/no-extra-bind.js +2 -2
  134. package/lib/rules/no-extra-boolean-cast.js +2 -2
  135. package/lib/rules/no-extra-label.js +2 -2
  136. package/lib/rules/no-extra-parens.js +48 -12
  137. package/lib/rules/no-extra-semi.js +31 -13
  138. package/lib/rules/no-fallthrough.js +3 -3
  139. package/lib/rules/no-floating-decimal.js +2 -2
  140. package/lib/rules/no-func-assign.js +2 -2
  141. package/lib/rules/no-global-assign.js +2 -2
  142. package/lib/rules/no-implicit-coercion.js +2 -2
  143. package/lib/rules/no-implicit-globals.js +2 -2
  144. package/lib/rules/no-implied-eval.js +2 -2
  145. package/lib/rules/no-import-assign.js +2 -2
  146. package/lib/rules/no-inline-comments.js +2 -2
  147. package/lib/rules/no-inner-declarations.js +1 -1
  148. package/lib/rules/no-invalid-regexp.js +23 -8
  149. package/lib/rules/no-invalid-this.js +2 -2
  150. package/lib/rules/no-irregular-whitespace.js +23 -6
  151. package/lib/rules/no-iterator.js +1 -1
  152. package/lib/rules/no-label-var.js +2 -2
  153. package/lib/rules/no-labels.js +1 -1
  154. package/lib/rules/no-lone-blocks.js +2 -2
  155. package/lib/rules/no-lonely-if.js +2 -2
  156. package/lib/rules/no-loop-func.js +3 -3
  157. package/lib/rules/no-loss-of-precision.js +15 -7
  158. package/lib/rules/no-magic-numbers.js +1 -1
  159. package/lib/rules/no-misleading-character-class.js +10 -4
  160. package/lib/rules/no-mixed-operators.js +2 -2
  161. package/lib/rules/no-mixed-requires.js +1 -1
  162. package/lib/rules/no-mixed-spaces-and-tabs.js +2 -2
  163. package/lib/rules/no-multi-assign.js +1 -1
  164. package/lib/rules/no-multi-spaces.js +2 -2
  165. package/lib/rules/no-multi-str.js +1 -1
  166. package/lib/rules/no-multiple-empty-lines.js +2 -2
  167. package/lib/rules/no-native-reassign.js +2 -2
  168. package/lib/rules/no-negated-condition.js +1 -1
  169. package/lib/rules/no-negated-in-lhs.js +1 -1
  170. package/lib/rules/no-nested-ternary.js +1 -1
  171. package/lib/rules/no-new-func.js +2 -2
  172. package/lib/rules/no-new-native-nonconstructor.js +2 -2
  173. package/lib/rules/no-new-object.js +2 -2
  174. package/lib/rules/no-new-require.js +1 -1
  175. package/lib/rules/no-new-symbol.js +2 -2
  176. package/lib/rules/no-new-wrappers.js +20 -8
  177. package/lib/rules/no-new.js +1 -1
  178. package/lib/rules/no-nonoctal-decimal-escape.js +2 -2
  179. package/lib/rules/no-obj-calls.js +2 -2
  180. package/lib/rules/no-octal-escape.js +1 -1
  181. package/lib/rules/no-octal.js +1 -1
  182. package/lib/rules/no-param-reassign.js +2 -2
  183. package/lib/rules/no-path-concat.js +1 -1
  184. package/lib/rules/no-plusplus.js +1 -1
  185. package/lib/rules/no-process-env.js +1 -1
  186. package/lib/rules/no-process-exit.js +1 -1
  187. package/lib/rules/no-promise-executor-return.js +2 -2
  188. package/lib/rules/no-proto.js +1 -1
  189. package/lib/rules/no-prototype-builtins.js +1 -1
  190. package/lib/rules/no-redeclare.js +2 -2
  191. package/lib/rules/no-regex-spaces.js +20 -5
  192. package/lib/rules/no-restricted-exports.js +2 -2
  193. package/lib/rules/no-restricted-globals.js +2 -2
  194. package/lib/rules/no-restricted-imports.js +2 -2
  195. package/lib/rules/no-restricted-modules.js +8 -11
  196. package/lib/rules/no-restricted-properties.js +1 -1
  197. package/lib/rules/no-restricted-syntax.js +1 -1
  198. package/lib/rules/no-return-assign.js +2 -2
  199. package/lib/rules/no-return-await.js +8 -3
  200. package/lib/rules/no-script-url.js +1 -1
  201. package/lib/rules/no-self-assign.js +2 -2
  202. package/lib/rules/no-self-compare.js +2 -2
  203. package/lib/rules/no-sequences.js +2 -2
  204. package/lib/rules/no-setter-return.js +2 -2
  205. package/lib/rules/no-shadow-restricted-names.js +2 -2
  206. package/lib/rules/no-shadow.js +2 -2
  207. package/lib/rules/no-spaced-func.js +2 -2
  208. package/lib/rules/no-sparse-arrays.js +1 -1
  209. package/lib/rules/no-sync.js +1 -1
  210. package/lib/rules/no-tabs.js +2 -2
  211. package/lib/rules/no-template-curly-in-string.js +1 -1
  212. package/lib/rules/no-ternary.js +1 -1
  213. package/lib/rules/no-this-before-super.js +1 -1
  214. package/lib/rules/no-throw-literal.js +1 -1
  215. package/lib/rules/no-trailing-spaces.js +2 -2
  216. package/lib/rules/no-undef-init.js +2 -2
  217. package/lib/rules/no-undef.js +2 -2
  218. package/lib/rules/no-undefined.js +2 -2
  219. package/lib/rules/no-underscore-dangle.js +2 -2
  220. package/lib/rules/no-unexpected-multiline.js +2 -2
  221. package/lib/rules/no-unmodified-loop-condition.js +2 -2
  222. package/lib/rules/no-unneeded-ternary.js +2 -2
  223. package/lib/rules/no-unreachable-loop.js +1 -1
  224. package/lib/rules/no-unreachable.js +2 -2
  225. package/lib/rules/no-unsafe-finally.js +1 -1
  226. package/lib/rules/no-unsafe-negation.js +2 -2
  227. package/lib/rules/no-unsafe-optional-chaining.js +1 -1
  228. package/lib/rules/no-unused-expressions.js +4 -6
  229. package/lib/rules/no-unused-labels.js +48 -15
  230. package/lib/rules/no-unused-private-class-members.js +1 -1
  231. package/lib/rules/no-unused-vars.js +4 -3
  232. package/lib/rules/no-use-before-define.js +2 -2
  233. package/lib/rules/no-useless-backreference.js +3 -3
  234. package/lib/rules/no-useless-call.js +2 -2
  235. package/lib/rules/no-useless-catch.js +1 -1
  236. package/lib/rules/no-useless-computed-key.js +2 -2
  237. package/lib/rules/no-useless-concat.js +2 -2
  238. package/lib/rules/no-useless-constructor.js +1 -1
  239. package/lib/rules/no-useless-escape.js +162 -83
  240. package/lib/rules/no-useless-rename.js +2 -2
  241. package/lib/rules/no-useless-return.js +37 -9
  242. package/lib/rules/no-var.js +2 -2
  243. package/lib/rules/no-void.js +1 -1
  244. package/lib/rules/no-warning-comments.js +2 -2
  245. package/lib/rules/no-whitespace-before-property.js +2 -2
  246. package/lib/rules/no-with.js +1 -1
  247. package/lib/rules/nonblock-statement-body-position.js +2 -2
  248. package/lib/rules/object-curly-newline.js +2 -2
  249. package/lib/rules/object-curly-spacing.js +4 -4
  250. package/lib/rules/object-property-newline.js +2 -2
  251. package/lib/rules/object-shorthand.js +2 -2
  252. package/lib/rules/one-var-declaration-per-line.js +1 -1
  253. package/lib/rules/one-var.js +2 -2
  254. package/lib/rules/operator-assignment.js +2 -2
  255. package/lib/rules/operator-linebreak.js +2 -2
  256. package/lib/rules/padded-blocks.js +2 -2
  257. package/lib/rules/padding-line-between-statements.js +8 -53
  258. package/lib/rules/prefer-arrow-callback.js +2 -2
  259. package/lib/rules/prefer-const.js +2 -2
  260. package/lib/rules/prefer-destructuring.js +2 -2
  261. package/lib/rules/prefer-exponentiation-operator.js +4 -3
  262. package/lib/rules/prefer-named-capture-group.js +10 -7
  263. package/lib/rules/prefer-numeric-literals.js +2 -2
  264. package/lib/rules/prefer-object-has-own.js +2 -2
  265. package/lib/rules/prefer-object-spread.js +2 -2
  266. package/lib/rules/prefer-promise-reject-errors.js +2 -2
  267. package/lib/rules/prefer-reflect.js +1 -1
  268. package/lib/rules/prefer-regex-literals.js +14 -17
  269. package/lib/rules/prefer-rest-params.js +2 -2
  270. package/lib/rules/prefer-spread.js +2 -2
  271. package/lib/rules/prefer-template.js +2 -2
  272. package/lib/rules/quote-props.js +2 -2
  273. package/lib/rules/quotes.js +16 -16
  274. package/lib/rules/radix.js +2 -2
  275. package/lib/rules/require-atomic-updates.js +2 -2
  276. package/lib/rules/require-await.js +2 -2
  277. package/lib/rules/require-jsdoc.js +2 -2
  278. package/lib/rules/require-unicode-regexp.js +5 -5
  279. package/lib/rules/require-yield.js +1 -1
  280. package/lib/rules/rest-spread-spacing.js +2 -2
  281. package/lib/rules/semi-spacing.js +2 -2
  282. package/lib/rules/semi-style.js +2 -2
  283. package/lib/rules/semi.js +30 -5
  284. package/lib/rules/sort-imports.js +2 -2
  285. package/lib/rules/sort-keys.js +2 -2
  286. package/lib/rules/sort-vars.js +2 -2
  287. package/lib/rules/space-before-blocks.js +2 -2
  288. package/lib/rules/space-before-function-paren.js +2 -2
  289. package/lib/rules/space-in-parens.js +2 -2
  290. package/lib/rules/space-infix-ops.js +2 -2
  291. package/lib/rules/space-unary-ops.js +2 -2
  292. package/lib/rules/spaced-comment.js +2 -2
  293. package/lib/rules/strict.js +1 -1
  294. package/lib/rules/switch-colon-spacing.js +2 -2
  295. package/lib/rules/symbol-description.js +2 -2
  296. package/lib/rules/template-curly-spacing.js +2 -2
  297. package/lib/rules/template-tag-spacing.js +2 -2
  298. package/lib/rules/unicode-bom.js +2 -2
  299. package/lib/rules/use-isnan.js +1 -1
  300. package/lib/rules/utils/ast-utils.js +55 -7
  301. package/lib/rules/utils/regular-expressions.js +2 -2
  302. package/lib/rules/valid-jsdoc.js +2 -2
  303. package/lib/rules/valid-typeof.js +9 -3
  304. package/lib/rules/vars-on-top.js +1 -1
  305. package/lib/rules/wrap-iife.js +2 -2
  306. package/lib/rules/wrap-regex.js +2 -2
  307. package/lib/rules/yield-star-spacing.js +2 -2
  308. package/lib/rules/yoda.js +4 -13
  309. package/lib/shared/string-utils.js +39 -1
  310. package/lib/shared/types.js +7 -3
  311. package/lib/unsupported-api.js +5 -2
  312. package/messages/eslintrc-incompat.js +98 -0
  313. package/messages/eslintrc-plugins.js +24 -0
  314. package/messages/invalid-rule-options.js +17 -0
  315. package/messages/invalid-rule-severity.js +13 -0
  316. package/messages/shared.js +18 -0
  317. package/package.json +15 -19
@@ -12,8 +12,6 @@
12
12
  // Requirements
13
13
  //------------------------------------------------------------------------------
14
14
 
15
- const { OrderedMap } = require("js-sdsl");
16
-
17
15
  const astUtils = require("./utils/ast-utils");
18
16
 
19
17
  //------------------------------------------------------------------------------
@@ -125,43 +123,48 @@ const KNOWN_NODES = new Set([
125
123
 
126
124
 
127
125
  /**
128
- * A mutable balanced binary search tree that stores (key, value) pairs. The keys are numeric, and must be unique.
129
- * This is intended to be a generic wrapper around a balanced binary search tree library, so that the underlying implementation
126
+ * A mutable map that stores (key, value) pairs. The keys are numeric indices, and must be unique.
127
+ * This is intended to be a generic wrapper around a map with non-negative integer keys, so that the underlying implementation
130
128
  * can easily be swapped out.
131
129
  */
132
- class BinarySearchTree {
130
+ class IndexMap {
133
131
 
134
132
  /**
135
- * Creates an empty tree
133
+ * Creates an empty map
134
+ * @param {number} maxKey The maximum key
136
135
  */
137
- constructor() {
138
- this._orderedMap = new OrderedMap();
139
- this._orderedMapEnd = this._orderedMap.end();
136
+ constructor(maxKey) {
137
+
138
+ // Initializing the array with the maximum expected size avoids dynamic reallocations that could degrade performance.
139
+ this._values = Array(maxKey + 1);
140
140
  }
141
141
 
142
142
  /**
143
- * Inserts an entry into the tree.
143
+ * Inserts an entry into the map.
144
144
  * @param {number} key The entry's key
145
145
  * @param {any} value The entry's value
146
146
  * @returns {void}
147
147
  */
148
148
  insert(key, value) {
149
- this._orderedMap.setElement(key, value);
149
+ this._values[key] = value;
150
150
  }
151
151
 
152
152
  /**
153
- * Finds the entry with the largest key less than or equal to the provided key
153
+ * Finds the value of the entry with the largest key less than or equal to the provided key
154
154
  * @param {number} key The provided key
155
- * @returns {{key: number, value: *}|null} The found entry, or null if no such entry exists.
155
+ * @returns {*|undefined} The value of the found entry, or undefined if no such entry exists.
156
156
  */
157
- findLe(key) {
158
- const iterator = this._orderedMap.reverseLowerBound(key);
157
+ findLastNotAfter(key) {
158
+ const values = this._values;
159
159
 
160
- if (iterator.equals(this._orderedMapEnd)) {
161
- return {};
162
- }
160
+ for (let index = key; index >= 0; index--) {
161
+ const value = values[index];
163
162
 
164
- return { key: iterator.pointer[0], value: iterator.pointer[1] };
163
+ if (value) {
164
+ return value;
165
+ }
166
+ }
167
+ return void 0;
165
168
  }
166
169
 
167
170
  /**
@@ -171,26 +174,7 @@ class BinarySearchTree {
171
174
  * @returns {void}
172
175
  */
173
176
  deleteRange(start, end) {
174
-
175
- // Exit without traversing the tree if the range has zero size.
176
- if (start === end) {
177
- return;
178
- }
179
- const iterator = this._orderedMap.lowerBound(start);
180
-
181
- if (iterator.equals(this._orderedMapEnd)) {
182
- return;
183
- }
184
-
185
- if (end > this._orderedMap.back()[0]) {
186
- while (!iterator.equals(this._orderedMapEnd)) {
187
- this._orderedMap.eraseElementByIterator(iterator);
188
- }
189
- } else {
190
- while (iterator.pointer[0] < end) {
191
- this._orderedMap.eraseElementByIterator(iterator);
192
- }
193
- }
177
+ this._values.fill(void 0, start, end);
194
178
  }
195
179
  }
196
180
 
@@ -204,15 +188,19 @@ class TokenInfo {
204
188
  */
205
189
  constructor(sourceCode) {
206
190
  this.sourceCode = sourceCode;
207
- this.firstTokensByLineNumber = sourceCode.tokensAndComments.reduce((map, token) => {
208
- if (!map.has(token.loc.start.line)) {
209
- map.set(token.loc.start.line, token);
191
+ this.firstTokensByLineNumber = new Map();
192
+ const tokens = sourceCode.tokensAndComments;
193
+
194
+ for (let i = 0; i < tokens.length; i++) {
195
+ const token = tokens[i];
196
+
197
+ if (!this.firstTokensByLineNumber.has(token.loc.start.line)) {
198
+ this.firstTokensByLineNumber.set(token.loc.start.line, token);
210
199
  }
211
- if (!map.has(token.loc.end.line) && sourceCode.text.slice(token.range[1] - token.loc.end.column, token.range[1]).trim()) {
212
- map.set(token.loc.end.line, token);
200
+ if (!this.firstTokensByLineNumber.has(token.loc.end.line) && sourceCode.text.slice(token.range[1] - token.loc.end.column, token.range[1]).trim()) {
201
+ this.firstTokensByLineNumber.set(token.loc.end.line, token);
213
202
  }
214
- return map;
215
- }, new Map());
203
+ }
216
204
  }
217
205
 
218
206
  /**
@@ -252,14 +240,15 @@ class OffsetStorage {
252
240
  * @param {TokenInfo} tokenInfo a TokenInfo instance
253
241
  * @param {number} indentSize The desired size of each indentation level
254
242
  * @param {string} indentType The indentation character
243
+ * @param {number} maxIndex The maximum end index of any token
255
244
  */
256
- constructor(tokenInfo, indentSize, indentType) {
245
+ constructor(tokenInfo, indentSize, indentType, maxIndex) {
257
246
  this._tokenInfo = tokenInfo;
258
247
  this._indentSize = indentSize;
259
248
  this._indentType = indentType;
260
249
 
261
- this._tree = new BinarySearchTree();
262
- this._tree.insert(0, { offset: 0, from: null, force: false });
250
+ this._indexMap = new IndexMap(maxIndex);
251
+ this._indexMap.insert(0, { offset: 0, from: null, force: false });
263
252
 
264
253
  this._lockedFirstTokens = new WeakMap();
265
254
  this._desiredIndentCache = new WeakMap();
@@ -267,7 +256,7 @@ class OffsetStorage {
267
256
  }
268
257
 
269
258
  _getOffsetDescriptor(token) {
270
- return this._tree.findLe(token.range[0]).value;
259
+ return this._indexMap.findLastNotAfter(token.range[0]);
271
260
  }
272
261
 
273
262
  /**
@@ -388,37 +377,36 @@ class OffsetStorage {
388
377
  * * key: 820, value: { offset: 1, from: bazToken }
389
378
  *
390
379
  * To find the offset descriptor for any given token, one needs to find the node with the largest key
391
- * which is <= token.start. To make this operation fast, the nodes are stored in a balanced binary
392
- * search tree indexed by key.
380
+ * which is <= token.start. To make this operation fast, the nodes are stored in a map indexed by key.
393
381
  */
394
382
 
395
383
  const descriptorToInsert = { offset, from: fromToken, force };
396
384
 
397
- const descriptorAfterRange = this._tree.findLe(range[1]).value;
385
+ const descriptorAfterRange = this._indexMap.findLastNotAfter(range[1]);
398
386
 
399
387
  const fromTokenIsInRange = fromToken && fromToken.range[0] >= range[0] && fromToken.range[1] <= range[1];
400
388
  const fromTokenDescriptor = fromTokenIsInRange && this._getOffsetDescriptor(fromToken);
401
389
 
402
- // First, remove any existing nodes in the range from the tree.
403
- this._tree.deleteRange(range[0] + 1, range[1]);
390
+ // First, remove any existing nodes in the range from the map.
391
+ this._indexMap.deleteRange(range[0] + 1, range[1]);
404
392
 
405
- // Insert a new node into the tree for this range
406
- this._tree.insert(range[0], descriptorToInsert);
393
+ // Insert a new node into the map for this range
394
+ this._indexMap.insert(range[0], descriptorToInsert);
407
395
 
408
396
  /*
409
397
  * To avoid circular offset dependencies, keep the `fromToken` token mapped to whatever it was mapped to previously,
410
398
  * even if it's in the current range.
411
399
  */
412
400
  if (fromTokenIsInRange) {
413
- this._tree.insert(fromToken.range[0], fromTokenDescriptor);
414
- this._tree.insert(fromToken.range[1], descriptorToInsert);
401
+ this._indexMap.insert(fromToken.range[0], fromTokenDescriptor);
402
+ this._indexMap.insert(fromToken.range[1], descriptorToInsert);
415
403
  }
416
404
 
417
405
  /*
418
406
  * To avoid modifying the offset of tokens after the range, insert another node to keep the offset of the following
419
407
  * tokens the same as it was before.
420
408
  */
421
- this._tree.insert(range[1], descriptorAfterRange);
409
+ this._indexMap.insert(range[1], descriptorAfterRange);
422
410
  }
423
411
 
424
412
  /**
@@ -510,7 +498,7 @@ module.exports = {
510
498
  docs: {
511
499
  description: "Enforce consistent indentation",
512
500
  recommended: false,
513
- url: "https://eslint.org/docs/rules/indent"
501
+ url: "https://eslint.org/docs/latest/rules/indent"
514
502
  },
515
503
 
516
504
  fixable: "whitespace",
@@ -703,9 +691,9 @@ module.exports = {
703
691
  }
704
692
  }
705
693
 
706
- const sourceCode = context.getSourceCode();
694
+ const sourceCode = context.sourceCode;
707
695
  const tokenInfo = new TokenInfo(sourceCode);
708
- const offsets = new OffsetStorage(tokenInfo, indentSize, indentType === "space" ? " " : "\t");
696
+ const offsets = new OffsetStorage(tokenInfo, indentSize, indentType === "space" ? " " : "\t", sourceCode.text.length);
709
697
  const parameterParens = new WeakSet();
710
698
 
711
699
  /**
@@ -980,19 +968,19 @@ module.exports = {
980
968
  const parenStack = [];
981
969
  const parenPairs = [];
982
970
 
983
- tokens.forEach(nextToken => {
971
+ for (let i = 0; i < tokens.length; i++) {
972
+ const nextToken = tokens[i];
984
973
 
985
- // Accumulate a list of parenthesis pairs
986
974
  if (astUtils.isOpeningParenToken(nextToken)) {
987
975
  parenStack.push(nextToken);
988
976
  } else if (astUtils.isClosingParenToken(nextToken)) {
989
- parenPairs.unshift({ left: parenStack.pop(), right: nextToken });
977
+ parenPairs.push({ left: parenStack.pop(), right: nextToken });
990
978
  }
991
- });
979
+ }
992
980
 
993
- parenPairs.forEach(pair => {
994
- const leftParen = pair.left;
995
- const rightParen = pair.right;
981
+ for (let i = parenPairs.length - 1; i >= 0; i--) {
982
+ const leftParen = parenPairs[i].left;
983
+ const rightParen = parenPairs[i].right;
996
984
 
997
985
  // We only want to handle parens around expressions, so exclude parentheses that are in function parameters and function call arguments.
998
986
  if (!parameterParens.has(leftParen) && !parameterParens.has(rightParen)) {
@@ -1006,7 +994,7 @@ module.exports = {
1006
994
  }
1007
995
 
1008
996
  offsets.setDesiredOffset(rightParen, leftParen, 0);
1009
- });
997
+ }
1010
998
  }
1011
999
 
1012
1000
  /**
@@ -1262,7 +1250,7 @@ module.exports = {
1262
1250
 
1263
1251
  IfStatement(node) {
1264
1252
  addBlocklessNodeIndent(node.consequent);
1265
- if (node.alternate && node.alternate.type !== "IfStatement") {
1253
+ if (node.alternate) {
1266
1254
  addBlocklessNodeIndent(node.alternate);
1267
1255
  }
1268
1256
  },
@@ -1727,9 +1715,13 @@ module.exports = {
1727
1715
  }
1728
1716
 
1729
1717
  // Invoke the queued offset listeners for the nodes that aren't ignored.
1730
- listenerCallQueue
1731
- .filter(nodeInfo => !ignoredNodes.has(nodeInfo.node))
1732
- .forEach(nodeInfo => nodeInfo.listener(nodeInfo.node));
1718
+ for (let i = 0; i < listenerCallQueue.length; i++) {
1719
+ const nodeInfo = listenerCallQueue[i];
1720
+
1721
+ if (!ignoredNodes.has(nodeInfo.node)) {
1722
+ nodeInfo.listener(nodeInfo.node);
1723
+ }
1724
+ }
1733
1725
 
1734
1726
  // Update the offsets for ignored nodes to prevent their child tokens from being reported.
1735
1727
  ignoredNodes.forEach(ignoreNode);
@@ -1740,27 +1732,31 @@ module.exports = {
1740
1732
  * Create a Map from (tokenOrComment) => (precedingToken).
1741
1733
  * This is necessary because sourceCode.getTokenBefore does not handle a comment as an argument correctly.
1742
1734
  */
1743
- const precedingTokens = sourceCode.ast.comments.reduce((commentMap, comment) => {
1735
+ const precedingTokens = new WeakMap();
1736
+
1737
+ for (let i = 0; i < sourceCode.ast.comments.length; i++) {
1738
+ const comment = sourceCode.ast.comments[i];
1739
+
1744
1740
  const tokenOrCommentBefore = sourceCode.getTokenBefore(comment, { includeComments: true });
1741
+ const hasToken = precedingTokens.has(tokenOrCommentBefore) ? precedingTokens.get(tokenOrCommentBefore) : tokenOrCommentBefore;
1745
1742
 
1746
- return commentMap.set(comment, commentMap.has(tokenOrCommentBefore) ? commentMap.get(tokenOrCommentBefore) : tokenOrCommentBefore);
1747
- }, new WeakMap());
1743
+ precedingTokens.set(comment, hasToken);
1744
+ }
1748
1745
 
1749
- sourceCode.lines.forEach((line, lineIndex) => {
1750
- const lineNumber = lineIndex + 1;
1746
+ for (let i = 1; i < sourceCode.lines.length + 1; i++) {
1751
1747
 
1752
- if (!tokenInfo.firstTokensByLineNumber.has(lineNumber)) {
1748
+ if (!tokenInfo.firstTokensByLineNumber.has(i)) {
1753
1749
 
1754
1750
  // Don't check indentation on blank lines
1755
- return;
1751
+ continue;
1756
1752
  }
1757
1753
 
1758
- const firstTokenOfLine = tokenInfo.firstTokensByLineNumber.get(lineNumber);
1754
+ const firstTokenOfLine = tokenInfo.firstTokensByLineNumber.get(i);
1759
1755
 
1760
- if (firstTokenOfLine.loc.start.line !== lineNumber) {
1756
+ if (firstTokenOfLine.loc.start.line !== i) {
1761
1757
 
1762
1758
  // Don't check the indentation of multi-line tokens (e.g. template literals or block comments) twice.
1763
- return;
1759
+ continue;
1764
1760
  }
1765
1761
 
1766
1762
  if (astUtils.isCommentToken(firstTokenOfLine)) {
@@ -1785,18 +1781,18 @@ module.exports = {
1785
1781
  mayAlignWithBefore && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenBefore)) ||
1786
1782
  mayAlignWithAfter && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenAfter))
1787
1783
  ) {
1788
- return;
1784
+ continue;
1789
1785
  }
1790
1786
  }
1791
1787
 
1792
1788
  // If the token matches the expected indentation, don't report it.
1793
1789
  if (validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine))) {
1794
- return;
1790
+ continue;
1795
1791
  }
1796
1792
 
1797
1793
  // Otherwise, report the token/comment.
1798
1794
  report(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine));
1799
- });
1795
+ }
1800
1796
  }
1801
1797
  }
1802
1798
  );
@@ -50,7 +50,7 @@ module.exports = {
50
50
  docs: {
51
51
  description: "Require or disallow initialization in variable declarations",
52
52
  recommended: false,
53
- url: "https://eslint.org/docs/rules/init-declarations"
53
+ url: "https://eslint.org/docs/latest/rules/init-declarations"
54
54
  },
55
55
 
56
56
  schema: {
@@ -44,7 +44,7 @@ module.exports = {
44
44
  docs: {
45
45
  description: "Enforce the consistent use of either double or single quotes in JSX attributes",
46
46
  recommended: false,
47
- url: "https://eslint.org/docs/rules/jsx-quotes"
47
+ url: "https://eslint.org/docs/latest/rules/jsx-quotes"
48
48
  },
49
49
 
50
50
  fixable: "whitespace",
@@ -9,13 +9,7 @@
9
9
  //------------------------------------------------------------------------------
10
10
 
11
11
  const astUtils = require("./utils/ast-utils");
12
- const GraphemeSplitter = require("grapheme-splitter");
13
-
14
- const splitter = new GraphemeSplitter();
15
-
16
- //------------------------------------------------------------------------------
17
- // Helpers
18
- //------------------------------------------------------------------------------
12
+ const { getGraphemeCount } = require("../shared/string-utils");
19
13
 
20
14
  /**
21
15
  * Checks whether a string contains a line terminator as defined in
@@ -144,7 +138,7 @@ module.exports = {
144
138
  docs: {
145
139
  description: "Enforce consistent spacing between keys and values in object literal properties",
146
140
  recommended: false,
147
- url: "https://eslint.org/docs/rules/key-spacing"
141
+ url: "https://eslint.org/docs/latest/rules/key-spacing"
148
142
  },
149
143
 
150
144
  fixable: "whitespace",
@@ -332,7 +326,7 @@ module.exports = {
332
326
  singleLineOptions = ruleOptions.singleLine,
333
327
  alignmentOptions = ruleOptions.align || null;
334
328
 
335
- const sourceCode = context.getSourceCode();
329
+ const sourceCode = context.sourceCode;
336
330
 
337
331
  /**
338
332
  * Determines if the given property is key-value property.
@@ -523,7 +517,7 @@ module.exports = {
523
517
  const startToken = sourceCode.getFirstToken(property);
524
518
  const endToken = getLastTokenBeforeColon(property.key);
525
519
 
526
- return splitter.countGraphemes(sourceCode.getText().slice(startToken.range[0], endToken.range[1]));
520
+ return getGraphemeCount(sourceCode.getText().slice(startToken.range[0], endToken.range[1]));
527
521
  }
528
522
 
529
523
  /**
@@ -69,7 +69,7 @@ module.exports = {
69
69
  docs: {
70
70
  description: "Enforce consistent spacing before and after keywords",
71
71
  recommended: false,
72
- url: "https://eslint.org/docs/rules/keyword-spacing"
72
+ url: "https://eslint.org/docs/latest/rules/keyword-spacing"
73
73
  },
74
74
 
75
75
  fixable: "whitespace",
@@ -108,7 +108,7 @@ module.exports = {
108
108
  },
109
109
 
110
110
  create(context) {
111
- const sourceCode = context.getSourceCode();
111
+ const sourceCode = context.sourceCode;
112
112
 
113
113
  const tokensToIgnore = new WeakSet();
114
114
 
@@ -18,7 +18,7 @@ module.exports = {
18
18
  docs: {
19
19
  description: "Enforce position of line comments",
20
20
  recommended: false,
21
- url: "https://eslint.org/docs/rules/line-comment-position"
21
+ url: "https://eslint.org/docs/latest/rules/line-comment-position"
22
22
  },
23
23
 
24
24
  schema: [
@@ -78,7 +78,7 @@ module.exports = {
78
78
  const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN;
79
79
  const fallThroughRegExp = /^\s*falls?\s?through/u;
80
80
  const customIgnoreRegExp = new RegExp(ignorePattern, "u");
81
- const sourceCode = context.getSourceCode();
81
+ const sourceCode = context.sourceCode;
82
82
 
83
83
  //--------------------------------------------------------------------------
84
84
  // Public
@@ -23,7 +23,7 @@ module.exports = {
23
23
  docs: {
24
24
  description: "Enforce consistent linebreak style",
25
25
  recommended: false,
26
- url: "https://eslint.org/docs/rules/linebreak-style"
26
+ url: "https://eslint.org/docs/latest/rules/linebreak-style"
27
27
  },
28
28
 
29
29
  fixable: "whitespace",
@@ -40,7 +40,7 @@ module.exports = {
40
40
  },
41
41
 
42
42
  create(context) {
43
- const sourceCode = context.getSourceCode();
43
+ const sourceCode = context.sourceCode;
44
44
 
45
45
  //--------------------------------------------------------------------------
46
46
  // Helpers
@@ -57,7 +57,7 @@ module.exports = {
57
57
  docs: {
58
58
  description: "Require empty lines around comments",
59
59
  recommended: false,
60
- url: "https://eslint.org/docs/rules/lines-around-comment"
60
+ url: "https://eslint.org/docs/latest/rules/lines-around-comment"
61
61
  },
62
62
 
63
63
  fixable: "whitespace",
@@ -138,7 +138,7 @@ module.exports = {
138
138
 
139
139
  options.beforeBlockComment = typeof options.beforeBlockComment !== "undefined" ? options.beforeBlockComment : true;
140
140
 
141
- const sourceCode = context.getSourceCode();
141
+ const sourceCode = context.sourceCode;
142
142
 
143
143
  const lines = sourceCode.lines,
144
144
  numLines = lines.length + 1,
@@ -20,7 +20,7 @@ module.exports = {
20
20
  docs: {
21
21
  description: "Require or disallow newlines around directives",
22
22
  recommended: false,
23
- url: "https://eslint.org/docs/rules/lines-around-directive"
23
+ url: "https://eslint.org/docs/latest/rules/lines-around-directive"
24
24
  },
25
25
 
26
26
  schema: [{
@@ -54,7 +54,7 @@ module.exports = {
54
54
  },
55
55
 
56
56
  create(context) {
57
- const sourceCode = context.getSourceCode();
57
+ const sourceCode = context.sourceCode;
58
58
  const config = context.options[0] || "always";
59
59
  const expectLineBefore = typeof config === "string" ? config : config.before;
60
60
  const expectLineAfter = typeof config === "string" ? config : config.after;
@@ -22,7 +22,7 @@ module.exports = {
22
22
  docs: {
23
23
  description: "Require or disallow an empty line between class members",
24
24
  recommended: false,
25
- url: "https://eslint.org/docs/rules/lines-between-class-members"
25
+ url: "https://eslint.org/docs/latest/rules/lines-between-class-members"
26
26
  },
27
27
 
28
28
  fixable: "whitespace",
@@ -55,7 +55,7 @@ module.exports = {
55
55
  options[0] = context.options[0] || "always";
56
56
  options[1] = context.options[1] || { exceptAfterSingleLine: false };
57
57
 
58
- const sourceCode = context.getSourceCode();
58
+ const sourceCode = context.sourceCode;
59
59
 
60
60
  /**
61
61
  * Gets a pair of tokens that should be used to check lines between two class member nodes.
@@ -161,7 +161,7 @@ module.exports = {
161
161
  docs: {
162
162
  description: "Require or disallow logical assignment operator shorthand",
163
163
  recommended: false,
164
- url: "https://eslint.org/docs/rules/logical-assignment-operators"
164
+ url: "https://eslint.org/docs/latest/rules/logical-assignment-operators"
165
165
  },
166
166
 
167
167
  schema: {
@@ -188,7 +188,6 @@ module.exports = {
188
188
  }]
189
189
  },
190
190
  fixable: "code",
191
- // eslint-disable-next-line eslint-plugin/require-meta-has-suggestions -- Does not detect conditional suggestions
192
191
  hasSuggestions: true,
193
192
  messages: {
194
193
  assignment: "Assignment (=) can be replaced with operator assignment ({{operator}}).",
@@ -205,7 +204,7 @@ module.exports = {
205
204
  create(context) {
206
205
  const mode = context.options[0] === "never" ? "never" : "always";
207
206
  const checkIf = mode === "always" && context.options.length > 1 && context.options[1].enforceForIfStatements;
208
- const sourceCode = context.getSourceCode();
207
+ const sourceCode = context.sourceCode;
209
208
  const isStrict = sourceCode.getScope(sourceCode.ast).isStrict;
210
209
 
211
210
  /**
@@ -371,8 +370,11 @@ module.exports = {
371
370
  return;
372
371
  }
373
372
 
374
- const requiresOuterParenthesis = logical.parent.type !== "ExpressionStatement" &&
375
- (astUtils.getPrecedence({ type: "AssignmentExpression" }) < astUtils.getPrecedence(logical.parent));
373
+ const parentPrecedence = astUtils.getPrecedence(logical.parent);
374
+ const requiresOuterParenthesis = logical.parent.type !== "ExpressionStatement" && (
375
+ parentPrecedence === -1 ||
376
+ astUtils.getPrecedence({ type: "AssignmentExpression" }) < parentPrecedence
377
+ );
376
378
 
377
379
  if (!astUtils.isParenthesised(sourceCode, logical) && requiresOuterParenthesis) {
378
380
  yield ruleFixer.insertTextBefore(logical, "(");
@@ -21,7 +21,7 @@ module.exports = {
21
21
  docs: {
22
22
  description: "Enforce a maximum number of classes per file",
23
23
  recommended: false,
24
- url: "https://eslint.org/docs/rules/max-classes-per-file"
24
+ url: "https://eslint.org/docs/latest/rules/max-classes-per-file"
25
25
  },
26
26
 
27
27
  schema: [
@@ -17,7 +17,7 @@ module.exports = {
17
17
  docs: {
18
18
  description: "Enforce a maximum depth that blocks can be nested",
19
19
  recommended: false,
20
- url: "https://eslint.org/docs/rules/max-depth"
20
+ url: "https://eslint.org/docs/latest/rules/max-depth"
21
21
  },
22
22
 
23
23
  schema: [
@@ -71,7 +71,7 @@ module.exports = {
71
71
  docs: {
72
72
  description: "Enforce a maximum line length",
73
73
  recommended: false,
74
- url: "https://eslint.org/docs/rules/max-len"
74
+ url: "https://eslint.org/docs/latest/rules/max-len"
75
75
  },
76
76
 
77
77
  schema: [
@@ -97,7 +97,7 @@ module.exports = {
97
97
  */
98
98
  const URL_REGEXP = /[^:/?#]:\/\/[^?#]/u;
99
99
 
100
- const sourceCode = context.getSourceCode();
100
+ const sourceCode = context.sourceCode;
101
101
 
102
102
  /**
103
103
  * Computes the length of a line that may contain tabs. The width of each
@@ -252,19 +252,23 @@ module.exports = {
252
252
  return sourceCode.ast.tokens.filter(token => token.type === "RegularExpression");
253
253
  }
254
254
 
255
-
256
255
  /**
257
- * A reducer to group an AST node by line number, both start and end.
258
- * @param {Object} acc the accumulator
259
- * @param {ASTNode} node the AST node in question
260
- * @returns {Object} the modified accumulator
261
- * @private
256
+ *
257
+ * reduce an array of AST nodes by line number, both start and end.
258
+ * @param {ASTNode[]} arr array of AST nodes
259
+ * @returns {Object} accululated AST nodes
262
260
  */
263
- function groupByLineNumber(acc, node) {
264
- for (let i = node.loc.start.line; i <= node.loc.end.line; ++i) {
265
- ensureArrayAndPush(acc, i, node);
261
+ function groupArrayByLineNumber(arr) {
262
+ const obj = {};
263
+
264
+ for (let i = 0; i < arr.length; i++) {
265
+ const node = arr[i];
266
+
267
+ for (let j = node.loc.start.line; j <= node.loc.end.line; ++j) {
268
+ ensureArrayAndPush(obj, j, node);
269
+ }
266
270
  }
267
- return acc;
271
+ return obj;
268
272
  }
269
273
 
270
274
  /**
@@ -312,13 +316,13 @@ module.exports = {
312
316
  let commentsIndex = 0;
313
317
 
314
318
  const strings = getAllStrings();
315
- const stringsByLine = strings.reduce(groupByLineNumber, {});
319
+ const stringsByLine = groupArrayByLineNumber(strings);
316
320
 
317
321
  const templateLiterals = getAllTemplateLiterals();
318
- const templateLiteralsByLine = templateLiterals.reduce(groupByLineNumber, {});
322
+ const templateLiteralsByLine = groupArrayByLineNumber(templateLiterals);
319
323
 
320
324
  const regExpLiterals = getAllRegExpLiterals();
321
- const regExpLiteralsByLine = regExpLiterals.reduce(groupByLineNumber, {});
325
+ const regExpLiteralsByLine = groupArrayByLineNumber(regExpLiterals);
322
326
 
323
327
  lines.forEach((line, i) => {
324
328