eslint 9.22.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 +47 -45
- 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 +2 -2
- 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 +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 +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 -198
- 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/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 +11 -17
package/lib/linter/linter.js
CHANGED
@@ -10,46 +10,55 @@
|
|
10
10
|
// Requirements
|
11
11
|
//------------------------------------------------------------------------------
|
12
12
|
|
13
|
-
const
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
ruleReplacements = require("../../conf/replacements.json");
|
13
|
+
const path = require("node:path"),
|
14
|
+
eslintScope = require("eslint-scope"),
|
15
|
+
evk = require("eslint-visitor-keys"),
|
16
|
+
espree = require("espree"),
|
17
|
+
merge = require("lodash.merge"),
|
18
|
+
pkg = require("../../package.json"),
|
19
|
+
{
|
20
|
+
Legacy: {
|
21
|
+
ConfigOps,
|
22
|
+
ConfigValidator,
|
23
|
+
environments: BuiltInEnvironments,
|
24
|
+
},
|
25
|
+
} = require("@eslint/eslintrc/universal"),
|
26
|
+
Traverser = require("../shared/traverser"),
|
27
|
+
{ SourceCode } = require("../languages/js/source-code"),
|
28
|
+
applyDisableDirectives = require("./apply-disable-directives"),
|
29
|
+
{ ConfigCommentParser } = require("@eslint/plugin-kit"),
|
30
|
+
NodeEventGenerator = require("./node-event-generator"),
|
31
|
+
createReportTranslator = require("./report-translator"),
|
32
|
+
Rules = require("./rules"),
|
33
|
+
createEmitter = require("./safe-emitter"),
|
34
|
+
SourceCodeFixer = require("./source-code-fixer"),
|
35
|
+
timing = require("./timing"),
|
36
|
+
ruleReplacements = require("../../conf/replacements.json");
|
38
37
|
const { getRuleFromConfig } = require("../config/flat-config-helpers");
|
39
38
|
const { FlatConfigArray } = require("../config/flat-config-array");
|
40
39
|
const { startTime, endTime } = require("../shared/stats");
|
41
40
|
const { RuleValidator } = require("../config/rule-validator");
|
42
41
|
const { assertIsRuleSeverity } = require("../config/flat-config-schema");
|
43
|
-
const {
|
42
|
+
const {
|
43
|
+
normalizeSeverityToString,
|
44
|
+
normalizeSeverityToNumber,
|
45
|
+
} = require("../shared/severity");
|
44
46
|
const { deepMergeArrays } = require("../shared/deep-merge-arrays");
|
45
47
|
const jslang = require("../languages/js");
|
46
|
-
const {
|
48
|
+
const {
|
49
|
+
activeFlags,
|
50
|
+
inactiveFlags,
|
51
|
+
getInactivityReasonMessage,
|
52
|
+
} = require("../shared/flags");
|
47
53
|
const debug = require("debug")("eslint:linter");
|
48
54
|
const MAX_AUTOFIX_PASSES = 10;
|
49
55
|
const DEFAULT_PARSER_NAME = "espree";
|
50
56
|
const DEFAULT_ECMA_VERSION = 5;
|
51
57
|
const commentParser = new ConfigCommentParser();
|
52
|
-
const DEFAULT_ERROR_LOC = {
|
58
|
+
const DEFAULT_ERROR_LOC = {
|
59
|
+
start: { line: 1, column: 0 },
|
60
|
+
end: { line: 1, column: 1 },
|
61
|
+
};
|
53
62
|
const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
54
63
|
const { LATEST_ECMA_VERSION } = require("../../conf/ecma-version");
|
55
64
|
const { VFile } = require("./vfile");
|
@@ -79,7 +88,6 @@ const STEP_KIND_CALL = 2;
|
|
79
88
|
/** @typedef {import("@eslint/core").RuleConfig} RuleConfig */
|
80
89
|
/** @typedef {import("../types").Linter.StringSeverity} StringSeverity */
|
81
90
|
|
82
|
-
|
83
91
|
/* eslint-disable jsdoc/valid-types -- https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/4#issuecomment-778805577 */
|
84
92
|
/**
|
85
93
|
* @template T
|
@@ -157,7 +165,7 @@ const STEP_KIND_CALL = 2;
|
|
157
165
|
* @returns {boolean} True if the parser is Espree or false if not.
|
158
166
|
*/
|
159
167
|
function isEspree(parser) {
|
160
|
-
|
168
|
+
return !!(parser === espree || parser[parserSymbol] === espree);
|
161
169
|
}
|
162
170
|
|
163
171
|
/**
|
@@ -169,72 +177,80 @@ function isEspree(parser) {
|
|
169
177
|
* @param {{exportedVariables: Object, enabledGlobals: Object}} commentDirectives Directives from comment configuration
|
170
178
|
* @returns {void}
|
171
179
|
*/
|
172
|
-
function addDeclaredGlobals(
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
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
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
180
|
+
function addDeclaredGlobals(
|
181
|
+
globalScope,
|
182
|
+
configGlobals,
|
183
|
+
{ exportedVariables, enabledGlobals },
|
184
|
+
) {
|
185
|
+
// Define configured global variables.
|
186
|
+
for (const id of new Set([
|
187
|
+
...Object.keys(configGlobals),
|
188
|
+
...Object.keys(enabledGlobals),
|
189
|
+
])) {
|
190
|
+
/*
|
191
|
+
* `ConfigOps.normalizeConfigGlobal` will throw an error if a configured global value is invalid. However, these errors would
|
192
|
+
* typically be caught when validating a config anyway (validity for inline global comments is checked separately).
|
193
|
+
*/
|
194
|
+
const configValue =
|
195
|
+
configGlobals[id] === void 0
|
196
|
+
? void 0
|
197
|
+
: ConfigOps.normalizeConfigGlobal(configGlobals[id]);
|
198
|
+
const commentValue = enabledGlobals[id] && enabledGlobals[id].value;
|
199
|
+
const value = commentValue || configValue;
|
200
|
+
const sourceComments =
|
201
|
+
enabledGlobals[id] && enabledGlobals[id].comments;
|
202
|
+
|
203
|
+
if (value === "off") {
|
204
|
+
continue;
|
205
|
+
}
|
206
|
+
|
207
|
+
let variable = globalScope.set.get(id);
|
208
|
+
|
209
|
+
if (!variable) {
|
210
|
+
variable = new eslintScope.Variable(id, globalScope);
|
211
|
+
|
212
|
+
globalScope.variables.push(variable);
|
213
|
+
globalScope.set.set(id, variable);
|
214
|
+
}
|
215
|
+
|
216
|
+
variable.eslintImplicitGlobalSetting = configValue;
|
217
|
+
variable.eslintExplicitGlobal = sourceComments !== void 0;
|
218
|
+
variable.eslintExplicitGlobalComments = sourceComments;
|
219
|
+
variable.writeable = value === "writable";
|
220
|
+
}
|
221
|
+
|
222
|
+
// mark all exported variables as such
|
223
|
+
Object.keys(exportedVariables).forEach(name => {
|
224
|
+
const variable = globalScope.set.get(name);
|
225
|
+
|
226
|
+
if (variable) {
|
227
|
+
variable.eslintUsed = true;
|
228
|
+
variable.eslintExported = true;
|
229
|
+
}
|
230
|
+
});
|
231
|
+
|
232
|
+
/*
|
233
|
+
* "through" contains all references which definitions cannot be found.
|
234
|
+
* Since we augment the global scope using configuration, we need to update
|
235
|
+
* references and remove the ones that were added by configuration.
|
236
|
+
*/
|
237
|
+
globalScope.through = globalScope.through.filter(reference => {
|
238
|
+
const name = reference.identifier.name;
|
239
|
+
const variable = globalScope.set.get(name);
|
240
|
+
|
241
|
+
if (variable) {
|
242
|
+
/*
|
243
|
+
* Links the variable and the reference.
|
244
|
+
* And this reference is removed from `Scope#through`.
|
245
|
+
*/
|
246
|
+
reference.resolved = variable;
|
247
|
+
variable.references.push(reference);
|
248
|
+
|
249
|
+
return false;
|
250
|
+
}
|
251
|
+
|
252
|
+
return true;
|
253
|
+
});
|
238
254
|
}
|
239
255
|
|
240
256
|
/**
|
@@ -244,9 +260,9 @@ function addDeclaredGlobals(globalScope, configGlobals, { exportedVariables, ena
|
|
244
260
|
* @private
|
245
261
|
*/
|
246
262
|
function createMissingRuleMessage(ruleId) {
|
247
|
-
|
248
|
-
|
249
|
-
|
263
|
+
return Object.hasOwn(ruleReplacements.rules, ruleId)
|
264
|
+
? `Rule '${ruleId}' was removed and replaced by: ${ruleReplacements.rules[ruleId].join(", ")}`
|
265
|
+
: `Definition for rule '${ruleId}' was not found.`;
|
250
266
|
}
|
251
267
|
|
252
268
|
/**
|
@@ -261,21 +277,24 @@ function createMissingRuleMessage(ruleId) {
|
|
261
277
|
* @param {Language} language The language to use to adjust the location information.
|
262
278
|
* @returns {Object} The updated location.
|
263
279
|
*/
|
264
|
-
function updateLocationInformation(
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
280
|
+
function updateLocationInformation(
|
281
|
+
{ line, column, endLine, endColumn },
|
282
|
+
language,
|
283
|
+
) {
|
284
|
+
const columnOffset = language.columnStart === 1 ? 0 : 1;
|
285
|
+
const lineOffset = language.lineStart === 1 ? 0 : 1;
|
286
|
+
|
287
|
+
// calculate separately to account for undefined
|
288
|
+
const finalEndLine = endLine === void 0 ? endLine : endLine + lineOffset;
|
289
|
+
const finalEndColumn =
|
290
|
+
endColumn === void 0 ? endColumn : endColumn + columnOffset;
|
291
|
+
|
292
|
+
return {
|
293
|
+
line: line + lineOffset,
|
294
|
+
column: column + columnOffset,
|
295
|
+
endLine: finalEndLine,
|
296
|
+
endColumn: finalEndColumn,
|
297
|
+
};
|
279
298
|
}
|
280
299
|
|
281
300
|
/**
|
@@ -290,31 +309,34 @@ function updateLocationInformation({ line, column, endLine, endColumn }, languag
|
|
290
309
|
* @private
|
291
310
|
*/
|
292
311
|
function createLintingProblem(options) {
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
312
|
+
const {
|
313
|
+
ruleId = null,
|
314
|
+
loc = DEFAULT_ERROR_LOC,
|
315
|
+
message = createMissingRuleMessage(options.ruleId),
|
316
|
+
severity = 2,
|
317
|
+
|
318
|
+
// fallback for eslintrc mode
|
319
|
+
language = {
|
320
|
+
columnStart: 0,
|
321
|
+
lineStart: 1,
|
322
|
+
},
|
323
|
+
} = options;
|
324
|
+
|
325
|
+
return {
|
326
|
+
ruleId,
|
327
|
+
message,
|
328
|
+
...updateLocationInformation(
|
329
|
+
{
|
330
|
+
line: loc.start.line,
|
331
|
+
column: loc.start.column,
|
332
|
+
endLine: loc.end.line,
|
333
|
+
endColumn: loc.end.column,
|
334
|
+
},
|
335
|
+
language,
|
336
|
+
),
|
337
|
+
severity,
|
338
|
+
nodeType: null,
|
339
|
+
};
|
318
340
|
}
|
319
341
|
|
320
342
|
/**
|
@@ -324,7 +346,7 @@ function createLintingProblem(options) {
|
|
324
346
|
* @returns {Array} The value as an array.
|
325
347
|
*/
|
326
348
|
function asArray(value) {
|
327
|
-
|
349
|
+
return Array.isArray(value) ? value : [value];
|
328
350
|
}
|
329
351
|
|
330
352
|
/**
|
@@ -338,39 +360,60 @@ function asArray(value) {
|
|
338
360
|
* @param {"error"|"warn"} severity The severity to report.
|
339
361
|
* @returns {void}
|
340
362
|
*/
|
341
|
-
function addProblemIfSameSeverityAndOptions(
|
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
|
-
|
363
|
+
function addProblemIfSameSeverityAndOptions(
|
364
|
+
config,
|
365
|
+
loc,
|
366
|
+
problems,
|
367
|
+
ruleId,
|
368
|
+
ruleOptions,
|
369
|
+
ruleOptionsInline,
|
370
|
+
severity,
|
371
|
+
) {
|
372
|
+
const existingConfigRaw = config.rules?.[ruleId];
|
373
|
+
const existingConfig = existingConfigRaw
|
374
|
+
? asArray(existingConfigRaw)
|
375
|
+
: ["off"];
|
376
|
+
const existingSeverity = normalizeSeverityToString(existingConfig[0]);
|
377
|
+
const inlineSeverity = normalizeSeverityToString(ruleOptions[0]);
|
378
|
+
const sameSeverity = existingSeverity === inlineSeverity;
|
379
|
+
|
380
|
+
if (!sameSeverity) {
|
381
|
+
return;
|
382
|
+
}
|
383
|
+
|
384
|
+
const alreadyConfigured = existingConfigRaw
|
385
|
+
? `is already configured to '${existingSeverity}'`
|
386
|
+
: "is not enabled so can't be turned off";
|
387
|
+
let message;
|
388
|
+
|
389
|
+
if (
|
390
|
+
(existingConfig.length === 1 && ruleOptions.length === 1) ||
|
391
|
+
existingSeverity === "off"
|
392
|
+
) {
|
393
|
+
message = `Unused inline config ('${ruleId}' ${alreadyConfigured}).`;
|
394
|
+
} else if (
|
395
|
+
!containsDifferentProperty(
|
396
|
+
ruleOptions.slice(1),
|
397
|
+
existingConfig.slice(1),
|
398
|
+
)
|
399
|
+
) {
|
400
|
+
message =
|
401
|
+
ruleOptionsInline.length === 1
|
402
|
+
? `Unused inline config ('${ruleId}' ${alreadyConfigured}).`
|
403
|
+
: `Unused inline config ('${ruleId}' ${alreadyConfigured} with the same options).`;
|
404
|
+
}
|
405
|
+
|
406
|
+
if (message) {
|
407
|
+
problems.push(
|
408
|
+
createLintingProblem({
|
409
|
+
ruleId: null,
|
410
|
+
message,
|
411
|
+
loc,
|
412
|
+
language: config.language,
|
413
|
+
severity: normalizeSeverityToNumber(severity),
|
414
|
+
}),
|
415
|
+
);
|
416
|
+
}
|
374
417
|
}
|
375
418
|
|
376
419
|
/**
|
@@ -386,57 +429,61 @@ function addProblemIfSameSeverityAndOptions(config, loc, problems, ruleId, ruleO
|
|
386
429
|
* @param {SourceCode} sourceCode The SourceCode object to get comments from.
|
387
430
|
* @returns {Object} Directives and problems from the comment
|
388
431
|
*/
|
389
|
-
function createDisableDirectives(
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
432
|
+
function createDisableDirectives(
|
433
|
+
{ type, value, justification, node },
|
434
|
+
ruleMapper,
|
435
|
+
language,
|
436
|
+
sourceCode,
|
437
|
+
) {
|
438
|
+
const ruleIds = Object.keys(commentParser.parseListConfig(value));
|
439
|
+
const directiveRules = ruleIds.length ? ruleIds : [null];
|
440
|
+
const result = {
|
441
|
+
directives: [], // valid disable directives
|
442
|
+
directiveProblems: [], // problems in directives
|
443
|
+
};
|
444
|
+
const parentDirective = { node, value, ruleIds };
|
445
|
+
|
446
|
+
for (const ruleId of directiveRules) {
|
447
|
+
const loc = sourceCode.getLoc(node);
|
448
|
+
|
449
|
+
// push to directives, if the rule is defined(including null, e.g. /*eslint enable*/)
|
450
|
+
if (ruleId === null || !!ruleMapper(ruleId)) {
|
451
|
+
if (type === "disable-next-line") {
|
452
|
+
const { line, column } = updateLocationInformation(
|
453
|
+
loc.end,
|
454
|
+
language,
|
455
|
+
);
|
456
|
+
|
457
|
+
result.directives.push({
|
458
|
+
parentDirective,
|
459
|
+
type,
|
460
|
+
line,
|
461
|
+
column,
|
462
|
+
ruleId,
|
463
|
+
justification,
|
464
|
+
});
|
465
|
+
} else {
|
466
|
+
const { line, column } = updateLocationInformation(
|
467
|
+
loc.start,
|
468
|
+
language,
|
469
|
+
);
|
470
|
+
|
471
|
+
result.directives.push({
|
472
|
+
parentDirective,
|
473
|
+
type,
|
474
|
+
line,
|
475
|
+
column,
|
476
|
+
ruleId,
|
477
|
+
justification,
|
478
|
+
});
|
479
|
+
}
|
480
|
+
} else {
|
481
|
+
result.directiveProblems.push(
|
482
|
+
createLintingProblem({ ruleId, loc, language }),
|
483
|
+
);
|
484
|
+
}
|
485
|
+
}
|
486
|
+
return result;
|
440
487
|
}
|
441
488
|
|
442
489
|
/**
|
@@ -450,223 +497,265 @@ function createDisableDirectives({ type, value, justification, node }, ruleMappe
|
|
450
497
|
* @returns {{configuredRules: Object, enabledGlobals: {value:string,comment:Token}[], exportedVariables: Object, problems: LintMessage[], disableDirectives: DisableDirective[]}}
|
451
498
|
* A collection of the directive comments that were found, along with any problems that occurred when parsing
|
452
499
|
*/
|
453
|
-
function getDirectiveComments(
|
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
|
-
|
500
|
+
function getDirectiveComments(
|
501
|
+
sourceCode,
|
502
|
+
ruleMapper,
|
503
|
+
warnInlineConfig,
|
504
|
+
config,
|
505
|
+
) {
|
506
|
+
const configuredRules = {};
|
507
|
+
const enabledGlobals = Object.create(null);
|
508
|
+
const exportedVariables = {};
|
509
|
+
const problems = [];
|
510
|
+
const disableDirectives = [];
|
511
|
+
const validator = new ConfigValidator({
|
512
|
+
builtInRules: Rules,
|
513
|
+
});
|
514
|
+
|
515
|
+
sourceCode
|
516
|
+
.getInlineConfigNodes()
|
517
|
+
.filter(token => token.type !== "Shebang")
|
518
|
+
.forEach(comment => {
|
519
|
+
const directive = commentParser.parseDirective(comment.value);
|
520
|
+
|
521
|
+
if (!directive) {
|
522
|
+
return;
|
523
|
+
}
|
524
|
+
|
525
|
+
const {
|
526
|
+
label,
|
527
|
+
value,
|
528
|
+
justification: justificationPart,
|
529
|
+
} = directive;
|
530
|
+
|
531
|
+
const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(
|
532
|
+
label,
|
533
|
+
);
|
534
|
+
|
535
|
+
if (comment.type === "Line" && !lineCommentSupported) {
|
536
|
+
return;
|
537
|
+
}
|
538
|
+
|
539
|
+
const loc = sourceCode.getLoc(comment);
|
540
|
+
|
541
|
+
if (warnInlineConfig) {
|
542
|
+
const kind =
|
543
|
+
comment.type === "Block" ? `/*${label}*/` : `//${label}`;
|
544
|
+
|
545
|
+
problems.push(
|
546
|
+
createLintingProblem({
|
547
|
+
ruleId: null,
|
548
|
+
message: `'${kind}' has no effect because you have 'noInlineConfig' setting in ${warnInlineConfig}.`,
|
549
|
+
loc,
|
550
|
+
severity: 1,
|
551
|
+
}),
|
552
|
+
);
|
553
|
+
return;
|
554
|
+
}
|
555
|
+
|
556
|
+
if (
|
557
|
+
label === "eslint-disable-line" &&
|
558
|
+
loc.start.line !== loc.end.line
|
559
|
+
) {
|
560
|
+
const message = `${label} comment should not span multiple lines.`;
|
561
|
+
|
562
|
+
problems.push(
|
563
|
+
createLintingProblem({
|
564
|
+
ruleId: null,
|
565
|
+
message,
|
566
|
+
loc,
|
567
|
+
}),
|
568
|
+
);
|
569
|
+
return;
|
570
|
+
}
|
571
|
+
|
572
|
+
switch (label) {
|
573
|
+
case "eslint-disable":
|
574
|
+
case "eslint-enable":
|
575
|
+
case "eslint-disable-next-line":
|
576
|
+
case "eslint-disable-line": {
|
577
|
+
const directiveType = label.slice("eslint-".length);
|
578
|
+
const { directives, directiveProblems } =
|
579
|
+
createDisableDirectives(
|
580
|
+
{
|
581
|
+
type: directiveType,
|
582
|
+
value,
|
583
|
+
justification: justificationPart,
|
584
|
+
node: comment,
|
585
|
+
},
|
586
|
+
ruleMapper,
|
587
|
+
jslang,
|
588
|
+
sourceCode,
|
589
|
+
);
|
590
|
+
|
591
|
+
disableDirectives.push(...directives);
|
592
|
+
problems.push(...directiveProblems);
|
593
|
+
break;
|
594
|
+
}
|
595
|
+
|
596
|
+
case "exported":
|
597
|
+
Object.assign(
|
598
|
+
exportedVariables,
|
599
|
+
commentParser.parseListConfig(value),
|
600
|
+
);
|
601
|
+
break;
|
602
|
+
|
603
|
+
case "globals":
|
604
|
+
case "global":
|
605
|
+
for (const [id, idSetting] of Object.entries(
|
606
|
+
commentParser.parseStringConfig(value),
|
607
|
+
)) {
|
608
|
+
let normalizedValue;
|
609
|
+
|
610
|
+
try {
|
611
|
+
normalizedValue =
|
612
|
+
ConfigOps.normalizeConfigGlobal(idSetting);
|
613
|
+
} catch (err) {
|
614
|
+
problems.push(
|
615
|
+
createLintingProblem({
|
616
|
+
ruleId: null,
|
617
|
+
loc,
|
618
|
+
message: err.message,
|
619
|
+
}),
|
620
|
+
);
|
621
|
+
continue;
|
622
|
+
}
|
623
|
+
|
624
|
+
if (enabledGlobals[id]) {
|
625
|
+
enabledGlobals[id].comments.push(comment);
|
626
|
+
enabledGlobals[id].value = normalizedValue;
|
627
|
+
} else {
|
628
|
+
enabledGlobals[id] = {
|
629
|
+
comments: [comment],
|
630
|
+
value: normalizedValue,
|
631
|
+
};
|
632
|
+
}
|
633
|
+
}
|
634
|
+
break;
|
635
|
+
|
636
|
+
case "eslint": {
|
637
|
+
const parseResult =
|
638
|
+
commentParser.parseJSONLikeConfig(value);
|
639
|
+
|
640
|
+
if (parseResult.ok) {
|
641
|
+
Object.keys(parseResult.config).forEach(name => {
|
642
|
+
const rule = ruleMapper(name);
|
643
|
+
const ruleValue = parseResult.config[name];
|
644
|
+
|
645
|
+
if (!rule) {
|
646
|
+
problems.push(
|
647
|
+
createLintingProblem({ ruleId: name, loc }),
|
648
|
+
);
|
649
|
+
return;
|
650
|
+
}
|
651
|
+
|
652
|
+
if (Object.hasOwn(configuredRules, name)) {
|
653
|
+
problems.push(
|
654
|
+
createLintingProblem({
|
655
|
+
message: `Rule "${name}" is already configured by another configuration comment in the preceding code. This configuration is ignored.`,
|
656
|
+
loc,
|
657
|
+
}),
|
658
|
+
);
|
659
|
+
return;
|
660
|
+
}
|
661
|
+
|
662
|
+
let ruleOptions = asArray(ruleValue);
|
663
|
+
|
664
|
+
/*
|
665
|
+
* If the rule was already configured, inline rule configuration that
|
666
|
+
* only has severity should retain options from the config and just override the severity.
|
667
|
+
*
|
668
|
+
* Example:
|
669
|
+
*
|
670
|
+
* {
|
671
|
+
* rules: {
|
672
|
+
* curly: ["error", "multi"]
|
673
|
+
* }
|
674
|
+
* }
|
675
|
+
*
|
676
|
+
* /* eslint curly: ["warn"] * /
|
677
|
+
*
|
678
|
+
* Results in:
|
679
|
+
*
|
680
|
+
* curly: ["warn", "multi"]
|
681
|
+
*/
|
682
|
+
if (
|
683
|
+
/*
|
684
|
+
* If inline config for the rule has only severity
|
685
|
+
*/
|
686
|
+
ruleOptions.length === 1 &&
|
687
|
+
/*
|
688
|
+
* And the rule was already configured
|
689
|
+
*/
|
690
|
+
config.rules &&
|
691
|
+
Object.hasOwn(config.rules, name)
|
692
|
+
) {
|
693
|
+
/*
|
694
|
+
* Then use severity from the inline config and options from the provided config
|
695
|
+
*/
|
696
|
+
ruleOptions = [
|
697
|
+
ruleOptions[0], // severity from the inline config
|
698
|
+
...asArray(config.rules[name]).slice(1), // options from the provided config
|
699
|
+
];
|
700
|
+
}
|
701
|
+
|
702
|
+
try {
|
703
|
+
validator.validateRuleOptions(
|
704
|
+
rule,
|
705
|
+
name,
|
706
|
+
ruleOptions,
|
707
|
+
);
|
708
|
+
} catch (err) {
|
709
|
+
/*
|
710
|
+
* If the rule has invalid `meta.schema`, throw the error because
|
711
|
+
* this is not an invalid inline configuration but an invalid rule.
|
712
|
+
*/
|
713
|
+
if (
|
714
|
+
err.code ===
|
715
|
+
"ESLINT_INVALID_RULE_OPTIONS_SCHEMA"
|
716
|
+
) {
|
717
|
+
throw err;
|
718
|
+
}
|
719
|
+
|
720
|
+
problems.push(
|
721
|
+
createLintingProblem({
|
722
|
+
ruleId: name,
|
723
|
+
message: err.message,
|
724
|
+
loc,
|
725
|
+
}),
|
726
|
+
);
|
727
|
+
|
728
|
+
// do not apply the config, if found invalid options.
|
729
|
+
return;
|
730
|
+
}
|
731
|
+
|
732
|
+
configuredRules[name] = ruleOptions;
|
733
|
+
});
|
734
|
+
} else {
|
735
|
+
const problem = createLintingProblem({
|
736
|
+
ruleId: null,
|
737
|
+
loc,
|
738
|
+
message: parseResult.error.message,
|
739
|
+
});
|
740
|
+
|
741
|
+
problem.fatal = true;
|
742
|
+
problems.push(problem);
|
743
|
+
}
|
744
|
+
|
745
|
+
break;
|
746
|
+
}
|
747
|
+
|
748
|
+
// no default
|
749
|
+
}
|
750
|
+
});
|
751
|
+
|
752
|
+
return {
|
753
|
+
configuredRules,
|
754
|
+
enabledGlobals,
|
755
|
+
exportedVariables,
|
756
|
+
problems,
|
757
|
+
disableDirectives,
|
758
|
+
};
|
670
759
|
}
|
671
760
|
|
672
761
|
/**
|
@@ -678,32 +767,39 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
|
|
678
767
|
* A collection of the directive comments that were found, along with any problems that occurred when parsing
|
679
768
|
*/
|
680
769
|
function getDirectiveCommentsForFlatConfig(sourceCode, ruleMapper, language) {
|
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
|
-
|
770
|
+
const disableDirectives = [];
|
771
|
+
const problems = [];
|
772
|
+
|
773
|
+
if (sourceCode.getDisableDirectives) {
|
774
|
+
const { directives: directivesSources, problems: directivesProblems } =
|
775
|
+
sourceCode.getDisableDirectives();
|
776
|
+
|
777
|
+
problems.push(
|
778
|
+
...directivesProblems.map(directiveProblem =>
|
779
|
+
createLintingProblem({
|
780
|
+
...directiveProblem,
|
781
|
+
language,
|
782
|
+
}),
|
783
|
+
),
|
784
|
+
);
|
785
|
+
|
786
|
+
directivesSources.forEach(directive => {
|
787
|
+
const { directives, directiveProblems } = createDisableDirectives(
|
788
|
+
directive,
|
789
|
+
ruleMapper,
|
790
|
+
language,
|
791
|
+
sourceCode,
|
792
|
+
);
|
793
|
+
|
794
|
+
disableDirectives.push(...directives);
|
795
|
+
problems.push(...directiveProblems);
|
796
|
+
});
|
797
|
+
}
|
798
|
+
|
799
|
+
return {
|
800
|
+
problems,
|
801
|
+
disableDirectives,
|
802
|
+
};
|
707
803
|
}
|
708
804
|
|
709
805
|
/**
|
@@ -713,18 +809,17 @@ function getDirectiveCommentsForFlatConfig(sourceCode, ruleMapper, language) {
|
|
713
809
|
* @returns {number} normalized ECMAScript version
|
714
810
|
*/
|
715
811
|
function normalizeEcmaVersion(parser, ecmaVersion) {
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
return ecmaVersion >= 2015 ? ecmaVersion - 2009 : ecmaVersion;
|
812
|
+
if (isEspree(parser)) {
|
813
|
+
if (ecmaVersion === "latest") {
|
814
|
+
return espree.latestEcmaVersion;
|
815
|
+
}
|
816
|
+
}
|
817
|
+
|
818
|
+
/*
|
819
|
+
* Calculate ECMAScript edition number from official year version starting with
|
820
|
+
* ES2015, which corresponds with ES6 (or a difference of 2009).
|
821
|
+
*/
|
822
|
+
return ecmaVersion >= 2015 ? ecmaVersion - 2009 : ecmaVersion;
|
728
823
|
}
|
729
824
|
|
730
825
|
/**
|
@@ -734,29 +829,28 @@ function normalizeEcmaVersion(parser, ecmaVersion) {
|
|
734
829
|
* @returns {number} normalized ECMAScript version
|
735
830
|
*/
|
736
831
|
function normalizeEcmaVersionForLanguageOptions(ecmaVersion) {
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
return LATEST_ECMA_VERSION;
|
832
|
+
switch (ecmaVersion) {
|
833
|
+
case 3:
|
834
|
+
return 3;
|
835
|
+
|
836
|
+
// void 0 = no ecmaVersion specified so use the default
|
837
|
+
case 5:
|
838
|
+
case void 0:
|
839
|
+
return 5;
|
840
|
+
|
841
|
+
default:
|
842
|
+
if (typeof ecmaVersion === "number") {
|
843
|
+
return ecmaVersion >= 2015 ? ecmaVersion : ecmaVersion + 2009;
|
844
|
+
}
|
845
|
+
}
|
846
|
+
|
847
|
+
/*
|
848
|
+
* We default to the latest supported ecmaVersion for everything else.
|
849
|
+
* Remember, this is for languageOptions.ecmaVersion, which sets the version
|
850
|
+
* that is used for a number of processes inside of ESLint. It's normally
|
851
|
+
* safe to assume people want the latest unless otherwise specified.
|
852
|
+
*/
|
853
|
+
return LATEST_ECMA_VERSION;
|
760
854
|
}
|
761
855
|
|
762
856
|
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu;
|
@@ -767,20 +861,22 @@ const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu;
|
|
767
861
|
* @returns {Object|null} A result of parseListConfig() with "eslint-env *" comment.
|
768
862
|
*/
|
769
863
|
function findEslintEnv(text) {
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
864
|
+
let match, retv;
|
865
|
+
|
866
|
+
eslintEnvPattern.lastIndex = 0;
|
867
|
+
|
868
|
+
while ((match = eslintEnvPattern.exec(text)) !== null) {
|
869
|
+
if (match[0].endsWith("*/")) {
|
870
|
+
retv = Object.assign(
|
871
|
+
retv || {},
|
872
|
+
commentParser.parseListConfig(
|
873
|
+
commentParser.parseDirective(match[0].slice(2, -2)).value,
|
874
|
+
),
|
875
|
+
);
|
876
|
+
}
|
877
|
+
}
|
878
|
+
|
879
|
+
return retv;
|
784
880
|
}
|
785
881
|
|
786
882
|
/**
|
@@ -796,10 +892,10 @@ function findEslintEnv(text) {
|
|
796
892
|
* @returns {string} The normalized filename.
|
797
893
|
*/
|
798
894
|
function normalizeFilename(filename) {
|
799
|
-
|
800
|
-
|
895
|
+
const parts = filename.split(path.sep);
|
896
|
+
const index = parts.lastIndexOf("<text>");
|
801
897
|
|
802
|
-
|
898
|
+
return index === -1 ? filename : parts.slice(index).join(path.sep);
|
803
899
|
}
|
804
900
|
|
805
901
|
/**
|
@@ -810,49 +906,63 @@ function normalizeFilename(filename) {
|
|
810
906
|
* @returns {Required<VerifyOptions> & InternalOptions} Normalized options
|
811
907
|
*/
|
812
908
|
function normalizeVerifyOptions(providedOptions, config) {
|
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
|
-
|
909
|
+
const linterOptions = config.linterOptions || config;
|
910
|
+
|
911
|
+
// .noInlineConfig for eslintrc, .linterOptions.noInlineConfig for flat
|
912
|
+
const disableInlineConfig = linterOptions.noInlineConfig === true;
|
913
|
+
const ignoreInlineConfig = providedOptions.allowInlineConfig === false;
|
914
|
+
const configNameOfNoInlineConfig = config.configNameOfNoInlineConfig
|
915
|
+
? ` (${config.configNameOfNoInlineConfig})`
|
916
|
+
: "";
|
917
|
+
|
918
|
+
let reportUnusedDisableDirectives =
|
919
|
+
providedOptions.reportUnusedDisableDirectives;
|
920
|
+
|
921
|
+
if (typeof reportUnusedDisableDirectives === "boolean") {
|
922
|
+
reportUnusedDisableDirectives = reportUnusedDisableDirectives
|
923
|
+
? "error"
|
924
|
+
: "off";
|
925
|
+
}
|
926
|
+
if (typeof reportUnusedDisableDirectives !== "string") {
|
927
|
+
if (typeof linterOptions.reportUnusedDisableDirectives === "boolean") {
|
928
|
+
reportUnusedDisableDirectives =
|
929
|
+
linterOptions.reportUnusedDisableDirectives ? "warn" : "off";
|
930
|
+
} else {
|
931
|
+
reportUnusedDisableDirectives =
|
932
|
+
linterOptions.reportUnusedDisableDirectives === void 0
|
933
|
+
? "off"
|
934
|
+
: normalizeSeverityToString(
|
935
|
+
linterOptions.reportUnusedDisableDirectives,
|
936
|
+
);
|
937
|
+
}
|
938
|
+
}
|
939
|
+
|
940
|
+
const reportUnusedInlineConfigs =
|
941
|
+
linterOptions.reportUnusedInlineConfigs === void 0
|
942
|
+
? "off"
|
943
|
+
: normalizeSeverityToString(
|
944
|
+
linterOptions.reportUnusedInlineConfigs,
|
945
|
+
);
|
946
|
+
|
947
|
+
let ruleFilter = providedOptions.ruleFilter;
|
948
|
+
|
949
|
+
if (typeof ruleFilter !== "function") {
|
950
|
+
ruleFilter = () => true;
|
951
|
+
}
|
952
|
+
|
953
|
+
return {
|
954
|
+
filename: normalizeFilename(providedOptions.filename || "<input>"),
|
955
|
+
allowInlineConfig: !ignoreInlineConfig,
|
956
|
+
warnInlineConfig:
|
957
|
+
disableInlineConfig && !ignoreInlineConfig
|
958
|
+
? `your config${configNameOfNoInlineConfig}`
|
959
|
+
: null,
|
960
|
+
reportUnusedDisableDirectives,
|
961
|
+
reportUnusedInlineConfigs,
|
962
|
+
disableFixes: Boolean(providedOptions.disableFixes),
|
963
|
+
stats: providedOptions.stats,
|
964
|
+
ruleFilter,
|
965
|
+
};
|
856
966
|
}
|
857
967
|
|
858
968
|
/**
|
@@ -863,25 +973,36 @@ function normalizeVerifyOptions(providedOptions, config) {
|
|
863
973
|
* @returns {ParserOptions} Resulting parser options after merge
|
864
974
|
*/
|
865
975
|
function resolveParserOptions(parser, providedOptions, enabledEnvironments) {
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
976
|
+
const parserOptionsFromEnv = enabledEnvironments
|
977
|
+
.filter(env => env.parserOptions)
|
978
|
+
.reduce(
|
979
|
+
(parserOptions, env) => merge(parserOptions, env.parserOptions),
|
980
|
+
{},
|
981
|
+
);
|
982
|
+
const mergedParserOptions = merge(
|
983
|
+
parserOptionsFromEnv,
|
984
|
+
providedOptions || {},
|
985
|
+
);
|
986
|
+
const isModule = mergedParserOptions.sourceType === "module";
|
987
|
+
|
988
|
+
if (isModule) {
|
989
|
+
/*
|
990
|
+
* can't have global return inside of modules
|
991
|
+
* TODO: espree validate parserOptions.globalReturn when sourceType is setting to module.(@aladdin-add)
|
992
|
+
*/
|
993
|
+
mergedParserOptions.ecmaFeatures = Object.assign(
|
994
|
+
{},
|
995
|
+
mergedParserOptions.ecmaFeatures,
|
996
|
+
{ globalReturn: false },
|
997
|
+
);
|
998
|
+
}
|
999
|
+
|
1000
|
+
mergedParserOptions.ecmaVersion = normalizeEcmaVersion(
|
1001
|
+
parser,
|
1002
|
+
mergedParserOptions.ecmaVersion,
|
1003
|
+
);
|
1004
|
+
|
1005
|
+
return mergedParserOptions;
|
885
1006
|
}
|
886
1007
|
|
887
1008
|
/**
|
@@ -892,20 +1013,20 @@ function resolveParserOptions(parser, providedOptions, enabledEnvironments) {
|
|
892
1013
|
* @param {ParserOptions} config.parserOptions The parserOptions to use.
|
893
1014
|
* @returns {LanguageOptions} The languageOptions equivalent.
|
894
1015
|
*/
|
895
|
-
function createLanguageOptions({
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
1016
|
+
function createLanguageOptions({
|
1017
|
+
globals: configuredGlobals,
|
1018
|
+
parser,
|
1019
|
+
parserOptions,
|
1020
|
+
}) {
|
1021
|
+
const { ecmaVersion, sourceType } = parserOptions;
|
1022
|
+
|
1023
|
+
return {
|
1024
|
+
globals: configuredGlobals,
|
1025
|
+
ecmaVersion: normalizeEcmaVersionForLanguageOptions(ecmaVersion),
|
1026
|
+
sourceType,
|
1027
|
+
parser,
|
1028
|
+
parserOptions,
|
1029
|
+
};
|
909
1030
|
}
|
910
1031
|
|
911
1032
|
/**
|
@@ -915,11 +1036,13 @@ function createLanguageOptions({ globals: configuredGlobals, parser, parserOptio
|
|
915
1036
|
* @returns {Record<string, GlobalConf>} The resolved globals object
|
916
1037
|
*/
|
917
1038
|
function resolveGlobals(providedGlobals, enabledEnvironments) {
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
1039
|
+
return Object.assign(
|
1040
|
+
Object.create(null),
|
1041
|
+
...enabledEnvironments
|
1042
|
+
.filter(env => env.globals)
|
1043
|
+
.map(env => env.globals),
|
1044
|
+
providedGlobals,
|
1045
|
+
);
|
923
1046
|
}
|
924
1047
|
|
925
1048
|
/**
|
@@ -930,26 +1053,26 @@ function resolveGlobals(providedGlobals, enabledEnvironments) {
|
|
930
1053
|
* @returns {void}
|
931
1054
|
*/
|
932
1055
|
function storeTime(time, timeOpts, slots) {
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
1056
|
+
const { type, key } = timeOpts;
|
1057
|
+
|
1058
|
+
if (!slots.times) {
|
1059
|
+
slots.times = { passes: [{}] };
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
const passIndex = slots.fixPasses;
|
1063
|
+
|
1064
|
+
if (passIndex > slots.times.passes.length - 1) {
|
1065
|
+
slots.times.passes.push({});
|
1066
|
+
}
|
1067
|
+
|
1068
|
+
if (key) {
|
1069
|
+
slots.times.passes[passIndex][type] ??= {};
|
1070
|
+
slots.times.passes[passIndex][type][key] ??= { total: 0 };
|
1071
|
+
slots.times.passes[passIndex][type][key].total += time;
|
1072
|
+
} else {
|
1073
|
+
slots.times.passes[passIndex][type] ??= { total: 0 };
|
1074
|
+
slots.times.passes[passIndex][type].total += time;
|
1075
|
+
}
|
953
1076
|
}
|
954
1077
|
|
955
1078
|
/**
|
@@ -959,10 +1082,10 @@ function storeTime(time, timeOpts, slots) {
|
|
959
1082
|
* @returns {Array} of rule options, empty Array if none
|
960
1083
|
*/
|
961
1084
|
function getRuleOptions(ruleConfig, defaultOptions) {
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
1085
|
+
if (Array.isArray(ruleConfig)) {
|
1086
|
+
return deepMergeArrays(defaultOptions, ruleConfig.slice(1));
|
1087
|
+
}
|
1088
|
+
return defaultOptions ?? [];
|
966
1089
|
}
|
967
1090
|
|
968
1091
|
/**
|
@@ -973,19 +1096,19 @@ function getRuleOptions(ruleConfig, defaultOptions) {
|
|
973
1096
|
* @returns {ScopeManager} The analysis result.
|
974
1097
|
*/
|
975
1098
|
function analyzeScope(ast, languageOptions, visitorKeys) {
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
1099
|
+
const parserOptions = languageOptions.parserOptions;
|
1100
|
+
const ecmaFeatures = parserOptions.ecmaFeatures || {};
|
1101
|
+
const ecmaVersion = languageOptions.ecmaVersion || DEFAULT_ECMA_VERSION;
|
1102
|
+
|
1103
|
+
return eslintScope.analyze(ast, {
|
1104
|
+
ignoreEval: true,
|
1105
|
+
nodejsScope: ecmaFeatures.globalReturn,
|
1106
|
+
impliedStrict: ecmaFeatures.impliedStrict,
|
1107
|
+
ecmaVersion: typeof ecmaVersion === "number" ? ecmaVersion : 6,
|
1108
|
+
sourceType: languageOptions.sourceType || "script",
|
1109
|
+
childVisitorKeys: visitorKeys || evk.KEYS,
|
1110
|
+
fallback: Traverser.getKeys,
|
1111
|
+
});
|
989
1112
|
}
|
990
1113
|
|
991
1114
|
/**
|
@@ -997,17 +1120,22 @@ function analyzeScope(ast, languageOptions, visitorKeys) {
|
|
997
1120
|
* @returns {Object} A map of selector listeners provided by the rule
|
998
1121
|
*/
|
999
1122
|
function createRuleListeners(rule, ruleContext) {
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1123
|
+
if (
|
1124
|
+
!rule ||
|
1125
|
+
typeof rule !== "object" ||
|
1126
|
+
typeof rule.create !== "function"
|
1127
|
+
) {
|
1128
|
+
throw new TypeError(
|
1129
|
+
`Error while loading rule '${ruleContext.id}': Rule must be an object with a \`create\` method`,
|
1130
|
+
);
|
1131
|
+
}
|
1132
|
+
|
1133
|
+
try {
|
1134
|
+
return rule.create(ruleContext);
|
1135
|
+
} catch (ex) {
|
1136
|
+
ex.message = `Error while loading rule '${ruleContext.id}': ${ex.message}`;
|
1137
|
+
throw ex;
|
1138
|
+
}
|
1011
1139
|
}
|
1012
1140
|
|
1013
1141
|
/**
|
@@ -1031,199 +1159,230 @@ function createRuleListeners(rule, ruleContext) {
|
|
1031
1159
|
* @throws {Error} If traversal into a node fails.
|
1032
1160
|
*/
|
1033
1161
|
function runRules(
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1162
|
+
sourceCode,
|
1163
|
+
configuredRules,
|
1164
|
+
ruleMapper,
|
1165
|
+
parserName,
|
1166
|
+
language,
|
1167
|
+
languageOptions,
|
1168
|
+
settings,
|
1169
|
+
filename,
|
1170
|
+
applyDefaultOptions,
|
1171
|
+
disableFixes,
|
1172
|
+
cwd,
|
1173
|
+
physicalFilename,
|
1174
|
+
ruleFilter,
|
1175
|
+
stats,
|
1176
|
+
slots,
|
1049
1177
|
) {
|
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
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1178
|
+
const emitter = createEmitter();
|
1179
|
+
|
1180
|
+
// must happen first to assign all node.parent properties
|
1181
|
+
const eventQueue = sourceCode.traverse();
|
1182
|
+
|
1183
|
+
/*
|
1184
|
+
* Create a frozen object with the ruleContext properties and methods that are shared by all rules.
|
1185
|
+
* All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
|
1186
|
+
* properties once for each rule.
|
1187
|
+
*/
|
1188
|
+
const sharedTraversalContext = new FileContext({
|
1189
|
+
cwd,
|
1190
|
+
filename,
|
1191
|
+
physicalFilename: physicalFilename || filename,
|
1192
|
+
sourceCode,
|
1193
|
+
parserOptions: {
|
1194
|
+
...languageOptions.parserOptions,
|
1195
|
+
},
|
1196
|
+
parserPath: parserName,
|
1197
|
+
languageOptions,
|
1198
|
+
settings,
|
1199
|
+
});
|
1200
|
+
|
1201
|
+
const lintingProblems = [];
|
1202
|
+
|
1203
|
+
Object.keys(configuredRules).forEach(ruleId => {
|
1204
|
+
const severity = ConfigOps.getRuleSeverity(configuredRules[ruleId]);
|
1205
|
+
|
1206
|
+
// not load disabled rules
|
1207
|
+
if (severity === 0) {
|
1208
|
+
return;
|
1209
|
+
}
|
1210
|
+
|
1211
|
+
if (ruleFilter && !ruleFilter({ ruleId, severity })) {
|
1212
|
+
return;
|
1213
|
+
}
|
1214
|
+
|
1215
|
+
const rule = ruleMapper(ruleId);
|
1216
|
+
|
1217
|
+
if (!rule) {
|
1218
|
+
lintingProblems.push(createLintingProblem({ ruleId, language }));
|
1219
|
+
return;
|
1220
|
+
}
|
1221
|
+
|
1222
|
+
const messageIds = rule.meta && rule.meta.messages;
|
1223
|
+
let reportTranslator = null;
|
1224
|
+
const ruleContext = Object.freeze(
|
1225
|
+
Object.assign(Object.create(sharedTraversalContext), {
|
1226
|
+
id: ruleId,
|
1227
|
+
options: getRuleOptions(
|
1228
|
+
configuredRules[ruleId],
|
1229
|
+
applyDefaultOptions ? rule.meta?.defaultOptions : void 0,
|
1230
|
+
),
|
1231
|
+
report(...args) {
|
1232
|
+
/*
|
1233
|
+
* Create a report translator lazily.
|
1234
|
+
* In a vast majority of cases, any given rule reports zero errors on a given
|
1235
|
+
* piece of code. Creating a translator lazily avoids the performance cost of
|
1236
|
+
* creating a new translator function for each rule that usually doesn't get
|
1237
|
+
* called.
|
1238
|
+
*
|
1239
|
+
* Using lazy report translators improves end-to-end performance by about 3%
|
1240
|
+
* with Node 8.4.0.
|
1241
|
+
*/
|
1242
|
+
if (reportTranslator === null) {
|
1243
|
+
reportTranslator = createReportTranslator({
|
1244
|
+
ruleId,
|
1245
|
+
severity,
|
1246
|
+
sourceCode,
|
1247
|
+
messageIds,
|
1248
|
+
disableFixes,
|
1249
|
+
language,
|
1250
|
+
});
|
1251
|
+
}
|
1252
|
+
const problem = reportTranslator(...args);
|
1253
|
+
|
1254
|
+
if (problem.fix && !(rule.meta && rule.meta.fixable)) {
|
1255
|
+
throw new Error(
|
1256
|
+
'Fixable rules must set the `meta.fixable` property to "code" or "whitespace".',
|
1257
|
+
);
|
1258
|
+
}
|
1259
|
+
if (
|
1260
|
+
problem.suggestions &&
|
1261
|
+
!(rule.meta && rule.meta.hasSuggestions === true)
|
1262
|
+
) {
|
1263
|
+
if (
|
1264
|
+
rule.meta &&
|
1265
|
+
rule.meta.docs &&
|
1266
|
+
typeof rule.meta.docs.suggestion !== "undefined"
|
1267
|
+
) {
|
1268
|
+
// Encourage migration from the former property name.
|
1269
|
+
throw new Error(
|
1270
|
+
"Rules with suggestions must set the `meta.hasSuggestions` property to `true`. `meta.docs.suggestion` is ignored by ESLint.",
|
1271
|
+
);
|
1272
|
+
}
|
1273
|
+
throw new Error(
|
1274
|
+
"Rules with suggestions must set the `meta.hasSuggestions` property to `true`.",
|
1275
|
+
);
|
1276
|
+
}
|
1277
|
+
lintingProblems.push(problem);
|
1278
|
+
},
|
1279
|
+
}),
|
1280
|
+
);
|
1281
|
+
|
1282
|
+
const ruleListenersReturn =
|
1283
|
+
timing.enabled || stats
|
1284
|
+
? timing.time(
|
1285
|
+
ruleId,
|
1286
|
+
createRuleListeners,
|
1287
|
+
stats,
|
1288
|
+
)(rule, ruleContext)
|
1289
|
+
: createRuleListeners(rule, ruleContext);
|
1290
|
+
|
1291
|
+
const ruleListeners = stats
|
1292
|
+
? ruleListenersReturn.result
|
1293
|
+
: ruleListenersReturn;
|
1294
|
+
|
1295
|
+
if (stats) {
|
1296
|
+
storeTime(
|
1297
|
+
ruleListenersReturn.tdiff,
|
1298
|
+
{ type: "rules", key: ruleId },
|
1299
|
+
slots,
|
1300
|
+
);
|
1301
|
+
}
|
1302
|
+
|
1303
|
+
/**
|
1304
|
+
* Include `ruleId` in error logs
|
1305
|
+
* @param {Function} ruleListener A rule method that listens for a node.
|
1306
|
+
* @returns {Function} ruleListener wrapped in error handler
|
1307
|
+
*/
|
1308
|
+
function addRuleErrorHandler(ruleListener) {
|
1309
|
+
return function ruleErrorHandler(...listenerArgs) {
|
1310
|
+
try {
|
1311
|
+
const ruleListenerReturn = ruleListener(...listenerArgs);
|
1312
|
+
|
1313
|
+
const ruleListenerResult = stats
|
1314
|
+
? ruleListenerReturn.result
|
1315
|
+
: ruleListenerReturn;
|
1316
|
+
|
1317
|
+
if (stats) {
|
1318
|
+
storeTime(
|
1319
|
+
ruleListenerReturn.tdiff,
|
1320
|
+
{ type: "rules", key: ruleId },
|
1321
|
+
slots,
|
1322
|
+
);
|
1323
|
+
}
|
1324
|
+
|
1325
|
+
return ruleListenerResult;
|
1326
|
+
} catch (e) {
|
1327
|
+
e.ruleId = ruleId;
|
1328
|
+
throw e;
|
1329
|
+
}
|
1330
|
+
};
|
1331
|
+
}
|
1332
|
+
|
1333
|
+
if (typeof ruleListeners === "undefined" || ruleListeners === null) {
|
1334
|
+
throw new Error(
|
1335
|
+
`The create() function for rule '${ruleId}' did not return an object.`,
|
1336
|
+
);
|
1337
|
+
}
|
1338
|
+
|
1339
|
+
// add all the selectors from the rule as listeners
|
1340
|
+
Object.keys(ruleListeners).forEach(selector => {
|
1341
|
+
const ruleListener =
|
1342
|
+
timing.enabled || stats
|
1343
|
+
? timing.time(ruleId, ruleListeners[selector], stats)
|
1344
|
+
: ruleListeners[selector];
|
1345
|
+
|
1346
|
+
emitter.on(selector, addRuleErrorHandler(ruleListener));
|
1347
|
+
});
|
1348
|
+
});
|
1349
|
+
|
1350
|
+
const eventGenerator = new NodeEventGenerator(emitter, {
|
1351
|
+
visitorKeys: sourceCode.visitorKeys ?? language.visitorKeys,
|
1352
|
+
fallback: Traverser.getKeys,
|
1353
|
+
matchClass: language.matchesSelectorClass ?? (() => false),
|
1354
|
+
nodeTypeKey: language.nodeTypeKey,
|
1355
|
+
});
|
1356
|
+
|
1357
|
+
for (const step of eventQueue) {
|
1358
|
+
switch (step.kind) {
|
1359
|
+
case STEP_KIND_VISIT: {
|
1360
|
+
try {
|
1361
|
+
if (step.phase === 1) {
|
1362
|
+
eventGenerator.enterNode(step.target);
|
1363
|
+
} else {
|
1364
|
+
eventGenerator.leaveNode(step.target);
|
1365
|
+
}
|
1366
|
+
} catch (err) {
|
1367
|
+
err.currentNode = step.target;
|
1368
|
+
throw err;
|
1369
|
+
}
|
1370
|
+
break;
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
case STEP_KIND_CALL: {
|
1374
|
+
emitter.emit(step.target, ...step.args);
|
1375
|
+
break;
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
default:
|
1379
|
+
throw new Error(
|
1380
|
+
`Invalid traversal step found: "${step.type}".`,
|
1381
|
+
);
|
1382
|
+
}
|
1383
|
+
}
|
1384
|
+
|
1385
|
+
return lintingProblems;
|
1227
1386
|
}
|
1228
1387
|
|
1229
1388
|
/**
|
@@ -1232,14 +1391,14 @@ function runRules(
|
|
1232
1391
|
* @returns {string} The source code text.
|
1233
1392
|
*/
|
1234
1393
|
function ensureText(textOrSourceCode) {
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1394
|
+
if (typeof textOrSourceCode === "object") {
|
1395
|
+
const { hasBOM, text } = textOrSourceCode;
|
1396
|
+
const bom = hasBOM ? "\uFEFF" : "";
|
1238
1397
|
|
1239
|
-
|
1240
|
-
|
1398
|
+
return bom + text;
|
1399
|
+
}
|
1241
1400
|
|
1242
|
-
|
1401
|
+
return String(textOrSourceCode);
|
1243
1402
|
}
|
1244
1403
|
|
1245
1404
|
/**
|
@@ -1249,11 +1408,12 @@ function ensureText(textOrSourceCode) {
|
|
1249
1408
|
* @returns {Environment|null} The environment.
|
1250
1409
|
*/
|
1251
1410
|
function getEnv(slots, envId) {
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1411
|
+
return (
|
1412
|
+
(slots.lastConfigArray &&
|
1413
|
+
slots.lastConfigArray.pluginEnvironments.get(envId)) ||
|
1414
|
+
BuiltInEnvironments.get(envId) ||
|
1415
|
+
null
|
1416
|
+
);
|
1257
1417
|
}
|
1258
1418
|
|
1259
1419
|
/**
|
@@ -1263,10 +1423,11 @@ function getEnv(slots, envId) {
|
|
1263
1423
|
* @returns {Rule|null} The rule.
|
1264
1424
|
*/
|
1265
1425
|
function getRule(slots, ruleId) {
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1426
|
+
return (
|
1427
|
+
(slots.lastConfigArray &&
|
1428
|
+
slots.lastConfigArray.pluginRules.get(ruleId)) ||
|
1429
|
+
slots.ruleMap.get(ruleId)
|
1430
|
+
);
|
1270
1431
|
}
|
1271
1432
|
|
1272
1433
|
/**
|
@@ -1275,16 +1436,16 @@ function getRule(slots, ruleId) {
|
|
1275
1436
|
* @returns {string | undefined} normalized cwd
|
1276
1437
|
*/
|
1277
1438
|
function normalizeCwd(cwd) {
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1439
|
+
if (cwd) {
|
1440
|
+
return cwd;
|
1441
|
+
}
|
1442
|
+
if (typeof process === "object") {
|
1443
|
+
return process.cwd();
|
1444
|
+
}
|
1445
|
+
|
1446
|
+
// It's more explicit to assign the undefined
|
1447
|
+
// eslint-disable-next-line no-undefined -- Consistently returning a value
|
1448
|
+
return undefined;
|
1288
1449
|
}
|
1289
1450
|
|
1290
1451
|
/**
|
@@ -1300,11 +1461,13 @@ const internalSlotsMap = new WeakMap();
|
|
1300
1461
|
* @throws {Error} If the linter is in flat config mode.
|
1301
1462
|
*/
|
1302
1463
|
function assertEslintrcConfig(linter) {
|
1303
|
-
|
1464
|
+
const { configType } = internalSlotsMap.get(linter);
|
1304
1465
|
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1466
|
+
if (configType === "flat") {
|
1467
|
+
throw new Error(
|
1468
|
+
"This method cannot be used with flat config. Add your entries directly into the config array.",
|
1469
|
+
);
|
1470
|
+
}
|
1308
1471
|
}
|
1309
1472
|
|
1310
1473
|
//------------------------------------------------------------------------------
|
@@ -1316,1182 +1479,1377 @@ function assertEslintrcConfig(linter) {
|
|
1316
1479
|
* @name Linter
|
1317
1480
|
*/
|
1318
1481
|
class Linter {
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1659
|
-
|
1660
|
-
|
1661
|
-
|
1662
|
-
|
1663
|
-
|
1664
|
-
|
1665
|
-
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
|
1762
|
-
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
1797
|
-
|
1798
|
-
|
1799
|
-
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
1813
|
-
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
1818
|
-
|
1819
|
-
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1850
|
-
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1854
|
-
|
1855
|
-
|
1856
|
-
|
1857
|
-
|
1858
|
-
|
1859
|
-
|
1860
|
-
|
1861
|
-
|
1862
|
-
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1867
|
-
|
1868
|
-
|
1869
|
-
|
1870
|
-
|
1871
|
-
|
1872
|
-
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
1890
|
-
|
1891
|
-
|
1892
|
-
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
1896
|
-
|
1897
|
-
|
1898
|
-
|
1899
|
-
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
|
1913
|
-
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
1917
|
-
|
1918
|
-
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1928
|
-
|
1929
|
-
|
1930
|
-
|
1931
|
-
|
1932
|
-
|
1933
|
-
|
1934
|
-
|
1935
|
-
|
1936
|
-
|
1937
|
-
|
1938
|
-
|
1939
|
-
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
1950
|
-
|
1951
|
-
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
1962
|
-
|
1963
|
-
|
1964
|
-
|
1965
|
-
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
1990
|
-
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
1996
|
-
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
2016
|
-
|
2017
|
-
|
2018
|
-
|
2019
|
-
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2023
|
-
|
2024
|
-
|
2025
|
-
|
2026
|
-
|
2027
|
-
|
2028
|
-
|
2029
|
-
|
2030
|
-
|
2031
|
-
|
2032
|
-
|
2033
|
-
|
2034
|
-
|
2035
|
-
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
2049
|
-
|
2050
|
-
|
2051
|
-
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2056
|
-
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
2060
|
-
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
2071
|
-
|
2072
|
-
|
2073
|
-
|
2074
|
-
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
2101
|
-
|
2102
|
-
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
2106
|
-
|
2107
|
-
|
2108
|
-
|
2109
|
-
|
2110
|
-
|
2111
|
-
|
2112
|
-
|
2113
|
-
|
2114
|
-
|
2115
|
-
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2125
|
-
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
2136
|
-
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2147
|
-
|
2148
|
-
|
2149
|
-
|
2150
|
-
|
2151
|
-
|
2152
|
-
|
2153
|
-
|
2154
|
-
|
2155
|
-
|
2156
|
-
|
2157
|
-
|
2158
|
-
|
2159
|
-
|
2160
|
-
|
2161
|
-
|
2162
|
-
|
2163
|
-
|
2164
|
-
|
2165
|
-
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2169
|
-
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
|
2177
|
-
|
2178
|
-
|
2179
|
-
|
2180
|
-
|
2181
|
-
|
2182
|
-
|
2183
|
-
|
2184
|
-
|
2185
|
-
|
2186
|
-
|
2187
|
-
|
2188
|
-
|
2189
|
-
|
2190
|
-
|
2191
|
-
|
2192
|
-
|
2193
|
-
|
2194
|
-
|
2195
|
-
|
2196
|
-
|
2197
|
-
|
2198
|
-
|
2199
|
-
|
2200
|
-
|
2201
|
-
|
2202
|
-
|
2203
|
-
|
2204
|
-
|
2205
|
-
|
2206
|
-
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
|
2214
|
-
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2222
|
-
|
2223
|
-
|
2224
|
-
|
2225
|
-
|
2226
|
-
|
2227
|
-
|
2228
|
-
|
2229
|
-
|
2230
|
-
|
2231
|
-
|
2232
|
-
|
2233
|
-
|
2234
|
-
|
2235
|
-
|
2236
|
-
|
2237
|
-
|
2238
|
-
|
2239
|
-
|
2240
|
-
|
2241
|
-
|
2242
|
-
|
2243
|
-
|
2244
|
-
|
2245
|
-
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2250
|
-
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2254
|
-
|
2255
|
-
|
2256
|
-
|
2257
|
-
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
2269
|
-
|
2270
|
-
|
2271
|
-
|
2272
|
-
|
2273
|
-
|
2274
|
-
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2297
|
-
|
2298
|
-
|
2299
|
-
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
|
2316
|
-
|
2317
|
-
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2321
|
-
|
2322
|
-
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2328
|
-
|
2329
|
-
|
2330
|
-
|
2331
|
-
|
2332
|
-
|
2333
|
-
|
2334
|
-
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2395
|
-
|
2396
|
-
|
2397
|
-
|
2398
|
-
|
2399
|
-
|
2400
|
-
|
2401
|
-
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2405
|
-
|
2406
|
-
|
2407
|
-
|
2408
|
-
|
2409
|
-
|
2410
|
-
|
2411
|
-
|
2412
|
-
|
2413
|
-
|
2414
|
-
|
2415
|
-
|
2416
|
-
|
2417
|
-
|
2418
|
-
|
2419
|
-
|
2420
|
-
|
2421
|
-
|
2422
|
-
|
2423
|
-
|
2424
|
-
|
2425
|
-
|
2426
|
-
|
2427
|
-
|
2428
|
-
|
2429
|
-
|
2430
|
-
|
2431
|
-
|
2432
|
-
|
2433
|
-
|
2434
|
-
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
|
2455
|
-
|
2456
|
-
|
2457
|
-
|
2458
|
-
|
2459
|
-
|
2460
|
-
|
2461
|
-
|
2462
|
-
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
|
2468
|
-
|
2469
|
-
|
2470
|
-
|
2471
|
-
|
2472
|
-
|
2473
|
-
|
2474
|
-
|
2475
|
-
|
2476
|
-
|
2477
|
-
|
2478
|
-
|
2479
|
-
|
2480
|
-
|
2481
|
-
|
2482
|
-
|
2483
|
-
|
1482
|
+
/**
|
1483
|
+
* Initialize the Linter.
|
1484
|
+
* @param {Object} [config] the config object
|
1485
|
+
* @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
|
1486
|
+
* @param {Array<string>} [config.flags] the feature flags to enable.
|
1487
|
+
* @param {"flat"|"eslintrc"} [config.configType="flat"] the type of config used.
|
1488
|
+
*/
|
1489
|
+
constructor({ cwd, configType = "flat", flags = [] } = {}) {
|
1490
|
+
const processedFlags = [];
|
1491
|
+
|
1492
|
+
flags.forEach(flag => {
|
1493
|
+
if (inactiveFlags.has(flag)) {
|
1494
|
+
const inactiveFlagData = inactiveFlags.get(flag);
|
1495
|
+
const inactivityReason =
|
1496
|
+
getInactivityReasonMessage(inactiveFlagData);
|
1497
|
+
|
1498
|
+
if (typeof inactiveFlagData.replacedBy === "undefined") {
|
1499
|
+
throw new Error(
|
1500
|
+
`The flag '${flag}' is inactive: ${inactivityReason}`,
|
1501
|
+
);
|
1502
|
+
}
|
1503
|
+
|
1504
|
+
// if there's a replacement, enable it instead of original
|
1505
|
+
if (typeof inactiveFlagData.replacedBy === "string") {
|
1506
|
+
processedFlags.push(inactiveFlagData.replacedBy);
|
1507
|
+
}
|
1508
|
+
|
1509
|
+
globalThis.process?.emitWarning?.(
|
1510
|
+
`The flag '${flag}' is inactive: ${inactivityReason}`,
|
1511
|
+
`ESLintInactiveFlag_${flag}`,
|
1512
|
+
);
|
1513
|
+
|
1514
|
+
return;
|
1515
|
+
}
|
1516
|
+
|
1517
|
+
if (!activeFlags.has(flag)) {
|
1518
|
+
throw new Error(`Unknown flag '${flag}'.`);
|
1519
|
+
}
|
1520
|
+
|
1521
|
+
processedFlags.push(flag);
|
1522
|
+
});
|
1523
|
+
|
1524
|
+
internalSlotsMap.set(this, {
|
1525
|
+
cwd: normalizeCwd(cwd),
|
1526
|
+
flags: processedFlags,
|
1527
|
+
lastConfigArray: null,
|
1528
|
+
lastSourceCode: null,
|
1529
|
+
lastSuppressedMessages: [],
|
1530
|
+
configType, // TODO: Remove after flat config conversion
|
1531
|
+
parserMap: new Map([["espree", espree]]),
|
1532
|
+
ruleMap: new Rules(),
|
1533
|
+
});
|
1534
|
+
|
1535
|
+
this.version = pkg.version;
|
1536
|
+
}
|
1537
|
+
|
1538
|
+
/**
|
1539
|
+
* Getter for package version.
|
1540
|
+
* @static
|
1541
|
+
* @returns {string} The version from package.json.
|
1542
|
+
*/
|
1543
|
+
static get version() {
|
1544
|
+
return pkg.version;
|
1545
|
+
}
|
1546
|
+
|
1547
|
+
/**
|
1548
|
+
* Indicates if the given feature flag is enabled for this instance.
|
1549
|
+
* @param {string} flag The feature flag to check.
|
1550
|
+
* @returns {boolean} `true` if the feature flag is enabled, `false` if not.
|
1551
|
+
*/
|
1552
|
+
hasFlag(flag) {
|
1553
|
+
return internalSlotsMap.get(this).flags.includes(flag);
|
1554
|
+
}
|
1555
|
+
|
1556
|
+
/**
|
1557
|
+
* Lint using eslintrc and without processors.
|
1558
|
+
* @param {VFile} file The file to lint.
|
1559
|
+
* @param {ConfigData} providedConfig An ESLintConfig instance to configure everything.
|
1560
|
+
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1561
|
+
* @throws {Error} If during rule execution.
|
1562
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
1563
|
+
*/
|
1564
|
+
#eslintrcVerifyWithoutProcessors(file, providedConfig, providedOptions) {
|
1565
|
+
const slots = internalSlotsMap.get(this);
|
1566
|
+
const config = providedConfig || {};
|
1567
|
+
const options = normalizeVerifyOptions(providedOptions, config);
|
1568
|
+
|
1569
|
+
// Resolve parser.
|
1570
|
+
let parserName = DEFAULT_PARSER_NAME;
|
1571
|
+
let parser = espree;
|
1572
|
+
|
1573
|
+
if (typeof config.parser === "object" && config.parser !== null) {
|
1574
|
+
parserName = config.parser.filePath;
|
1575
|
+
parser = config.parser.definition;
|
1576
|
+
} else if (typeof config.parser === "string") {
|
1577
|
+
if (!slots.parserMap.has(config.parser)) {
|
1578
|
+
return [
|
1579
|
+
{
|
1580
|
+
ruleId: null,
|
1581
|
+
fatal: true,
|
1582
|
+
severity: 2,
|
1583
|
+
message: `Configured parser '${config.parser}' was not found.`,
|
1584
|
+
line: 0,
|
1585
|
+
column: 0,
|
1586
|
+
nodeType: null,
|
1587
|
+
},
|
1588
|
+
];
|
1589
|
+
}
|
1590
|
+
parserName = config.parser;
|
1591
|
+
parser = slots.parserMap.get(config.parser);
|
1592
|
+
}
|
1593
|
+
|
1594
|
+
// search and apply "eslint-env *".
|
1595
|
+
const envInFile =
|
1596
|
+
options.allowInlineConfig && !options.warnInlineConfig
|
1597
|
+
? findEslintEnv(file.body)
|
1598
|
+
: {};
|
1599
|
+
const resolvedEnvConfig = Object.assign(
|
1600
|
+
{ builtin: true },
|
1601
|
+
config.env,
|
1602
|
+
envInFile,
|
1603
|
+
);
|
1604
|
+
const enabledEnvs = Object.keys(resolvedEnvConfig)
|
1605
|
+
.filter(envName => resolvedEnvConfig[envName])
|
1606
|
+
.map(envName => getEnv(slots, envName))
|
1607
|
+
.filter(env => env);
|
1608
|
+
|
1609
|
+
const parserOptions = resolveParserOptions(
|
1610
|
+
parser,
|
1611
|
+
config.parserOptions || {},
|
1612
|
+
enabledEnvs,
|
1613
|
+
);
|
1614
|
+
const configuredGlobals = resolveGlobals(
|
1615
|
+
config.globals || {},
|
1616
|
+
enabledEnvs,
|
1617
|
+
);
|
1618
|
+
const settings = config.settings || {};
|
1619
|
+
const languageOptions = createLanguageOptions({
|
1620
|
+
globals: config.globals,
|
1621
|
+
parser,
|
1622
|
+
parserOptions,
|
1623
|
+
});
|
1624
|
+
|
1625
|
+
if (!slots.lastSourceCode) {
|
1626
|
+
let t;
|
1627
|
+
|
1628
|
+
if (options.stats) {
|
1629
|
+
t = startTime();
|
1630
|
+
}
|
1631
|
+
|
1632
|
+
const parserService = new ParserService();
|
1633
|
+
const parseResult = parserService.parseSync(file, {
|
1634
|
+
language: jslang,
|
1635
|
+
languageOptions,
|
1636
|
+
});
|
1637
|
+
|
1638
|
+
if (options.stats) {
|
1639
|
+
const time = endTime(t);
|
1640
|
+
const timeOpts = { type: "parse" };
|
1641
|
+
|
1642
|
+
storeTime(time, timeOpts, slots);
|
1643
|
+
}
|
1644
|
+
|
1645
|
+
if (!parseResult.ok) {
|
1646
|
+
return parseResult.errors;
|
1647
|
+
}
|
1648
|
+
|
1649
|
+
slots.lastSourceCode = parseResult.sourceCode;
|
1650
|
+
} else {
|
1651
|
+
/*
|
1652
|
+
* If the given source code object as the first argument does not have scopeManager, analyze the scope.
|
1653
|
+
* This is for backward compatibility (SourceCode is frozen so it cannot rebind).
|
1654
|
+
*/
|
1655
|
+
if (!slots.lastSourceCode.scopeManager) {
|
1656
|
+
slots.lastSourceCode = new SourceCode({
|
1657
|
+
text: slots.lastSourceCode.text,
|
1658
|
+
ast: slots.lastSourceCode.ast,
|
1659
|
+
hasBOM: slots.lastSourceCode.hasBOM,
|
1660
|
+
parserServices: slots.lastSourceCode.parserServices,
|
1661
|
+
visitorKeys: slots.lastSourceCode.visitorKeys,
|
1662
|
+
scopeManager: analyzeScope(
|
1663
|
+
slots.lastSourceCode.ast,
|
1664
|
+
languageOptions,
|
1665
|
+
),
|
1666
|
+
});
|
1667
|
+
}
|
1668
|
+
}
|
1669
|
+
|
1670
|
+
const sourceCode = slots.lastSourceCode;
|
1671
|
+
const commentDirectives = options.allowInlineConfig
|
1672
|
+
? getDirectiveComments(
|
1673
|
+
sourceCode,
|
1674
|
+
ruleId => getRule(slots, ruleId),
|
1675
|
+
options.warnInlineConfig,
|
1676
|
+
config,
|
1677
|
+
)
|
1678
|
+
: {
|
1679
|
+
configuredRules: {},
|
1680
|
+
enabledGlobals: {},
|
1681
|
+
exportedVariables: {},
|
1682
|
+
problems: [],
|
1683
|
+
disableDirectives: [],
|
1684
|
+
};
|
1685
|
+
|
1686
|
+
addDeclaredGlobals(
|
1687
|
+
sourceCode.scopeManager.scopes[0],
|
1688
|
+
configuredGlobals,
|
1689
|
+
{
|
1690
|
+
exportedVariables: commentDirectives.exportedVariables,
|
1691
|
+
enabledGlobals: commentDirectives.enabledGlobals,
|
1692
|
+
},
|
1693
|
+
);
|
1694
|
+
|
1695
|
+
const configuredRules = Object.assign(
|
1696
|
+
{},
|
1697
|
+
config.rules,
|
1698
|
+
commentDirectives.configuredRules,
|
1699
|
+
);
|
1700
|
+
|
1701
|
+
let lintingProblems;
|
1702
|
+
|
1703
|
+
try {
|
1704
|
+
lintingProblems = runRules(
|
1705
|
+
sourceCode,
|
1706
|
+
configuredRules,
|
1707
|
+
ruleId => getRule(slots, ruleId),
|
1708
|
+
parserName,
|
1709
|
+
jslang,
|
1710
|
+
languageOptions,
|
1711
|
+
settings,
|
1712
|
+
options.filename,
|
1713
|
+
true,
|
1714
|
+
options.disableFixes,
|
1715
|
+
slots.cwd,
|
1716
|
+
providedOptions.physicalFilename,
|
1717
|
+
null,
|
1718
|
+
options.stats,
|
1719
|
+
slots,
|
1720
|
+
);
|
1721
|
+
} catch (err) {
|
1722
|
+
err.message += `\nOccurred while linting ${options.filename}`;
|
1723
|
+
debug("An error occurred while traversing");
|
1724
|
+
debug("Filename:", options.filename);
|
1725
|
+
if (err.currentNode) {
|
1726
|
+
const { line } = sourceCode.getLoc(err.currentNode).start;
|
1727
|
+
|
1728
|
+
debug("Line:", line);
|
1729
|
+
err.message += `:${line}`;
|
1730
|
+
}
|
1731
|
+
debug("Parser Options:", parserOptions);
|
1732
|
+
debug("Parser Path:", parserName);
|
1733
|
+
debug("Settings:", settings);
|
1734
|
+
|
1735
|
+
if (err.ruleId) {
|
1736
|
+
err.message += `\nRule: "${err.ruleId}"`;
|
1737
|
+
}
|
1738
|
+
|
1739
|
+
throw err;
|
1740
|
+
}
|
1741
|
+
|
1742
|
+
return applyDisableDirectives({
|
1743
|
+
language: jslang,
|
1744
|
+
sourceCode,
|
1745
|
+
directives: commentDirectives.disableDirectives,
|
1746
|
+
disableFixes: options.disableFixes,
|
1747
|
+
problems: lintingProblems
|
1748
|
+
.concat(commentDirectives.problems)
|
1749
|
+
.sort(
|
1750
|
+
(problemA, problemB) =>
|
1751
|
+
problemA.line - problemB.line ||
|
1752
|
+
problemA.column - problemB.column,
|
1753
|
+
),
|
1754
|
+
reportUnusedDisableDirectives:
|
1755
|
+
options.reportUnusedDisableDirectives,
|
1756
|
+
});
|
1757
|
+
}
|
1758
|
+
|
1759
|
+
/**
|
1760
|
+
* Same as linter.verify, except without support for processors.
|
1761
|
+
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
|
1762
|
+
* @param {ConfigData} providedConfig An ESLintConfig instance to configure everything.
|
1763
|
+
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1764
|
+
* @throws {Error} If during rule execution.
|
1765
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
1766
|
+
*/
|
1767
|
+
_verifyWithoutProcessors(
|
1768
|
+
textOrSourceCode,
|
1769
|
+
providedConfig,
|
1770
|
+
providedOptions,
|
1771
|
+
) {
|
1772
|
+
const slots = internalSlotsMap.get(this);
|
1773
|
+
const filename = normalizeFilename(
|
1774
|
+
providedOptions.filename || "<input>",
|
1775
|
+
);
|
1776
|
+
let text;
|
1777
|
+
|
1778
|
+
// evaluate arguments
|
1779
|
+
if (typeof textOrSourceCode === "string") {
|
1780
|
+
slots.lastSourceCode = null;
|
1781
|
+
text = textOrSourceCode;
|
1782
|
+
} else {
|
1783
|
+
slots.lastSourceCode = textOrSourceCode;
|
1784
|
+
text = textOrSourceCode.text;
|
1785
|
+
}
|
1786
|
+
|
1787
|
+
const file = new VFile(filename, text, {
|
1788
|
+
physicalPath: providedOptions.physicalFilename,
|
1789
|
+
});
|
1790
|
+
|
1791
|
+
return this.#eslintrcVerifyWithoutProcessors(
|
1792
|
+
file,
|
1793
|
+
providedConfig,
|
1794
|
+
providedOptions,
|
1795
|
+
);
|
1796
|
+
}
|
1797
|
+
|
1798
|
+
/**
|
1799
|
+
* Verifies the text against the rules specified by the second argument.
|
1800
|
+
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
|
1801
|
+
* @param {ConfigData|ConfigArray} config An ESLintConfig instance to configure everything.
|
1802
|
+
* @param {(string|(VerifyOptions&ProcessorOptions))} [filenameOrOptions] The optional filename of the file being checked.
|
1803
|
+
* If this is not set, the filename will default to '<input>' in the rule context. If
|
1804
|
+
* an object, then it has "filename", "allowInlineConfig", and some properties.
|
1805
|
+
* @returns {LintMessage[]} The results as an array of messages or an empty array if no messages.
|
1806
|
+
*/
|
1807
|
+
verify(textOrSourceCode, config, filenameOrOptions) {
|
1808
|
+
debug("Verify");
|
1809
|
+
|
1810
|
+
const { configType, cwd } = internalSlotsMap.get(this);
|
1811
|
+
|
1812
|
+
const options =
|
1813
|
+
typeof filenameOrOptions === "string"
|
1814
|
+
? { filename: filenameOrOptions }
|
1815
|
+
: filenameOrOptions || {};
|
1816
|
+
|
1817
|
+
const configToUse = config ?? {};
|
1818
|
+
|
1819
|
+
if (configType !== "eslintrc") {
|
1820
|
+
/*
|
1821
|
+
* Because of how Webpack packages up the files, we can't
|
1822
|
+
* compare directly to `FlatConfigArray` using `instanceof`
|
1823
|
+
* because it's not the same `FlatConfigArray` as in the tests.
|
1824
|
+
* So, we work around it by assuming an array is, in fact, a
|
1825
|
+
* `FlatConfigArray` if it has a `getConfig()` method.
|
1826
|
+
*/
|
1827
|
+
let configArray = configToUse;
|
1828
|
+
|
1829
|
+
if (
|
1830
|
+
!Array.isArray(configToUse) ||
|
1831
|
+
typeof configToUse.getConfig !== "function"
|
1832
|
+
) {
|
1833
|
+
configArray = new FlatConfigArray(configToUse, {
|
1834
|
+
basePath: cwd,
|
1835
|
+
});
|
1836
|
+
configArray.normalizeSync();
|
1837
|
+
}
|
1838
|
+
|
1839
|
+
return this._distinguishSuppressedMessages(
|
1840
|
+
this._verifyWithFlatConfigArray(
|
1841
|
+
textOrSourceCode,
|
1842
|
+
configArray,
|
1843
|
+
options,
|
1844
|
+
true,
|
1845
|
+
),
|
1846
|
+
);
|
1847
|
+
}
|
1848
|
+
|
1849
|
+
if (typeof configToUse.extractConfig === "function") {
|
1850
|
+
return this._distinguishSuppressedMessages(
|
1851
|
+
this._verifyWithConfigArray(
|
1852
|
+
textOrSourceCode,
|
1853
|
+
configToUse,
|
1854
|
+
options,
|
1855
|
+
),
|
1856
|
+
);
|
1857
|
+
}
|
1858
|
+
|
1859
|
+
/*
|
1860
|
+
* If we get to here, it means `config` is just an object rather
|
1861
|
+
* than a config array so we can go right into linting.
|
1862
|
+
*/
|
1863
|
+
|
1864
|
+
/*
|
1865
|
+
* `Linter` doesn't support `overrides` property in configuration.
|
1866
|
+
* So we cannot apply multiple processors.
|
1867
|
+
*/
|
1868
|
+
if (options.preprocess || options.postprocess) {
|
1869
|
+
return this._distinguishSuppressedMessages(
|
1870
|
+
this._verifyWithProcessor(
|
1871
|
+
textOrSourceCode,
|
1872
|
+
configToUse,
|
1873
|
+
options,
|
1874
|
+
),
|
1875
|
+
);
|
1876
|
+
}
|
1877
|
+
return this._distinguishSuppressedMessages(
|
1878
|
+
this._verifyWithoutProcessors(
|
1879
|
+
textOrSourceCode,
|
1880
|
+
configToUse,
|
1881
|
+
options,
|
1882
|
+
),
|
1883
|
+
);
|
1884
|
+
}
|
1885
|
+
|
1886
|
+
/**
|
1887
|
+
* Verify with a processor.
|
1888
|
+
* @param {string|SourceCode} textOrSourceCode The source code.
|
1889
|
+
* @param {FlatConfig} config The config array.
|
1890
|
+
* @param {VerifyOptions&ProcessorOptions} options The options.
|
1891
|
+
* @param {FlatConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
|
1892
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
|
1893
|
+
*/
|
1894
|
+
_verifyWithFlatConfigArrayAndProcessor(
|
1895
|
+
textOrSourceCode,
|
1896
|
+
config,
|
1897
|
+
options,
|
1898
|
+
configForRecursive,
|
1899
|
+
) {
|
1900
|
+
const slots = internalSlotsMap.get(this);
|
1901
|
+
const filename = options.filename || "<input>";
|
1902
|
+
const filenameToExpose = normalizeFilename(filename);
|
1903
|
+
const physicalFilename = options.physicalFilename || filenameToExpose;
|
1904
|
+
const text = ensureText(textOrSourceCode);
|
1905
|
+
const file = new VFile(filenameToExpose, text, {
|
1906
|
+
physicalPath: physicalFilename,
|
1907
|
+
});
|
1908
|
+
|
1909
|
+
const preprocess = options.preprocess || (rawText => [rawText]);
|
1910
|
+
const postprocess =
|
1911
|
+
options.postprocess || (messagesList => messagesList.flat());
|
1912
|
+
|
1913
|
+
const processorService = new ProcessorService();
|
1914
|
+
const preprocessResult = processorService.preprocessSync(file, {
|
1915
|
+
processor: {
|
1916
|
+
preprocess,
|
1917
|
+
postprocess,
|
1918
|
+
},
|
1919
|
+
});
|
1920
|
+
|
1921
|
+
if (!preprocessResult.ok) {
|
1922
|
+
return preprocessResult.errors;
|
1923
|
+
}
|
1924
|
+
|
1925
|
+
const filterCodeBlock =
|
1926
|
+
options.filterCodeBlock ||
|
1927
|
+
(blockFilename => blockFilename.endsWith(".js"));
|
1928
|
+
const originalExtname = path.extname(filename);
|
1929
|
+
const { files } = preprocessResult;
|
1930
|
+
|
1931
|
+
const messageLists = files.map(block => {
|
1932
|
+
debug("A code block was found: %o", block.path || "(unnamed)");
|
1933
|
+
|
1934
|
+
// Keep the legacy behavior.
|
1935
|
+
if (typeof block === "string") {
|
1936
|
+
return this._verifyWithFlatConfigArrayAndWithoutProcessors(
|
1937
|
+
block,
|
1938
|
+
config,
|
1939
|
+
options,
|
1940
|
+
);
|
1941
|
+
}
|
1942
|
+
|
1943
|
+
// Skip this block if filtered.
|
1944
|
+
if (!filterCodeBlock(block.path, block.body)) {
|
1945
|
+
debug("This code block was skipped.");
|
1946
|
+
return [];
|
1947
|
+
}
|
1948
|
+
|
1949
|
+
// Resolve configuration again if the file content or extension was changed.
|
1950
|
+
if (
|
1951
|
+
configForRecursive &&
|
1952
|
+
(text !== block.rawBody ||
|
1953
|
+
path.extname(block.path) !== originalExtname)
|
1954
|
+
) {
|
1955
|
+
debug(
|
1956
|
+
"Resolving configuration again because the file content or extension was changed.",
|
1957
|
+
);
|
1958
|
+
return this._verifyWithFlatConfigArray(
|
1959
|
+
block.rawBody,
|
1960
|
+
configForRecursive,
|
1961
|
+
{
|
1962
|
+
...options,
|
1963
|
+
filename: block.path,
|
1964
|
+
physicalFilename: block.physicalPath,
|
1965
|
+
},
|
1966
|
+
);
|
1967
|
+
}
|
1968
|
+
|
1969
|
+
slots.lastSourceCode = null;
|
1970
|
+
|
1971
|
+
// Does lint.
|
1972
|
+
return this.#flatVerifyWithoutProcessors(block, config, {
|
1973
|
+
...options,
|
1974
|
+
filename: block.path,
|
1975
|
+
physicalFilename: block.physicalPath,
|
1976
|
+
});
|
1977
|
+
});
|
1978
|
+
|
1979
|
+
return processorService.postprocessSync(file, messageLists, {
|
1980
|
+
processor: {
|
1981
|
+
preprocess,
|
1982
|
+
postprocess,
|
1983
|
+
},
|
1984
|
+
});
|
1985
|
+
}
|
1986
|
+
|
1987
|
+
/**
|
1988
|
+
* Verify using flat config and without any processors.
|
1989
|
+
* @param {VFile} file The file to lint.
|
1990
|
+
* @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
|
1991
|
+
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
1992
|
+
* @throws {Error} If during rule execution.
|
1993
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
1994
|
+
*/
|
1995
|
+
#flatVerifyWithoutProcessors(file, providedConfig, providedOptions) {
|
1996
|
+
const slots = internalSlotsMap.get(this);
|
1997
|
+
const config = providedConfig || {};
|
1998
|
+
const { settings = {}, languageOptions } = config;
|
1999
|
+
const options = normalizeVerifyOptions(providedOptions, config);
|
2000
|
+
|
2001
|
+
if (!slots.lastSourceCode) {
|
2002
|
+
let t;
|
2003
|
+
|
2004
|
+
if (options.stats) {
|
2005
|
+
t = startTime();
|
2006
|
+
}
|
2007
|
+
|
2008
|
+
const parserService = new ParserService();
|
2009
|
+
const parseResult = parserService.parseSync(file, config);
|
2010
|
+
|
2011
|
+
if (options.stats) {
|
2012
|
+
const time = endTime(t);
|
2013
|
+
|
2014
|
+
storeTime(time, { type: "parse" }, slots);
|
2015
|
+
}
|
2016
|
+
|
2017
|
+
if (!parseResult.ok) {
|
2018
|
+
return parseResult.errors;
|
2019
|
+
}
|
2020
|
+
|
2021
|
+
slots.lastSourceCode = parseResult.sourceCode;
|
2022
|
+
} else {
|
2023
|
+
/*
|
2024
|
+
* If the given source code object as the first argument does not have scopeManager, analyze the scope.
|
2025
|
+
* This is for backward compatibility (SourceCode is frozen so it cannot rebind).
|
2026
|
+
*
|
2027
|
+
* We check explicitly for `null` to ensure that this is a JS-flavored language.
|
2028
|
+
* For non-JS languages we don't want to do this.
|
2029
|
+
*
|
2030
|
+
* TODO: Remove this check when we stop exporting the `SourceCode` object.
|
2031
|
+
*/
|
2032
|
+
if (slots.lastSourceCode.scopeManager === null) {
|
2033
|
+
slots.lastSourceCode = new SourceCode({
|
2034
|
+
text: slots.lastSourceCode.text,
|
2035
|
+
ast: slots.lastSourceCode.ast,
|
2036
|
+
hasBOM: slots.lastSourceCode.hasBOM,
|
2037
|
+
parserServices: slots.lastSourceCode.parserServices,
|
2038
|
+
visitorKeys: slots.lastSourceCode.visitorKeys,
|
2039
|
+
scopeManager: analyzeScope(
|
2040
|
+
slots.lastSourceCode.ast,
|
2041
|
+
languageOptions,
|
2042
|
+
),
|
2043
|
+
});
|
2044
|
+
}
|
2045
|
+
}
|
2046
|
+
|
2047
|
+
const sourceCode = slots.lastSourceCode;
|
2048
|
+
|
2049
|
+
/*
|
2050
|
+
* Make adjustments based on the language options. For JavaScript,
|
2051
|
+
* this is primarily about adding variables into the global scope
|
2052
|
+
* to account for ecmaVersion and configured globals.
|
2053
|
+
*/
|
2054
|
+
sourceCode.applyLanguageOptions?.(languageOptions);
|
2055
|
+
|
2056
|
+
const mergedInlineConfig = {
|
2057
|
+
rules: {},
|
2058
|
+
};
|
2059
|
+
const inlineConfigProblems = [];
|
2060
|
+
|
2061
|
+
/*
|
2062
|
+
* Inline config can be either enabled or disabled. If disabled, it's possible
|
2063
|
+
* to detect the inline config and emit a warning (though this is not required).
|
2064
|
+
* So we first check to see if inline config is allowed at all, and if so, we
|
2065
|
+
* need to check if it's a warning or not.
|
2066
|
+
*/
|
2067
|
+
if (options.allowInlineConfig) {
|
2068
|
+
// if inline config should warn then add the warnings
|
2069
|
+
if (options.warnInlineConfig) {
|
2070
|
+
if (sourceCode.getInlineConfigNodes) {
|
2071
|
+
sourceCode.getInlineConfigNodes().forEach(node => {
|
2072
|
+
const loc = sourceCode.getLoc(node);
|
2073
|
+
const range = sourceCode.getRange(node);
|
2074
|
+
|
2075
|
+
inlineConfigProblems.push(
|
2076
|
+
createLintingProblem({
|
2077
|
+
ruleId: null,
|
2078
|
+
message: `'${sourceCode.text.slice(range[0], range[1])}' has no effect because you have 'noInlineConfig' setting in ${options.warnInlineConfig}.`,
|
2079
|
+
loc,
|
2080
|
+
severity: 1,
|
2081
|
+
language: config.language,
|
2082
|
+
}),
|
2083
|
+
);
|
2084
|
+
});
|
2085
|
+
}
|
2086
|
+
} else {
|
2087
|
+
const inlineConfigResult = sourceCode.applyInlineConfig?.();
|
2088
|
+
|
2089
|
+
if (inlineConfigResult) {
|
2090
|
+
inlineConfigProblems.push(
|
2091
|
+
...inlineConfigResult.problems
|
2092
|
+
.map(problem =>
|
2093
|
+
createLintingProblem({
|
2094
|
+
...problem,
|
2095
|
+
language: config.language,
|
2096
|
+
}),
|
2097
|
+
)
|
2098
|
+
.map(problem => {
|
2099
|
+
problem.fatal = true;
|
2100
|
+
return problem;
|
2101
|
+
}),
|
2102
|
+
);
|
2103
|
+
|
2104
|
+
// next we need to verify information about the specified rules
|
2105
|
+
const ruleValidator = new RuleValidator();
|
2106
|
+
|
2107
|
+
for (const {
|
2108
|
+
config: inlineConfig,
|
2109
|
+
loc,
|
2110
|
+
} of inlineConfigResult.configs) {
|
2111
|
+
Object.keys(inlineConfig.rules).forEach(ruleId => {
|
2112
|
+
const rule = getRuleFromConfig(ruleId, config);
|
2113
|
+
const ruleValue = inlineConfig.rules[ruleId];
|
2114
|
+
|
2115
|
+
if (!rule) {
|
2116
|
+
inlineConfigProblems.push(
|
2117
|
+
createLintingProblem({
|
2118
|
+
ruleId,
|
2119
|
+
loc,
|
2120
|
+
language: config.language,
|
2121
|
+
}),
|
2122
|
+
);
|
2123
|
+
return;
|
2124
|
+
}
|
2125
|
+
|
2126
|
+
if (
|
2127
|
+
Object.hasOwn(mergedInlineConfig.rules, ruleId)
|
2128
|
+
) {
|
2129
|
+
inlineConfigProblems.push(
|
2130
|
+
createLintingProblem({
|
2131
|
+
message: `Rule "${ruleId}" is already configured by another configuration comment in the preceding code. This configuration is ignored.`,
|
2132
|
+
loc,
|
2133
|
+
language: config.language,
|
2134
|
+
}),
|
2135
|
+
);
|
2136
|
+
return;
|
2137
|
+
}
|
2138
|
+
|
2139
|
+
try {
|
2140
|
+
const ruleOptionsInline = asArray(ruleValue);
|
2141
|
+
let ruleOptions = ruleOptionsInline;
|
2142
|
+
|
2143
|
+
assertIsRuleSeverity(ruleId, ruleOptions[0]);
|
2144
|
+
|
2145
|
+
/*
|
2146
|
+
* If the rule was already configured, inline rule configuration that
|
2147
|
+
* only has severity should retain options from the config and just override the severity.
|
2148
|
+
*
|
2149
|
+
* Example:
|
2150
|
+
*
|
2151
|
+
* {
|
2152
|
+
* rules: {
|
2153
|
+
* curly: ["error", "multi"]
|
2154
|
+
* }
|
2155
|
+
* }
|
2156
|
+
*
|
2157
|
+
* /* eslint curly: ["warn"] * /
|
2158
|
+
*
|
2159
|
+
* Results in:
|
2160
|
+
*
|
2161
|
+
* curly: ["warn", "multi"]
|
2162
|
+
*/
|
2163
|
+
|
2164
|
+
let shouldValidateOptions = true;
|
2165
|
+
|
2166
|
+
if (
|
2167
|
+
/*
|
2168
|
+
* If inline config for the rule has only severity
|
2169
|
+
*/
|
2170
|
+
ruleOptions.length === 1 &&
|
2171
|
+
/*
|
2172
|
+
* And the rule was already configured
|
2173
|
+
*/
|
2174
|
+
config.rules &&
|
2175
|
+
Object.hasOwn(config.rules, ruleId)
|
2176
|
+
) {
|
2177
|
+
/*
|
2178
|
+
* Then use severity from the inline config and options from the provided config
|
2179
|
+
*/
|
2180
|
+
ruleOptions = [
|
2181
|
+
ruleOptions[0], // severity from the inline config
|
2182
|
+
...config.rules[ruleId].slice(1), // options from the provided config
|
2183
|
+
];
|
2184
|
+
|
2185
|
+
// if the rule was enabled, the options have already been validated
|
2186
|
+
if (config.rules[ruleId][0] > 0) {
|
2187
|
+
shouldValidateOptions = false;
|
2188
|
+
}
|
2189
|
+
} else {
|
2190
|
+
/**
|
2191
|
+
* Since we know the user provided options, apply defaults on top of them
|
2192
|
+
*/
|
2193
|
+
const slicedOptions = ruleOptions.slice(1);
|
2194
|
+
const mergedOptions = deepMergeArrays(
|
2195
|
+
rule.meta?.defaultOptions,
|
2196
|
+
slicedOptions,
|
2197
|
+
);
|
2198
|
+
|
2199
|
+
if (mergedOptions.length) {
|
2200
|
+
ruleOptions = [
|
2201
|
+
ruleOptions[0],
|
2202
|
+
...mergedOptions,
|
2203
|
+
];
|
2204
|
+
}
|
2205
|
+
}
|
2206
|
+
|
2207
|
+
if (
|
2208
|
+
options.reportUnusedInlineConfigs !== "off"
|
2209
|
+
) {
|
2210
|
+
addProblemIfSameSeverityAndOptions(
|
2211
|
+
config,
|
2212
|
+
loc,
|
2213
|
+
inlineConfigProblems,
|
2214
|
+
ruleId,
|
2215
|
+
ruleOptions,
|
2216
|
+
ruleOptionsInline,
|
2217
|
+
options.reportUnusedInlineConfigs,
|
2218
|
+
);
|
2219
|
+
}
|
2220
|
+
|
2221
|
+
if (shouldValidateOptions) {
|
2222
|
+
ruleValidator.validate({
|
2223
|
+
plugins: config.plugins,
|
2224
|
+
rules: {
|
2225
|
+
[ruleId]: ruleOptions,
|
2226
|
+
},
|
2227
|
+
});
|
2228
|
+
}
|
2229
|
+
|
2230
|
+
mergedInlineConfig.rules[ruleId] = ruleOptions;
|
2231
|
+
} catch (err) {
|
2232
|
+
/*
|
2233
|
+
* If the rule has invalid `meta.schema`, throw the error because
|
2234
|
+
* this is not an invalid inline configuration but an invalid rule.
|
2235
|
+
*/
|
2236
|
+
if (
|
2237
|
+
err.code ===
|
2238
|
+
"ESLINT_INVALID_RULE_OPTIONS_SCHEMA"
|
2239
|
+
) {
|
2240
|
+
throw err;
|
2241
|
+
}
|
2242
|
+
|
2243
|
+
let baseMessage = err.message
|
2244
|
+
.slice(
|
2245
|
+
err.message.startsWith('Key "rules":')
|
2246
|
+
? err.message.indexOf(":", 12) + 1
|
2247
|
+
: err.message.indexOf(":") + 1,
|
2248
|
+
)
|
2249
|
+
.trim();
|
2250
|
+
|
2251
|
+
if (err.messageTemplate) {
|
2252
|
+
baseMessage += ` You passed "${ruleValue}".`;
|
2253
|
+
}
|
2254
|
+
|
2255
|
+
inlineConfigProblems.push(
|
2256
|
+
createLintingProblem({
|
2257
|
+
ruleId,
|
2258
|
+
message: `Inline configuration for rule "${ruleId}" is invalid:\n\t${baseMessage}\n`,
|
2259
|
+
loc,
|
2260
|
+
language: config.language,
|
2261
|
+
}),
|
2262
|
+
);
|
2263
|
+
}
|
2264
|
+
});
|
2265
|
+
}
|
2266
|
+
}
|
2267
|
+
}
|
2268
|
+
}
|
2269
|
+
|
2270
|
+
const commentDirectives =
|
2271
|
+
options.allowInlineConfig && !options.warnInlineConfig
|
2272
|
+
? getDirectiveCommentsForFlatConfig(
|
2273
|
+
sourceCode,
|
2274
|
+
ruleId => getRuleFromConfig(ruleId, config),
|
2275
|
+
config.language,
|
2276
|
+
)
|
2277
|
+
: { problems: [], disableDirectives: [] };
|
2278
|
+
|
2279
|
+
const configuredRules = Object.assign(
|
2280
|
+
{},
|
2281
|
+
config.rules,
|
2282
|
+
mergedInlineConfig.rules,
|
2283
|
+
);
|
2284
|
+
|
2285
|
+
let lintingProblems;
|
2286
|
+
|
2287
|
+
sourceCode.finalize?.();
|
2288
|
+
|
2289
|
+
try {
|
2290
|
+
lintingProblems = runRules(
|
2291
|
+
sourceCode,
|
2292
|
+
configuredRules,
|
2293
|
+
ruleId => getRuleFromConfig(ruleId, config),
|
2294
|
+
void 0,
|
2295
|
+
config.language,
|
2296
|
+
languageOptions,
|
2297
|
+
settings,
|
2298
|
+
options.filename,
|
2299
|
+
false,
|
2300
|
+
options.disableFixes,
|
2301
|
+
slots.cwd,
|
2302
|
+
providedOptions.physicalFilename,
|
2303
|
+
options.ruleFilter,
|
2304
|
+
options.stats,
|
2305
|
+
slots,
|
2306
|
+
);
|
2307
|
+
} catch (err) {
|
2308
|
+
err.message += `\nOccurred while linting ${options.filename}`;
|
2309
|
+
debug("An error occurred while traversing");
|
2310
|
+
debug("Filename:", options.filename);
|
2311
|
+
if (err.currentNode) {
|
2312
|
+
const { line } = sourceCode.getLoc(err.currentNode).start;
|
2313
|
+
|
2314
|
+
debug("Line:", line);
|
2315
|
+
err.message += `:${line}`;
|
2316
|
+
}
|
2317
|
+
debug("Parser Options:", languageOptions.parserOptions);
|
2318
|
+
|
2319
|
+
// debug("Parser Path:", parserName);
|
2320
|
+
debug("Settings:", settings);
|
2321
|
+
|
2322
|
+
if (err.ruleId) {
|
2323
|
+
err.message += `\nRule: "${err.ruleId}"`;
|
2324
|
+
}
|
2325
|
+
|
2326
|
+
throw err;
|
2327
|
+
}
|
2328
|
+
|
2329
|
+
return applyDisableDirectives({
|
2330
|
+
language: config.language,
|
2331
|
+
sourceCode,
|
2332
|
+
directives: commentDirectives.disableDirectives,
|
2333
|
+
disableFixes: options.disableFixes,
|
2334
|
+
problems: lintingProblems
|
2335
|
+
.concat(commentDirectives.problems)
|
2336
|
+
.concat(inlineConfigProblems)
|
2337
|
+
.sort(
|
2338
|
+
(problemA, problemB) =>
|
2339
|
+
problemA.line - problemB.line ||
|
2340
|
+
problemA.column - problemB.column,
|
2341
|
+
),
|
2342
|
+
reportUnusedDisableDirectives:
|
2343
|
+
options.reportUnusedDisableDirectives,
|
2344
|
+
ruleFilter: options.ruleFilter,
|
2345
|
+
configuredRules,
|
2346
|
+
});
|
2347
|
+
}
|
2348
|
+
|
2349
|
+
/**
|
2350
|
+
* Same as linter.verify, except without support for processors.
|
2351
|
+
* @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
|
2352
|
+
* @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
|
2353
|
+
* @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
|
2354
|
+
* @throws {Error} If during rule execution.
|
2355
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
|
2356
|
+
*/
|
2357
|
+
_verifyWithFlatConfigArrayAndWithoutProcessors(
|
2358
|
+
textOrSourceCode,
|
2359
|
+
providedConfig,
|
2360
|
+
providedOptions,
|
2361
|
+
) {
|
2362
|
+
const slots = internalSlotsMap.get(this);
|
2363
|
+
const filename = normalizeFilename(
|
2364
|
+
providedOptions.filename || "<input>",
|
2365
|
+
);
|
2366
|
+
let text;
|
2367
|
+
|
2368
|
+
// evaluate arguments
|
2369
|
+
if (typeof textOrSourceCode === "string") {
|
2370
|
+
slots.lastSourceCode = null;
|
2371
|
+
text = textOrSourceCode;
|
2372
|
+
} else {
|
2373
|
+
slots.lastSourceCode = textOrSourceCode;
|
2374
|
+
text = textOrSourceCode.text;
|
2375
|
+
}
|
2376
|
+
|
2377
|
+
const file = new VFile(filename, text, {
|
2378
|
+
physicalPath: providedOptions.physicalFilename,
|
2379
|
+
});
|
2380
|
+
|
2381
|
+
return this.#flatVerifyWithoutProcessors(
|
2382
|
+
file,
|
2383
|
+
providedConfig,
|
2384
|
+
providedOptions,
|
2385
|
+
);
|
2386
|
+
}
|
2387
|
+
|
2388
|
+
/**
|
2389
|
+
* Verify a given code with `ConfigArray`.
|
2390
|
+
* @param {string|SourceCode} textOrSourceCode The source code.
|
2391
|
+
* @param {ConfigArray} configArray The config array.
|
2392
|
+
* @param {VerifyOptions&ProcessorOptions} options The options.
|
2393
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
|
2394
|
+
*/
|
2395
|
+
_verifyWithConfigArray(textOrSourceCode, configArray, options) {
|
2396
|
+
debug("With ConfigArray: %s", options.filename);
|
2397
|
+
|
2398
|
+
// Store the config array in order to get plugin envs and rules later.
|
2399
|
+
internalSlotsMap.get(this).lastConfigArray = configArray;
|
2400
|
+
|
2401
|
+
// Extract the final config for this file.
|
2402
|
+
const config = configArray.extractConfig(options.filename);
|
2403
|
+
const processor =
|
2404
|
+
config.processor &&
|
2405
|
+
configArray.pluginProcessors.get(config.processor);
|
2406
|
+
|
2407
|
+
// Verify.
|
2408
|
+
if (processor) {
|
2409
|
+
debug("Apply the processor: %o", config.processor);
|
2410
|
+
const { preprocess, postprocess, supportsAutofix } = processor;
|
2411
|
+
const disableFixes = options.disableFixes || !supportsAutofix;
|
2412
|
+
|
2413
|
+
return this._verifyWithProcessor(
|
2414
|
+
textOrSourceCode,
|
2415
|
+
config,
|
2416
|
+
{ ...options, disableFixes, postprocess, preprocess },
|
2417
|
+
configArray,
|
2418
|
+
);
|
2419
|
+
}
|
2420
|
+
return this._verifyWithoutProcessors(textOrSourceCode, config, options);
|
2421
|
+
}
|
2422
|
+
|
2423
|
+
/**
|
2424
|
+
* Verify a given code with a flat config.
|
2425
|
+
* @param {string|SourceCode} textOrSourceCode The source code.
|
2426
|
+
* @param {FlatConfigArray} configArray The config array.
|
2427
|
+
* @param {VerifyOptions&ProcessorOptions} options The options.
|
2428
|
+
* @param {boolean} [firstCall=false] Indicates if this is being called directly
|
2429
|
+
* from verify(). (TODO: Remove once eslintrc is removed.)
|
2430
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
|
2431
|
+
*/
|
2432
|
+
_verifyWithFlatConfigArray(
|
2433
|
+
textOrSourceCode,
|
2434
|
+
configArray,
|
2435
|
+
options,
|
2436
|
+
firstCall = false,
|
2437
|
+
) {
|
2438
|
+
debug("With flat config: %s", options.filename);
|
2439
|
+
|
2440
|
+
// we need a filename to match configs against
|
2441
|
+
const filename = options.filename || "__placeholder__.js";
|
2442
|
+
|
2443
|
+
// Store the config array in order to get plugin envs and rules later.
|
2444
|
+
internalSlotsMap.get(this).lastConfigArray = configArray;
|
2445
|
+
const config = configArray.getConfig(filename);
|
2446
|
+
|
2447
|
+
if (!config) {
|
2448
|
+
return [
|
2449
|
+
{
|
2450
|
+
ruleId: null,
|
2451
|
+
severity: 1,
|
2452
|
+
message: `No matching configuration found for ${filename}.`,
|
2453
|
+
line: 0,
|
2454
|
+
column: 0,
|
2455
|
+
nodeType: null,
|
2456
|
+
},
|
2457
|
+
];
|
2458
|
+
}
|
2459
|
+
|
2460
|
+
// Verify.
|
2461
|
+
if (config.processor) {
|
2462
|
+
debug("Apply the processor: %o", config.processor);
|
2463
|
+
const { preprocess, postprocess, supportsAutofix } =
|
2464
|
+
config.processor;
|
2465
|
+
const disableFixes = options.disableFixes || !supportsAutofix;
|
2466
|
+
|
2467
|
+
return this._verifyWithFlatConfigArrayAndProcessor(
|
2468
|
+
textOrSourceCode,
|
2469
|
+
config,
|
2470
|
+
{ ...options, filename, disableFixes, postprocess, preprocess },
|
2471
|
+
configArray,
|
2472
|
+
);
|
2473
|
+
}
|
2474
|
+
|
2475
|
+
// check for options-based processing
|
2476
|
+
if (firstCall && (options.preprocess || options.postprocess)) {
|
2477
|
+
return this._verifyWithFlatConfigArrayAndProcessor(
|
2478
|
+
textOrSourceCode,
|
2479
|
+
config,
|
2480
|
+
options,
|
2481
|
+
);
|
2482
|
+
}
|
2483
|
+
|
2484
|
+
return this._verifyWithFlatConfigArrayAndWithoutProcessors(
|
2485
|
+
textOrSourceCode,
|
2486
|
+
config,
|
2487
|
+
options,
|
2488
|
+
);
|
2489
|
+
}
|
2490
|
+
|
2491
|
+
/**
|
2492
|
+
* Verify with a processor.
|
2493
|
+
* @param {string|SourceCode} textOrSourceCode The source code.
|
2494
|
+
* @param {ConfigData|ExtractedConfig} config The config array.
|
2495
|
+
* @param {VerifyOptions&ProcessorOptions} options The options.
|
2496
|
+
* @param {ConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
|
2497
|
+
* @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
|
2498
|
+
*/
|
2499
|
+
_verifyWithProcessor(
|
2500
|
+
textOrSourceCode,
|
2501
|
+
config,
|
2502
|
+
options,
|
2503
|
+
configForRecursive,
|
2504
|
+
) {
|
2505
|
+
const slots = internalSlotsMap.get(this);
|
2506
|
+
const filename = options.filename || "<input>";
|
2507
|
+
const filenameToExpose = normalizeFilename(filename);
|
2508
|
+
const physicalFilename = options.physicalFilename || filenameToExpose;
|
2509
|
+
const text = ensureText(textOrSourceCode);
|
2510
|
+
const file = new VFile(filenameToExpose, text, {
|
2511
|
+
physicalPath: physicalFilename,
|
2512
|
+
});
|
2513
|
+
|
2514
|
+
const preprocess = options.preprocess || (rawText => [rawText]);
|
2515
|
+
const postprocess =
|
2516
|
+
options.postprocess || (messagesList => messagesList.flat());
|
2517
|
+
|
2518
|
+
const processorService = new ProcessorService();
|
2519
|
+
const preprocessResult = processorService.preprocessSync(file, {
|
2520
|
+
processor: {
|
2521
|
+
preprocess,
|
2522
|
+
postprocess,
|
2523
|
+
},
|
2524
|
+
});
|
2525
|
+
|
2526
|
+
if (!preprocessResult.ok) {
|
2527
|
+
return preprocessResult.errors;
|
2528
|
+
}
|
2529
|
+
|
2530
|
+
const filterCodeBlock =
|
2531
|
+
options.filterCodeBlock ||
|
2532
|
+
(blockFilePath => blockFilePath.endsWith(".js"));
|
2533
|
+
const originalExtname = path.extname(filename);
|
2534
|
+
|
2535
|
+
const { files } = preprocessResult;
|
2536
|
+
|
2537
|
+
const messageLists = files.map(block => {
|
2538
|
+
debug("A code block was found: %o", block.path ?? "(unnamed)");
|
2539
|
+
|
2540
|
+
// Keep the legacy behavior.
|
2541
|
+
if (typeof block === "string") {
|
2542
|
+
return this._verifyWithoutProcessors(block, config, options);
|
2543
|
+
}
|
2544
|
+
|
2545
|
+
// Skip this block if filtered.
|
2546
|
+
if (!filterCodeBlock(block.path, block.body)) {
|
2547
|
+
debug("This code block was skipped.");
|
2548
|
+
return [];
|
2549
|
+
}
|
2550
|
+
|
2551
|
+
// Resolve configuration again if the file content or extension was changed.
|
2552
|
+
if (
|
2553
|
+
configForRecursive &&
|
2554
|
+
(text !== block.rawBody ||
|
2555
|
+
path.extname(block.path) !== originalExtname)
|
2556
|
+
) {
|
2557
|
+
debug(
|
2558
|
+
"Resolving configuration again because the file content or extension was changed.",
|
2559
|
+
);
|
2560
|
+
return this._verifyWithConfigArray(
|
2561
|
+
block.rawBody,
|
2562
|
+
configForRecursive,
|
2563
|
+
{
|
2564
|
+
...options,
|
2565
|
+
filename: block.path,
|
2566
|
+
physicalFilename: block.physicalPath,
|
2567
|
+
},
|
2568
|
+
);
|
2569
|
+
}
|
2570
|
+
|
2571
|
+
slots.lastSourceCode = null;
|
2572
|
+
|
2573
|
+
// Does lint.
|
2574
|
+
return this.#eslintrcVerifyWithoutProcessors(block, config, {
|
2575
|
+
...options,
|
2576
|
+
filename: block.path,
|
2577
|
+
physicalFilename: block.physicalPath,
|
2578
|
+
});
|
2579
|
+
});
|
2580
|
+
|
2581
|
+
return processorService.postprocessSync(file, messageLists, {
|
2582
|
+
processor: {
|
2583
|
+
preprocess,
|
2584
|
+
postprocess,
|
2585
|
+
},
|
2586
|
+
});
|
2587
|
+
}
|
2588
|
+
|
2589
|
+
/**
|
2590
|
+
* Given a list of reported problems, distinguish problems between normal messages and suppressed messages.
|
2591
|
+
* The normal messages will be returned and the suppressed messages will be stored as lastSuppressedMessages.
|
2592
|
+
* @param {Array<LintMessage|SuppressedLintMessage>} problems A list of reported problems.
|
2593
|
+
* @returns {LintMessage[]} A list of LintMessage.
|
2594
|
+
*/
|
2595
|
+
_distinguishSuppressedMessages(problems) {
|
2596
|
+
const messages = [];
|
2597
|
+
const suppressedMessages = [];
|
2598
|
+
const slots = internalSlotsMap.get(this);
|
2599
|
+
|
2600
|
+
for (const problem of problems) {
|
2601
|
+
if (problem.suppressions) {
|
2602
|
+
suppressedMessages.push(problem);
|
2603
|
+
} else {
|
2604
|
+
messages.push(problem);
|
2605
|
+
}
|
2606
|
+
}
|
2607
|
+
|
2608
|
+
slots.lastSuppressedMessages = suppressedMessages;
|
2609
|
+
|
2610
|
+
return messages;
|
2611
|
+
}
|
2612
|
+
|
2613
|
+
/**
|
2614
|
+
* Gets the SourceCode object representing the parsed source.
|
2615
|
+
* @returns {SourceCode} The SourceCode object.
|
2616
|
+
*/
|
2617
|
+
getSourceCode() {
|
2618
|
+
return internalSlotsMap.get(this).lastSourceCode;
|
2619
|
+
}
|
2620
|
+
|
2621
|
+
/**
|
2622
|
+
* Gets the times spent on (parsing, fixing, linting) a file.
|
2623
|
+
* @returns {LintTimes} The times.
|
2624
|
+
*/
|
2625
|
+
getTimes() {
|
2626
|
+
return internalSlotsMap.get(this).times ?? { passes: [] };
|
2627
|
+
}
|
2628
|
+
|
2629
|
+
/**
|
2630
|
+
* Gets the number of autofix passes that were made in the last run.
|
2631
|
+
* @returns {number} The number of autofix passes.
|
2632
|
+
*/
|
2633
|
+
getFixPassCount() {
|
2634
|
+
return internalSlotsMap.get(this).fixPasses ?? 0;
|
2635
|
+
}
|
2636
|
+
|
2637
|
+
/**
|
2638
|
+
* Gets the list of SuppressedLintMessage produced in the last running.
|
2639
|
+
* @returns {SuppressedLintMessage[]} The list of SuppressedLintMessage
|
2640
|
+
*/
|
2641
|
+
getSuppressedMessages() {
|
2642
|
+
return internalSlotsMap.get(this).lastSuppressedMessages;
|
2643
|
+
}
|
2644
|
+
|
2645
|
+
/**
|
2646
|
+
* Defines a new linting rule.
|
2647
|
+
* @param {string} ruleId A unique rule identifier
|
2648
|
+
* @param {Rule} rule A rule object
|
2649
|
+
* @returns {void}
|
2650
|
+
*/
|
2651
|
+
defineRule(ruleId, rule) {
|
2652
|
+
assertEslintrcConfig(this);
|
2653
|
+
internalSlotsMap.get(this).ruleMap.define(ruleId, rule);
|
2654
|
+
}
|
2655
|
+
|
2656
|
+
/**
|
2657
|
+
* Defines many new linting rules.
|
2658
|
+
* @param {Record<string, Rule>} rulesToDefine map from unique rule identifier to rule
|
2659
|
+
* @returns {void}
|
2660
|
+
*/
|
2661
|
+
defineRules(rulesToDefine) {
|
2662
|
+
assertEslintrcConfig(this);
|
2663
|
+
Object.getOwnPropertyNames(rulesToDefine).forEach(ruleId => {
|
2664
|
+
this.defineRule(ruleId, rulesToDefine[ruleId]);
|
2665
|
+
});
|
2666
|
+
}
|
2667
|
+
|
2668
|
+
/**
|
2669
|
+
* Gets an object with all loaded rules.
|
2670
|
+
* @returns {Map<string, Rule>} All loaded rules
|
2671
|
+
*/
|
2672
|
+
getRules() {
|
2673
|
+
assertEslintrcConfig(this);
|
2674
|
+
const { lastConfigArray, ruleMap } = internalSlotsMap.get(this);
|
2675
|
+
|
2676
|
+
return new Map(
|
2677
|
+
(function* () {
|
2678
|
+
yield* ruleMap;
|
2679
|
+
|
2680
|
+
if (lastConfigArray) {
|
2681
|
+
yield* lastConfigArray.pluginRules;
|
2682
|
+
}
|
2683
|
+
})(),
|
2684
|
+
);
|
2685
|
+
}
|
2686
|
+
|
2687
|
+
/**
|
2688
|
+
* Define a new parser module
|
2689
|
+
* @param {string} parserId Name of the parser
|
2690
|
+
* @param {Parser} parserModule The parser object
|
2691
|
+
* @returns {void}
|
2692
|
+
*/
|
2693
|
+
defineParser(parserId, parserModule) {
|
2694
|
+
assertEslintrcConfig(this);
|
2695
|
+
internalSlotsMap.get(this).parserMap.set(parserId, parserModule);
|
2696
|
+
}
|
2697
|
+
|
2698
|
+
/**
|
2699
|
+
* Performs multiple autofix passes over the text until as many fixes as possible
|
2700
|
+
* have been applied.
|
2701
|
+
* @param {string} text The source text to apply fixes to.
|
2702
|
+
* @param {ConfigData|ConfigArray|FlatConfigArray} config The ESLint config object to use.
|
2703
|
+
* @param {VerifyOptions&ProcessorOptions&FixOptions} options The ESLint options object to use.
|
2704
|
+
* @returns {{fixed:boolean,messages:LintMessage[],output:string}} The result of the fix operation as returned from the
|
2705
|
+
* SourceCodeFixer.
|
2706
|
+
*/
|
2707
|
+
verifyAndFix(text, config, options) {
|
2708
|
+
let messages,
|
2709
|
+
fixedResult,
|
2710
|
+
fixed = false,
|
2711
|
+
passNumber = 0,
|
2712
|
+
currentText = text,
|
2713
|
+
secondPreviousText,
|
2714
|
+
previousText;
|
2715
|
+
const debugTextDescription =
|
2716
|
+
(options && options.filename) || `${text.slice(0, 10)}...`;
|
2717
|
+
const shouldFix =
|
2718
|
+
options && typeof options.fix !== "undefined" ? options.fix : true;
|
2719
|
+
const stats = options?.stats;
|
2720
|
+
|
2721
|
+
/**
|
2722
|
+
* This loop continues until one of the following is true:
|
2723
|
+
*
|
2724
|
+
* 1. No more fixes have been applied.
|
2725
|
+
* 2. Ten passes have been made.
|
2726
|
+
*
|
2727
|
+
* That means anytime a fix is successfully applied, there will be another pass.
|
2728
|
+
* Essentially, guaranteeing a minimum of two passes.
|
2729
|
+
*/
|
2730
|
+
const slots = internalSlotsMap.get(this);
|
2731
|
+
|
2732
|
+
// Remove lint times from the last run.
|
2733
|
+
if (stats) {
|
2734
|
+
delete slots.times;
|
2735
|
+
slots.fixPasses = 0;
|
2736
|
+
}
|
2737
|
+
|
2738
|
+
do {
|
2739
|
+
passNumber++;
|
2740
|
+
let tTotal;
|
2741
|
+
|
2742
|
+
if (stats) {
|
2743
|
+
tTotal = startTime();
|
2744
|
+
}
|
2745
|
+
|
2746
|
+
debug(
|
2747
|
+
`Linting code for ${debugTextDescription} (pass ${passNumber})`,
|
2748
|
+
);
|
2749
|
+
messages = this.verify(currentText, config, options);
|
2750
|
+
|
2751
|
+
debug(
|
2752
|
+
`Generating fixed text for ${debugTextDescription} (pass ${passNumber})`,
|
2753
|
+
);
|
2754
|
+
let t;
|
2755
|
+
|
2756
|
+
if (stats) {
|
2757
|
+
t = startTime();
|
2758
|
+
}
|
2759
|
+
|
2760
|
+
fixedResult = SourceCodeFixer.applyFixes(
|
2761
|
+
currentText,
|
2762
|
+
messages,
|
2763
|
+
shouldFix,
|
2764
|
+
);
|
2765
|
+
|
2766
|
+
if (stats) {
|
2767
|
+
if (fixedResult.fixed) {
|
2768
|
+
const time = endTime(t);
|
2769
|
+
|
2770
|
+
storeTime(time, { type: "fix" }, slots);
|
2771
|
+
slots.fixPasses++;
|
2772
|
+
} else {
|
2773
|
+
storeTime(0, { type: "fix" }, slots);
|
2774
|
+
}
|
2775
|
+
}
|
2776
|
+
|
2777
|
+
/*
|
2778
|
+
* stop if there are any syntax errors.
|
2779
|
+
* 'fixedResult.output' is a empty string.
|
2780
|
+
*/
|
2781
|
+
if (messages.length === 1 && messages[0].fatal) {
|
2782
|
+
break;
|
2783
|
+
}
|
2784
|
+
|
2785
|
+
// keep track if any fixes were ever applied - important for return value
|
2786
|
+
fixed = fixed || fixedResult.fixed;
|
2787
|
+
|
2788
|
+
// update to use the fixed output instead of the original text
|
2789
|
+
secondPreviousText = previousText;
|
2790
|
+
previousText = currentText;
|
2791
|
+
currentText = fixedResult.output;
|
2792
|
+
|
2793
|
+
if (stats) {
|
2794
|
+
tTotal = endTime(tTotal);
|
2795
|
+
const passIndex = slots.times.passes.length - 1;
|
2796
|
+
|
2797
|
+
slots.times.passes[passIndex].total = tTotal;
|
2798
|
+
}
|
2799
|
+
|
2800
|
+
// Stop if we've made a circular fix
|
2801
|
+
if (
|
2802
|
+
passNumber > 1 &&
|
2803
|
+
currentText.length === secondPreviousText.length &&
|
2804
|
+
currentText === secondPreviousText
|
2805
|
+
) {
|
2806
|
+
debug(
|
2807
|
+
`Circular fixes detected after pass ${passNumber}. Exiting fix loop.`,
|
2808
|
+
);
|
2809
|
+
globalThis?.process?.emitWarning?.(
|
2810
|
+
`Circular fixes detected while fixing ${options?.filename ?? "text"}. It is likely that you have conflicting rules in your configuration.`,
|
2811
|
+
"ESLintCircularFixesWarning",
|
2812
|
+
);
|
2813
|
+
break;
|
2814
|
+
}
|
2815
|
+
} while (fixedResult.fixed && passNumber < MAX_AUTOFIX_PASSES);
|
2816
|
+
|
2817
|
+
/*
|
2818
|
+
* If the last result had fixes, we need to lint again to be sure we have
|
2819
|
+
* the most up-to-date information.
|
2820
|
+
*/
|
2821
|
+
if (fixedResult.fixed) {
|
2822
|
+
let tTotal;
|
2823
|
+
|
2824
|
+
if (stats) {
|
2825
|
+
tTotal = startTime();
|
2826
|
+
}
|
2827
|
+
|
2828
|
+
fixedResult.messages = this.verify(currentText, config, options);
|
2829
|
+
|
2830
|
+
if (stats) {
|
2831
|
+
storeTime(0, { type: "fix" }, slots);
|
2832
|
+
slots.times.passes.at(-1).total = endTime(tTotal);
|
2833
|
+
}
|
2834
|
+
}
|
2835
|
+
|
2836
|
+
// ensure the last result properly reflects if fixes were done
|
2837
|
+
fixedResult.fixed = fixed;
|
2838
|
+
fixedResult.output = currentText;
|
2839
|
+
|
2840
|
+
return fixedResult;
|
2841
|
+
}
|
2484
2842
|
}
|
2485
2843
|
|
2486
2844
|
module.exports = {
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
|
2494
|
-
|
2495
|
-
|
2496
|
-
|
2845
|
+
Linter,
|
2846
|
+
|
2847
|
+
/**
|
2848
|
+
* Get the internal slots of a given Linter instance for tests.
|
2849
|
+
* @param {Linter} instance The Linter instance to get.
|
2850
|
+
* @returns {LinterInternalSlots} The internal slots.
|
2851
|
+
*/
|
2852
|
+
getLinterInternalSlots(instance) {
|
2853
|
+
return internalSlotsMap.get(instance);
|
2854
|
+
},
|
2497
2855
|
};
|