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
@@ -6,7 +6,12 @@
6
6
  "use strict";
7
7
 
8
8
  const astUtils = require("./utils/ast-utils");
9
+ const { RegExpParser, visitRegExpAST } = require("@eslint-community/regexpp");
9
10
 
11
+ /**
12
+ * @typedef {import('@eslint-community/regexpp').AST.CharacterClass} CharacterClass
13
+ * @typedef {import('@eslint-community/regexpp').AST.ExpressionCharacterClass} ExpressionCharacterClass
14
+ */
10
15
  //------------------------------------------------------------------------------
11
16
  // Rule Definition
12
17
  //------------------------------------------------------------------------------
@@ -28,55 +33,17 @@ const VALID_STRING_ESCAPES = union(new Set("\\nrvtbfux"), astUtils.LINEBREAKS);
28
33
  const REGEX_GENERAL_ESCAPES = new Set("\\bcdDfnpPrsStvwWxu0123456789]");
29
34
  const REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()Bk"));
30
35
 
31
- /**
32
- * Parses a regular expression into a list of characters with character class info.
33
- * @param {string} regExpText The raw text used to create the regular expression
34
- * @returns {Object[]} A list of characters, each with info on escaping and whether they're in a character class.
35
- * @example
36
- *
37
- * parseRegExp("a\\b[cd-]");
38
- *
39
- * // returns:
40
- * [
41
- * { text: "a", index: 0, escaped: false, inCharClass: false, startsCharClass: false, endsCharClass: false },
42
- * { text: "b", index: 2, escaped: true, inCharClass: false, startsCharClass: false, endsCharClass: false },
43
- * { text: "c", index: 4, escaped: false, inCharClass: true, startsCharClass: true, endsCharClass: false },
44
- * { text: "d", index: 5, escaped: false, inCharClass: true, startsCharClass: false, endsCharClass: false },
45
- * { text: "-", index: 6, escaped: false, inCharClass: true, startsCharClass: false, endsCharClass: false }
46
- * ];
47
- *
36
+ /*
37
+ * Set of characters that require escaping in character classes in `unicodeSets` mode.
38
+ * ( ) [ ] { } / - \ | are ClassSetSyntaxCharacter
48
39
  */
49
- function parseRegExp(regExpText) {
50
- const charList = [];
40
+ const REGEX_CLASSSET_CHARACTER_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("q/[{}|()-"));
51
41
 
52
- regExpText.split("").reduce((state, char, index) => {
53
- if (!state.escapeNextChar) {
54
- if (char === "\\") {
55
- return Object.assign(state, { escapeNextChar: true });
56
- }
57
- if (char === "[" && !state.inCharClass) {
58
- return Object.assign(state, { inCharClass: true, startingCharClass: true });
59
- }
60
- if (char === "]" && state.inCharClass) {
61
- if (charList.length && charList[charList.length - 1].inCharClass) {
62
- charList[charList.length - 1].endsCharClass = true;
63
- }
64
- return Object.assign(state, { inCharClass: false, startingCharClass: false });
65
- }
66
- }
67
- charList.push({
68
- text: char,
69
- index,
70
- escaped: state.escapeNextChar,
71
- inCharClass: state.inCharClass,
72
- startsCharClass: state.startingCharClass,
73
- endsCharClass: false
74
- });
75
- return Object.assign(state, { escapeNextChar: false, startingCharClass: false });
76
- }, { escapeNextChar: false, inCharClass: false, startingCharClass: false });
77
-
78
- return charList;
79
- }
42
+ /*
43
+ * A single character set of ClassSetReservedDoublePunctuator.
44
+ * && !! ## $$ %% ** ++ ,, .. :: ;; << == >> ?? @@ ^^ `` ~~ are ClassSetReservedDoublePunctuator
45
+ */
46
+ const REGEX_CLASS_SET_RESERVED_DOUBLE_PUNCTUATOR = new Set("!#$%&*+,.:;<=>?@^`~");
80
47
 
81
48
  /** @type {import('../shared/types').Rule} */
