eslint 9.22.0 → 9.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -46
- package/bin/eslint.js +92 -90
- package/conf/default-cli-options.js +22 -22
- package/conf/ecma-version.js +1 -1
- package/conf/globals.js +97 -98
- package/conf/replacements.json +24 -20
- package/conf/rule-type-list.json +88 -92
- package/lib/api.js +12 -12
- package/lib/cli-engine/cli-engine.js +830 -810
- package/lib/cli-engine/file-enumerator.js +381 -387
- package/lib/cli-engine/formatters/formatters-meta.json +16 -16
- package/lib/cli-engine/formatters/html.js +107 -99
- package/lib/cli-engine/formatters/json-with-metadata.js +5 -5
- package/lib/cli-engine/formatters/json.js +2 -2
- package/lib/cli-engine/formatters/stylish.js +96 -75
- package/lib/cli-engine/hash.js +1 -1
- package/lib/cli-engine/index.js +1 -1
- package/lib/cli-engine/lint-result-cache.js +144 -145
- package/lib/cli-engine/load-rules.js +16 -16
- package/lib/cli.js +638 -457
- package/lib/config/config-loader.js +726 -622
- package/lib/config/config.js +247 -221
- package/lib/config/default-config.js +54 -45
- package/lib/config/flat-config-array.js +167 -172
- package/lib/config/flat-config-helpers.js +72 -72
- package/lib/config/flat-config-schema.js +375 -368
- package/lib/config/rule-validator.js +139 -144
- package/lib/config-api.js +2 -2
- package/lib/eslint/eslint-helpers.js +756 -681
- package/lib/eslint/eslint.js +934 -912
- package/lib/eslint/index.js +2 -2
- package/lib/eslint/legacy-eslint.js +577 -533
- package/lib/languages/js/index.js +263 -264
- package/lib/languages/js/source-code/index.js +1 -1
- package/lib/languages/js/source-code/source-code.js +1128 -1057
- package/lib/languages/js/source-code/token-store/backward-token-comment-cursor.js +39 -35
- package/lib/languages/js/source-code/token-store/backward-token-cursor.js +35 -36
- package/lib/languages/js/source-code/token-store/cursor.js +36 -36
- package/lib/languages/js/source-code/token-store/cursors.js +80 -52
- package/lib/languages/js/source-code/token-store/decorative-cursor.js +17 -18
- package/lib/languages/js/source-code/token-store/filter-cursor.js +19 -20
- package/lib/languages/js/source-code/token-store/forward-token-comment-cursor.js +40 -32
- package/lib/languages/js/source-code/token-store/forward-token-cursor.js +40 -41
- package/lib/languages/js/source-code/token-store/index.js +592 -498
- package/lib/languages/js/source-code/token-store/limit-cursor.js +17 -18
- package/lib/languages/js/source-code/token-store/padded-token-cursor.js +23 -16
- package/lib/languages/js/source-code/token-store/skip-cursor.js +19 -20
- package/lib/languages/js/source-code/token-store/utils.js +63 -60
- package/lib/languages/js/validate-language-options.js +104 -89
- package/lib/linter/apply-disable-directives.js +467 -383
- package/lib/linter/code-path-analysis/code-path-analyzer.js +650 -672
- package/lib/linter/code-path-analysis/code-path-segment.js +215 -216
- package/lib/linter/code-path-analysis/code-path-state.js +2118 -2096
- package/lib/linter/code-path-analysis/code-path.js +307 -319
- package/lib/linter/code-path-analysis/debug-helpers.js +183 -163
- package/lib/linter/code-path-analysis/fork-context.js +296 -271
- package/lib/linter/code-path-analysis/id-generator.js +22 -23
- package/lib/linter/file-context.js +119 -120
- package/lib/linter/index.js +3 -3
- package/lib/linter/interpolate.js +16 -16
- package/lib/linter/linter.js +2403 -2045
- package/lib/linter/node-event-generator.js +284 -225
- package/lib/linter/report-translator.js +256 -219
- package/lib/linter/rule-fixer.js +122 -124
- package/lib/linter/rules.js +36 -36
- package/lib/linter/safe-emitter.js +18 -18
- package/lib/linter/source-code-fixer.js +94 -92
- package/lib/linter/timing.js +104 -101
- package/lib/linter/vfile.js +70 -73
- package/lib/options.js +404 -361
- package/lib/rule-tester/index.js +1 -1
- package/lib/rule-tester/rule-tester.js +1308 -1046
- package/lib/rules/accessor-pairs.js +298 -263
- package/lib/rules/array-bracket-newline.js +250 -238
- package/lib/rules/array-bracket-spacing.js +263 -224
- package/lib/rules/array-callback-return.js +402 -356
- package/lib/rules/array-element-newline.js +358 -313
- package/lib/rules/arrow-body-style.js +400 -281
- package/lib/rules/arrow-parens.js +206 -173
- package/lib/rules/arrow-spacing.js +169 -163
- package/lib/rules/block-scoped-var.js +125 -123
- package/lib/rules/block-spacing.js +186 -176
- package/lib/rules/brace-style.js +262 -199
- package/lib/rules/callback-return.js +203 -190
- package/lib/rules/camelcase.js +403 -392
- package/lib/rules/capitalized-comments.js +253 -232
- package/lib/rules/class-methods-use-this.js +224 -172
- package/lib/rules/comma-dangle.js +379 -346
- package/lib/rules/comma-spacing.js +193 -195
- package/lib/rules/comma-style.js +375 -316
- package/lib/rules/complexity.js +173 -169
- package/lib/rules/computed-property-spacing.js +236 -211
- package/lib/rules/consistent-return.js +181 -170
- package/lib/rules/consistent-this.js +167 -147
- package/lib/rules/constructor-super.js +412 -404
- package/lib/rules/curly.js +407 -332
- package/lib/rules/default-case-last.js +38 -31
- package/lib/rules/default-case.js +89 -85
- package/lib/rules/default-param-last.js +69 -54
- package/lib/rules/dot-location.js +122 -110
- package/lib/rules/dot-notation.js +192 -156
- package/lib/rules/eol-last.js +122 -120
- package/lib/rules/eqeqeq.js +168 -155
- package/lib/rules/for-direction.js +146 -121
- package/lib/rules/func-call-spacing.js +261 -231
- package/lib/rules/func-name-matching.js +293 -209
- package/lib/rules/func-names.js +165 -164
- package/lib/rules/func-style.js +159 -127
- package/lib/rules/function-call-argument-newline.js +152 -129
- package/lib/rules/function-paren-newline.js +349 -291
- package/lib/rules/generator-star-spacing.js +229 -210
- package/lib/rules/getter-return.js +208 -172
- package/lib/rules/global-require.js +85 -74
- package/lib/rules/grouped-accessor-pairs.js +170 -150
- package/lib/rules/guard-for-in.js +72 -63
- package/lib/rules/handle-callback-err.js +108 -103
- package/lib/rules/id-blacklist.js +182 -199
- package/lib/rules/id-denylist.js +168 -187
- package/lib/rules/id-length.js +197 -171
- package/lib/rules/id-match.js +344 -289
- package/lib/rules/implicit-arrow-linebreak.js +102 -79
- package/lib/rules/indent-legacy.js +1344 -1118
- package/lib/rules/indent.js +2272 -1759
- package/lib/rules/index.js +317 -292
- package/lib/rules/init-declarations.js +137 -107
- package/lib/rules/jsx-quotes.js +94 -82
- package/lib/rules/key-spacing.js +750 -633
- package/lib/rules/keyword-spacing.js +648 -605
- package/lib/rules/line-comment-position.js +142 -128
- package/lib/rules/linebreak-style.js +107 -106
- package/lib/rules/lines-around-comment.js +540 -448
- package/lib/rules/lines-around-directive.js +233 -203
- package/lib/rules/lines-between-class-members.js +305 -234
- package/lib/rules/logical-assignment-operators.js +582 -399
- package/lib/rules/max-classes-per-file.js +69 -68
- package/lib/rules/max-depth.js +146 -143
- package/lib/rules/max-len.js +473 -434
- package/lib/rules/max-lines-per-function.js +201 -176
- package/lib/rules/max-lines.js +158 -162
- package/lib/rules/max-nested-callbacks.js +102 -104
- package/lib/rules/max-params.js +78 -76
- package/lib/rules/max-statements-per-line.js +205 -198
- package/lib/rules/max-statements.js +168 -164
- package/lib/rules/multiline-comment-style.js +637 -479
- package/lib/rules/multiline-ternary.js +241 -176
- package/lib/rules/new-cap.js +233 -213
- package/lib/rules/new-parens.js +88 -79
- package/lib/rules/newline-after-var.js +287 -250
- package/lib/rules/newline-before-return.js +229 -222
- package/lib/rules/newline-per-chained-call.js +142 -127
- package/lib/rules/no-alert.js +90 -79
- package/lib/rules/no-array-constructor.js +125 -113
- package/lib/rules/no-async-promise-executor.js +30 -24
- package/lib/rules/no-await-in-loop.js +69 -71
- package/lib/rules/no-bitwise.js +124 -100
- package/lib/rules/no-buffer-constructor.js +55 -47
- package/lib/rules/no-caller.js +39 -33
- package/lib/rules/no-case-declarations.js +61 -57
- package/lib/rules/no-catch-shadow.js +76 -73
- package/lib/rules/no-class-assign.js +51 -48
- package/lib/rules/no-compare-neg-zero.js +62 -48
- package/lib/rules/no-cond-assign.js +148 -132
- package/lib/rules/no-confusing-arrow.js +98 -81
- package/lib/rules/no-console.js +202 -199
- package/lib/rules/no-const-assign.js +47 -41
- package/lib/rules/no-constant-binary-expression.js +500 -405
- package/lib/rules/no-constant-condition.js +158 -143
- package/lib/rules/no-constructor-return.js +49 -49
- package/lib/rules/no-continue.js +25 -27
- package/lib/rules/no-control-regex.js +125 -121
- package/lib/rules/no-debugger.js +28 -30
- package/lib/rules/no-delete-var.js +29 -29
- package/lib/rules/no-div-regex.js +47 -41
- package/lib/rules/no-dupe-args.js +68 -69
- package/lib/rules/no-dupe-class-members.js +102 -89
- package/lib/rules/no-dupe-else-if.js +100 -77
- package/lib/rules/no-dupe-keys.js +133 -110
- package/lib/rules/no-duplicate-case.js +50 -43
- package/lib/rules/no-duplicate-imports.js +179 -176
- package/lib/rules/no-else-return.js +430 -385
- package/lib/rules/no-empty-character-class.js +57 -50
- package/lib/rules/no-empty-function.js +127 -128
- package/lib/rules/no-empty-pattern.js +63 -58
- package/lib/rules/no-empty-static-block.js +37 -35
- package/lib/rules/no-empty.js +98 -86
- package/lib/rules/no-eq-null.js +37 -32
- package/lib/rules/no-eval.js +256 -250
- package/lib/rules/no-ex-assign.js +42 -39
- package/lib/rules/no-extend-native.js +161 -159
- package/lib/rules/no-extra-bind.js +201 -190
- package/lib/rules/no-extra-boolean-cast.js +398 -348
- package/lib/rules/no-extra-label.js +150 -131
- package/lib/rules/no-extra-parens.js +1654 -1325
- package/lib/rules/no-extra-semi.js +146 -144
- package/lib/rules/no-fallthrough.js +199 -157
- package/lib/rules/no-floating-decimal.js +74 -66
- package/lib/rules/no-func-assign.js +54 -55
- package/lib/rules/no-global-assign.js +78 -73
- package/lib/rules/no-implicit-coercion.js +349 -293
- package/lib/rules/no-implicit-globals.js +158 -135
- package/lib/rules/no-implied-eval.js +140 -112
- package/lib/rules/no-import-assign.js +145 -159
- package/lib/rules/no-inline-comments.js +101 -95
- package/lib/rules/no-inner-declarations.js +115 -101
- package/lib/rules/no-invalid-regexp.js +222 -190
- package/lib/rules/no-invalid-this.js +123 -117
- package/lib/rules/no-irregular-whitespace.js +266 -252
- package/lib/rules/no-iterator.js +29 -33
- package/lib/rules/no-label-var.js +59 -62
- package/lib/rules/no-labels.js +138 -133
- package/lib/rules/no-lone-blocks.js +127 -123
- package/lib/rules/no-lonely-if.js +108 -77
- package/lib/rules/no-loop-func.js +238 -213
- package/lib/rules/no-loss-of-precision.js +218 -201
- package/lib/rules/no-magic-numbers.js +246 -218
- package/lib/rules/no-misleading-character-class.js +499 -446
- package/lib/rules/no-mixed-operators.js +188 -182
- package/lib/rules/no-mixed-requires.js +253 -240
- package/lib/rules/no-mixed-spaces-and-tabs.js +134 -121
- package/lib/rules/no-multi-assign.js +46 -44
- package/lib/rules/no-multi-spaces.js +163 -143
- package/lib/rules/no-multi-str.js +42 -41
- package/lib/rules/no-multiple-empty-lines.js +196 -158
- package/lib/rules/no-native-reassign.js +90 -85
- package/lib/rules/no-negated-condition.js +79 -75
- package/lib/rules/no-negated-in-lhs.js +45 -43
- package/lib/rules/no-nested-ternary.js +33 -32
- package/lib/rules/no-new-func.js +71 -62
- package/lib/rules/no-new-native-nonconstructor.js +43 -39
- package/lib/rules/no-new-object.js +48 -48
- package/lib/rules/no-new-require.js +48 -47
- package/lib/rules/no-new-symbol.js +52 -50
- package/lib/rules/no-new-wrappers.js +43 -41
- package/lib/rules/no-new.js +28 -29
- package/lib/rules/no-nonoctal-decimal-escape.js +141 -121
- package/lib/rules/no-obj-calls.js +66 -53
- package/lib/rules/no-object-constructor.js +104 -97
- package/lib/rules/no-octal-escape.js +40 -43
- package/lib/rules/no-octal.js +32 -32
- package/lib/rules/no-param-reassign.js +235 -217
- package/lib/rules/no-path-concat.js +66 -67
- package/lib/rules/no-plusplus.js +60 -61
- package/lib/rules/no-process-env.js +49 -48
- package/lib/rules/no-process-exit.js +54 -50
- package/lib/rules/no-promise-executor-return.js +214 -182
- package/lib/rules/no-proto.js +26 -29
- package/lib/rules/no-prototype-builtins.js +146 -124
- package/lib/rules/no-redeclare.js +154 -152
- package/lib/rules/no-regex-spaces.js +183 -161
- package/lib/rules/no-restricted-exports.js +208 -185
- package/lib/rules/no-restricted-globals.js +111 -112
- package/lib/rules/no-restricted-imports.js +657 -537
- package/lib/rules/no-restricted-modules.js +222 -202
- package/lib/rules/no-restricted-properties.js +181 -153
- package/lib/rules/no-restricted-syntax.js +56 -52
- package/lib/rules/no-return-assign.js +55 -50
- package/lib/rules/no-return-await.js +148 -124
- package/lib/rules/no-script-url.js +52 -45
- package/lib/rules/no-self-assign.js +148 -146
- package/lib/rules/no-self-compare.js +63 -46
- package/lib/rules/no-sequences.js +135 -116
- package/lib/rules/no-setter-return.js +185 -152
- package/lib/rules/no-shadow-restricted-names.js +61 -46
- package/lib/rules/no-shadow.js +342 -316
- package/lib/rules/no-spaced-func.js +82 -77
- package/lib/rules/no-sparse-arrays.js +54 -59
- package/lib/rules/no-sync.js +61 -60
- package/lib/rules/no-tabs.js +83 -72
- package/lib/rules/no-template-curly-in-string.js +33 -32
- package/lib/rules/no-ternary.js +25 -29
- package/lib/rules/no-this-before-super.js +321 -319
- package/lib/rules/no-throw-literal.js +31 -36
- package/lib/rules/no-trailing-spaces.js +199 -191
- package/lib/rules/no-undef-init.js +76 -61
- package/lib/rules/no-undef.js +51 -48
- package/lib/rules/no-undefined.js +73 -75
- package/lib/rules/no-underscore-dangle.js +370 -327
- package/lib/rules/no-unexpected-multiline.js +112 -102
- package/lib/rules/no-unmodified-loop-condition.js +254 -254
- package/lib/rules/no-unneeded-ternary.js +212 -147
- package/lib/rules/no-unreachable-loop.js +145 -142
- package/lib/rules/no-unreachable.js +255 -248
- package/lib/rules/no-unsafe-finally.js +93 -85
- package/lib/rules/no-unsafe-negation.js +105 -83
- package/lib/rules/no-unsafe-optional-chaining.js +192 -178
- package/lib/rules/no-unused-expressions.js +178 -162
- package/lib/rules/no-unused-labels.js +139 -124
- package/lib/rules/no-unused-private-class-members.js +206 -182
- package/lib/rules/no-unused-vars.js +1669 -1449
- package/lib/rules/no-use-before-define.js +229 -231
- package/lib/rules/no-useless-assignment.js +590 -511
- package/lib/rules/no-useless-backreference.js +212 -193
- package/lib/rules/no-useless-call.js +58 -53
- package/lib/rules/no-useless-catch.js +40 -40
- package/lib/rules/no-useless-computed-key.js +144 -115
- package/lib/rules/no-useless-concat.js +65 -60
- package/lib/rules/no-useless-constructor.js +158 -111
- package/lib/rules/no-useless-escape.js +342 -291
- package/lib/rules/no-useless-rename.js +183 -156
- package/lib/rules/no-useless-return.js +344 -312
- package/lib/rules/no-var.js +233 -212
- package/lib/rules/no-void.js +50 -48
- package/lib/rules/no-warning-comments.js +191 -186
- package/lib/rules/no-whitespace-before-property.js +131 -115
- package/lib/rules/no-with.js +24 -26
- package/lib/rules/nonblock-statement-body-position.js +149 -130
- package/lib/rules/object-curly-newline.js +306 -265
- package/lib/rules/object-curly-spacing.js +360 -314
- package/lib/rules/object-property-newline.js +137 -106
- package/lib/rules/object-shorthand.js +607 -502
- package/lib/rules/one-var-declaration-per-line.js +104 -100
- package/lib/rules/one-var.js +653 -537
- package/lib/rules/operator-assignment.js +219 -161
- package/lib/rules/operator-linebreak.js +295 -251
- package/lib/rules/padded-blocks.js +346 -308
- package/lib/rules/padding-line-between-statements.js +443 -439
- package/lib/rules/prefer-arrow-callback.js +362 -313
- package/lib/rules/prefer-const.js +418 -377
- package/lib/rules/prefer-destructuring.js +301 -279
- package/lib/rules/prefer-exponentiation-operator.js +176 -133
- package/lib/rules/prefer-named-capture-group.js +153 -140
- package/lib/rules/prefer-numeric-literals.js +121 -113
- package/lib/rules/prefer-object-has-own.js +116 -82
- package/lib/rules/prefer-object-spread.js +213 -193
- package/lib/rules/prefer-promise-reject-errors.js +140 -122
- package/lib/rules/prefer-reflect.js +127 -107
- package/lib/rules/prefer-regex-literals.js +578 -466
- package/lib/rules/prefer-rest-params.js +79 -80
- package/lib/rules/prefer-spread.js +47 -44
- package/lib/rules/prefer-template.js +266 -195
- package/lib/rules/quote-props.js +373 -307
- package/lib/rules/quotes.js +374 -326
- package/lib/rules/radix.js +152 -136
- package/lib/rules/require-atomic-updates.js +316 -285
- package/lib/rules/require-await.js +144 -116
- package/lib/rules/require-unicode-regexp.js +282 -177
- package/lib/rules/require-yield.js +53 -54
- package/lib/rules/rest-spread-spacing.js +128 -116
- package/lib/rules/semi-spacing.js +281 -250
- package/lib/rules/semi-style.js +176 -134
- package/lib/rules/semi.js +456 -436
- package/lib/rules/sort-imports.js +306 -233
- package/lib/rules/sort-keys.js +219 -188
- package/lib/rules/sort-vars.js +127 -93
- package/lib/rules/space-before-blocks.js +199 -189
- package/lib/rules/space-before-function-paren.js +186 -166
- package/lib/rules/space-in-parens.js +359 -288
- package/lib/rules/space-infix-ops.js +237 -201
- package/lib/rules/space-unary-ops.js +356 -298
- package/lib/rules/spaced-comment.js +363 -319
- package/lib/rules/strict.js +265 -230
- package/lib/rules/switch-colon-spacing.js +130 -122
- package/lib/rules/symbol-description.js +45 -48
- package/lib/rules/template-curly-spacing.js +148 -142
- package/lib/rules/template-tag-spacing.js +98 -88
- package/lib/rules/unicode-bom.js +54 -56
- package/lib/rules/use-isnan.js +237 -206
- package/lib/rules/utils/ast-utils.js +2039 -1860
- package/lib/rules/utils/char-source.js +162 -155
- package/lib/rules/utils/fix-tracker.js +83 -80
- package/lib/rules/utils/keywords.js +59 -59
- package/lib/rules/utils/lazy-loading-rule-map.js +79 -76
- package/lib/rules/utils/regular-expressions.js +32 -24
- package/lib/rules/utils/unicode/index.js +4 -4
- package/lib/rules/utils/unicode/is-combining-character.js +1 -1
- package/lib/rules/utils/unicode/is-emoji-modifier.js +1 -1
- package/lib/rules/utils/unicode/is-regional-indicator-symbol.js +1 -1
- package/lib/rules/utils/unicode/is-surrogate-pair.js +1 -1
- package/lib/rules/valid-typeof.js +153 -111
- package/lib/rules/vars-on-top.js +152 -145
- package/lib/rules/wrap-iife.js +204 -191
- package/lib/rules/wrap-regex.js +70 -58
- package/lib/rules/yield-star-spacing.js +145 -134
- package/lib/rules/yoda.js +283 -272
- package/lib/services/parser-service.js +35 -35
- package/lib/services/processor-service.js +66 -73
- package/lib/services/suppressions-service.js +289 -0
- package/lib/shared/ajv.js +14 -14
- package/lib/shared/assert.js +3 -4
- package/lib/shared/ast-utils.js +7 -6
- package/lib/shared/deep-merge-arrays.js +24 -22
- package/lib/shared/directives.js +3 -2
- package/lib/shared/flags.js +50 -17
- package/lib/shared/logging.js +24 -25
- package/lib/shared/option-utils.js +43 -36
- package/lib/shared/runtime-info.js +136 -127
- package/lib/shared/serialization.js +27 -27
- package/lib/shared/severity.js +22 -22
- package/lib/shared/stats.js +5 -5
- package/lib/shared/string-utils.js +16 -16
- package/lib/shared/text-table.js +28 -27
- package/lib/shared/traverser.js +153 -146
- package/lib/shared/types.js +4 -27
- package/lib/types/index.d.ts +2010 -1559
- package/lib/types/rules.d.ts +5253 -5140
- package/lib/types/use-at-your-own-risk.d.ts +32 -30
- package/lib/unsupported-api.js +5 -5
- package/messages/all-files-ignored.js +3 -3
- package/messages/all-matched-files-ignored.js +3 -3
- package/messages/config-file-missing.js +2 -2
- package/messages/config-plugin-missing.js +3 -3
- package/messages/config-serialize-function.js +9 -7
- package/messages/eslintrc-incompat.js +13 -15
- package/messages/eslintrc-plugins.js +3 -4
- package/messages/extend-config-missing.js +3 -3
- package/messages/failed-to-read-json.js +3 -3
- package/messages/file-not-found.js +3 -3
- package/messages/invalid-rule-options.js +2 -2
- package/messages/invalid-rule-severity.js +2 -2
- package/messages/no-config-found.js +3 -3
- package/messages/plugin-conflict.js +8 -8
- package/messages/plugin-invalid.js +3 -3
- package/messages/plugin-missing.js +3 -3
- package/messages/print-config-with-directory-path.js +2 -2
- package/messages/shared.js +6 -1
- package/messages/whitespace-found.js +3 -3
- package/package.json +14 -20
package/lib/eslint/eslint.js
CHANGED
@@ -17,26 +17,25 @@ const { Linter } = require("../linter");
|
|
17
17
|
const { getRuleFromConfig } = require("../config/flat-config-helpers");
|
18
18
|
const { defaultConfig } = require("../config/default-config");
|
19
19
|
const {
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
naming
|
26
|
-
}
|
20
|
+
Legacy: {
|
21
|
+
ConfigOps: { getRuleSeverity },
|
22
|
+
ModuleResolver,
|
23
|
+
naming,
|
24
|
+
},
|
27
25
|
} = require("@eslint/eslintrc");
|
28
26
|
|
29
27
|
const {
|
30
|
-
|
31
|
-
|
28
|
+
findFiles,
|
29
|
+
getCacheFile,
|
32
30
|
|
33
|
-
|
34
|
-
|
31
|
+
isNonEmptyString,
|
32
|
+
isArrayOfNonEmptyString,
|
35
33
|
|
36
|
-
|
37
|
-
|
34
|
+
createIgnoreResult,
|
35
|
+
isErrorMessage,
|
36
|
+
calculateStatsPerFile,
|
38
37
|
|
39
|
-
|
38
|
+
processOptions,
|
40
39
|
} = require("./eslint-helpers");
|
41
40
|
const { pathToFileURL } = require("node:url");
|
42
41
|
const LintResultCache = require("../cli-engine/lint-result-cache");
|
@@ -53,19 +52,15 @@ const { ConfigLoader, LegacyConfigLoader } = require("../config/config-loader");
|
|
53
52
|
//------------------------------------------------------------------------------
|
54
53
|
|
55
54
|
// For VSCode IntelliSense
|
56
|
-
/**
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
/** @typedef {import("../shared/types").RuleConf} RuleConf */
|
65
|
-
/** @typedef {import("../shared/types").Rule} Rule */
|
55
|
+
/**
|
56
|
+
* @import { ConfigArray } from "../cli-engine/cli-engine.js";
|
57
|
+
* @import { CLIEngineLintReport } from "./legacy-eslint.js";
|
58
|
+
* @import { FlatConfigArray } from "../config/flat-config-array.js";
|
59
|
+
* @import { RuleDefinition } from "@eslint/core";
|
60
|
+
* @import { ConfigData, DeprecatedRuleInfo, LintMessage, LintResult, Plugin, ResultsMeta } from "../shared/types.js";
|
61
|
+
*/
|
62
|
+
|
66
63
|
/** @typedef {ReturnType<ConfigArray.extractConfig>} ExtractedConfig */
|
67
|
-
/** @typedef {import('../cli-engine/cli-engine').CLIEngine} CLIEngine */
|
68
|
-
/** @typedef {import('./legacy-eslint').CLIEngineLintReport} CLIEngineLintReport */
|
69
64
|
|
70
65
|
/**
|
71
66
|
* The options with which to configure the ESLint instance.
|
@@ -101,63 +96,27 @@ const { ConfigLoader, LegacyConfigLoader } = require("../config/config-loader");
|
|
101
96
|
const debug = require("debug")("eslint:eslint");
|
102
97
|
const privateMembers = new WeakMap();
|
103
98
|
const removedFormatters = new Set([
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
99
|
+
"checkstyle",
|
100
|
+
"codeframe",
|
101
|
+
"compact",
|
102
|
+
"jslint-xml",
|
103
|
+
"junit",
|
104
|
+
"table",
|
105
|
+
"tap",
|
106
|
+
"unix",
|
107
|
+
"visualstudio",
|
113
108
|
]);
|
114
109
|
|
115
|
-
/**
|
116
|
-
* It will calculate the error and warning count for collection of messages per file
|
117
|
-
* @param {LintMessage[]} messages Collection of messages
|
118
|
-
* @returns {Object} Contains the stats
|
119
|
-
* @private
|
120
|
-
*/
|
121
|
-
function calculateStatsPerFile(messages) {
|
122
|
-
const stat = {
|
123
|
-
errorCount: 0,
|
124
|
-
fatalErrorCount: 0,
|
125
|
-
warningCount: 0,
|
126
|
-
fixableErrorCount: 0,
|
127
|
-
fixableWarningCount: 0
|
128
|
-
};
|
129
|
-
|
130
|
-
for (let i = 0; i < messages.length; i++) {
|
131
|
-
const message = messages[i];
|
132
|
-
|
133
|
-
if (message.fatal || message.severity === 2) {
|
134
|
-
stat.errorCount++;
|
135
|
-
if (message.fatal) {
|
136
|
-
stat.fatalErrorCount++;
|
137
|
-
}
|
138
|
-
if (message.fix) {
|
139
|
-
stat.fixableErrorCount++;
|
140
|
-
}
|
141
|
-
} else {
|
142
|
-
stat.warningCount++;
|
143
|
-
if (message.fix) {
|
144
|
-
stat.fixableWarningCount++;
|
145
|
-
}
|
146
|
-
}
|
147
|
-
}
|
148
|
-
return stat;
|
149
|
-
}
|
150
|
-
|
151
110
|
/**
|
152
111
|
* Create rulesMeta object.
|
153
|
-
* @param {Map<string,
|
112
|
+
* @param {Map<string,RuleDefinition>} rules a map of rules from which to generate the object.
|
154
113
|
* @returns {Object} metadata for all enabled rules.
|
155
114
|
*/
|
156
115
|
function createRulesMeta(rules) {
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
116
|
+
return Array.from(rules).reduce((retVal, [id, rule]) => {
|
117
|
+
retVal[id] = rule.meta;
|
118
|
+
return retVal;
|
119
|
+
}, {});
|
161
120
|
}
|
162
121
|
|
163
122
|
/**
|
@@ -167,7 +126,7 @@ function createRulesMeta(rules) {
|
|
167
126
|
* @returns {string} The absolute path of a file named `"__placeholder__.js"` in the given directory.
|
168
127
|
*/
|
169
128
|
function getPlaceholderPath(cwd) {
|
170
|
-
|
129
|
+
return path.join(cwd, "__placeholder__.js");
|
171
130
|
}
|
172
131
|
|
173
132
|
/** @type {WeakMap<ExtractedConfig, DeprecatedRuleInfo[]>} */
|
@@ -175,73 +134,77 @@ const usedDeprecatedRulesCache = new WeakMap();
|
|
175
134
|
|
176
135
|
/**
|
177
136
|
* Create used deprecated rule list.
|
178
|
-
* @param {
|
137
|
+
* @param {ESLint} eslint The ESLint instance.
|
179
138
|
* @param {string} maybeFilePath The absolute path to a lint target file or `"<text>"`.
|
180
139
|
* @returns {DeprecatedRuleInfo[]} The used deprecated rule list.
|
181
140
|
*/
|
182
141
|
function getOrFindUsedDeprecatedRules(eslint, maybeFilePath) {
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
142
|
+
const {
|
143
|
+
options: { cwd },
|
144
|
+
configLoader,
|
145
|
+
} = privateMembers.get(eslint);
|
146
|
+
const filePath = path.isAbsolute(maybeFilePath)
|
147
|
+
? maybeFilePath
|
148
|
+
: getPlaceholderPath(cwd);
|
149
|
+
const configs = configLoader.getCachedConfigArrayForFile(filePath);
|
150
|
+
const config = configs.getConfig(filePath);
|
151
|
+
|
152
|
+
// Most files use the same config, so cache it.
|
153
|
+
if (config && !usedDeprecatedRulesCache.has(config)) {
|
154
|
+
const retv = [];
|
155
|
+
|
156
|
+
if (config.rules) {
|
157
|
+
for (const [ruleId, ruleConf] of Object.entries(config.rules)) {
|
158
|
+
if (getRuleSeverity(ruleConf) === 0) {
|
159
|
+
continue;
|
160
|
+
}
|
161
|
+
const rule = getRuleFromConfig(ruleId, config);
|
162
|
+
const meta = rule && rule.meta;
|
163
|
+
|
164
|
+
if (meta && meta.deprecated) {
|
165
|
+
const usesNewFormat = typeof meta.deprecated === "object";
|
166
|
+
|
167
|
+
retv.push({
|
168
|
+
ruleId,
|
169
|
+
replacedBy: usesNewFormat
|
170
|
+
? (meta.deprecated.replacedBy?.map(
|
171
|
+
replacement =>
|
172
|
+
`${replacement.plugin?.name !== void 0 ? `${naming.getShorthandName(replacement.plugin.name, "eslint-plugin")}/` : ""}${replacement.rule?.name ?? ""}`,
|
173
|
+
) ?? [])
|
174
|
+
: meta.replacedBy || [],
|
175
|
+
info: usesNewFormat ? meta.deprecated : void 0,
|
176
|
+
});
|
177
|
+
}
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
usedDeprecatedRulesCache.set(config, Object.freeze(retv));
|
182
|
+
}
|
183
|
+
|
184
|
+
return config ? usedDeprecatedRulesCache.get(config) : Object.freeze([]);
|
222
185
|
}
|
223
186
|
|
224
187
|
/**
|
225
188
|
* Processes the linting results generated by a CLIEngine linting report to
|
226
189
|
* match the ESLint class's API.
|
227
|
-
* @param {
|
190
|
+
* @param {ESLint} eslint The ESLint instance.
|
228
191
|
* @param {CLIEngineLintReport} report The CLIEngine linting report to process.
|
229
192
|
* @returns {LintResult[]} The processed linting results.
|
230
193
|
*/
|
231
194
|
function processLintReport(eslint, { results }) {
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
195
|
+
const descriptor = {
|
196
|
+
configurable: true,
|
197
|
+
enumerable: true,
|
198
|
+
get() {
|
199
|
+
return getOrFindUsedDeprecatedRules(eslint, this.filePath);
|
200
|
+
},
|
201
|
+
};
|
202
|
+
|
203
|
+
for (const result of results) {
|
204
|
+
Object.defineProperty(result, "usedDeprecatedRules", descriptor);
|
205
|
+
}
|
206
|
+
|
207
|
+
return results;
|
245
208
|
}
|
246
209
|
|
247
210
|
/**
|
@@ -251,18 +214,17 @@ function processLintReport(eslint, { results }) {
|
|
251
214
|
* @returns {number} An integer representing the order in which the two results should occur.
|
252
215
|
*/
|
253
216
|
function compareResultsByFilePath(a, b) {
|
254
|
-
|
255
|
-
|
256
|
-
|
217
|
+
if (a.filePath < b.filePath) {
|
218
|
+
return -1;
|
219
|
+
}
|
257
220
|
|
258
|
-
|
259
|
-
|
260
|
-
|
221
|
+
if (a.filePath > b.filePath) {
|
222
|
+
return 1;
|
223
|
+
}
|
261
224
|
|
262
|
-
|
225
|
+
return 0;
|
263
226
|
}
|
264
227
|
|
265
|
-
|
266
228
|
/**
|
267
229
|
* Determines which config file to use. This is determined by seeing if an
|
268
230
|
* override config file was passed, and if so, using it; otherwise, as long
|
@@ -276,22 +238,23 @@ function compareResultsByFilePath(a, b) {
|
|
276
238
|
* the config file.
|
277
239
|
*/
|
278
240
|
async function locateConfigFileToUse({ configFile, cwd }) {
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
241
|
+
const configLoader = new ConfigLoader({
|
242
|
+
cwd,
|
243
|
+
configFile,
|
244
|
+
});
|
245
|
+
|
246
|
+
const configFilePath = await configLoader.findConfigFileForPath(
|
247
|
+
path.join(cwd, "__placeholder__.js"),
|
248
|
+
);
|
249
|
+
|
250
|
+
if (!configFilePath) {
|
251
|
+
throw new Error("No ESLint configuration file was found.");
|
252
|
+
}
|
253
|
+
|
254
|
+
return {
|
255
|
+
configFilePath,
|
256
|
+
basePath: configFile ? cwd : path.dirname(configFilePath),
|
257
|
+
};
|
295
258
|
}
|
296
259
|
|
297
260
|
/**
|
@@ -310,91 +273,88 @@ async function locateConfigFileToUse({ configFile, cwd }) {
|
|
310
273
|
* @private
|
311
274
|
*/
|
312
275
|
function verifyText({
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
276
|
+
text,
|
277
|
+
cwd,
|
278
|
+
filePath: providedFilePath,
|
279
|
+
configs,
|
280
|
+
fix,
|
281
|
+
allowInlineConfig,
|
282
|
+
ruleFilter,
|
283
|
+
stats,
|
284
|
+
linter,
|
322
285
|
}) {
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
}
|
379
|
-
|
380
|
-
return result;
|
286
|
+
const filePath = providedFilePath || "<text>";
|
287
|
+
|
288
|
+
debug(`Lint ${filePath}`);
|
289
|
+
|
290
|
+
/*
|
291
|
+
* Verify.
|
292
|
+
* `config.extractConfig(filePath)` requires an absolute path, but `linter`
|
293
|
+
* doesn't know CWD, so it gives `linter` an absolute path always.
|
294
|
+
*/
|
295
|
+
const filePathToVerify =
|
296
|
+
filePath === "<text>" ? getPlaceholderPath(cwd) : filePath;
|
297
|
+
const { fixed, messages, output } = linter.verifyAndFix(text, configs, {
|
298
|
+
allowInlineConfig,
|
299
|
+
filename: filePathToVerify,
|
300
|
+
fix,
|
301
|
+
ruleFilter,
|
302
|
+
stats,
|
303
|
+
|
304
|
+
/**
|
305
|
+
* Check if the linter should adopt a given code block or not.
|
306
|
+
* @param {string} blockFilename The virtual filename of a code block.
|
307
|
+
* @returns {boolean} `true` if the linter should adopt the code block.
|
308
|
+
*/
|
309
|
+
filterCodeBlock(blockFilename) {
|
310
|
+
return configs.getConfig(blockFilename) !== void 0;
|
311
|
+
},
|
312
|
+
});
|
313
|
+
|
314
|
+
// Tweak and return.
|
315
|
+
const result = {
|
316
|
+
filePath: filePath === "<text>" ? filePath : path.resolve(filePath),
|
317
|
+
messages,
|
318
|
+
suppressedMessages: linter.getSuppressedMessages(),
|
319
|
+
...calculateStatsPerFile(messages),
|
320
|
+
};
|
321
|
+
|
322
|
+
if (fixed) {
|
323
|
+
result.output = output;
|
324
|
+
}
|
325
|
+
|
326
|
+
if (
|
327
|
+
result.errorCount + result.warningCount > 0 &&
|
328
|
+
typeof result.output === "undefined"
|
329
|
+
) {
|
330
|
+
result.source = text;
|
331
|
+
}
|
332
|
+
|
333
|
+
if (stats) {
|
334
|
+
result.stats = {
|
335
|
+
times: linter.getTimes(),
|
336
|
+
fixPasses: linter.getFixPassCount(),
|
337
|
+
};
|
338
|
+
}
|
339
|
+
|
340
|
+
return result;
|
381
341
|
}
|
382
342
|
|
383
343
|
/**
|
384
344
|
* Checks whether a message's rule type should be fixed.
|
385
345
|
* @param {LintMessage} message The message to check.
|
386
|
-
* @param {
|
346
|
+
* @param {FlatConfigArray} config The config for the file that generated the message.
|
387
347
|
* @param {string[]} fixTypes An array of fix types to check.
|
388
348
|
* @returns {boolean} Whether the message should be fixed.
|
389
349
|
*/
|
390
350
|
function shouldMessageBeFixed(message, config, fixTypes) {
|
391
|
-
|
392
|
-
|
393
|
-
|
351
|
+
if (!message.ruleId) {
|
352
|
+
return fixTypes.has("directive");
|
353
|
+
}
|
394
354
|
|
395
|
-
|
355
|
+
const rule = message.ruleId && getRuleFromConfig(message.ruleId, config);
|
396
356
|
|
397
|
-
|
357
|
+
return Boolean(rule && rule.meta && fixTypes.has(rule.meta.type));
|
398
358
|
}
|
399
359
|
|
400
360
|
/**
|
@@ -402,24 +362,28 @@ function shouldMessageBeFixed(message, config, fixTypes) {
|
|
402
362
|
* @returns {TypeError} An error object.
|
403
363
|
*/
|
404
364
|
function createExtraneousResultsError() {
|
405
|
-
|
365
|
+
return new TypeError(
|
366
|
+
"Results object was not created from this ESLint instance.",
|
367
|
+
);
|
406
368
|
}
|
407
369
|
|
408
370
|
/**
|
409
371
|
* Creates a fixer function based on the provided fix, fixTypesSet, and config.
|
410
372
|
* @param {Function|boolean} fix The original fix option.
|
411
373
|
* @param {Set<string>} fixTypesSet A set of fix types to filter messages for fixing.
|
412
|
-
* @param {
|
374
|
+
* @param {FlatConfigArray} config The config for the file that generated the message.
|
413
375
|
* @returns {Function|boolean} The fixer function or the original fix value.
|
414
376
|
*/
|
415
377
|
function getFixerForFixTypes(fix, fixTypesSet, config) {
|
416
|
-
|
417
|
-
|
418
|
-
|
378
|
+
if (!fix || !fixTypesSet) {
|
379
|
+
return fix;
|
380
|
+
}
|
419
381
|
|
420
|
-
|
382
|
+
const originalFix = typeof fix === "function" ? fix : () => true;
|
421
383
|
|
422
|
-
|
384
|
+
return message =>
|
385
|
+
shouldMessageBeFixed(message, config, fixTypesSet) &&
|
386
|
+
originalFix(message);
|
423
387
|
}
|
424
388
|
|
425
389
|
//-----------------------------------------------------------------------------
|
@@ -430,679 +394,737 @@ function getFixerForFixTypes(fix, fixTypesSet, config) {
|
|
430
394
|
* Primary Node.js API for ESLint.
|
431
395
|
*/
|
432
396
|
class ESLint {
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
397
|
+
/**
|
398
|
+
* The type of configuration used by this class.
|
399
|
+
* @type {string}
|
400
|
+
*/
|
401
|
+
static configType = "flat";
|
402
|
+
|
403
|
+
/**
|
404
|
+
* The loader to use for finding config files.
|
405
|
+
* @type {ConfigLoader|LegacyConfigLoader}
|
406
|
+
*/
|
407
|
+
#configLoader;
|
408
|
+
|
409
|
+
/**
|
410
|
+
* Creates a new instance of the main ESLint API.
|
411
|
+
* @param {ESLintOptions} options The options for this instance.
|
412
|
+
*/
|
413
|
+
constructor(options = {}) {
|
414
|
+
const defaultConfigs = [];
|
415
|
+
const processedOptions = processOptions(options);
|
416
|
+
const linter = new Linter({
|
417
|
+
cwd: processedOptions.cwd,
|
418
|
+
configType: "flat",
|
419
|
+
flags: processedOptions.flags,
|
420
|
+
});
|
421
|
+
|
422
|
+
const cacheFilePath = getCacheFile(
|
423
|
+
processedOptions.cacheLocation,
|
424
|
+
processedOptions.cwd,
|
425
|
+
);
|
426
|
+
|
427
|
+
const lintResultCache = processedOptions.cache
|
428
|
+
? new LintResultCache(cacheFilePath, processedOptions.cacheStrategy)
|
429
|
+
: null;
|
430
|
+
|
431
|
+
const configLoaderOptions = {
|
432
|
+
cwd: processedOptions.cwd,
|
433
|
+
baseConfig: processedOptions.baseConfig,
|
434
|
+
overrideConfig: processedOptions.overrideConfig,
|
435
|
+
configFile: processedOptions.configFile,
|
436
|
+
ignoreEnabled: processedOptions.ignore,
|
437
|
+
ignorePatterns: processedOptions.ignorePatterns,
|
438
|
+
defaultConfigs,
|
439
|
+
hasUnstableNativeNodeJsTSConfigFlag: linter.hasFlag(
|
440
|
+
"unstable_native_nodejs_ts_config",
|
441
|
+
),
|
442
|
+
};
|
443
|
+
|
444
|
+
this.#configLoader = linter.hasFlag("unstable_config_lookup_from_file")
|
445
|
+
? new ConfigLoader(configLoaderOptions)
|
446
|
+
: new LegacyConfigLoader(configLoaderOptions);
|
447
|
+
|
448
|
+
debug(`Using config loader ${this.#configLoader.constructor.name}`);
|
449
|
+
|
450
|
+
privateMembers.set(this, {
|
451
|
+
options: processedOptions,
|
452
|
+
linter,
|
453
|
+
cacheFilePath,
|
454
|
+
lintResultCache,
|
455
|
+
defaultConfigs,
|
456
|
+
configs: null,
|
457
|
+
configLoader: this.#configLoader,
|
458
|
+
});
|
459
|
+
|
460
|
+
/**
|
461
|
+
* If additional plugins are passed in, add that to the default
|
462
|
+
* configs for this instance.
|
463
|
+
*/
|
464
|
+
if (options.plugins) {
|
465
|
+
const plugins = {};
|
466
|
+
|
467
|
+
for (const [pluginName, plugin] of Object.entries(
|
468
|
+
options.plugins,
|
469
|
+
)) {
|
470
|
+
plugins[naming.getShorthandName(pluginName, "eslint-plugin")] =
|
471
|
+
plugin;
|
472
|
+
}
|
473
|
+
|
474
|
+
defaultConfigs.push({
|
475
|
+
plugins,
|
476
|
+
});
|
477
|
+
}
|
478
|
+
|
479
|
+
// Check for the .eslintignore file, and warn if it's present.
|
480
|
+
if (existsSync(path.resolve(processedOptions.cwd, ".eslintignore"))) {
|
481
|
+
process.emitWarning(
|
482
|
+
'The ".eslintignore" file is no longer supported. Switch to using the "ignores" property in "eslint.config.js": https://eslint.org/docs/latest/use/configure/migration-guide#ignoring-files',
|
483
|
+
"ESLintIgnoreWarning",
|
484
|
+
);
|
485
|
+
}
|
486
|
+
}
|
487
|
+
|
488
|
+
/**
|
489
|
+
* The version text.
|
490
|
+
* @type {string}
|
491
|
+
*/
|
492
|
+
static get version() {
|
493
|
+
return version;
|
494
|
+
}
|
495
|
+
|
496
|
+
/**
|
497
|
+
* The default configuration that ESLint uses internally. This is provided for tooling that wants to calculate configurations using the same defaults as ESLint.
|
498
|
+
* Keep in mind that the default configuration may change from version to version, so you shouldn't rely on any particular keys or values to be present.
|
499
|
+
* @type {ConfigArray}
|
500
|
+
*/
|
501
|
+
static get defaultConfig() {
|
502
|
+
return defaultConfig;
|
503
|
+
}
|
504
|
+
|
505
|
+
/**
|
506
|
+
* Outputs fixes from the given results to files.
|
507
|
+
* @param {LintResult[]} results The lint results.
|
508
|
+
* @returns {Promise<void>} Returns a promise that is used to track side effects.
|
509
|
+
*/
|
510
|
+
static async outputFixes(results) {
|
511
|
+
if (!Array.isArray(results)) {
|
512
|
+
throw new Error("'results' must be an array");
|
513
|
+
}
|
514
|
+
|
515
|
+
await Promise.all(
|
516
|
+
results
|
517
|
+
.filter(result => {
|
518
|
+
if (typeof result !== "object" || result === null) {
|
519
|
+
throw new Error("'results' must include only objects");
|
520
|
+
}
|
521
|
+
return (
|
522
|
+
typeof result.output === "string" &&
|
523
|
+
path.isAbsolute(result.filePath)
|
524
|
+
);
|
525
|
+
})
|
526
|
+
.map(r => fs.writeFile(r.filePath, r.output)),
|
527
|
+
);
|
528
|
+
}
|
529
|
+
|
530
|
+
/**
|
531
|
+
* Returns results that only contains errors.
|
532
|
+
* @param {LintResult[]} results The results to filter.
|
533
|
+
* @returns {LintResult[]} The filtered results.
|
534
|
+
*/
|
535
|
+
static getErrorResults(results) {
|
536
|
+
const filtered = [];
|
537
|
+
|
538
|
+
results.forEach(result => {
|
539
|
+
const filteredMessages = result.messages.filter(isErrorMessage);
|
540
|
+
const filteredSuppressedMessages =
|
541
|
+
result.suppressedMessages.filter(isErrorMessage);
|
542
|
+
|
543
|
+
if (filteredMessages.length > 0) {
|
544
|
+
filtered.push({
|
545
|
+
...result,
|
546
|
+
messages: filteredMessages,
|
547
|
+
suppressedMessages: filteredSuppressedMessages,
|
548
|
+
errorCount: filteredMessages.length,
|
549
|
+
warningCount: 0,
|
550
|
+
fixableErrorCount: result.fixableErrorCount,
|
551
|
+
fixableWarningCount: 0,
|
552
|
+
});
|
553
|
+
}
|
554
|
+
});
|
555
|
+
|
556
|
+
return filtered;
|
557
|
+
}
|
558
|
+
|
559
|
+
/**
|
560
|
+
* Returns meta objects for each rule represented in the lint results.
|
561
|
+
* @param {LintResult[]} results The results to fetch rules meta for.
|
562
|
+
* @returns {Object} A mapping of ruleIds to rule meta objects.
|
563
|
+
* @throws {TypeError} When the results object wasn't created from this ESLint instance.
|
564
|
+
* @throws {TypeError} When a plugin or rule is missing.
|
565
|
+
*/
|
566
|
+
getRulesMetaForResults(results) {
|
567
|
+
// short-circuit simple case
|
568
|
+
if (results.length === 0) {
|
569
|
+
return {};
|
570
|
+
}
|
571
|
+
|
572
|
+
const resultRules = new Map();
|
573
|
+
const {
|
574
|
+
configLoader,
|
575
|
+
options: { cwd },
|
576
|
+
} = privateMembers.get(this);
|
577
|
+
|
578
|
+
for (const result of results) {
|
579
|
+
/*
|
580
|
+
* Normalize filename for <text>.
|
581
|
+
*/
|
582
|
+
const filePath =
|
583
|
+
result.filePath === "<text>"
|
584
|
+
? getPlaceholderPath(cwd)
|
585
|
+
: result.filePath;
|
586
|
+
const allMessages = result.messages.concat(
|
587
|
+
result.suppressedMessages,
|
588
|
+
);
|
589
|
+
|
590
|
+
for (const { ruleId } of allMessages) {
|
591
|
+
if (!ruleId) {
|
592
|
+
continue;
|
593
|
+
}
|
594
|
+
|
595
|
+
/*
|
596
|
+
* All of the plugin and rule information is contained within the
|
597
|
+
* calculated config for the given file.
|
598
|
+
*/
|
599
|
+
let configs;
|
600
|
+
|
601
|
+
try {
|
602
|
+
configs =
|
603
|
+
configLoader.getCachedConfigArrayForFile(filePath);
|
604
|
+
} catch {
|
605
|
+
throw createExtraneousResultsError();
|
606
|
+
}
|
607
|
+
|
608
|
+
const config = configs.getConfig(filePath);
|
609
|
+
|
610
|
+
if (!config) {
|
611
|
+
throw createExtraneousResultsError();
|
612
|
+
}
|
613
|
+
const rule = getRuleFromConfig(ruleId, config);
|
614
|
+
|
615
|
+
// ignore unknown rules
|
616
|
+
if (rule) {
|
617
|
+
resultRules.set(ruleId, rule);
|
618
|
+
}
|
619
|
+
}
|
620
|
+
}
|
621
|
+
|
622
|
+
return createRulesMeta(resultRules);
|
623
|
+
}
|
624
|
+
|
625
|
+
/**
|
626
|
+
* Indicates if the given feature flag is enabled for this instance.
|
627
|
+
* @param {string} flag The feature flag to check.
|
628
|
+
* @returns {boolean} `true` if the feature flag is enabled, `false` if not.
|
629
|
+
*/
|
630
|
+
hasFlag(flag) {
|
631
|
+
// note: Linter does validation of the flags
|
632
|
+
return privateMembers.get(this).linter.hasFlag(flag);
|
633
|
+
}
|
634
|
+
|
635
|
+
/**
|
636
|
+
* Executes the current configuration on an array of file and directory names.
|
637
|
+
* @param {string|string[]} patterns An array of file and directory names.
|
638
|
+
* @returns {Promise<LintResult[]>} The results of linting the file patterns given.
|
639
|
+
*/
|
640
|
+
async lintFiles(patterns) {
|
641
|
+
let normalizedPatterns = patterns;
|
642
|
+
const {
|
643
|
+
cacheFilePath,
|
644
|
+
lintResultCache,
|
645
|
+
linter,
|
646
|
+
options: eslintOptions,
|
647
|
+
} = privateMembers.get(this);
|
648
|
+
|
649
|
+
/*
|
650
|
+
* Special cases:
|
651
|
+
* 1. `patterns` is an empty string
|
652
|
+
* 2. `patterns` is an empty array
|
653
|
+
*
|
654
|
+
* In both cases, we use the cwd as the directory to lint.
|
655
|
+
*/
|
656
|
+
if (
|
657
|
+
patterns === "" ||
|
658
|
+
(Array.isArray(patterns) && patterns.length === 0)
|
659
|
+
) {
|
660
|
+
/*
|
661
|
+
* Special case: If `passOnNoPatterns` is true, then we just exit
|
662
|
+
* without doing any work.
|
663
|
+
*/
|
664
|
+
if (eslintOptions.passOnNoPatterns) {
|
665
|
+
return [];
|
666
|
+
}
|
667
|
+
|
668
|
+
normalizedPatterns = ["."];
|
669
|
+
} else {
|
670
|
+
if (
|
671
|
+
!isNonEmptyString(patterns) &&
|
672
|
+
!isArrayOfNonEmptyString(patterns)
|
673
|
+
) {
|
674
|
+
throw new Error(
|
675
|
+
"'patterns' must be a non-empty string or an array of non-empty strings",
|
676
|
+
);
|
677
|
+
}
|
678
|
+
|
679
|
+
if (typeof patterns === "string") {
|
680
|
+
normalizedPatterns = [patterns];
|
681
|
+
}
|
682
|
+
}
|
683
|
+
|
684
|
+
debug(`Using file patterns: ${normalizedPatterns}`);
|
685
|
+
|
686
|
+
const {
|
687
|
+
allowInlineConfig,
|
688
|
+
cache,
|
689
|
+
cwd,
|
690
|
+
fix,
|
691
|
+
fixTypes,
|
692
|
+
ruleFilter,
|
693
|
+
stats,
|
694
|
+
globInputPaths,
|
695
|
+
errorOnUnmatchedPattern,
|
696
|
+
warnIgnored,
|
697
|
+
} = eslintOptions;
|
698
|
+
const startTime = Date.now();
|
699
|
+
const fixTypesSet = fixTypes ? new Set(fixTypes) : null;
|
700
|
+
|
701
|
+
// Delete cache file; should this be done here?
|
702
|
+
if (!cache && cacheFilePath) {
|
703
|
+
debug(`Deleting cache file at ${cacheFilePath}`);
|
704
|
+
|
705
|
+
try {
|
706
|
+
await fs.unlink(cacheFilePath);
|
707
|
+
} catch (error) {
|
708
|
+
const errorCode = error && error.code;
|
709
|
+
|
710
|
+
// Ignore errors when no such file exists or file system is read only (and cache file does not exist)
|
711
|
+
if (
|
712
|
+
errorCode !== "ENOENT" &&
|
713
|
+
!(errorCode === "EROFS" && !existsSync(cacheFilePath))
|
714
|
+
) {
|
715
|
+
throw error;
|
716
|
+
}
|
717
|
+
}
|
718
|
+
}
|
719
|
+
|
720
|
+
const filePaths = await findFiles({
|
721
|
+
patterns: normalizedPatterns,
|
722
|
+
cwd,
|
723
|
+
globInputPaths,
|
724
|
+
configLoader: this.#configLoader,
|
725
|
+
errorOnUnmatchedPattern,
|
726
|
+
});
|
727
|
+
const controller = new AbortController();
|
728
|
+
const retryCodes = new Set(["ENFILE", "EMFILE"]);
|
729
|
+
const retrier = new Retrier(error => retryCodes.has(error.code), {
|
730
|
+
concurrency: 100,
|
731
|
+
});
|
732
|
+
|
733
|
+
debug(
|
734
|
+
`${filePaths.length} files found in: ${Date.now() - startTime}ms`,
|
735
|
+
);
|
736
|
+
|
737
|
+
/*
|
738
|
+
* Because we need to process multiple files, including reading from disk,
|
739
|
+
* it is most efficient to start by reading each file via promises so that
|
740
|
+
* they can be done in parallel. Then, we can lint the returned text. This
|
741
|
+
* ensures we are waiting the minimum amount of time in between lints.
|
742
|
+
*/
|
743
|
+
const results = await Promise.all(
|
744
|
+
filePaths.map(async filePath => {
|
745
|
+
const configs =
|
746
|
+
await this.#configLoader.loadConfigArrayForFile(filePath);
|
747
|
+
const config = configs.getConfig(filePath);
|
748
|
+
|
749
|
+
/*
|
750
|
+
* If a filename was entered that cannot be matched
|
751
|
+
* to a config, then notify the user.
|
752
|
+
*/
|
753
|
+
if (!config) {
|
754
|
+
if (warnIgnored) {
|
755
|
+
const configStatus = configs.getConfigStatus(filePath);
|
756
|
+
|
757
|
+
return createIgnoreResult(filePath, cwd, configStatus);
|
758
|
+
}
|
759
|
+
|
760
|
+
return void 0;
|
761
|
+
}
|
762
|
+
|
763
|
+
// Skip if there is cached result.
|
764
|
+
if (lintResultCache) {
|
765
|
+
const cachedResult = lintResultCache.getCachedLintResults(
|
766
|
+
filePath,
|
767
|
+
config,
|
768
|
+
);
|
769
|
+
|
770
|
+
if (cachedResult) {
|
771
|
+
const hadMessages =
|
772
|
+
cachedResult.messages &&
|
773
|
+
cachedResult.messages.length > 0;
|
774
|
+
|
775
|
+
if (hadMessages && fix) {
|
776
|
+
debug(
|
777
|
+
`Reprocessing cached file to allow autofix: ${filePath}`,
|
778
|
+
);
|
779
|
+
} else {
|
780
|
+
debug(
|
781
|
+
`Skipping file since it hasn't changed: ${filePath}`,
|
782
|
+
);
|
783
|
+
return cachedResult;
|
784
|
+
}
|
785
|
+
}
|
786
|
+
}
|
787
|
+
|
788
|
+
// set up fixer for fixTypes if necessary
|
789
|
+
const fixer = getFixerForFixTypes(fix, fixTypesSet, config);
|
790
|
+
|
791
|
+
return retrier
|
792
|
+
.retry(
|
793
|
+
() =>
|
794
|
+
fs
|
795
|
+
.readFile(filePath, {
|
796
|
+
encoding: "utf8",
|
797
|
+
signal: controller.signal,
|
798
|
+
})
|
799
|
+
.then(text => {
|
800
|
+
// fail immediately if an error occurred in another file
|
801
|
+
controller.signal.throwIfAborted();
|
802
|
+
|
803
|
+
// do the linting
|
804
|
+
const result = verifyText({
|
805
|
+
text,
|
806
|
+
filePath,
|
807
|
+
configs,
|
808
|
+
cwd,
|
809
|
+
fix: fixer,
|
810
|
+
allowInlineConfig,
|
811
|
+
ruleFilter,
|
812
|
+
stats,
|
813
|
+
linter,
|
814
|
+
});
|
815
|
+
|
816
|
+
/*
|
817
|
+
* Store the lint result in the LintResultCache.
|
818
|
+
* NOTE: The LintResultCache will remove the file source and any
|
819
|
+
* other properties that are difficult to serialize, and will
|
820
|
+
* hydrate those properties back in on future lint runs.
|
821
|
+
*/
|
822
|
+
if (lintResultCache) {
|
823
|
+
lintResultCache.setCachedLintResults(
|
824
|
+
filePath,
|
825
|
+
config,
|
826
|
+
result,
|
827
|
+
);
|
828
|
+
}
|
829
|
+
|
830
|
+
return result;
|
831
|
+
}),
|
832
|
+
{ signal: controller.signal },
|
833
|
+
)
|
834
|
+
.catch(error => {
|
835
|
+
controller.abort(error);
|
836
|
+
throw error;
|
837
|
+
});
|
838
|
+
}),
|
839
|
+
);
|
840
|
+
|
841
|
+
// Persist the cache to disk.
|
842
|
+
if (lintResultCache) {
|
843
|
+
lintResultCache.reconcile();
|
844
|
+
}
|
845
|
+
|
846
|
+
const finalResults = results.filter(result => !!result);
|
847
|
+
|
848
|
+
return processLintReport(this, {
|
849
|
+
results: finalResults,
|
850
|
+
});
|
851
|
+
}
|
852
|
+
|
853
|
+
/**
|
854
|
+
* Executes the current configuration on text.
|
855
|
+
* @param {string} code A string of JavaScript code to lint.
|
856
|
+
* @param {Object} [options] The options.
|
857
|
+
* @param {string} [options.filePath] The path to the file of the source code.
|
858
|
+
* @param {boolean} [options.warnIgnored] When set to true, warn if given filePath is an ignored path.
|
859
|
+
* @returns {Promise<LintResult[]>} The results of linting the string of code given.
|
860
|
+
*/
|
861
|
+
async lintText(code, options = {}) {
|
862
|
+
// Parameter validation
|
863
|
+
|
864
|
+
if (typeof code !== "string") {
|
865
|
+
throw new Error("'code' must be a string");
|
866
|
+
}
|
867
|
+
|
868
|
+
if (typeof options !== "object") {
|
869
|
+
throw new Error("'options' must be an object, null, or undefined");
|
870
|
+
}
|
871
|
+
|
872
|
+
// Options validation
|
873
|
+
|
874
|
+
const { filePath, warnIgnored, ...unknownOptions } = options || {};
|
875
|
+
|
876
|
+
const unknownOptionKeys = Object.keys(unknownOptions);
|
877
|
+
|
878
|
+
if (unknownOptionKeys.length > 0) {
|
879
|
+
throw new Error(
|
880
|
+
`'options' must not include the unknown option(s): ${unknownOptionKeys.join(", ")}`,
|
881
|
+
);
|
882
|
+
}
|
883
|
+
|
884
|
+
if (filePath !== void 0 && !isNonEmptyString(filePath)) {
|
885
|
+
throw new Error(
|
886
|
+
"'options.filePath' must be a non-empty string or undefined",
|
887
|
+
);
|
888
|
+
}
|
889
|
+
|
890
|
+
if (
|
891
|
+
typeof warnIgnored !== "boolean" &&
|
892
|
+
typeof warnIgnored !== "undefined"
|
893
|
+
) {
|
894
|
+
throw new Error(
|
895
|
+
"'options.warnIgnored' must be a boolean or undefined",
|
896
|
+
);
|
897
|
+
}
|
898
|
+
|
899
|
+
// Now we can get down to linting
|
900
|
+
|
901
|
+
const { linter, options: eslintOptions } = privateMembers.get(this);
|
902
|
+
const {
|
903
|
+
allowInlineConfig,
|
904
|
+
cwd,
|
905
|
+
fix,
|
906
|
+
fixTypes,
|
907
|
+
warnIgnored: constructorWarnIgnored,
|
908
|
+
ruleFilter,
|
909
|
+
stats,
|
910
|
+
} = eslintOptions;
|
911
|
+
const results = [];
|
912
|
+
const startTime = Date.now();
|
913
|
+
const fixTypesSet = fixTypes ? new Set(fixTypes) : null;
|
914
|
+
const resolvedFilename = path.resolve(
|
915
|
+
cwd,
|
916
|
+
filePath || "__placeholder__.js",
|
917
|
+
);
|
918
|
+
const configs =
|
919
|
+
await this.#configLoader.loadConfigArrayForFile(resolvedFilename);
|
920
|
+
const configStatus =
|
921
|
+
configs?.getConfigStatus(resolvedFilename) ?? "unconfigured";
|
922
|
+
|
923
|
+
// Clear the last used config arrays.
|
924
|
+
if (resolvedFilename && configStatus !== "matched") {
|
925
|
+
const shouldWarnIgnored =
|
926
|
+
typeof warnIgnored === "boolean"
|
927
|
+
? warnIgnored
|
928
|
+
: constructorWarnIgnored;
|
929
|
+
|
930
|
+
if (shouldWarnIgnored) {
|
931
|
+
results.push(
|
932
|
+
createIgnoreResult(resolvedFilename, cwd, configStatus),
|
933
|
+
);
|
934
|
+
}
|
935
|
+
} else {
|
936
|
+
const config = configs.getConfig(resolvedFilename);
|
937
|
+
const fixer = getFixerForFixTypes(fix, fixTypesSet, config);
|
938
|
+
|
939
|
+
// Do lint.
|
940
|
+
results.push(
|
941
|
+
verifyText({
|
942
|
+
text: code,
|
943
|
+
filePath: resolvedFilename.endsWith("__placeholder__.js")
|
944
|
+
? "<text>"
|
945
|
+
: resolvedFilename,
|
946
|
+
configs,
|
947
|
+
cwd,
|
948
|
+
fix: fixer,
|
949
|
+
allowInlineConfig,
|
950
|
+
ruleFilter,
|
951
|
+
stats,
|
952
|
+
linter,
|
953
|
+
}),
|
954
|
+
);
|
955
|
+
}
|
956
|
+
|
957
|
+
debug(`Linting complete in: ${Date.now() - startTime}ms`);
|
958
|
+
|
959
|
+
return processLintReport(this, {
|
960
|
+
results,
|
961
|
+
});
|
962
|
+
}
|
963
|
+
|
964
|
+
/**
|
965
|
+
* Returns the formatter representing the given formatter name.
|
966
|
+
* @param {string} [name] The name of the formatter to load.
|
967
|
+
* The following values are allowed:
|
968
|
+
* - `undefined` ... Load `stylish` builtin formatter.
|
969
|
+
* - A builtin formatter name ... Load the builtin formatter.
|
970
|
+
* - A third-party formatter name:
|
971
|
+
* - `foo` → `eslint-formatter-foo`
|
972
|
+
* - `@foo` → `@foo/eslint-formatter`
|
973
|
+
* - `@foo/bar` → `@foo/eslint-formatter-bar`
|
974
|
+
* - A file path ... Load the file.
|
975
|
+
* @returns {Promise<Formatter>} A promise resolving to the formatter object.
|
976
|
+
* This promise will be rejected if the given formatter was not found or not
|
977
|
+
* a function.
|
978
|
+
*/
|
979
|
+
async loadFormatter(name = "stylish") {
|
980
|
+
if (typeof name !== "string") {
|
981
|
+
throw new Error("'name' must be a string");
|
982
|
+
}
|
983
|
+
|
984
|
+
// replace \ with / for Windows compatibility
|
985
|
+
const normalizedFormatName = name.replace(/\\/gu, "/");
|
986
|
+
const namespace = naming.getNamespaceFromTerm(normalizedFormatName);
|
987
|
+
|
988
|
+
// grab our options
|
989
|
+
const { cwd } = privateMembers.get(this).options;
|
990
|
+
|
991
|
+
let formatterPath;
|
992
|
+
|
993
|
+
// if there's a slash, then it's a file (TODO: this check seems dubious for scoped npm packages)
|
994
|
+
if (!namespace && normalizedFormatName.includes("/")) {
|
995
|
+
formatterPath = path.resolve(cwd, normalizedFormatName);
|
996
|
+
} else {
|
997
|
+
try {
|
998
|
+
const npmFormat = naming.normalizePackageName(
|
999
|
+
normalizedFormatName,
|
1000
|
+
"eslint-formatter",
|
1001
|
+
);
|
1002
|
+
|
1003
|
+
// TODO: This is pretty dirty...would be nice to clean up at some point.
|
1004
|
+
formatterPath = ModuleResolver.resolve(
|
1005
|
+
npmFormat,
|
1006
|
+
getPlaceholderPath(cwd),
|
1007
|
+
);
|
1008
|
+
} catch {
|
1009
|
+
formatterPath = path.resolve(
|
1010
|
+
__dirname,
|
1011
|
+
"../",
|
1012
|
+
"cli-engine",
|
1013
|
+
"formatters",
|
1014
|
+
`${normalizedFormatName}.js`,
|
1015
|
+
);
|
1016
|
+
}
|
1017
|
+
}
|
1018
|
+
|
1019
|
+
let formatter;
|
1020
|
+
|
1021
|
+
try {
|
1022
|
+
formatter = (await import(pathToFileURL(formatterPath))).default;
|
1023
|
+
} catch (ex) {
|
1024
|
+
// check for formatters that have been removed
|
1025
|
+
if (removedFormatters.has(name)) {
|
1026
|
+
ex.message = `The ${name} formatter is no longer part of core ESLint. Install it manually with \`npm install -D eslint-formatter-${name}\``;
|
1027
|
+
} else {
|
1028
|
+
ex.message = `There was a problem loading formatter: ${formatterPath}\nError: ${ex.message}`;
|
1029
|
+
}
|
1030
|
+
|
1031
|
+
throw ex;
|
1032
|
+
}
|
1033
|
+
|
1034
|
+
if (typeof formatter !== "function") {
|
1035
|
+
throw new TypeError(
|
1036
|
+
`Formatter must be a function, but got a ${typeof formatter}.`,
|
1037
|
+
);
|
1038
|
+
}
|
1039
|
+
|
1040
|
+
const eslint = this;
|
1041
|
+
|
1042
|
+
return {
|
1043
|
+
/**
|
1044
|
+
* The main formatter method.
|
1045
|
+
* @param {LintResult[]} results The lint results to format.
|
1046
|
+
* @param {ResultsMeta} resultsMeta Warning count and max threshold.
|
1047
|
+
* @returns {string} The formatted lint results.
|
1048
|
+
*/
|
1049
|
+
format(results, resultsMeta) {
|
1050
|
+
let rulesMeta = null;
|
1051
|
+
|
1052
|
+
results.sort(compareResultsByFilePath);
|
1053
|
+
|
1054
|
+
return formatter(results, {
|
1055
|
+
...resultsMeta,
|
1056
|
+
cwd,
|
1057
|
+
get rulesMeta() {
|
1058
|
+
if (!rulesMeta) {
|
1059
|
+
rulesMeta = eslint.getRulesMetaForResults(results);
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
return rulesMeta;
|
1063
|
+
},
|
1064
|
+
});
|
1065
|
+
},
|
1066
|
+
};
|
1067
|
+
}
|
1068
|
+
|
1069
|
+
/**
|
1070
|
+
* Returns a configuration object for the given file based on the CLI options.
|
1071
|
+
* This is the same logic used by the ESLint CLI executable to determine
|
1072
|
+
* configuration for each file it processes.
|
1073
|
+
* @param {string} filePath The path of the file to retrieve a config object for.
|
1074
|
+
* @returns {Promise<ConfigData|undefined>} A configuration object for the file
|
1075
|
+
* or `undefined` if there is no configuration data for the object.
|
1076
|
+
*/
|
1077
|
+
async calculateConfigForFile(filePath) {
|
1078
|
+
if (!isNonEmptyString(filePath)) {
|
1079
|
+
throw new Error("'filePath' must be a non-empty string");
|
1080
|
+
}
|
1081
|
+
const options = privateMembers.get(this).options;
|
1082
|
+
const absolutePath = path.resolve(options.cwd, filePath);
|
1083
|
+
const configs =
|
1084
|
+
await this.#configLoader.loadConfigArrayForFile(absolutePath);
|
1085
|
+
|
1086
|
+
if (!configs) {
|
1087
|
+
const error = new Error("Could not find config file.");
|
1088
|
+
|
1089
|
+
error.messageTemplate = "config-file-missing";
|
1090
|
+
throw error;
|
1091
|
+
}
|
1092
|
+
|
1093
|
+
return configs.getConfig(absolutePath);
|
1094
|
+
}
|
1095
|
+
|
1096
|
+
/**
|
1097
|
+
* Finds the config file being used by this instance based on the options
|
1098
|
+
* passed to the constructor.
|
1099
|
+
* @param {string} [filePath] The path of the file to find the config file for.
|
1100
|
+
* @returns {Promise<string|undefined>} The path to the config file being used or
|
1101
|
+
* `undefined` if no config file is being used.
|
1102
|
+
*/
|
1103
|
+
findConfigFile(filePath) {
|
1104
|
+
const options = privateMembers.get(this).options;
|
1105
|
+
|
1106
|
+
/*
|
1107
|
+
* Because the new config lookup scheme skips the current directory
|
1108
|
+
* and looks into the parent directories, we need to use a placeholder
|
1109
|
+
* directory to ensure the file in cwd is checked.
|
1110
|
+
*/
|
1111
|
+
const fakeCwd = path.join(options.cwd, "__placeholder__");
|
1112
|
+
|
1113
|
+
return this.#configLoader
|
1114
|
+
.findConfigFileForPath(filePath ?? fakeCwd)
|
1115
|
+
.catch(() => void 0);
|
1116
|
+
}
|
1117
|
+
|
1118
|
+
/**
|
1119
|
+
* Checks if a given path is ignored by ESLint.
|
1120
|
+
* @param {string} filePath The path of the file to check.
|
1121
|
+
* @returns {Promise<boolean>} Whether or not the given path is ignored.
|
1122
|
+
*/
|
1123
|
+
async isPathIgnored(filePath) {
|
1124
|
+
const config = await this.calculateConfigForFile(filePath);
|
1125
|
+
|
1126
|
+
return config === void 0;
|
1127
|
+
}
|
1106
1128
|
}
|
1107
1129
|
|
1108
1130
|
/**
|
@@ -1110,7 +1132,7 @@ class ESLint {
|
|
1110
1132
|
* @returns {Promise<boolean>} Whether flat config should be used.
|
1111
1133
|
*/
|
1112
1134
|
async function shouldUseFlatConfig() {
|
1113
|
-
|
1135
|
+
return process.env.ESLINT_USE_FLAT_CONFIG !== "false";
|
1114
1136
|
}
|
1115
1137
|
|
1116
1138
|
//------------------------------------------------------------------------------
|
@@ -1118,7 +1140,7 @@ async function shouldUseFlatConfig() {
|
|
1118
1140
|
//------------------------------------------------------------------------------
|
1119
1141
|
|
1120
1142
|
module.exports = {
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1143
|
+
ESLint,
|
1144
|
+
shouldUseFlatConfig,
|
1145
|
+
locateConfigFileToUse,
|
1124
1146
|
};
|