bahlint 28.58.6934

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 (420) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +370 -0
  3. package/bin/eslint.js +195 -0
  4. package/conf/ecma-version.js +16 -0
  5. package/conf/globals.js +169 -0
  6. package/conf/replacements.json +26 -0
  7. package/conf/rule-type-list.json +91 -0
  8. package/lib/api.js +39 -0
  9. package/lib/cli-engine/formatters/formatters-meta.json +22 -0
  10. package/lib/cli-engine/formatters/gasoline.js +168 -0
  11. package/lib/cli-engine/formatters/html.js +359 -0
  12. package/lib/cli-engine/formatters/json-with-metadata.js +16 -0
  13. package/lib/cli-engine/formatters/json.js +13 -0
  14. package/lib/cli-engine/formatters/stylish.js +153 -0
  15. package/lib/cli-engine/hash.js +35 -0
  16. package/lib/cli-engine/lint-result-cache.js +220 -0
  17. package/lib/cli.js +607 -0
  18. package/lib/config/config-loader.js +683 -0
  19. package/lib/config/config.js +674 -0
  20. package/lib/config/default-config.js +78 -0
  21. package/lib/config/flat-config-array.js +217 -0
  22. package/lib/config/flat-config-schema.js +598 -0
  23. package/lib/config-api.js +12 -0
  24. package/lib/eslint/eslint-helpers.js +1462 -0
  25. package/lib/eslint/eslint.js +1364 -0
  26. package/lib/eslint/index.js +7 -0
  27. package/lib/eslint/worker.js +173 -0
  28. package/lib/languages/js/index.js +336 -0
  29. package/lib/languages/js/source-code/index.js +7 -0
  30. package/lib/languages/js/source-code/source-code.js +1178 -0
  31. package/lib/languages/js/source-code/token-store/backward-token-comment-cursor.js +61 -0
  32. package/lib/languages/js/source-code/token-store/backward-token-cursor.js +57 -0
  33. package/lib/languages/js/source-code/token-store/cursor.js +76 -0
  34. package/lib/languages/js/source-code/token-store/cursors.js +120 -0
  35. package/lib/languages/js/source-code/token-store/decorative-cursor.js +38 -0
  36. package/lib/languages/js/source-code/token-store/filter-cursor.js +42 -0
  37. package/lib/languages/js/source-code/token-store/forward-token-comment-cursor.js +65 -0
  38. package/lib/languages/js/source-code/token-store/forward-token-cursor.js +62 -0
  39. package/lib/languages/js/source-code/token-store/index.js +695 -0
  40. package/lib/languages/js/source-code/token-store/limit-cursor.js +39 -0
  41. package/lib/languages/js/source-code/token-store/padded-token-cursor.js +45 -0
  42. package/lib/languages/js/source-code/token-store/skip-cursor.js +41 -0
  43. package/lib/languages/js/source-code/token-store/utils.js +131 -0
  44. package/lib/languages/js/validate-language-options.js +196 -0
  45. package/lib/linter/apply-disable-directives.js +583 -0
  46. package/lib/linter/code-path-analysis/code-path-analyzer.js +828 -0
  47. package/lib/linter/code-path-analysis/code-path-segment.js +262 -0
  48. package/lib/linter/code-path-analysis/code-path-state.js +2370 -0
  49. package/lib/linter/code-path-analysis/code-path.js +332 -0
  50. package/lib/linter/code-path-analysis/debug-helpers.js +223 -0
  51. package/lib/linter/code-path-analysis/fork-context.js +374 -0
  52. package/lib/linter/code-path-analysis/id-generator.js +44 -0
  53. package/lib/linter/esquery.js +332 -0
  54. package/lib/linter/file-context.js +88 -0
  55. package/lib/linter/file-report.js +604 -0
  56. package/lib/linter/index.js +11 -0
  57. package/lib/linter/interpolate.js +50 -0
  58. package/lib/linter/linter.js +1614 -0
  59. package/lib/linter/rule-fixer.js +199 -0
  60. package/lib/linter/source-code-fixer.js +154 -0
  61. package/lib/linter/source-code-traverser.js +333 -0
  62. package/lib/linter/source-code-visitor.js +81 -0
  63. package/lib/linter/timing.js +209 -0
  64. package/lib/linter/vfile.js +115 -0
  65. package/lib/options.js +416 -0
  66. package/lib/rule-tester/index.js +7 -0
  67. package/lib/rule-tester/rule-tester.js +1817 -0
  68. package/lib/rules/accessor-pairs.js +420 -0
  69. package/lib/rules/array-bracket-newline.js +291 -0
  70. package/lib/rules/array-bracket-spacing.js +301 -0
  71. package/lib/rules/array-callback-return.js +493 -0
  72. package/lib/rules/array-element-newline.js +374 -0
  73. package/lib/rules/arrow-body-style.js +418 -0
  74. package/lib/rules/arrow-parens.js +237 -0
  75. package/lib/rules/arrow-spacing.js +188 -0
  76. package/lib/rules/block-scoped-var.js +137 -0
  77. package/lib/rules/block-spacing.js +202 -0
  78. package/lib/rules/brace-style.js +278 -0
  79. package/lib/rules/callback-return.js +216 -0
  80. package/lib/rules/camelcase.js +422 -0
  81. package/lib/rules/capitalized-comments.js +325 -0
  82. package/lib/rules/class-methods-use-this.js +250 -0
  83. package/lib/rules/comma-dangle.js +424 -0
  84. package/lib/rules/comma-spacing.js +205 -0
  85. package/lib/rules/comma-style.js +391 -0
  86. package/lib/rules/complexity.js +201 -0
  87. package/lib/rules/computed-property-spacing.js +251 -0
  88. package/lib/rules/consistent-return.js +221 -0
  89. package/lib/rules/consistent-this.js +179 -0
  90. package/lib/rules/constructor-super.js +453 -0
  91. package/lib/rules/curly.js +425 -0
  92. package/lib/rules/default-case-last.js +51 -0
  93. package/lib/rules/default-case.js +103 -0
  94. package/lib/rules/default-param-last.js +78 -0
  95. package/lib/rules/dot-location.js +138 -0
  96. package/lib/rules/dot-notation.js +216 -0
  97. package/lib/rules/eol-last.js +135 -0
  98. package/lib/rules/eqeqeq.js +210 -0
  99. package/lib/rules/for-direction.js +168 -0
  100. package/lib/rules/func-call-spacing.js +281 -0
  101. package/lib/rules/func-name-matching.js +338 -0
  102. package/lib/rules/func-names.js +194 -0
  103. package/lib/rules/func-style.js +221 -0
  104. package/lib/rules/function-call-argument-newline.js +166 -0
  105. package/lib/rules/function-paren-newline.js +368 -0
  106. package/lib/rules/generator-star-spacing.js +246 -0
  107. package/lib/rules/getter-return.js +242 -0
  108. package/lib/rules/global-require.js +117 -0
  109. package/lib/rules/grouped-accessor-pairs.js +268 -0
  110. package/lib/rules/guard-for-in.js +85 -0
  111. package/lib/rules/handle-callback-err.js +122 -0
  112. package/lib/rules/id-blacklist.js +241 -0
  113. package/lib/rules/id-denylist.js +223 -0
  114. package/lib/rules/id-length.js +217 -0
  115. package/lib/rules/id-match.js +363 -0
  116. package/lib/rules/implicit-arrow-linebreak.js +125 -0
  117. package/lib/rules/indent-legacy.js +1369 -0
  118. package/lib/rules/indent.js +2334 -0
  119. package/lib/rules/index.js +332 -0
  120. package/lib/rules/init-declarations.js +172 -0
  121. package/lib/rules/jsx-quotes.js +128 -0
  122. package/lib/rules/key-spacing.js +822 -0
  123. package/lib/rules/keyword-spacing.js +701 -0
  124. package/lib/rules/line-comment-position.js +157 -0
  125. package/lib/rules/linebreak-style.js +135 -0
  126. package/lib/rules/lines-around-comment.js +581 -0
  127. package/lib/rules/lines-around-directive.js +249 -0
  128. package/lib/rules/lines-between-class-members.js +358 -0
  129. package/lib/rules/logical-assignment-operators.js +688 -0
  130. package/lib/rules/max-classes-per-file.js +90 -0
  131. package/lib/rules/max-depth.js +159 -0
  132. package/lib/rules/max-len.js +497 -0
  133. package/lib/rules/max-lines-per-function.js +238 -0
  134. package/lib/rules/max-lines.js +189 -0
  135. package/lib/rules/max-nested-callbacks.js +115 -0
  136. package/lib/rules/max-params.js +148 -0
  137. package/lib/rules/max-statements-per-line.js +224 -0
  138. package/lib/rules/max-statements.js +188 -0
  139. package/lib/rules/multiline-comment-style.js +652 -0
  140. package/lib/rules/multiline-ternary.js +257 -0
  141. package/lib/rules/new-cap.js +277 -0
  142. package/lib/rules/new-parens.js +120 -0
  143. package/lib/rules/newline-after-var.js +307 -0
  144. package/lib/rules/newline-before-return.js +242 -0
  145. package/lib/rules/newline-per-chained-call.js +159 -0
  146. package/lib/rules/no-alert.js +149 -0
  147. package/lib/rules/no-array-constructor.js +195 -0
  148. package/lib/rules/no-async-promise-executor.js +45 -0
  149. package/lib/rules/no-await-in-loop.js +115 -0
  150. package/lib/rules/no-bitwise.js +145 -0
  151. package/lib/rules/no-buffer-constructor.js +74 -0
  152. package/lib/rules/no-caller.js +52 -0
  153. package/lib/rules/no-case-declarations.js +80 -0
  154. package/lib/rules/no-catch-shadow.js +96 -0
  155. package/lib/rules/no-class-assign.js +66 -0
  156. package/lib/rules/no-compare-neg-zero.js +74 -0
  157. package/lib/rules/no-cond-assign.js +175 -0
  158. package/lib/rules/no-confusing-arrow.js +127 -0
  159. package/lib/rules/no-console.js +221 -0
  160. package/lib/rules/no-const-assign.js +73 -0
  161. package/lib/rules/no-constant-binary-expression.js +603 -0
  162. package/lib/rules/no-constant-condition.js +177 -0
  163. package/lib/rules/no-constructor-return.js +62 -0
  164. package/lib/rules/no-continue.js +38 -0
  165. package/lib/rules/no-control-regex.js +142 -0
  166. package/lib/rules/no-debugger.js +41 -0
  167. package/lib/rules/no-delete-var.js +42 -0
  168. package/lib/rules/no-div-regex.js +60 -0
  169. package/lib/rules/no-dupe-args.js +92 -0
  170. package/lib/rules/no-dupe-class-members.js +117 -0
  171. package/lib/rules/no-dupe-else-if.js +145 -0
  172. package/lib/rules/no-dupe-keys.js +165 -0
  173. package/lib/rules/no-duplicate-case.js +78 -0
  174. package/lib/rules/no-duplicate-imports.js +368 -0
  175. package/lib/rules/no-else-return.js +450 -0
  176. package/lib/rules/no-empty-character-class.js +83 -0
  177. package/lib/rules/no-empty-function.js +236 -0
  178. package/lib/rules/no-empty-pattern.js +85 -0
  179. package/lib/rules/no-empty-static-block.js +73 -0
  180. package/lib/rules/no-empty.js +153 -0
  181. package/lib/rules/no-eq-null.js +51 -0
  182. package/lib/rules/no-eval.js +295 -0
  183. package/lib/rules/no-ex-assign.js +57 -0
  184. package/lib/rules/no-extend-native.js +180 -0
  185. package/lib/rules/no-extra-bind.js +224 -0
  186. package/lib/rules/no-extra-boolean-cast.js +420 -0
  187. package/lib/rules/no-extra-label.js +169 -0
  188. package/lib/rules/no-extra-parens.js +1669 -0
  189. package/lib/rules/no-extra-semi.js +167 -0
  190. package/lib/rules/no-fallthrough.js +260 -0
  191. package/lib/rules/no-floating-decimal.js +99 -0
  192. package/lib/rules/no-func-assign.js +77 -0
  193. package/lib/rules/no-global-assign.js +101 -0
  194. package/lib/rules/no-implicit-coercion.js +468 -0
  195. package/lib/rules/no-implicit-globals.js +187 -0
  196. package/lib/rules/no-implied-eval.js +170 -0
  197. package/lib/rules/no-import-assign.js +227 -0
  198. package/lib/rules/no-inline-comments.js +115 -0
  199. package/lib/rules/no-inner-declarations.js +147 -0
  200. package/lib/rules/no-invalid-regexp.js +244 -0
  201. package/lib/rules/no-invalid-this.js +178 -0
  202. package/lib/rules/no-irregular-whitespace.js +292 -0
  203. package/lib/rules/no-iterator.js +48 -0
  204. package/lib/rules/no-label-var.js +78 -0
  205. package/lib/rules/no-labels.js +156 -0
  206. package/lib/rules/no-lone-blocks.js +140 -0
  207. package/lib/rules/no-lonely-if.js +126 -0
  208. package/lib/rules/no-loop-func.js +267 -0
  209. package/lib/rules/no-loss-of-precision.js +249 -0
  210. package/lib/rules/no-magic-numbers.js +365 -0
  211. package/lib/rules/no-misleading-character-class.js +595 -0
  212. package/lib/rules/no-mixed-operators.js +253 -0
  213. package/lib/rules/no-mixed-requires.js +267 -0
  214. package/lib/rules/no-mixed-spaces-and-tabs.js +148 -0
  215. package/lib/rules/no-multi-assign.js +66 -0
  216. package/lib/rules/no-multi-spaces.js +179 -0
  217. package/lib/rules/no-multi-str.js +67 -0
  218. package/lib/rules/no-multiple-empty-lines.js +210 -0
  219. package/lib/rules/no-native-reassign.js +114 -0
  220. package/lib/rules/no-negated-condition.js +100 -0
  221. package/lib/rules/no-negated-in-lhs.js +59 -0
  222. package/lib/rules/no-nested-ternary.js +46 -0
  223. package/lib/rules/no-new-func.js +96 -0
  224. package/lib/rules/no-new-native-nonconstructor.js +70 -0
  225. package/lib/rules/no-new-object.js +76 -0
  226. package/lib/rules/no-new-require.js +67 -0
  227. package/lib/rules/no-new-symbol.js +74 -0
  228. package/lib/rules/no-new-wrappers.js +62 -0
  229. package/lib/rules/no-new.js +42 -0
  230. package/lib/rules/no-nonoctal-decimal-escape.js +176 -0
  231. package/lib/rules/no-obj-calls.js +99 -0
  232. package/lib/rules/no-object-constructor.js +124 -0
  233. package/lib/rules/no-octal-escape.js +53 -0
  234. package/lib/rules/no-octal.js +42 -0
  235. package/lib/rules/no-param-reassign.js +248 -0
  236. package/lib/rules/no-path-concat.js +79 -0
  237. package/lib/rules/no-plusplus.js +102 -0
  238. package/lib/rules/no-process-env.js +68 -0
  239. package/lib/rules/no-process-exit.js +67 -0
  240. package/lib/rules/no-promise-executor-return.js +264 -0
  241. package/lib/rules/no-proto.js +45 -0
  242. package/lib/rules/no-prototype-builtins.js +181 -0
  243. package/lib/rules/no-redeclare.js +173 -0
  244. package/lib/rules/no-regex-spaces.js +219 -0
  245. package/lib/rules/no-restricted-exports.js +227 -0
  246. package/lib/rules/no-restricted-globals.js +266 -0
  247. package/lib/rules/no-restricted-imports.js +892 -0
  248. package/lib/rules/no-restricted-modules.js +249 -0
  249. package/lib/rules/no-restricted-properties.js +233 -0
  250. package/lib/rules/no-restricted-syntax.js +74 -0
  251. package/lib/rules/no-return-assign.js +87 -0
  252. package/lib/rules/no-return-await.js +162 -0
  253. package/lib/rules/no-script-url.js +68 -0
  254. package/lib/rules/no-self-assign.js +186 -0
  255. package/lib/rules/no-self-compare.js +77 -0
  256. package/lib/rules/no-sequences.js +158 -0
  257. package/lib/rules/no-setter-return.js +224 -0
  258. package/lib/rules/no-shadow-restricted-names.js +113 -0
  259. package/lib/rules/no-shadow.js +624 -0
  260. package/lib/rules/no-spaced-func.js +105 -0
  261. package/lib/rules/no-sparse-arrays.js +68 -0
  262. package/lib/rules/no-sync.js +81 -0
  263. package/lib/rules/no-tabs.js +110 -0
  264. package/lib/rules/no-template-curly-in-string.js +45 -0
  265. package/lib/rules/no-ternary.js +38 -0
  266. package/lib/rules/no-this-before-super.js +365 -0
  267. package/lib/rules/no-throw-literal.js +46 -0
  268. package/lib/rules/no-trailing-spaces.js +227 -0
  269. package/lib/rules/no-unassigned-vars.js +80 -0
  270. package/lib/rules/no-undef-init.js +101 -0
  271. package/lib/rules/no-undef.js +84 -0
  272. package/lib/rules/no-undefined.js +85 -0
  273. package/lib/rules/no-underscore-dangle.js +383 -0
  274. package/lib/rules/no-unexpected-multiline.js +130 -0
  275. package/lib/rules/no-unmodified-loop-condition.js +360 -0
  276. package/lib/rules/no-unneeded-ternary.js +232 -0
  277. package/lib/rules/no-unreachable-loop.js +190 -0
  278. package/lib/rules/no-unreachable.js +300 -0
  279. package/lib/rules/no-unsafe-finally.js +119 -0
  280. package/lib/rules/no-unsafe-negation.js +152 -0
  281. package/lib/rules/no-unsafe-optional-chaining.js +221 -0
  282. package/lib/rules/no-unused-expressions.js +227 -0
  283. package/lib/rules/no-unused-labels.js +158 -0
  284. package/lib/rules/no-unused-private-class-members.js +219 -0
  285. package/lib/rules/no-unused-vars.js +1739 -0
  286. package/lib/rules/no-use-before-define.js +446 -0
  287. package/lib/rules/no-useless-assignment.js +657 -0
  288. package/lib/rules/no-useless-backreference.js +263 -0
  289. package/lib/rules/no-useless-call.js +95 -0
  290. package/lib/rules/no-useless-catch.js +57 -0
  291. package/lib/rules/no-useless-computed-key.js +204 -0
  292. package/lib/rules/no-useless-concat.js +121 -0
  293. package/lib/rules/no-useless-constructor.js +262 -0
  294. package/lib/rules/no-useless-escape.js +406 -0
  295. package/lib/rules/no-useless-rename.js +202 -0
  296. package/lib/rules/no-useless-return.js +401 -0
  297. package/lib/rules/no-var.js +367 -0
  298. package/lib/rules/no-void.js +69 -0
  299. package/lib/rules/no-warning-comments.js +209 -0
  300. package/lib/rules/no-whitespace-before-property.js +150 -0
  301. package/lib/rules/no-with.js +37 -0
  302. package/lib/rules/nonblock-statement-body-position.js +164 -0
  303. package/lib/rules/object-curly-newline.js +383 -0
  304. package/lib/rules/object-curly-spacing.js +369 -0
  305. package/lib/rules/object-property-newline.js +151 -0
  306. package/lib/rules/object-shorthand.js +652 -0
  307. package/lib/rules/one-var-declaration-per-line.js +117 -0
  308. package/lib/rules/one-var.js +717 -0
  309. package/lib/rules/operator-assignment.js +270 -0
  310. package/lib/rules/operator-linebreak.js +315 -0
  311. package/lib/rules/padded-blocks.js +366 -0
  312. package/lib/rules/padding-line-between-statements.js +612 -0
  313. package/lib/rules/prefer-arrow-callback.js +437 -0
  314. package/lib/rules/prefer-const.js +546 -0
  315. package/lib/rules/prefer-destructuring.js +332 -0
  316. package/lib/rules/prefer-exponentiation-operator.js +235 -0
  317. package/lib/rules/prefer-named-capture-group.js +197 -0
  318. package/lib/rules/prefer-numeric-literals.js +157 -0
  319. package/lib/rules/prefer-object-has-own.js +148 -0
  320. package/lib/rules/prefer-object-spread.js +319 -0
  321. package/lib/rules/prefer-promise-reject-errors.js +154 -0
  322. package/lib/rules/prefer-reflect.js +150 -0
  323. package/lib/rules/prefer-regex-literals.js +605 -0
  324. package/lib/rules/prefer-rest-params.js +117 -0
  325. package/lib/rules/prefer-spread.js +91 -0
  326. package/lib/rules/prefer-template.js +347 -0
  327. package/lib/rules/preserve-caught-error.js +535 -0
  328. package/lib/rules/quote-props.js +394 -0
  329. package/lib/rules/quotes.js +416 -0
  330. package/lib/rules/radix.js +193 -0
  331. package/lib/rules/require-atomic-updates.js +365 -0
  332. package/lib/rules/require-await.js +184 -0
  333. package/lib/rules/require-unicode-regexp.js +317 -0
  334. package/lib/rules/require-yield.js +86 -0
  335. package/lib/rules/rest-spread-spacing.js +150 -0
  336. package/lib/rules/semi-spacing.js +297 -0
  337. package/lib/rules/semi-style.js +218 -0
  338. package/lib/rules/semi.js +476 -0
  339. package/lib/rules/sort-imports.js +319 -0
  340. package/lib/rules/sort-keys.js +268 -0
  341. package/lib/rules/sort-vars.js +140 -0
  342. package/lib/rules/space-before-blocks.js +232 -0
  343. package/lib/rules/space-before-function-paren.js +202 -0
  344. package/lib/rules/space-in-parens.js +374 -0
  345. package/lib/rules/space-infix-ops.js +249 -0
  346. package/lib/rules/space-unary-ops.js +400 -0
  347. package/lib/rules/spaced-comment.js +447 -0
  348. package/lib/rules/strict.js +314 -0
  349. package/lib/rules/switch-colon-spacing.js +158 -0
  350. package/lib/rules/symbol-description.js +70 -0
  351. package/lib/rules/template-curly-spacing.js +168 -0
  352. package/lib/rules/template-tag-spacing.js +121 -0
  353. package/lib/rules/unicode-bom.js +73 -0
  354. package/lib/rules/use-isnan.js +268 -0
  355. package/lib/rules/utils/ast-utils.js +2828 -0
  356. package/lib/rules/utils/char-source.js +247 -0
  357. package/lib/rules/utils/fix-tracker.js +125 -0
  358. package/lib/rules/utils/keywords.js +67 -0
  359. package/lib/rules/utils/lazy-loading-rule-map.js +118 -0
  360. package/lib/rules/utils/regular-expressions.js +58 -0
  361. package/lib/rules/utils/unicode/index.js +16 -0
  362. package/lib/rules/utils/unicode/is-combining-character.js +13 -0
  363. package/lib/rules/utils/unicode/is-emoji-modifier.js +13 -0
  364. package/lib/rules/utils/unicode/is-regional-indicator-symbol.js +13 -0
  365. package/lib/rules/utils/unicode/is-surrogate-pair.js +14 -0
  366. package/lib/rules/valid-typeof.js +171 -0
  367. package/lib/rules/vars-on-top.js +165 -0
  368. package/lib/rules/wrap-iife.js +238 -0
  369. package/lib/rules/wrap-regex.js +91 -0
  370. package/lib/rules/yield-star-spacing.js +158 -0
  371. package/lib/rules/yoda.js +362 -0
  372. package/lib/services/parser-service.js +64 -0
  373. package/lib/services/processor-service.js +100 -0
  374. package/lib/services/suppressions-service.js +302 -0
  375. package/lib/services/warning-service.js +87 -0
  376. package/lib/shared/ajv.js +34 -0
  377. package/lib/shared/assert.js +21 -0
  378. package/lib/shared/ast-utils.js +30 -0
  379. package/lib/shared/deep-merge-arrays.js +62 -0
  380. package/lib/shared/directives.js +16 -0
  381. package/lib/shared/flags.js +89 -0
  382. package/lib/shared/logging.js +38 -0
  383. package/lib/shared/naming.js +109 -0
  384. package/lib/shared/option-utils.js +63 -0
  385. package/lib/shared/relative-module-resolver.js +28 -0
  386. package/lib/shared/runtime-info.js +177 -0
  387. package/lib/shared/serialization.js +78 -0
  388. package/lib/shared/severity.js +49 -0
  389. package/lib/shared/stats.js +30 -0
  390. package/lib/shared/string-utils.js +58 -0
  391. package/lib/shared/text-table.js +68 -0
  392. package/lib/shared/translate-cli-options.js +223 -0
  393. package/lib/shared/traverser.js +202 -0
  394. package/lib/types/config-api.d.ts +12 -0
  395. package/lib/types/index.d.ts +1482 -0
  396. package/lib/types/rules.d.ts +5603 -0
  397. package/lib/types/universal.d.ts +6 -0
  398. package/lib/types/use-at-your-own-risk.d.ts +34 -0
  399. package/lib/universal.js +10 -0
  400. package/lib/unsupported-api.js +26 -0
  401. package/messages/all-files-ignored.js +16 -0
  402. package/messages/all-matched-files-ignored.js +21 -0
  403. package/messages/config-file-missing.js +16 -0
  404. package/messages/config-plugin-missing.js +14 -0
  405. package/messages/config-serialize-function.js +30 -0
  406. package/messages/eslintrc-incompat.js +117 -0
  407. package/messages/eslintrc-plugins.js +27 -0
  408. package/messages/extend-config-missing.js +13 -0
  409. package/messages/failed-to-read-json.js +11 -0
  410. package/messages/file-not-found.js +10 -0
  411. package/messages/invalid-rule-options.js +17 -0
  412. package/messages/invalid-rule-severity.js +13 -0
  413. package/messages/no-config-found.js +15 -0
  414. package/messages/plugin-conflict.js +22 -0
  415. package/messages/plugin-invalid.js +16 -0
  416. package/messages/plugin-missing.js +19 -0
  417. package/messages/print-config-with-directory-path.js +8 -0
  418. package/messages/shared.js +23 -0
  419. package/messages/whitespace-found.js +11 -0
  420. package/package.json +220 -0