82
49
  module.exports = {
@@ -86,7 +53,7 @@ module.exports = {
86
53
  docs: {
87
54
  description: "Disallow unnecessary escape characters",
88
55
  recommended: true,
89
- url: "https://eslint.org/docs/rules/no-useless-escape"
56
+ url: "https://eslint.org/docs/latest/rules/no-useless-escape"
90
57
  },
91
58
 
92
59
  hasSuggestions: true,
@@ -94,6 +61,7 @@ module.exports = {
94
61
  messages: {
95
62
  unnecessaryEscape: "Unnecessary escape character: \\{{character}}.",
96
63
  removeEscape: "Remove the `\\`. This maintains the current functionality.",
64
+ removeEscapeDoNotKeepSemantics: "Remove the `\\` if it was inserted by mistake.",
97
65
  escapeBackslash: "Replace the `\\` with `\\\\` to include the actual backslash character."
98
66
  },
99
67
 
@@ -101,16 +69,18 @@ module.exports = {
101
69
  },
102
70
 
103
71
  create(context) {
104
- const sourceCode = context.getSourceCode();
72
+ const sourceCode = context.sourceCode;
73
+ const parser = new RegExpParser();
105
74
 
106
75
  /**
107
76
  * Reports a node
108
77
  * @param {ASTNode} node The node to report
109
78
  * @param {number} startOffset The backslash's offset from the start of the node
110
79
  * @param {string} character The uselessly escaped character (not including the backslash)
80
+ * @param {boolean} [disableEscapeBackslashSuggest] `true` if escapeBackslash suggestion should be turned off.
111
81
  * @returns {void}
112
82
  */
113
- function report(node, startOffset, character) {
83
+ function report(node, startOffset, character, disableEscapeBackslashSuggest) {
114
84
  const rangeStart = node.range[0] + startOffset;
115
85
  const range = [rangeStart, rangeStart + 1];
116
86
  const start = sourceCode.getLocFromIndex(rangeStart);
@@ -125,17 +95,24 @@ module.exports = {
125
95
  data: { character },
126
96
  suggest: [
127
97
  {
128
- messageId: "removeEscape",
98
+
99
+ // Removing unnecessary `\` characters in a directive is not guaranteed to maintain functionality.
100
+ messageId: astUtils.isDirective(node.parent)
101
+ ? "removeEscapeDoNotKeepSemantics" : "removeEscape",
129
102
  fix(fixer) {
130
103
  return fixer.removeRange(range);
131
104
  }
132
105
  },
133
- {
134
- messageId: "escapeBackslash",
135
- fix(fixer) {
136
- return fixer.insertTextBeforeRange(range, "\\");
137
- }
138
- }
106
+ ...disableEscapeBackslashSuggest
107
+ ? []
108
+ : [
109
+ {
110
+ messageId: "escapeBackslash",
111
+ fix(fixer) {
112
+ return fixer.insertTextBeforeRange(range, "\\");
113
+ }
114
+ }
115
+ ]
139
116
  ]
140
117
  });
141
118
  }
@@ -178,6 +155,133 @@ module.exports = {
178
155
  }
179
156
  }
180
157
 
158
+ /**
159
+ * Checks if the escape character in given regexp is unnecessary.
160
+ * @private
161
+ * @param {ASTNode} node node to validate.
162
+ * @returns {void}
163
+ */
164
+ function validateRegExp(node) {
165
+ const { pattern, flags } = node.regex;
166
+ let patternNode;
167
+ const unicode = flags.includes("u");
168
+ const unicodeSets = flags.includes("v");
169
+
170
+ try {
171
+ patternNode = parser.parsePattern(pattern, 0, pattern.length, { unicode, unicodeSets });
172
+ } catch {
173
+
174
+ // Ignore regular expressions with syntax errors
175
+ return;
176
+ }
177
+
178
+ /** @type {(CharacterClass | ExpressionCharacterClass)[]} */
179
+ const characterClassStack = [];
180
+
181
+ visitRegExpAST(patternNode, {
182
+ onCharacterClassEnter: characterClassNode => characterClassStack.unshift(characterClassNode),
183
+ onCharacterClassLeave: () => characterClassStack.shift(),
184
+ onExpressionCharacterClassEnter: characterClassNode => characterClassStack.unshift(characterClassNode),
185
+ onExpressionCharacterClassLeave: () => characterClassStack.shift(),
186
+ onCharacterEnter(characterNode) {
187
+ if (!characterNode.raw.startsWith("\\")) {
188
+
189
+ // It's not an escaped character.
190
+ return;
191
+ }
192
+
193
+ const escapedChar = characterNode.raw.slice(1);
194
+
195
+ if (escapedChar !== String.fromCodePoint(characterNode.value)) {
196
+
197
+ // It's a valid escape.
198
+ return;
199
+ }
200
+ let allowedEscapes;
201
+
202
+ if (characterClassStack.length) {
203
+ allowedEscapes = unicodeSets ? REGEX_CLASSSET_CHARACTER_ESCAPES : REGEX_GENERAL_ESCAPES;
204
+ } else {
205
+ allowedEscapes = REGEX_NON_CHARCLASS_ESCAPES;
206
+ }
207
+ if (allowedEscapes.has(escapedChar)) {
208
+ return;
209
+ }
210
+
211
+ const reportedIndex = characterNode.start + 1;
212
+ let disableEscapeBackslashSuggest = false;
213
+
214
+ if (characterClassStack.length) {
215
+ const characterClassNode = characterClassStack[0];
216
+
217
+ if (escapedChar === "^") {
218
+
219
+ /*
220
+ * The '^' character is also a special case; it must always be escaped outside of character classes, but
221
+ * it only needs to be escaped in character classes if it's at the beginning of the character class. To
222
+ * account for this, consider it to be a valid escape character outside of character classes, and filter
223
+ * out '^' characters that appear at the start of a character class.
224
+ */
225
+ if (characterClassNode.start + 1 === characterNode.start) {
226
+
227
+ return;
228
+ }
229
+ }
230
+ if (!unicodeSets) {
231
+ if (escapedChar === "-") {
232
+
233
+ /*
234
+ * The '-' character is a special case, because it's only valid to escape it if it's in a character
235
+ * class, and is not at either edge of the character class. To account for this, don't consider '-'
236
+ * characters to be valid in general, and filter out '-' characters that appear in the middle of a
237
+ * character class.
238
+ */
239
+ if (characterClassNode.start + 1 !== characterNode.start && characterNode.end !== characterClassNode.end - 1) {
240
+
241
+ return;
242
+ }
243
+ }
244
+ } else { // unicodeSets mode
245
+ if (REGEX_CLASS_SET_RESERVED_DOUBLE_PUNCTUATOR.has(escapedChar)) {
246
+
247
+ // Escaping is valid if it is a ClassSetReservedDoublePunctuator.
248
+ if (pattern[characterNode.end] === escapedChar) {
249
+ return;
250
+ }
251
+ if (pattern[characterNode.start - 1] === escapedChar) {
252
+ if (escapedChar !== "^") {
253
+ return;
254
+ }
255
+
256
+ // If the previous character is a `negate` caret(`^`), escape to caret is unnecessary.
257
+
258
+ if (!characterClassNode.negate) {
259
+ return;
260
+ }
261
+ const negateCaretIndex = characterClassNode.start + 1;
262
+
263
+ if (negateCaretIndex < characterNode.start - 1) {
264
+ return;
265
+ }
266
+ }
267
+ }
268
+
269
+ if (characterNode.parent.type === "ClassIntersection" || characterNode.parent.type === "ClassSubtraction") {
270
+ disableEscapeBackslashSuggest = true;
271
+ }
272
+ }
273
+ }
274
+
275
+ report(
276
+ node,
277
+ reportedIndex,
278
+ escapedChar,
279
+ disableEscapeBackslashSuggest
280
+ );
281
+ }
282
+ });
283
+ }
284
+
181
285
  /**
182
286
  * Checks if a node has an escape.
183
287
  * @param {ASTNode} node node to check.
@@ -216,32 +320,7 @@ module.exports = {
216
320
  validateString(node, match);
217
321
  }
218
322
  } else if (node.regex) {
219
- parseRegExp(node.regex.pattern)
220
-
221
- /*
222
- * The '-' character is a special case, because it's only valid to escape it if it's in a character
223
- * class, and is not at either edge of the character class. To account for this, don't consider '-'
224
- * characters to be valid in general, and filter out '-' characters that appear in the middle of a
225
- * character class.
226
- */
227
- .filter(charInfo => !(charInfo.text === "-" && charInfo.inCharClass && !charInfo.startsCharClass && !charInfo.endsCharClass))
228
-
229
- /*
230
- * The '^' character is also a special case; it must always be escaped outside of character classes, but
231
- * it only needs to be escaped in character classes if it's at the beginning of the character class. To
232
- * account for this, consider it to be a valid escape character outside of character classes, and filter
233
- * out '^' characters that appear at the start of a character class.
234
- */
235
- .filter(charInfo => !(charInfo.text === "^" && charInfo.startsCharClass))
236
-
237
- // Filter out characters that aren't escaped.
238
- .filter(charInfo => charInfo.escaped)
239
-
240
- // Filter out characters that are valid to escape, based on their position in the regular expression.
241
- .filter(charInfo => !(charInfo.inCharClass ? REGEX_GENERAL_ESCAPES : REGEX_NON_CHARCLASS_ESCAPES).has(charInfo.text))
242
-
243
- // Report all the remaining characters.
244
- .forEach(charInfo => report(node, charInfo.index, charInfo.text));
323
+ validateRegExp(node);
245
324
  }
246
325
 
247
326
  }
@@ -23,7 +23,7 @@ module.exports = {
23
23
  docs: {
24
24
  description: "Disallow renaming import, export, and destructured assignments to the same name",
25
25
  recommended: false,
26
- url: "https://eslint.org/docs/rules/no-useless-rename"
26
+ url: "https://eslint.org/docs/latest/rules/no-useless-rename"
27
27
  },
28
28
 
29
29
  fixable: "code",
@@ -46,7 +46,7 @@ module.exports = {
46
46
  },
47
47
 
48
48
  create(context) {
49
- const sourceCode = context.getSourceCode(),
49
+ const sourceCode = context.sourceCode,
50
50
  options = context.options[0] || {},
51
51
  ignoreDestructuring = options.ignoreDestructuring === true,
52
52
  ignoreImport = options.ignoreImport === true,
@@ -69,7 +69,7 @@ module.exports = {
69
69
  docs: {
70
70
  description: "Disallow redundant return statements",
71
71
  recommended: false,
72
- url: "https://eslint.org/docs/rules/no-useless-return"
72
+ url: "https://eslint.org/docs/latest/rules/no-useless-return"
73
73
  },
74
74
 
75
75
  fixable: "code",
@@ -82,8 +82,7 @@ module.exports = {
82
82
 
83
83
  create(context) {
84
84
  const segmentInfoMap = new WeakMap();
85
- const usedUnreachableSegments = new WeakSet();
86
- const sourceCode = context.getSourceCode();
85
+ const sourceCode = context.sourceCode;
87
86
  let scopeInfo = null;
88
87
 
89
88
  /**
@@ -152,24 +151,44 @@ module.exports = {
152
151
  * This behavior would simulate code paths for the case that the return
153
152
  * statement does not exist.
154
153
  * @param {CodePathSegment} segment The segment to get return statements.
154
+ * @param {Set<CodePathSegment>} usedUnreachableSegments A set of segments that have already been traversed in this call.
155
155
  * @returns {void}
156
156
  */
157
- function markReturnStatementsOnSegmentAsUsed(segment) {
157
+ function markReturnStatementsOnSegmentAsUsed(segment, usedUnreachableSegments) {
158
158
  if (!segment.reachable) {
159
159
  usedUnreachableSegments.add(segment);
160
160
  segment.allPrevSegments
161
161
  .filter(isReturned)
162
162
  .filter(prevSegment => !usedUnreachableSegments.has(prevSegment))
163
- .forEach(markReturnStatementsOnSegmentAsUsed);
163
+ .forEach(prevSegment => markReturnStatementsOnSegmentAsUsed(prevSegment, usedUnreachableSegments));
164
164
  return;
165
165
  }
166
166
 
167
167
  const info = segmentInfoMap.get(segment);
168
168
 
169
- for (const node of info.uselessReturns) {
169
+ info.uselessReturns = info.uselessReturns.filter(node => {
170
+ if (scopeInfo.traversedTryBlockStatements && scopeInfo.traversedTryBlockStatements.length > 0) {
171
+ const returnInitialRange = node.range[0];
172
+ const returnFinalRange = node.range[1];
173
+
174
+ const areBlocksInRange = scopeInfo.traversedTryBlockStatements.some(tryBlockStatement => {
175
+ const blockInitialRange = tryBlockStatement.range[0];
176
+ const blockFinalRange = tryBlockStatement.range[1];
177
+
178
+ return (
179
+ returnInitialRange >= blockInitialRange &&
180
+ returnFinalRange <= blockFinalRange
181
+ );
182
+ });
183
+
184
+ if (areBlocksInRange) {
185
+ return true;
186
+ }
187
+ }
188
+
170
189
  remove(scopeInfo.uselessReturns, node);
171
- }
172
- info.uselessReturns = [];
190
+ return false;
191
+ });
173
192
  }
174
193
 
175
194
  /**
@@ -188,7 +207,7 @@ module.exports = {
188
207
  scopeInfo
189
208
  .codePath
190
209
  .currentSegments
191
- .forEach(markReturnStatementsOnSegmentAsUsed);
210
+ .forEach(segment => markReturnStatementsOnSegmentAsUsed(segment, new Set()));
192
211
  }
193
212
 
194
213
  //----------------------------------------------------------------------
@@ -202,6 +221,7 @@ module.exports = {
202
221
  scopeInfo = {
203
222
  upper: scopeInfo,
204
223
  uselessReturns: [],
224
+ traversedTryBlockStatements: [],
205
225
  codePath
206
226
  };
207
227
  },
@@ -275,6 +295,14 @@ module.exports = {
275
295
  scopeInfo.uselessReturns.push(node);
276
296
  },
277
297
 
298
+ "TryStatement > BlockStatement.block:exit"(node) {
299
+ scopeInfo.traversedTryBlockStatements.push(node);
300
+ },
301
+
302
+ "TryStatement:exit"() {
303
+ scopeInfo.traversedTryBlockStatements.pop();
304
+ },
305
+
278
306
  /*
279
307
  * Registers for all statement nodes except FunctionDeclaration, BlockStatement, BreakStatement.
280
308
  * Removes return statements of the current segments from the useless return statement list.
@@ -187,7 +187,7 @@ module.exports = {
187
187
  docs: {
188
188
  description: "Require `let` or `const` instead of `var`",
189
189
  recommended: false,
190
- url: "https://eslint.org/docs/rules/no-var"
190
+ url: "https://eslint.org/docs/latest/rules/no-var"
191
191
  },
192
192
 
193
193
  schema: [],
@@ -199,7 +199,7 @@ module.exports = {
199
199
  },
200
200
 
201
201
  create(context) {
202
- const sourceCode = context.getSourceCode();
202
+ const sourceCode = context.sourceCode;
203
203
 
204
204
  /**
205
205
  * Checks whether the variables which are defined by the given declarator node have their references in TDZ.
@@ -16,7 +16,7 @@ module.exports = {
16
16
  docs: {
17
17
  description: "Disallow `void` operators",
18
18
  recommended: false,
19
- url: "https://eslint.org/docs/rules/no-void"
19
+ url: "https://eslint.org/docs/latest/rules/no-void"
20
20
  },
21
21
 
22
22
  messages: {
@@ -22,7 +22,7 @@ module.exports = {
22
22
  docs: {
23
23
  description: "Disallow specified warning terms in comments",
24
24
  recommended: false,
25
- url: "https://eslint.org/docs/rules/no-warning-comments"
25
+ url: "https://eslint.org/docs/latest/rules/no-warning-comments"
26
26
  },
27
27
 
28
28
  schema: [
@@ -58,7 +58,7 @@ module.exports = {
58
58
  },
59
59
 
60
60
  create(context) {
61
- const sourceCode = context.getSourceCode(),
61
+ const sourceCode = context.sourceCode,
62
62
  configuration = context.options[0] || {},
63
63
  warningTerms = configuration.terms || ["todo", "fixme", "xxx"],
64
64
  location = configuration.location || "start",
@@ -22,7 +22,7 @@ module.exports = {
22
22
  docs: {
23
23
  description: "Disallow whitespace before properties",
24
24
  recommended: false,
25
- url: "https://eslint.org/docs/rules/no-whitespace-before-property"
25
+ url: "https://eslint.org/docs/latest/rules/no-whitespace-before-property"
26
26
  },
27
27
 
28
28
  fixable: "whitespace",
@@ -34,7 +34,7 @@ module.exports = {
34
34
  },
35
35
 
36
36
  create(context) {
37
- const sourceCode = context.getSourceCode();
37
+ const sourceCode = context.sourceCode;
38
38
 
39
39
  //--------------------------------------------------------------------------
40
40
  // Helpers
@@ -17,7 +17,7 @@ module.exports = {
17
17
  docs: {
18
18
  description: "Disallow `with` statements",
19
19
  recommended: true,
20
- url: "https://eslint.org/docs/rules/no-with"
20
+ url: "https://eslint.org/docs/latest/rules/no-with"
21
21
  },
22
22
 
23
23
  schema: [],
@@ -18,7 +18,7 @@ module.exports = {
18
18
  docs: {
19
19
  description: "Enforce the location of single-line statements",
20
20
  recommended: false,
21
- url: "https://eslint.org/docs/rules/nonblock-statement-body-position"
21
+ url: "https://eslint.org/docs/latest/rules/nonblock-statement-body-position"
22
22
  },
23
23
 
24
24
  fixable: "whitespace",
@@ -49,7 +49,7 @@ module.exports = {
49
49
  },
50
50
 
51
51
  create(context) {
52
- const sourceCode = context.getSourceCode();
52
+ const sourceCode = context.sourceCode;
53
53
 
54
54
  //----------------------------------------------------------------------
55
55
  // Helpers
@@ -152,7 +152,7 @@ module.exports = {
152
152
  docs: {
153
153
  description: "Enforce consistent line breaks after opening and before closing braces",
154
154
  recommended: false,
155
- url: "https://eslint.org/docs/rules/object-curly-newline"
155
+ url: "https://eslint.org/docs/latest/rules/object-curly-newline"
156
156
  },
157
157
 
158
158
  fixable: "whitespace",
@@ -185,7 +185,7 @@ module.exports = {
185
185
  },
186
186
 
187
187
  create(context) {
188
- const sourceCode = context.getSourceCode();
188
+ const sourceCode = context.sourceCode;
189
189
  const normalizedOptions = normalizeOptions(context.options[0]);
190
190
 
191
191
  /**
@@ -18,7 +18,7 @@ module.exports = {
18
18
  docs: {
19
19
  description: "Enforce consistent spacing inside braces",
20
20
  recommended: false,
21
- url: "https://eslint.org/docs/rules/object-curly-spacing"
21
+ url: "https://eslint.org/docs/latest/rules/object-curly-spacing"
22
22
  },
23
23
 
24
24
  fixable: "whitespace",
@@ -51,7 +51,7 @@ module.exports = {
51
51
 
52
52
  create(context) {
53
53
  const spaced = context.options[0] === "always",
54
- sourceCode = context.getSourceCode();
54
+ sourceCode = context.sourceCode;
55
55
 
56
56
  /**
57
57
  * Determines whether an option is set, relative to the spacing option.
@@ -81,7 +81,7 @@ module.exports = {
81
81
  * @returns {void}
82
82
  */
83
83
  function reportNoBeginningSpace(node, token) {
84
- const nextToken = context.getSourceCode().getTokenAfter(token, { includeComments: true });
84
+ const nextToken = context.sourceCode.getTokenAfter(token, { includeComments: true });
85
85
 
86
86
  context.report({
87
87
  node,
@@ -103,7 +103,7 @@ module.exports = {
103
103
  * @returns {void}
104
104
  */
105
105
  function reportNoEndingSpace(node, token) {
106
- const previousToken = context.getSourceCode().getTokenBefore(token, { includeComments: true });
106
+ const previousToken = context.sourceCode.getTokenBefore(token, { includeComments: true });
107
107
 
108
108
  context.report({
109
109
  node,
@@ -17,7 +17,7 @@ module.exports = {
17
17
  docs: {
18
18
  description: "Enforce placing object properties on separate lines",
19
19
  recommended: false,
20
- url: "https://eslint.org/docs/rules/object-property-newline"
20
+ url: "https://eslint.org/docs/latest/rules/object-property-newline"
21
21
  },
22
22
 
23
23
  schema: [
@@ -53,7 +53,7 @@ module.exports = {
53
53
  ? "propertiesOnNewlineAll"
54
54
  : "propertiesOnNewline";
55
55
 
56
- const sourceCode = context.getSourceCode();
56
+ const sourceCode = context.sourceCode;
57
57
 
58
58
  return {
59
59
  ObjectExpression(node) {
@@ -30,7 +30,7 @@ module.exports = {
30
30
  docs: {
31
31
  description: "Require or disallow method and property shorthand syntax for object literals",
32
32
  recommended: false,
33
- url: "https://eslint.org/docs/rules/object-shorthand"
33
+ url: "https://eslint.org/docs/latest/rules/object-shorthand"
34
34
  },
35
35
 
36
36
  fixable: "code",
@@ -123,7 +123,7 @@ module.exports = {
123
123
  : null;
124
124
  const AVOID_QUOTES = PARAMS.avoidQuotes;
125
125
  const AVOID_EXPLICIT_RETURN_ARROWS = !!PARAMS.avoidExplicitReturnArrows;
126
- const sourceCode = context.getSourceCode();
126
+ const sourceCode = context.sourceCode;
127
127
 
128
128
  //--------------------------------------------------------------------------
129
129
  // Helpers
@@ -16,7 +16,7 @@ module.exports = {
16
16
  docs: {
17
17
  description: "Require or disallow newlines around variable declarations",
18
18
  recommended: false,
19
- url: "https://eslint.org/docs/rules/one-var-declaration-per-line"
19
+ url: "https://eslint.org/docs/latest/rules/one-var-declaration-per-line"
20
20
  },
21
21
 
22
22
  schema: [
@@ -36,7 +36,7 @@ module.exports = {
36
36
  docs: {
37
37
  description: "Enforce variables to be declared either together or separately in functions",
38
38
  recommended: false,
39
- url: "https://eslint.org/docs/rules/one-var"
39
+ url: "https://eslint.org/docs/latest/rules/one-var"
40
40
  },
41
41
 
42
42
  fixable: "code",
@@ -121,7 +121,7 @@ module.exports = {
121
121
  }
122
122
  }
123
123
 
124
- const sourceCode = context.getSourceCode();
124
+ const sourceCode = context.sourceCode;
125
125
 
126
126
  //--------------------------------------------------------------------------
127
127
  // Helpers
@@ -65,7 +65,7 @@ module.exports = {
65
65
  docs: {
66
66
  description: "Require or disallow assignment operator shorthand where possible",
67
67
  recommended: false,
68
- url: "https://eslint.org/docs/rules/operator-assignment"
68
+ url: "https://eslint.org/docs/latest/rules/operator-assignment"
69
69
  },
70
70
 
71
71
  schema: [
@@ -83,7 +83,7 @@ module.exports = {
83
83
 
84
84
  create(context) {
85
85
 
86
- const sourceCode = context.getSourceCode();
86
+ const sourceCode = context.sourceCode;
87
87
 
88
88
  /**
89
89
  * Returns the operator token of an AssignmentExpression or BinaryExpression