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