@@ -0,0 +1,1462 @@
1
+ /**
2
+ * @fileoverview Helper functions for ESLint class
3
+ * @author Nicholas C. Zakas
4
+ */
5
+
6
+ "use strict";
7
+
8
+ //-----------------------------------------------------------------------------
9
+ // Requirements
10
+ //-----------------------------------------------------------------------------
11
+
12
+ const path = require("node:path");
13
+ const fs = require("node:fs");
14
+ const { isMainThread, threadId } = require("node:worker_threads");
15
+ const fsp = fs.promises;
16
+ const isGlob = require("is-glob");
17
+ const hash = require("../cli-engine/hash");
18
+ const minimatch = require("minimatch");
19
+ const globParent = require("glob-parent");
20
+ const { Linter } = require("../linter");
21
+ const { getShorthandName } = require("../shared/naming");
22
+ const LintResultCache = require("../cli-engine/lint-result-cache");
23
+ const { ConfigLoader } = require("../config/config-loader");
24
+ const createDebug = require("debug");
25
+
26
+ //-----------------------------------------------------------------------------
27
+ // Fixup references
28
+ //-----------------------------------------------------------------------------
29
+
30
+ const Minimatch = minimatch.Minimatch;
31
+ const MINIMATCH_OPTIONS = { dot: true };
32
+ const hrtimeBigint = process.hrtime.bigint;
33
+
34
+ //-----------------------------------------------------------------------------
35
+ // Types
36
+ //-----------------------------------------------------------------------------
37
+
38
+ /**
39
+ * @import { ESLintOptions } from "./eslint.js";
40
+ * @import { Config as CalculatedConfig } from "../config/config.js";
41
+ * @import { FlatConfigArray } from "../config/flat-config-array.js";
42
+ * @import { WarningService } from "../services/warning-service.js";
43
+ * @import { Retrier } from "@humanwhocodes/retry";
44
+ */
45
+
46
+ /** @typedef {import("../types").Linter.Config} Config */
47
+ /** @typedef {import("../types").Linter.LintMessage} LintMessage */
48
+ /** @typedef {import("../types").ESLint.LintResult} LintResult */
49
+ /** @typedef {import("../types").ESLint.Plugin} Plugin */
50
+
51
+ /**
52
+ * @typedef {Object} GlobSearch
53
+ * @property {Array<string>} patterns The normalized patterns to use for a search.
54
+ * @property {Array<string>} rawPatterns The patterns as entered by the user
55
+ * before doing any normalization.
56
+ */
57
+
58
+ //------------------------------------------------------------------------------
59
+ // Debug Helpers
60
+ //------------------------------------------------------------------------------
61
+
62
+ // Add %t formatter to print bigint nanosecond times in milliseconds.
63
+ createDebug.formatters.t = timeDiff =>
64
+ `${(timeDiff + 500_000n) / 1_000_000n} ms`;
65
+
66
+ const debug = createDebug(
67
+ `eslint:eslint-helpers${isMainThread ? "" : `:thread-${threadId}`}`,
68
+ );
69
+
70
+ //-----------------------------------------------------------------------------
71
+ // Errors
72
+ //-----------------------------------------------------------------------------
73
+
74
+ /**
75
+ * The error type when no files match a glob.
76
+ */
77
+ class NoFilesFoundError extends Error {
78
+ /**
79
+ * @param {string} pattern The glob pattern which was not found.
80
+ * @param {boolean} globEnabled If `false` then the pattern was a glob pattern, but glob was disabled.
81
+ */
82
+ constructor(pattern, globEnabled) {
83
+ super(
84
+ `No files matching '${pattern}' were found${!globEnabled ? " (glob was disabled)" : ""}.`,
85
+ );
86
+ this.messageTemplate = "file-not-found";
87
+ this.messageData = { pattern, globDisabled: !globEnabled };
88
+ }
89
+ }
90
+
91
+ /**
92
+ * The error type when a search fails to match multiple patterns.
93
+ */
94
+ class UnmatchedSearchPatternsError extends Error {
95
+ /**
96
+ * @param {Object} options The options for the error.
97
+ * @param {string} options.basePath The directory that was searched.
98
+ * @param {Array<string>} options.unmatchedPatterns The glob patterns
99
+ * which were not found.
100
+ * @param {Array<string>} options.patterns The glob patterns that were
101
+ * searched.
102
+ * @param {Array<string>} options.rawPatterns The raw glob patterns that
103
+ * were searched.
104
+ */
105
+ constructor({ basePath, unmatchedPatterns, patterns, rawPatterns }) {
106
+ super(
107
+ `No files matching '${rawPatterns}' in '${basePath}' were found.`,
108
+ );
109
+ this.basePath = basePath;
110
+ this.unmatchedPatterns = unmatchedPatterns;
111
+ this.patterns = patterns;
112
+ this.rawPatterns = rawPatterns;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * The error type when there are files matched by a glob, but all of them have been ignored.
118
+ */
119
+ class AllFilesIgnoredError extends Error {
120
+ /**
121
+ * @param {string} pattern The glob pattern which was not found.
122
+ */
123
+ constructor(pattern) {
124
+ super(`All files matched by '${pattern}' are ignored.`);
125
+ this.messageTemplate = "all-matched-files-ignored";
126
+ this.messageData = { pattern };
127
+ }
128
+ }
129
+
130
+ //-----------------------------------------------------------------------------
131
+ // General Helpers
132
+ //-----------------------------------------------------------------------------
133
+
134
+ /**
135
+ * Check if a given value is a non-empty string or not.
136
+ * @param {any} value The value to check.
137
+ * @returns {boolean} `true` if `value` is a non-empty string.
138
+ */
139
+ function isNonEmptyString(value) {
140
+ return typeof value === "string" && value.trim() !== "";
141
+ }
142
+
143
+ /**
144
+ * Check if a given value is an array of non-empty strings or not.
145
+ * @param {any} value The value to check.
146
+ * @returns {boolean} `true` if `value` is an array of non-empty strings.
147
+ */
148
+ function isArrayOfNonEmptyString(value) {
149
+ return (
150
+ Array.isArray(value) && !!value.length && value.every(isNonEmptyString)
151
+ );
152
+ }
153
+
154
+ /**
155
+ * Check if a given value is an empty array or an array of non-empty strings.
156
+ * @param {any} value The value to check.
157
+ * @returns {boolean} `true` if `value` is an empty array or an array of non-empty
158
+ * strings.
159
+ */
160
+ function isEmptyArrayOrArrayOfNonEmptyString(value) {
161
+ return Array.isArray(value) && value.every(isNonEmptyString);
162
+ }
163
+
164
+ /**
165
+ * Check if a given value is a positive integer.
166
+ * @param {unknown} value The value to check.
167
+ * @returns {boolean} `true` if `value` is a positive integer.
168
+ */
169
+ function isPositiveInteger(value) {
170
+ return Number.isInteger(value) && value > 0;
171
+ }
172
+
173
+ //-----------------------------------------------------------------------------
174
+ // File-related Helpers
175
+ //-----------------------------------------------------------------------------
176
+
177
+ /**
178
+ * Normalizes slashes in a file pattern to posix-style.
179
+ * @param {string} pattern The pattern to replace slashes in.
180
+ * @returns {string} The pattern with slashes normalized.
181
+ */
182
+ function normalizeToPosix(pattern) {
183
+ return pattern.replace(/\\/gu, "/");
184
+ }
185
+
186
+ /**
187
+ * Check if a string is a glob pattern or not.
188
+ * @param {string} pattern A glob pattern.
189
+ * @returns {boolean} `true` if the string is a glob pattern.
190
+ */
191
+ function isGlobPattern(pattern) {
192
+ return isGlob(path.sep === "\\" ? normalizeToPosix(pattern) : pattern);
193
+ }
194
+
195
+ /**
196
+ * Determines if a given glob pattern will return any results.
197
+ * Used primarily to help with useful error messages.
198
+ * @param {Object} options The options for the function.
199
+ * @param {string} options.basePath The directory to search.
200
+ * @param {string} options.pattern An absolute path glob pattern to match.
201
+ * @returns {Promise<boolean>} True if there is a glob match, false if not.
202
+ */
203
+ async function globMatch({ basePath, pattern }) {
204
+ let found = false;
205
+ const { hfs } = await import("@humanfs/node");
206
+ const patternToUse = normalizeToPosix(path.relative(basePath, pattern));
207
+
208
+ const matcher = new Minimatch(patternToUse, MINIMATCH_OPTIONS);
209
+
210
+ const walkSettings = {
211
+ directoryFilter(entry) {
212
+ return !found && matcher.match(entry.path, true);
213
+ },
214
+
215
+ entryFilter(entry) {
216
+ if (found || entry.isDirectory) {
217
+ return false;
218
+ }
219
+
220
+ if (matcher.match(entry.path)) {
221
+ found = true;
222
+ return true;
223
+ }
224
+
225
+ return false;
226
+ },
227
+ };
228
+
229
+ if (await hfs.isDirectory(basePath)) {
230
+ return hfs
231
+ .walk(basePath, walkSettings)
232
+ .next()
233
+ .then(() => found);
234
+ }
235
+
236
+ return found;
237
+ }
238
+
239
+ /**
240
+ * Searches a directory looking for matching glob patterns. This uses
241
+ * the config array's logic to determine if a directory or file should
242
+ * be ignored, so it is consistent with how ignoring works throughout
243
+ * ESLint.
244
+ * @param {Object} options The options for this function.
245
+ * @param {string} options.basePath The directory to search.
246
+ * @param {Array<string>} options.patterns An array of absolute path glob patterns
247
+ * to match.
248
+ * @param {Array<string>} options.rawPatterns An array of glob patterns
249
+ * as the user inputted them. Used for errors.
250
+ * @param {ConfigLoader} options.configLoader The config array to use for
251
+ * determining what to ignore.
252
+ * @param {boolean} options.errorOnUnmatchedPattern Determines if an error
253
+ * should be thrown when a pattern is unmatched.
254
+ * @returns {Promise<Array<string>>} An array of matching file paths
255
+ * or an empty array if there are no matches.
256
+ * @throws {UnmatchedSearchPatternsError} If there is a pattern that doesn't
257
+ * match any files.
258
+ */
259
+ async function globSearch({
260
+ basePath,
261
+ patterns,
262
+ rawPatterns,
263
+ configLoader,
264
+ errorOnUnmatchedPattern,
265
+ }) {
266
+ if (patterns.length === 0) {
267
+ return [];
268
+ }
269
+
270
+ /*
271
+ * In this section we are converting the patterns into Minimatch
272
+ * instances for performance reasons. Because we are doing the same
273
+ * matches repeatedly, it's best to compile those patterns once and
274
+ * reuse them multiple times.
275
+ *
276
+ * To do that, we convert any patterns with an absolute path into a
277
+ * relative path and normalize it to Posix-style slashes. We also keep
278
+ * track of the relative patterns to map them back to the original
279
+ * patterns, which we need in order to throw an error if there are any
280
+ * unmatched patterns.
281
+ */
282
+ const relativeToPatterns = new Map();
283
+ const matchers = patterns.map((pattern, i) => {
284
+ const patternToUse = normalizeToPosix(path.relative(basePath, pattern));
285
+
286
+ relativeToPatterns.set(patternToUse, patterns[i]);
287
+
288
+ return new Minimatch(patternToUse, MINIMATCH_OPTIONS);
289
+ });
290
+
291
+ /*
292
+ * We track unmatched patterns because we may want to throw an error when
293
+ * they occur. To start, this set is initialized with all of the patterns.
294
+ * Every time a match occurs, the pattern is removed from the set, making
295
+ * it easy to tell if we have any unmatched patterns left at the end of
296
+ * search.
297
+ */
298
+ const unmatchedPatterns = new Set([...relativeToPatterns.keys()]);
299
+ const { hfs } = await import("@humanfs/node");
300
+
301
+ const walk = hfs.walk(basePath, {
302
+ async directoryFilter(entry) {
303
+ if (!matchers.some(matcher => matcher.match(entry.path, true))) {
304
+ return false;
305
+ }
306
+
307
+ const absolutePath = path.resolve(basePath, entry.path);
308
+ const configs =
309
+ await configLoader.loadConfigArrayForDirectory(absolutePath);
310
+
311
+ return !configs.isDirectoryIgnored(absolutePath);
312
+ },
313
+ async entryFilter(entry) {
314
+ const absolutePath = path.resolve(basePath, entry.path);
315
+
316
+ // entries may be directories or files so filter out directories
317
+ if (entry.isDirectory) {
318
+ return false;
319
+ }
320
+
321
+ const configs =
322
+ await configLoader.loadConfigArrayForFile(absolutePath);
323
+ const config = configs.getConfig(absolutePath);
324
+
325
+ /*
326
+ * Optimization: We need to track when patterns are left unmatched
327
+ * and so we use `unmatchedPatterns` to do that. There is a bit of
328
+ * complexity here because the same file can be matched by more than
329
+ * one pattern. So, when we start, we actually need to test every
330
+ * pattern against every file. Once we know there are no remaining
331
+ * unmatched patterns, then we can switch to just looking for the
332
+ * first matching pattern for improved speed.
333
+ */
334
+ const matchesPattern =
335
+ unmatchedPatterns.size > 0
336
+ ? matchers.reduce((previousValue, matcher) => {
337
+ const pathMatches = matcher.match(entry.path);
338
+
339
+ /*
340
+ * We updated the unmatched patterns set only if the path
341
+ * matches and the file has a config. If the file has no
342
+ * config, that means there wasn't a match for the
343
+ * pattern so it should not be removed.
344
+ *
345
+ * Performance note: `getConfig()` aggressively caches
346
+ * results so there is no performance penalty for calling
347
+ * it multiple times with the same argument.
348
+ */
349
+ if (pathMatches && config) {
350
+ unmatchedPatterns.delete(matcher.pattern);
351
+ }
352
+
353
+ return pathMatches || previousValue;
354
+ }, false)
355
+ : matchers.some(matcher => matcher.match(entry.path));
356
+
357
+ return matchesPattern && config !== void 0;
358
+ },
359
+ });
360
+
361
+ const filePaths = [];
362
+
363
+ if (await hfs.isDirectory(basePath)) {
364
+ for await (const entry of walk) {
365
+ filePaths.push(path.resolve(basePath, entry.path));
366
+ }
367
+ }
368
+
369
+ // now check to see if we have any unmatched patterns
370
+ if (errorOnUnmatchedPattern && unmatchedPatterns.size > 0) {
371
+ throw new UnmatchedSearchPatternsError({
372
+ basePath,
373
+ unmatchedPatterns: [...unmatchedPatterns].map(pattern =>
374
+ relativeToPatterns.get(pattern),
375
+ ),
376
+ patterns,
377
+ rawPatterns,
378
+ });
379
+ }
380
+
381
+ return filePaths;
382
+ }
383
+
384
+ /**
385
+ * Throws an error for unmatched patterns. The error will only contain information about the first one.
386
+ * Checks to see if there are any ignored results for a given search.
387
+ * @param {Object} options The options for this function.
388
+ * @param {string} options.basePath The directory to search.
389
+ * @param {Array<string>} options.patterns An array of glob patterns
390
+ * that were used in the original search.
391
+ * @param {Array<string>} options.rawPatterns An array of glob patterns
392
+ * as the user inputted them. Used for errors.
393
+ * @param {Array<string>} options.unmatchedPatterns A non-empty array of absolute path glob patterns
394
+ * that were unmatched in the original search.
395
+ * @returns {Promise<never>} Always throws an error.
396
+ * @throws {NoFilesFoundError} If the first unmatched pattern
397
+ * doesn't match any files even when there are no ignores.
398
+ * @throws {AllFilesIgnoredError} If the first unmatched pattern
399
+ * matches some files when there are no ignores.
400
+ */
401
+ async function throwErrorForUnmatchedPatterns({
402
+ basePath,
403
+ patterns,
404
+ rawPatterns,
405
+ unmatchedPatterns,
406
+ }) {
407
+ const pattern = unmatchedPatterns[0];
408
+ const rawPattern = rawPatterns[patterns.indexOf(pattern)];
409
+
410
+ const patternHasMatch = await globMatch({
411
+ basePath,
412
+ pattern,
413
+ });
414
+
415
+ if (patternHasMatch) {
416
+ throw new AllFilesIgnoredError(rawPattern);
417
+ }
418
+
419
+ // if we get here there are truly no matches
420
+ throw new NoFilesFoundError(rawPattern, true);
421
+ }
422
+
423
+ /**
424
+ * Performs multiple glob searches in parallel.
425
+ * @param {Object} options The options for this function.
426
+ * @param {Map<string,GlobSearch>} options.searches
427
+ * A map of absolute path glob patterns to match.
428
+ * @param {ConfigLoader} options.configLoader The config loader to use for
429
+ * determining what to ignore.
430
+ * @param {boolean} options.errorOnUnmatchedPattern Determines if an
431
+ * unmatched glob pattern should throw an error.
432
+ * @returns {Promise<Array<string>>} An array of matching file paths
433
+ * or an empty array if there are no matches.
434
+ */
435
+ async function globMultiSearch({
436
+ searches,
437
+ configLoader,
438
+ errorOnUnmatchedPattern,
439
+ }) {
440
+ /*
441
+ * For convenience, we normalized the search map into an array of objects.
442
+ * Next, we filter out all searches that have no patterns. This happens
443
+ * primarily for the cwd, which is prepopulated in the searches map as an
444
+ * optimization. However, if it has no patterns, it means all patterns
445
+ * occur outside of the cwd and we can safely filter out that search.
446
+ */
447
+ const normalizedSearches = [...searches]
448
+ .map(([basePath, { patterns, rawPatterns }]) => ({
449
+ basePath,
450
+ patterns,
451
+ rawPatterns,
452
+ }))
453
+ .filter(({ patterns }) => patterns.length > 0);
454
+
455
+ const results = await Promise.allSettled(
456
+ normalizedSearches.map(({ basePath, patterns, rawPatterns }) =>
457
+ globSearch({
458
+ basePath,
459
+ patterns,
460
+ rawPatterns,
461
+ configLoader,
462
+ errorOnUnmatchedPattern,
463
+ }),
464
+ ),
465
+ );
466
+
467
+ /*
468
+ * The first loop handles errors from the glob searches. Since we can't
469
+ * use `await` inside `flatMap`, we process errors separately in this loop.
470
+ * This results in two iterations over `results`, but since the length is
471
+ * less than or equal to the number of globs and directories passed on the
472
+ * command line, the performance impact should be minimal.
473
+ */
474
+ for (let i = 0; i < results.length; i++) {
475
+ const result = results[i];
476
+ const currentSearch = normalizedSearches[i];
477
+
478
+ if (result.status === "fulfilled") {
479
+ continue;
480
+ }
481
+
482
+ // if we make it here then there was an error
483
+ const error = result.reason;
484
+
485
+ // unexpected errors should be re-thrown
486
+ if (!error.basePath) {
487
+ throw error;
488
+ }
489
+
490
+ if (errorOnUnmatchedPattern) {
491
+ await throwErrorForUnmatchedPatterns({
492
+ ...currentSearch,
493
+ unmatchedPatterns: error.unmatchedPatterns,
494
+ });
495
+ }
496
+ }
497
+
498
+ // second loop for `fulfilled` results
499
+ return results.flatMap(result => result.value);
500
+ }
501
+
502
+ /**
503
+ * Finds all files matching the options specified.
504
+ * @param {Object} args The arguments objects.
505
+ * @param {Array<string>} args.patterns An array of glob patterns.
506
+ * @param {boolean} args.globInputPaths true to interpret glob patterns,
507
+ * false to not interpret glob patterns.
508
+ * @param {string} args.cwd The current working directory to find from.
509
+ * @param {ConfigLoader} args.configLoader The config loader for the current run.
510
+ * @param {boolean} args.errorOnUnmatchedPattern Determines if an unmatched pattern
511
+ * should throw an error.
512
+ * @returns {Promise<Array<string>>} The fully resolved file paths.
513
+ * @throws {AllFilesIgnoredError} If there are no results due to an ignore pattern.
514
+ * @throws {NoFilesFoundError} If no files matched the given patterns.
515
+ */
516
+ async function findFiles({
517
+ patterns,
518
+ globInputPaths,
519
+ cwd,
520
+ configLoader,
521
+ errorOnUnmatchedPattern,
522
+ }) {
523
+ const results = [];
524
+ const missingPatterns = [];
525
+ let globbyPatterns = [];
526
+ let rawPatterns = [];
527
+ const searches = new Map([
528
+ [cwd, { patterns: globbyPatterns, rawPatterns: [] }],
529
+ ]);
530
+
531
+ /*
532
+ * This part is a bit involved because we need to account for
533
+ * the different ways that the patterns can match directories.
534
+ * For each different way, we need to decide if we should look
535
+ * for a config file or just use the default config. (Directories
536
+ * without a config file always use the default config.)
537
+ *
538
+ * Here are the cases:
539
+ *
540
+ * 1. A directory is passed directly (e.g., "subdir"). In this case, we
541
+ * can assume that the user intends to lint this directory and we should
542
+ * not look for a config file in the parent directory, because the only
543
+ * reason to do that would be to ignore this directory (which we already
544
+ * know we don't want to do). Instead, we use the default config until we
545
+ * get to the directory that was passed, at which point we start looking
546
+ * for config files again.
547
+ *
548
+ * 2. A dot (".") or star ("*"). In this case, we want to read
549
+ * the config file in the current directory because the user is
550
+ * explicitly asking to lint the current directory. Note that "."
551
+ * will traverse into subdirectories while "*" will not.
552
+ *
553
+ * 3. A directory is passed in the form of "subdir/subsubdir".
554
+ * In this case, we don't want to look for a config file in the
555
+ * parent directory ("subdir"). We can skip looking for a config
556
+ * file until `entry.depth` is greater than 1 because there's no
557
+ * way that the pattern can match `entry.path` yet.
558
+ *
559
+ * 4. A directory glob pattern is passed (e.g., "subd*"). We want
560
+ * this case to act like case 2 because it's unclear whether or not
561
+ * any particular directory is meant to be traversed.
562
+ *
563
+ * 5. A recursive glob pattern is passed (e.g., "**"). We want this
564
+ * case to act like case 2.
565
+ */
566
+
567
+ // check to see if we have explicit files and directories
568
+ const filePaths = patterns.map(filePath => path.resolve(cwd, filePath));
569
+ const stats = await Promise.all(
570
+ filePaths.map(filePath => fsp.stat(filePath).catch(() => {})),
571
+ );
572
+
573
+ const promises = [];
574
+ stats.forEach((stat, index) => {
575
+ const filePath = filePaths[index];
576
+ const pattern = normalizeToPosix(patterns[index]);
577
+
578
+ if (stat) {
579
+ // files are added directly to the list
580
+ if (stat.isFile()) {
581
+ results.push(filePath);
582
+ promises.push(configLoader.loadConfigArrayForFile(filePath));
583
+ }
584
+
585
+ // directories need extensions attached
586
+ if (stat.isDirectory()) {
587
+ if (!searches.has(filePath)) {
588
+ searches.set(filePath, { patterns: [], rawPatterns: [] });
589
+ }
590
+ ({ patterns: globbyPatterns, rawPatterns } =
591
+ searches.get(filePath));
592
+
593
+ globbyPatterns.push(`${normalizeToPosix(filePath)}/**`);
594
+ rawPatterns.push(pattern);
595
+ }
596
+
597
+ return;
598
+ }
599
+
600
+ // save patterns for later use based on whether globs are enabled
601
+ if (globInputPaths && isGlobPattern(pattern)) {
602
+ /*
603
+ * We are grouping patterns by their glob parent. This is done to
604
+ * make it easier to determine when a config file should be loaded.
605
+ */
606
+
607
+ const basePath = path.resolve(cwd, globParent(pattern));
608
+
609
+ if (!searches.has(basePath)) {
610
+ searches.set(basePath, { patterns: [], rawPatterns: [] });
611
+ }
612
+ ({ patterns: globbyPatterns, rawPatterns } =
613
+ searches.get(basePath));
614
+
615
+ globbyPatterns.push(filePath);
616
+ rawPatterns.push(pattern);
617
+ } else {
618
+ missingPatterns.push(pattern);
619
+ }
620
+ });
621
+
622
+ // there were patterns that didn't match anything, tell the user
623
+ if (errorOnUnmatchedPattern && missingPatterns.length) {
624
+ throw new NoFilesFoundError(missingPatterns[0], globInputPaths);
625
+ }
626
+
627
+ // now we are safe to do the search
628
+ promises.push(
629
+ globMultiSearch({
630
+ searches,
631
+ configLoader,
632
+ errorOnUnmatchedPattern,
633
+ }),
634
+ );
635
+ const globbyResults = (await Promise.all(promises)).at(-1);
636
+
637
+ return [...new Set([...results, ...globbyResults])];
638
+ }
639
+
640
+ /**
641
+ * Return the absolute path of a file named `"__placeholder__.js"` in a given directory.
642
+ * This is used as a replacement for a missing file path.
643
+ * @param {string} cwd An absolute directory path.
644
+ * @returns {string} The absolute path of a file named `"__placeholder__.js"` in the given directory.
645
+ */
646
+ function getPlaceholderPath(cwd) {
647
+ return path.join(cwd, "__placeholder__.js");
648
+ }
649
+
650
+ //-----------------------------------------------------------------------------
651
+ // Results-related Helpers
652
+ //-----------------------------------------------------------------------------
653
+
654
+ /**
655
+ * Checks if the given message is an error message.
656
+ * @param {LintMessage} message The message to check.
657
+ * @returns {boolean} Whether or not the message is an error message.
658
+ * @private
659
+ */
660
+ function isErrorMessage(message) {
661
+ return message.severity === 2;
662
+ }
663
+
664
+ /**
665
+ * Returns result with warning by ignore settings
666
+ * @param {string} filePath Absolute file path of checked code
667
+ * @param {string} baseDir Absolute path of base directory
668
+ * @param {"ignored"|"external"|"unconfigured"} configStatus A status that determines why the file is ignored
669
+ * @returns {LintResult} Result with single warning
670
+ * @private
671
+ */
672
+ function createIgnoreResult(filePath, baseDir, configStatus) {
673
+ let message;
674
+
675
+ switch (configStatus) {
676
+ case "external":
677
+ message = "File ignored because outside of base path.";
678
+ break;
679
+ case "unconfigured":
680
+ message =
681
+ "File ignored because no matching configuration was supplied.";
682
+ break;
683
+ default:
684
+ {
685
+ const isInNodeModules =
686
+ baseDir &&
687
+ path
688
+ .dirname(path.relative(baseDir, filePath))
689
+ .split(path.sep)
690
+ .includes("node_modules");
691
+
692
+ if (isInNodeModules) {
693
+ message =
694
+ 'File ignored by default because it is located under the node_modules directory. Use ignore pattern "!**/node_modules/" to disable file ignore settings or use "--no-warn-ignored" to suppress this warning.';
695
+ } else {
696
+ message =
697
+ 'File ignored because of a matching ignore pattern. Use "--no-ignore" to disable file ignore settings or use "--no-warn-ignored" to suppress this warning.';
698
+ }
699
+ }
700
+ break;
701
+ }
702
+
703
+ return {
704
+ filePath,
705
+ messages: [
706
+ {
707
+ ruleId: null,
708
+ fatal: false,
709
+ severity: 1,
710
+ message,
711
+ },
712
+ ],
713
+ suppressedMessages: [],
714
+ errorCount: 0,
715
+ warningCount: 1,
716
+ fatalErrorCount: 0,
717
+ fixableErrorCount: 0,
718
+ fixableWarningCount: 0,
719
+ };
720
+ }
721
+
722
+ /**
723
+ * It will calculate the error and warning count for collection of messages per file
724
+ * @param {LintMessage[]} messages Collection of messages
725
+ * @returns {Object} Contains the stats
726
+ * @private
727
+ */
728
+ function calculateStatsPerFile(messages) {
729
+ const stat = {
730
+ errorCount: 0,
731
+ fatalErrorCount: 0,
732
+ warningCount: 0,
733
+ fixableErrorCount: 0,
734
+ fixableWarningCount: 0,
735
+ };
736
+
737
+ for (let i = 0; i < messages.length; i++) {
738
+ const message = messages[i];
739
+
740
+ if (message.fatal || message.severity === 2) {
741
+ stat.errorCount++;
742
+ if (message.fatal) {
743
+ stat.fatalErrorCount++;
744
+ }
745
+ if (message.fix) {
746
+ stat.fixableErrorCount++;
747
+ }
748
+ } else {
749
+ stat.warningCount++;
750
+ if (message.fix) {
751
+ stat.fixableWarningCount++;
752
+ }
753
+ }
754
+ }
755
+ return stat;
756
+ }
757
+
758
+ //-----------------------------------------------------------------------------
759
+ // Options-related Helpers
760
+ //-----------------------------------------------------------------------------
761
+
762
+ /**
763
+ * Check if a given value is a valid fix type or not.
764
+ * @param {any} x The value to check.
765
+ * @returns {boolean} `true` if `x` is valid fix type.
766
+ */
767
+ function isFixType(x) {
768
+ return (
769
+ x === "directive" ||
770
+ x === "problem" ||
771
+ x === "suggestion" ||
772
+ x === "layout"
773
+ );
774
+ }
775
+
776
+ /**
777
+ * Check if a given value is an array of fix types or not.
778
+ * @param {any} x The value to check.
779
+ * @returns {boolean} `true` if `x` is an array of fix types.
780
+ */
781
+ function isFixTypeArray(x) {
782
+ return Array.isArray(x) && x.every(isFixType);
783
+ }
784
+
785
+ /**
786
+ * The error for invalid options.
787
+ */
788
+ class ESLintInvalidOptionsError extends Error {
789
+ constructor(messages) {
790
+ super(`Invalid Options:\n- ${messages.join("\n- ")}`);
791
+ this.code = "ESLINT_INVALID_OPTIONS";
792
+ Error.captureStackTrace(this, ESLintInvalidOptionsError);
793
+ }
794
+ }
795
+
796
+ /**
797
+ * Validates and normalizes options for the wrapped CLIEngine instance.
798
+ * @param {ESLintOptions} options The options to process.
799
+ * @throws {ESLintInvalidOptionsError} If of any of a variety of type errors.
800
+ * @returns {ESLintOptions} The normalized options.
801
+ */
802
+ function processOptions({
803
+ allowInlineConfig = true, // ← we cannot use `overrideConfig.noInlineConfig` instead because `allowInlineConfig` has side-effect that suppress warnings that show inline configs are ignored.
804
+ baseConfig = null,
805
+ cache = false,
806
+ cacheLocation = ".eslintcache",
807
+ cacheStrategy = "metadata",
808
+ concurrency = "off",
809
+ cwd = process.cwd(),
810
+ errorOnUnmatchedPattern = true,
811
+ fix = false,
812
+ fixTypes = null, // ← should be null by default because if it's an array then it suppresses rules that don't have the `meta.type` property.
813
+ flags = [],
814
+ globInputPaths = true,
815
+ ignore = true,
816
+ ignorePatterns = null,
817
+ overrideConfig = null,
818
+ overrideConfigFile = null,
819
+ plugins = {},
820
+ stats = false,
821
+ warnIgnored = true,
822
+ passOnNoPatterns = false,
823
+ ruleFilter = () => true,
824
+ ...unknownOptions
825
+ }) {
826
+ const errors = [];
827
+ const unknownOptionKeys = Object.keys(unknownOptions);
828
+
829
+ if (unknownOptionKeys.length >= 1) {
830
+ errors.push(`Unknown options: ${unknownOptionKeys.join(", ")}`);
831
+ if (unknownOptionKeys.includes("cacheFile")) {
832
+ errors.push(
833
+ "'cacheFile' has been removed. Please use the 'cacheLocation' option instead.",
834
+ );
835
+ }
836
+ if (unknownOptionKeys.includes("configFile")) {
837
+ errors.push(
838
+ "'configFile' has been removed. Please use the 'overrideConfigFile' option instead.",
839
+ );
840
+ }
841
+ if (unknownOptionKeys.includes("envs")) {
842
+ errors.push("'envs' has been removed.");
843
+ }
844
+ if (unknownOptionKeys.includes("extensions")) {
845
+ errors.push("'extensions' has been removed.");
846
+ }
847
+ if (unknownOptionKeys.includes("resolvePluginsRelativeTo")) {
848
+ errors.push("'resolvePluginsRelativeTo' has been removed.");
849
+ }
850
+ if (unknownOptionKeys.includes("globals")) {
851
+ errors.push(
852
+ "'globals' has been removed. Please use the 'overrideConfig.languageOptions.globals' option instead.",
853
+ );
854
+ }
855
+ if (unknownOptionKeys.includes("ignorePath")) {
856
+ errors.push("'ignorePath' has been removed.");
857
+ }
858
+ if (unknownOptionKeys.includes("ignorePattern")) {
859
+ errors.push(
860
+ "'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.",
861
+ );
862
+ }
863
+ if (unknownOptionKeys.includes("parser")) {
864
+ errors.push(
865
+ "'parser' has been removed. Please use the 'overrideConfig.languageOptions.parser' option instead.",
866
+ );
867
+ }
868
+ if (unknownOptionKeys.includes("parserOptions")) {
869
+ errors.push(
870
+ "'parserOptions' has been removed. Please use the 'overrideConfig.languageOptions.parserOptions' option instead.",
871
+ );
872
+ }
873
+ if (unknownOptionKeys.includes("rules")) {
874
+ errors.push(
875
+ "'rules' has been removed. Please use the 'overrideConfig.rules' option instead.",
876
+ );
877
+ }
878
+ if (unknownOptionKeys.includes("rulePaths")) {
879
+ errors.push(
880
+ "'rulePaths' has been removed. Please define your rules using plugins.",
881
+ );
882
+ }
883
+ if (unknownOptionKeys.includes("reportUnusedDisableDirectives")) {
884
+ errors.push(
885
+ "'reportUnusedDisableDirectives' has been removed. Please use the 'overrideConfig.linterOptions.reportUnusedDisableDirectives' option instead.",
886
+ );
887
+ }
888
+ }
889
+ if (typeof allowInlineConfig !== "boolean") {
890
+ errors.push("'allowInlineConfig' must be a boolean.");
891
+ }
892
+ if (typeof baseConfig !== "object") {
893
+ errors.push("'baseConfig' must be an object or null.");
894
+ }
895
+ if (typeof cache !== "boolean") {
896
+ errors.push("'cache' must be a boolean.");
897
+ }
898
+ if (!isNonEmptyString(cacheLocation)) {
899
+ errors.push("'cacheLocation' must be a non-empty string.");
900
+ }
901
+ if (cacheStrategy !== "metadata" && cacheStrategy !== "content") {
902
+ errors.push('\'cacheStrategy\' must be any of "metadata", "content".');
903
+ }
904
+ if (
905
+ concurrency !== "off" &&
906
+ concurrency !== "auto" &&
907
+ !isPositiveInteger(concurrency)
908
+ ) {
909
+ errors.push(
910
+ '\'concurrency\' must be a positive integer, "auto", or "off".',
911
+ );
912
+ }
913
+ if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) {
914
+ errors.push("'cwd' must be an absolute path.");
915
+ }
916
+ if (typeof errorOnUnmatchedPattern !== "boolean") {
917
+ errors.push("'errorOnUnmatchedPattern' must be a boolean.");
918
+ }
919
+ if (typeof fix !== "boolean" && typeof fix !== "function") {
920
+ errors.push("'fix' must be a boolean or a function.");
921
+ }
922
+ if (fixTypes !== null && !isFixTypeArray(fixTypes)) {
923
+ errors.push(
924
+ '\'fixTypes\' must be an array of any of "directive", "problem", "suggestion", and "layout".',
925
+ );
926
+ }
927
+ if (!isEmptyArrayOrArrayOfNonEmptyString(flags)) {
928
+ errors.push("'flags' must be an array of non-empty strings.");
929
+ }
930
+ if (typeof globInputPaths !== "boolean") {
931
+ errors.push("'globInputPaths' must be a boolean.");
932
+ }
933
+ if (typeof ignore !== "boolean") {
934
+ errors.push("'ignore' must be a boolean.");
935
+ }
936
+ if (
937
+ !isEmptyArrayOrArrayOfNonEmptyString(ignorePatterns) &&
938
+ ignorePatterns !== null
939
+ ) {
940
+ errors.push(
941
+ "'ignorePatterns' must be an array of non-empty strings or null.",
942
+ );
943
+ }
944
+ if (typeof overrideConfig !== "object") {
945
+ errors.push("'overrideConfig' must be an object or null.");
946
+ }
947
+ if (
948
+ !isNonEmptyString(overrideConfigFile) &&
949
+ overrideConfigFile !== null &&
950
+ overrideConfigFile !== true
951
+ ) {
952
+ errors.push(
953
+ "'overrideConfigFile' must be a non-empty string, null, or true.",
954
+ );
955
+ }
956
+ if (typeof passOnNoPatterns !== "boolean") {
957
+ errors.push("'passOnNoPatterns' must be a boolean.");
958
+ }
959
+ if (typeof plugins !== "object") {
960
+ errors.push("'plugins' must be an object or null.");
961
+ } else if (plugins !== null && Object.keys(plugins).includes("")) {
962
+ errors.push("'plugins' must not include an empty string.");
963
+ }
964
+ if (Array.isArray(plugins)) {
965
+ errors.push(
966
+ "'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead.",
967
+ );
968
+ }
969
+ if (typeof stats !== "boolean") {
970
+ errors.push("'stats' must be a boolean.");
971
+ }
972
+ if (typeof warnIgnored !== "boolean") {
973
+ errors.push("'warnIgnored' must be a boolean.");
974
+ }
975
+ if (typeof ruleFilter !== "function") {
976
+ errors.push("'ruleFilter' must be a function.");
977
+ }
978
+ if (errors.length > 0) {
979
+ throw new ESLintInvalidOptionsError(errors);
980
+ }
981
+
982
+ return {
983
+ allowInlineConfig,
984
+ baseConfig,
985
+ cache,
986
+ cacheLocation,
987
+ cacheStrategy,
988
+ concurrency,
989
+
990
+ // when overrideConfigFile is true that means don't do config file lookup
991
+ configFile: overrideConfigFile === true ? false : overrideConfigFile,
992
+ overrideConfig,
993
+ cwd: path.normalize(cwd),
994
+ errorOnUnmatchedPattern,
995
+ fix,
996
+ fixTypes,
997
+ flags: [...flags],
998
+ globInputPaths,
999
+ ignore,
1000
+ ignorePatterns,
1001
+ stats,
1002
+ passOnNoPatterns,
1003
+ warnIgnored,
1004
+ ruleFilter,
1005
+ };
1006
+ }
1007
+
1008
+ /**
1009
+ * Loads ESLint constructor options from an options module.
1010
+ * @param {string} optionsURL The URL string of the options module to load.
1011
+ * @returns {Promise<ESLintOptions>} ESLint constructor options.
1012
+ */
1013
+ async function loadOptionsFromModule(optionsURL) {
1014
+ return (await import(optionsURL)).default;
1015
+ }
1016
+
1017
+ //-----------------------------------------------------------------------------
1018
+ // Cache-related helpers
1019
+ //-----------------------------------------------------------------------------
1020
+
1021
+ /**
1022
+ * return the cacheFile to be used by eslint, based on whether the provided parameter is
1023
+ * a directory or looks like a directory (ends in `path.sep`), in which case the file
1024
+ * name will be the `cacheFile/.cache_hashOfCWD`
1025
+ *
1026
+ * if cacheFile points to a file or looks like a file then in will just use that file
1027
+ * @param {string} cacheFile The name of file to be used to store the cache
1028
+ * @param {string} cwd Current working directory
1029
+ * @param {Object} options The options
1030
+ * @param {string} [options.prefix] The prefix to use for the cache file
1031
+ * @returns {string} the resolved path to the cache file
1032
+ */
1033
+ function getCacheFile(cacheFile, cwd, { prefix = ".cache_" } = {}) {
1034
+ /*
1035
+ * make sure the path separators are normalized for the environment/os
1036
+ * keeping the trailing path separator if present
1037
+ */
1038
+ const normalizedCacheFile = path.normalize(cacheFile);
1039
+
1040
+ const resolvedCacheFile = path.resolve(cwd, normalizedCacheFile);
1041
+ const looksLikeADirectory = normalizedCacheFile.slice(-1) === path.sep;
1042
+
1043
+ /**
1044
+ * return the name for the cache file in case the provided parameter is a directory
1045
+ * @returns {string} the resolved path to the cacheFile
1046
+ */
1047
+ function getCacheFileForDirectory() {
1048
+ return path.join(resolvedCacheFile, `${prefix}${hash(cwd)}`);
1049
+ }
1050
+
1051
+ let fileStats;
1052
+
1053
+ try {
1054
+ fileStats = fs.lstatSync(resolvedCacheFile);
1055
+ } catch {
1056
+ fileStats = null;
1057
+ }
1058
+
1059
+ /*
1060
+ * in case the file exists we need to verify if the provided path
1061
+ * is a directory or a file. If it is a directory we want to create a file
1062
+ * inside that directory
1063
+ */
1064
+ if (fileStats) {
1065
+ /*
1066
+ * is a directory or is a file, but the original file the user provided
1067
+ * looks like a directory but `path.resolve` removed the `last path.sep`
1068
+ * so we need to still treat this like a directory
1069
+ */
1070
+ if (fileStats.isDirectory() || looksLikeADirectory) {
1071
+ return getCacheFileForDirectory();
1072
+ }
1073
+
1074
+ // is file so just use that file
1075
+ return resolvedCacheFile;
1076
+ }
1077
+
1078
+ /*
1079
+ * here we known the file or directory doesn't exist,
1080
+ * so we will try to infer if its a directory if it looks like a directory
1081
+ * for the current operating system.
1082
+ */
1083
+
1084
+ // if the last character passed is a path separator we assume is a directory
1085
+ if (looksLikeADirectory) {
1086
+ return getCacheFileForDirectory();
1087
+ }
1088
+
1089
+ return resolvedCacheFile;
1090
+ }
1091
+
1092
+ /**
1093
+ * Creates a new lint result cache.
1094
+ * @param {ESLintOptions} eslintOptions The processed ESLint options.
1095
+ * @param {string} cacheFilePath The path to the cache file.
1096
+ * @returns {?LintResultCache} A new lint result cache or `null`.
1097
+ */
1098
+ function createLintResultCache({ cache, cacheStrategy }, cacheFilePath) {
1099
+ return cache ? new LintResultCache(cacheFilePath, cacheStrategy) : null;
1100
+ }
1101
+
1102
+ //-----------------------------------------------------------------------------
1103
+ // Lint helpers
1104
+ //-----------------------------------------------------------------------------
1105
+
1106
+ /**
1107
+ * Checks whether a message's rule type should be fixed.
1108
+ * @param {LintMessage} message The message to check.
1109
+ * @param {CalculatedConfig} config The config for the file that generated the message.
1110
+ * @param {string[]} fixTypes An array of fix types to check.
1111
+ * @returns {boolean} Whether the message should be fixed.
1112
+ */
1113
+ function shouldMessageBeFixed(message, config, fixTypes) {
1114
+ if (!message.ruleId) {
1115
+ return fixTypes.has("directive");
1116
+ }
1117
+
1118
+ const rule = message.ruleId && config.getRuleDefinition(message.ruleId);
1119
+
1120
+ return Boolean(rule && rule.meta && fixTypes.has(rule.meta.type));
1121
+ }
1122
+
1123
+ /**
1124
+ * Creates a fixer function based on the provided fix, fixTypesSet, and config.
1125
+ * @param {Function|boolean} fix The original fix option.
1126
+ * @param {Set<string>} fixTypesSet A set of fix types to filter messages for fixing.
1127
+ * @param {CalculatedConfig} config The config for the file that generated the message.
1128
+ * @returns {Function|boolean} The fixer function or the original fix value.
1129
+ */
1130
+ function getFixerForFixTypes(fix, fixTypesSet, config) {
1131
+ if (!fix || !fixTypesSet) {
1132
+ return fix;
1133
+ }
1134
+
1135
+ const originalFix = typeof fix === "function" ? fix : () => true;
1136
+
1137
+ return message =>
1138
+ shouldMessageBeFixed(message, config, fixTypesSet) &&
1139
+ originalFix(message);
1140
+ }
1141
+
1142
+ /**
1143
+ * Processes a source code using ESLint.
1144
+ * @param {Object} config The config object.
1145
+ * @param {string} config.text The source code to verify.
1146
+ * @param {string} config.cwd The path to the current working directory.
1147
+ * @param {string|undefined} config.filePath The path to the file of `text`. If this is undefined, it uses `<text>`.
1148
+ * @param {FlatConfigArray} config.configs The config.
1149
+ * @param {boolean} config.fix If `true` then it does fix.
1150
+ * @param {boolean} config.allowInlineConfig If `true` then it uses directive comments.
1151
+ * @param {Function} config.ruleFilter A predicate function to filter which rules should be run.
1152
+ * @param {boolean} config.stats If `true`, then if reports extra statistics with the lint results.
1153
+ * @param {Linter} config.linter The linter instance to verify.
1154
+ * @returns {LintResult} The result of linting.
1155
+ * @private
1156
+ */
1157
+ function verifyText({
1158
+ text,
1159
+ cwd,
1160
+ filePath: providedFilePath,
1161
+ configs,
1162
+ fix,
1163
+ allowInlineConfig,
1164
+ ruleFilter,
1165
+ stats,
1166
+ linter,
1167
+ }) {
1168
+ const startTime = hrtimeBigint();
1169
+
1170
+ const filePath = providedFilePath || "<text>";
1171
+
1172
+ /*
1173
+ * Verify.
1174
+ * `config.extractConfig(filePath)` requires an absolute path, but `linter`
1175
+ * doesn't know CWD, so it gives `linter` an absolute path always.
1176
+ */
1177
+ const filePathToVerify =
1178
+ filePath === "<text>" ? getPlaceholderPath(cwd) : filePath;
1179
+ const { fixed, messages, output } = linter.verifyAndFix(text, configs, {
1180
+ allowInlineConfig,
1181
+ filename: filePathToVerify,
1182
+ fix,
1183
+ ruleFilter,
1184
+ stats,
1185
+
1186
+ /**
1187
+ * Check if the linter should adopt a given code block or not.
1188
+ * @param {string} blockFilename The virtual filename of a code block.
1189
+ * @returns {boolean} `true` if the linter should adopt the code block.
1190
+ */
1191
+ filterCodeBlock(blockFilename) {
1192
+ return configs.getConfig(blockFilename) !== void 0;
1193
+ },
1194
+ });
1195
+
1196
+ // Tweak and return.
1197
+ const result = {
1198
+ filePath: filePath === "<text>" ? filePath : path.resolve(filePath),
1199
+ messages,
1200
+ suppressedMessages: linter.getSuppressedMessages(),
1201
+ ...calculateStatsPerFile(messages),
1202
+ };
1203
+
1204
+ if (fixed) {
1205
+ result.output = output;
1206
+ }
1207
+
1208
+ if (
1209
+ result.errorCount + result.warningCount > 0 &&
1210
+ typeof result.output === "undefined"
1211
+ ) {
1212
+ result.source = text;
1213
+ }
1214
+
1215
+ if (stats) {
1216
+ result.stats = {
1217
+ times: linter.getTimes(),
1218
+ fixPasses: linter.getFixPassCount(),
1219
+ };
1220
+ }
1221
+
1222
+ const endTime = hrtimeBigint();
1223
+ debug('File "%s" linted in %t', filePath, endTime - startTime);
1224
+
1225
+ return result;
1226
+ }
1227
+
1228
+ /**
1229
+ * Lints a single file.
1230
+ * @param {string} filePath File path to lint.
1231
+ * @param {FlatConfigArray} configs The config array for the file.
1232
+ * @param {ESLintOptions} eslintOptions The processed ESLint options.
1233
+ * @param {Linter} linter The linter instance to use.
1234
+ * @param {?LintResultCache} lintResultCache The result cache or `null`.
1235
+ * @param {?{ duration: bigint; }} readFileCounter Used to keep track of the time spent reading files.
1236
+ * @param {Retrier} [retrier] Used to retry linting on certain errors.
1237
+ * @param {AbortController} [controller] Used to stop linting when an error occurs.
1238
+ * @returns {Promise<LintResult>} The lint result.
1239
+ */
1240
+ async function lintFile(
1241
+ filePath,
1242
+ configs,
1243
+ eslintOptions,
1244
+ linter,
1245
+ lintResultCache,
1246
+ readFileCounter,
1247
+ retrier,
1248
+ controller,
1249
+ ) {
1250
+ const config = configs.getConfig(filePath);
1251
+ const {
1252
+ allowInlineConfig,
1253
+ cwd,
1254
+ fix,
1255
+ fixTypes,
1256
+ ruleFilter,
1257
+ stats,
1258
+ warnIgnored,
1259
+ } = eslintOptions;
1260
+ const fixTypesSet = fixTypes ? new Set(fixTypes) : null;
1261
+
1262
+ /*
1263
+ * If a filename was entered that cannot be matched
1264
+ * to a config, then notify the user.
1265
+ */
1266
+ if (!config) {
1267
+ if (warnIgnored) {
1268
+ const configStatus = configs.getConfigStatus(filePath);
1269
+
1270
+ return createIgnoreResult(filePath, cwd, configStatus);
1271
+ }
1272
+
1273
+ return void 0;
1274
+ }
1275
+
1276
+ // Skip if there is cached result.
1277
+ if (lintResultCache) {
1278
+ const cachedResult = lintResultCache.getCachedLintResults(
1279
+ filePath,
1280
+ config,
1281
+ );
1282
+
1283
+ if (cachedResult) {
1284
+ const hadMessages =
1285
+ cachedResult.messages && cachedResult.messages.length > 0;
1286
+
1287
+ if (hadMessages && fix) {
1288
+ debug(`Reprocessing cached file to allow autofix: ${filePath}`);
1289
+ } else {
1290
+ debug(`Skipping file since it hasn't changed: ${filePath}`);
1291
+ return cachedResult;
1292
+ }
1293
+ }
1294
+ }
1295
+
1296
+ // set up fixer for fixTypes if necessary
1297
+ const fixer = getFixerForFixTypes(fix, fixTypesSet, config);
1298
+
1299
+ /**
1300
+ * Reads the file and lints its content.
1301
+ * @returns {Promise<LintResult>} A lint result.
1302
+ */
1303
+ async function readAndVerifyFile() {
1304
+ const readFileEnterTime = hrtimeBigint();
1305
+ const text = await fsp.readFile(filePath, {
1306
+ encoding: "utf8",
1307
+ signal: controller?.signal,
1308
+ });
1309
+ const readFileExitTime = hrtimeBigint();
1310
+ const readFileDuration = readFileExitTime - readFileEnterTime;
1311
+ debug('File "%s" read in %t', filePath, readFileDuration);
1312
+ if (readFileCounter) {
1313
+ readFileCounter.duration += readFileDuration;
1314
+ }
1315
+
1316
+ // fail immediately if an error occurred in another file
1317
+ controller?.signal.throwIfAborted();
1318
+
1319
+ // do the linting
1320
+ return verifyText({
1321
+ text,
1322
+ filePath,
1323
+ configs,
1324
+ cwd,
1325
+ fix: fixer,
1326
+ allowInlineConfig,
1327
+ ruleFilter,
1328
+ stats,
1329
+ linter,
1330
+ });
1331
+ }
1332
+
1333
+ // Use the retrier if provided, otherwise just call the function.
1334
+ const readAndVerifyFilePromise = retrier
1335
+ ? retrier.retry(readAndVerifyFile, { signal: controller?.signal })
1336
+ : readAndVerifyFile();
1337
+
1338
+ return readAndVerifyFilePromise.catch(error => {
1339
+ controller?.abort(error);
1340
+ throw error;
1341
+ });
1342
+ }
1343
+
1344
+ /**
1345
+ * Retrieves flags from the environment variable ESLINT_FLAGS.
1346
+ * @param {string[]} flags The flags defined via the API.
1347
+ * @returns {string[]} The merged flags to use.
1348
+ */
1349
+ function mergeEnvironmentFlags(flags) {
1350
+ if (!process.env.ESLINT_FLAGS) {
1351
+ return flags;
1352
+ }
1353
+
1354
+ const envFlags = process.env.ESLINT_FLAGS.trim().split(/\s*,\s*/gu);
1355
+ return Array.from(new Set([...envFlags, ...flags]));
1356
+ }
1357
+
1358
+ /**
1359
+ * Creates a new linter instance.
1360
+ * @param {ESLintOptions} eslintOptions The processed ESLint options.
1361
+ * @param {WarningService} warningService The warning service to use.
1362
+ * @returns {Linter} The linter instance.
1363
+ */
1364
+ function createLinter({ cwd, flags }, warningService) {
1365
+ return new Linter({
1366
+ configType: "flat",
1367
+ cwd,
1368
+ flags: mergeEnvironmentFlags(flags),
1369
+ warningService,
1370
+ });
1371
+ }
1372
+
1373
+ /**
1374
+ * Creates default configs with the specified plugins.
1375
+ * @param {Record<string, Plugin> | undefined} optionPlugins The plugins specified in the ESLint options.
1376
+ * @returns {Config[]} The default configs.
1377
+ */
1378
+ function createDefaultConfigs(optionPlugins) {
1379
+ const defaultConfigs = [];
1380
+
1381
+ // Add plugins
1382
+ if (optionPlugins) {
1383
+ const plugins = {};
1384
+
1385
+ for (const [pluginName, plugin] of Object.entries(optionPlugins)) {
1386
+ plugins[getShorthandName(pluginName, "eslint-plugin")] = plugin;
1387
+ }
1388
+
1389
+ defaultConfigs.push({ plugins });
1390
+ }
1391
+
1392
+ return defaultConfigs;
1393
+ }
1394
+
1395
+ /**
1396
+ * Creates a config loader.
1397
+ * @param {ESLintOptions} eslintOptions The processed ESLint options.
1398
+ * @param {Config[]} defaultConfigs The default configs.
1399
+ * @param {Linter} linter The linter instance.
1400
+ * @param {WarningService} warningService The warning service to use.
1401
+ * @returns {ConfigLoader} The config loader.
1402
+ */
1403
+ function createConfigLoader(
1404
+ {
1405
+ cwd,
1406
+ baseConfig,
1407
+ overrideConfig,
1408
+ configFile,
1409
+ ignore: ignoreEnabled,
1410
+ ignorePatterns,
1411
+ },
1412
+ defaultConfigs,
1413
+ linter,
1414
+ warningService,
1415
+ ) {
1416
+ const configLoaderOptions = {
1417
+ cwd,
1418
+ baseConfig,
1419
+ overrideConfig,
1420
+ configFile,
1421
+ ignoreEnabled,
1422
+ ignorePatterns,
1423
+ defaultConfigs,
1424
+ hasUnstableNativeNodeJsTSConfigFlag: linter.hasFlag(
1425
+ "unstable_native_nodejs_ts_config",
1426
+ ),
1427
+ warningService,
1428
+ };
1429
+
1430
+ return new ConfigLoader(configLoaderOptions);
1431
+ }
1432
+
1433
+ //-----------------------------------------------------------------------------
1434
+ // Exports
1435
+ //-----------------------------------------------------------------------------
1436
+
1437
+ module.exports = {
1438
+ createDebug,
1439
+
1440
+ findFiles,
1441
+
1442
+ isNonEmptyString,
1443
+ isArrayOfNonEmptyString,
1444
+
1445
+ createIgnoreResult,
1446
+ isErrorMessage,
1447
+ calculateStatsPerFile,
1448
+ getPlaceholderPath,
1449
+
1450
+ processOptions,
1451
+ loadOptionsFromModule,
1452
+
1453
+ getCacheFile,
1454
+ createLintResultCache,
1455
+
1456
+ getFixerForFixTypes,
1457
+ verifyText,
1458
+ lintFile,
1459
+ createLinter,
1460
+ createDefaultConfigs,
1461
+ createConfigLoader,
1462
+ };