eslint 8.57.1 → 9.39.1
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 +165 -115
- package/bin/eslint.js +112 -89
- package/conf/default-cli-options.js +22 -22
- package/conf/ecma-version.js +16 -0
- package/conf/globals.js +109 -94
- package/conf/replacements.json +24 -20
- package/conf/rule-type-list.json +89 -26
- package/lib/api.js +16 -20
- package/lib/cli-engine/cli-engine.js +841 -810
- package/lib/cli-engine/file-enumerator.js +384 -390
- package/lib/cli-engine/formatters/formatters-meta.json +17 -45
- package/lib/cli-engine/formatters/html.js +110 -102
- 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 +97 -76
- package/lib/cli-engine/hash.js +1 -1
- package/lib/cli-engine/index.js +1 -1
- package/lib/cli-engine/lint-result-cache.js +165 -148
- package/lib/cli-engine/load-rules.js +17 -17
- package/lib/cli.js +481 -399
- package/lib/config/config-loader.js +816 -0
- package/lib/config/config.js +674 -0
- package/lib/config/default-config.js +57 -46
- package/lib/config/flat-config-array.js +170 -333
- package/lib/config/flat-config-schema.js +389 -389
- package/lib/config-api.js +12 -0
- package/lib/eslint/eslint-helpers.js +1196 -663
- package/lib/eslint/eslint.js +1262 -607
- package/lib/eslint/index.js +3 -3
- package/lib/eslint/legacy-eslint.js +786 -0
- package/lib/eslint/worker.js +173 -0
- package/lib/languages/js/index.js +336 -0
- package/lib/languages/js/source-code/index.js +7 -0
- package/lib/languages/js/source-code/source-code.js +1364 -0
- package/lib/languages/js/source-code/token-store/backward-token-comment-cursor.js +61 -0
- package/lib/languages/js/source-code/token-store/backward-token-cursor.js +57 -0
- package/lib/{source-code → languages/js/source-code}/token-store/cursor.js +36 -36
- package/lib/languages/js/source-code/token-store/cursors.js +120 -0
- package/lib/{source-code → languages/js/source-code}/token-store/decorative-cursor.js +17 -18
- package/lib/{source-code → languages/js/source-code}/token-store/filter-cursor.js +19 -20
- package/lib/languages/js/source-code/token-store/forward-token-comment-cursor.js +65 -0
- package/lib/languages/js/source-code/token-store/forward-token-cursor.js +62 -0
- package/lib/languages/js/source-code/token-store/index.js +721 -0
- package/lib/{source-code → languages/js/source-code}/token-store/limit-cursor.js +17 -18
- package/lib/languages/js/source-code/token-store/padded-token-cursor.js +45 -0
- package/lib/{source-code → languages/js/source-code}/token-store/skip-cursor.js +19 -20
- package/lib/languages/js/source-code/token-store/utils.js +110 -0
- package/lib/languages/js/validate-language-options.js +196 -0
- package/lib/linter/apply-disable-directives.js +490 -371
- package/lib/linter/code-path-analysis/code-path-analyzer.js +650 -674
- 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 -317
- package/lib/linter/code-path-analysis/debug-helpers.js +183 -163
- package/lib/linter/code-path-analysis/fork-context.js +297 -272
- package/lib/linter/code-path-analysis/id-generator.js +22 -23
- package/lib/linter/esquery.js +332 -0
- package/lib/linter/file-context.js +144 -0
- package/lib/linter/file-report.js +608 -0
- package/lib/linter/index.js +3 -5
- package/lib/linter/interpolate.js +38 -16
- package/lib/linter/linter.js +2328 -1785
- package/lib/linter/rule-fixer.js +136 -107
- package/lib/linter/rules.js +37 -46
- package/lib/linter/source-code-fixer.js +96 -94
- package/lib/linter/source-code-traverser.js +333 -0
- package/lib/linter/source-code-visitor.js +81 -0
- package/lib/linter/timing.js +145 -97
- package/lib/linter/vfile.js +115 -0
- package/lib/options.js +464 -326
- package/lib/rule-tester/index.js +3 -1
- package/lib/rule-tester/rule-tester.js +1371 -998
- package/lib/rules/accessor-pairs.js +333 -259
- package/lib/rules/array-bracket-newline.js +250 -220
- package/lib/rules/array-bracket-spacing.js +286 -229
- package/lib/rules/array-callback-return.js +401 -354
- package/lib/rules/array-element-newline.js +358 -295
- package/lib/rules/arrow-body-style.js +400 -278
- package/lib/rules/arrow-parens.js +206 -155
- package/lib/rules/arrow-spacing.js +169 -145
- package/lib/rules/block-scoped-var.js +125 -123
- package/lib/rules/block-spacing.js +186 -158
- package/lib/rules/brace-style.js +262 -181
- package/lib/rules/callback-return.js +203 -174
- package/lib/rules/camelcase.js +403 -380
- package/lib/rules/capitalized-comments.js +253 -228
- package/lib/rules/class-methods-use-this.js +231 -168
- package/lib/rules/comma-dangle.js +379 -328
- package/lib/rules/comma-spacing.js +193 -177
- package/lib/rules/comma-style.js +375 -298
- package/lib/rules/complexity.js +180 -144
- package/lib/rules/computed-property-spacing.js +236 -193
- package/lib/rules/consistent-return.js +181 -170
- package/lib/rules/consistent-this.js +167 -141
- package/lib/rules/constructor-super.js +418 -411
- package/lib/rules/curly.js +407 -468
- package/lib/rules/default-case-last.js +39 -32
- package/lib/rules/default-case.js +89 -83
- package/lib/rules/default-param-last.js +69 -53
- package/lib/rules/dot-location.js +122 -92
- package/lib/rules/dot-notation.js +193 -153
- package/lib/rules/eol-last.js +122 -102
- package/lib/rules/eqeqeq.js +191 -155
- package/lib/rules/for-direction.js +150 -122
- package/lib/rules/func-call-spacing.js +261 -213
- package/lib/rules/func-name-matching.js +294 -209
- package/lib/rules/func-names.js +165 -164
- package/lib/rules/func-style.js +209 -86
- package/lib/rules/function-call-argument-newline.js +152 -111
- package/lib/rules/function-paren-newline.js +349 -273
- package/lib/rules/generator-star-spacing.js +229 -192
- package/lib/rules/getter-return.js +208 -170
- package/lib/rules/global-require.js +85 -58
- package/lib/rules/grouped-accessor-pairs.js +201 -148
- package/lib/rules/guard-for-in.js +72 -63
- package/lib/rules/handle-callback-err.js +108 -87
- package/lib/rules/id-blacklist.js +182 -187
- package/lib/rules/id-denylist.js +174 -179
- package/lib/rules/id-length.js +197 -157
- package/lib/rules/id-match.js +350 -286
- package/lib/rules/implicit-arrow-linebreak.js +102 -61
- package/lib/rules/indent-legacy.js +1345 -1102
- package/lib/rules/indent.js +2272 -1741
- package/lib/rules/index.js +320 -294
- package/lib/rules/init-declarations.js +139 -106
- package/lib/rules/jsx-quotes.js +94 -64
- package/lib/rules/key-spacing.js +750 -615
- package/lib/rules/keyword-spacing.js +648 -587
- package/lib/rules/line-comment-position.js +143 -108
- package/lib/rules/linebreak-style.js +115 -88
- package/lib/rules/lines-around-comment.js +540 -430
- package/lib/rules/lines-around-directive.js +233 -185
- package/lib/rules/lines-between-class-members.js +305 -216
- package/lib/rules/logical-assignment-operators.js +582 -398
- package/lib/rules/max-classes-per-file.js +69 -68
- package/lib/rules/max-depth.js +146 -143
- package/lib/rules/max-len.js +473 -416
- package/lib/rules/max-lines-per-function.js +201 -176
- package/lib/rules/max-lines.js +158 -162
- package/lib/rules/max-nested-callbacks.js +102 -104
- package/lib/rules/max-params.js +102 -75
- package/lib/rules/max-statements-per-line.js +205 -180
- package/lib/rules/max-statements.js +168 -164
- package/lib/rules/multiline-comment-style.js +638 -460
- package/lib/rules/multiline-ternary.js +241 -158
- package/lib/rules/new-cap.js +233 -232
- package/lib/rules/new-parens.js +88 -61
- package/lib/rules/newline-after-var.js +287 -233
- package/lib/rules/newline-before-return.js +229 -204
- package/lib/rules/newline-per-chained-call.js +142 -109
- package/lib/rules/no-alert.js +90 -79
- package/lib/rules/no-array-constructor.js +175 -113
- package/lib/rules/no-async-promise-executor.js +30 -24
- package/lib/rules/no-await-in-loop.js +79 -70
- package/lib/rules/no-bitwise.js +113 -87
- package/lib/rules/no-buffer-constructor.js +61 -37
- package/lib/rules/no-caller.js +39 -33
- package/lib/rules/no-case-declarations.js +61 -45
- package/lib/rules/no-catch-shadow.js +76 -62
- package/lib/rules/no-class-assign.js +51 -48
- package/lib/rules/no-compare-neg-zero.js +62 -48
- package/lib/rules/no-cond-assign.js +148 -132
- package/lib/rules/no-confusing-arrow.js +98 -63
- package/lib/rules/no-console.js +202 -188
- package/lib/rules/no-const-assign.js +58 -41
- package/lib/rules/no-constant-binary-expression.js +501 -407
- package/lib/rules/no-constant-condition.js +158 -131
- package/lib/rules/no-constructor-return.js +49 -49
- package/lib/rules/no-continue.js +25 -26
- package/lib/rules/no-control-regex.js +125 -121
- package/lib/rules/no-debugger.js +28 -30
- package/lib/rules/no-delete-var.js +29 -29
- package/lib/rules/no-div-regex.js +47 -40
- package/lib/rules/no-dupe-args.js +79 -69
- package/lib/rules/no-dupe-class-members.js +102 -89
- package/lib/rules/no-dupe-else-if.js +100 -77
- package/lib/rules/no-dupe-keys.js +133 -110
- package/lib/rules/no-duplicate-case.js +50 -43
- package/lib/rules/no-duplicate-imports.js +266 -188
- package/lib/rules/no-else-return.js +430 -385
- package/lib/rules/no-empty-character-class.js +57 -50
- package/lib/rules/no-empty-function.js +197 -128
- package/lib/rules/no-empty-pattern.js +63 -56
- package/lib/rules/no-empty-static-block.js +61 -35
- package/lib/rules/no-empty.js +135 -85
- package/lib/rules/no-eq-null.js +37 -32
- package/lib/rules/no-eval.js +258 -249
- package/lib/rules/no-ex-assign.js +42 -39
- package/lib/rules/no-extend-native.js +161 -160
- package/lib/rules/no-extra-bind.js +201 -190
- package/lib/rules/no-extra-boolean-cast.js +398 -295
- package/lib/rules/no-extra-label.js +150 -130
- package/lib/rules/no-extra-parens.js +1654 -1307
- package/lib/rules/no-extra-semi.js +146 -126
- package/lib/rules/no-fallthrough.js +200 -136
- package/lib/rules/no-floating-decimal.js +74 -48
- package/lib/rules/no-func-assign.js +54 -55
- package/lib/rules/no-global-assign.js +78 -72
- package/lib/rules/no-implicit-coercion.js +350 -262
- package/lib/rules/no-implicit-globals.js +174 -133
- package/lib/rules/no-implied-eval.js +150 -112
- package/lib/rules/no-import-assign.js +145 -159
- package/lib/rules/no-inline-comments.js +101 -96
- package/lib/rules/no-inner-declarations.js +115 -78
- package/lib/rules/no-invalid-regexp.js +223 -174
- package/lib/rules/no-invalid-this.js +145 -117
- package/lib/rules/no-irregular-whitespace.js +266 -250
- package/lib/rules/no-iterator.js +29 -33
- package/lib/rules/no-label-var.js +59 -61
- package/lib/rules/no-labels.js +138 -131
- package/lib/rules/no-lone-blocks.js +127 -123
- package/lib/rules/no-lonely-if.js +105 -67
- package/lib/rules/no-loop-func.js +245 -184
- package/lib/rules/no-loss-of-precision.js +236 -201
- package/lib/rules/no-magic-numbers.js +339 -217
- package/lib/rules/no-misleading-character-class.js +548 -253
- package/lib/rules/no-mixed-operators.js +188 -164
- package/lib/rules/no-mixed-requires.js +253 -224
- package/lib/rules/no-mixed-spaces-and-tabs.js +135 -103
- package/lib/rules/no-multi-assign.js +46 -47
- package/lib/rules/no-multi-spaces.js +163 -125
- package/lib/rules/no-multi-str.js +42 -40
- package/lib/rules/no-multiple-empty-lines.js +196 -140
- package/lib/rules/no-native-reassign.js +90 -74
- package/lib/rules/no-negated-condition.js +79 -74
- package/lib/rules/no-negated-in-lhs.js +45 -32
- package/lib/rules/no-nested-ternary.js +33 -31
- package/lib/rules/no-new-func.js +71 -62
- package/lib/rules/no-new-native-nonconstructor.js +43 -39
- package/lib/rules/no-new-object.js +48 -39
- package/lib/rules/no-new-require.js +48 -31
- package/lib/rules/no-new-symbol.js +61 -43
- package/lib/rules/no-new-wrappers.js +43 -41
- package/lib/rules/no-new.js +28 -29
- package/lib/rules/no-nonoctal-decimal-escape.js +149 -121
- package/lib/rules/no-obj-calls.js +66 -53
- package/lib/rules/no-object-constructor.js +104 -97
- package/lib/rules/no-octal-escape.js +40 -43
- package/lib/rules/no-octal.js +29 -32
- package/lib/rules/no-param-reassign.js +236 -218
- package/lib/rules/no-path-concat.js +66 -51
- package/lib/rules/no-plusplus.js +60 -63
- package/lib/rules/no-process-env.js +49 -32
- package/lib/rules/no-process-exit.js +48 -28
- package/lib/rules/no-promise-executor-return.js +205 -204
- package/lib/rules/no-proto.js +26 -29
- package/lib/rules/no-prototype-builtins.js +146 -124
- package/lib/rules/no-redeclare.js +154 -155
- package/lib/rules/no-regex-spaces.js +183 -161
- package/lib/rules/no-restricted-exports.js +208 -174
- package/lib/rules/no-restricted-globals.js +254 -112
- package/lib/rules/no-restricted-imports.js +824 -384
- package/lib/rules/no-restricted-modules.js +222 -186
- package/lib/rules/no-restricted-properties.js +218 -153
- package/lib/rules/no-restricted-syntax.js +56 -52
- package/lib/rules/no-return-assign.js +56 -49
- package/lib/rules/no-return-await.js +147 -120
- package/lib/rules/no-script-url.js +53 -46
- package/lib/rules/no-self-assign.js +148 -145
- package/lib/rules/no-self-compare.js +63 -46
- package/lib/rules/no-sequences.js +135 -115
- package/lib/rules/no-setter-return.js +176 -178
- package/lib/rules/no-shadow-restricted-names.js +84 -36
- package/lib/rules/no-shadow.js +598 -310
- package/lib/rules/no-spaced-func.js +82 -60
- package/lib/rules/no-sparse-arrays.js +46 -28
- package/lib/rules/no-sync.js +61 -44
- package/lib/rules/no-tabs.js +83 -54
- package/lib/rules/no-template-curly-in-string.js +33 -32
- package/lib/rules/no-ternary.js +25 -28
- package/lib/rules/no-this-before-super.js +332 -298
- package/lib/rules/no-throw-literal.js +31 -36
- package/lib/rules/no-trailing-spaces.js +208 -174
- package/lib/rules/no-unassigned-vars.js +80 -0
- package/lib/rules/no-undef-init.js +86 -60
- package/lib/rules/no-undef.js +52 -47
- package/lib/rules/no-undefined.js +73 -74
- package/lib/rules/no-underscore-dangle.js +370 -322
- package/lib/rules/no-unexpected-multiline.js +112 -102
- package/lib/rules/no-unmodified-loop-condition.js +254 -254
- package/lib/rules/no-unneeded-ternary.js +212 -146
- package/lib/rules/no-unreachable-loop.js +145 -140
- package/lib/rules/no-unreachable.js +255 -248
- package/lib/rules/no-unsafe-finally.js +93 -85
- package/lib/rules/no-unsafe-negation.js +105 -81
- package/lib/rules/no-unsafe-optional-chaining.js +193 -177
- package/lib/rules/no-unused-expressions.js +199 -158
- package/lib/rules/no-unused-labels.js +139 -124
- package/lib/rules/no-unused-private-class-members.js +206 -182
- package/lib/rules/no-unused-vars.js +1708 -687
- package/lib/rules/no-use-before-define.js +327 -229
- package/lib/rules/no-useless-assignment.js +654 -0
- package/lib/rules/no-useless-backreference.js +212 -143
- package/lib/rules/no-useless-call.js +58 -53
- package/lib/rules/no-useless-catch.js +40 -40
- package/lib/rules/no-useless-computed-key.js +144 -108
- package/lib/rules/no-useless-concat.js +65 -59
- package/lib/rules/no-useless-constructor.js +160 -97
- package/lib/rules/no-useless-escape.js +364 -291
- package/lib/rules/no-useless-rename.js +183 -153
- package/lib/rules/no-useless-return.js +344 -307
- package/lib/rules/no-var.js +245 -212
- package/lib/rules/no-void.js +51 -46
- package/lib/rules/no-warning-comments.js +191 -183
- package/lib/rules/no-whitespace-before-property.js +131 -97
- package/lib/rules/no-with.js +24 -26
- package/lib/rules/nonblock-statement-body-position.js +149 -112
- package/lib/rules/object-curly-newline.js +306 -247
- package/lib/rules/object-curly-spacing.js +360 -296
- package/lib/rules/object-property-newline.js +137 -88
- package/lib/rules/object-shorthand.js +632 -500
- package/lib/rules/one-var-declaration-per-line.js +104 -82
- package/lib/rules/one-var.js +686 -536
- package/lib/rules/operator-assignment.js +219 -158
- package/lib/rules/operator-linebreak.js +295 -233
- package/lib/rules/padded-blocks.js +346 -290
- package/lib/rules/padding-line-between-statements.js +443 -421
- package/lib/rules/prefer-arrow-callback.js +371 -315
- package/lib/rules/prefer-const.js +418 -373
- package/lib/rules/prefer-destructuring.js +309 -278
- package/lib/rules/prefer-exponentiation-operator.js +176 -132
- package/lib/rules/prefer-named-capture-group.js +160 -141
- package/lib/rules/prefer-numeric-literals.js +121 -112
- package/lib/rules/prefer-object-has-own.js +116 -82
- package/lib/rules/prefer-object-spread.js +214 -193
- package/lib/rules/prefer-promise-reject-errors.js +140 -118
- package/lib/rules/prefer-reflect.js +126 -103
- package/lib/rules/prefer-regex-literals.js +561 -463
- package/lib/rules/prefer-rest-params.js +79 -80
- package/lib/rules/prefer-spread.js +47 -43
- package/lib/rules/prefer-template.js +266 -194
- package/lib/rules/preserve-caught-error.js +535 -0
- package/lib/rules/quote-props.js +373 -289
- package/lib/rules/quotes.js +374 -308
- package/lib/rules/radix.js +152 -134
- package/lib/rules/require-atomic-updates.js +316 -282
- package/lib/rules/require-await.js +153 -82
- package/lib/rules/require-unicode-regexp.js +296 -108
- package/lib/rules/require-yield.js +53 -54
- package/lib/rules/rest-spread-spacing.js +128 -98
- package/lib/rules/semi-spacing.js +281 -232
- package/lib/rules/semi-style.js +176 -116
- package/lib/rules/semi.js +456 -418
- package/lib/rules/sort-imports.js +307 -229
- package/lib/rules/sort-keys.js +219 -181
- package/lib/rules/sort-vars.js +127 -91
- package/lib/rules/space-before-blocks.js +199 -171
- package/lib/rules/space-before-function-paren.js +186 -148
- package/lib/rules/space-in-parens.js +359 -270
- package/lib/rules/space-infix-ops.js +237 -183
- package/lib/rules/space-unary-ops.js +356 -280
- package/lib/rules/spaced-comment.js +363 -301
- package/lib/rules/strict.js +266 -229
- package/lib/rules/switch-colon-spacing.js +130 -104
- package/lib/rules/symbol-description.js +45 -48
- package/lib/rules/template-curly-spacing.js +148 -124
- package/lib/rules/template-tag-spacing.js +98 -70
- package/lib/rules/unicode-bom.js +54 -54
- package/lib/rules/use-isnan.js +237 -110
- package/lib/rules/utils/ast-utils.js +2139 -1688
- package/lib/rules/utils/char-source.js +247 -0
- package/lib/rules/utils/fix-tracker.js +99 -88
- package/lib/rules/utils/keywords.js +59 -59
- package/lib/rules/utils/lazy-loading-rule-map.js +81 -78
- package/lib/rules/utils/regular-expressions.js +35 -19
- package/lib/rules/utils/unicode/index.js +9 -4
- package/lib/rules/utils/unicode/is-combining-character.js +1 -1
- package/lib/rules/utils/unicode/is-emoji-modifier.js +1 -1
- package/lib/rules/utils/unicode/is-regional-indicator-symbol.js +1 -1
- package/lib/rules/utils/unicode/is-surrogate-pair.js +1 -1
- package/lib/rules/valid-typeof.js +153 -109
- package/lib/rules/vars-on-top.js +152 -144
- package/lib/rules/wrap-iife.js +204 -173
- package/lib/rules/wrap-regex.js +77 -47
- package/lib/rules/yield-star-spacing.js +145 -116
- package/lib/rules/yoda.js +283 -274
- package/lib/services/parser-service.js +65 -0
- package/lib/services/processor-service.js +101 -0
- package/lib/services/suppressions-service.js +302 -0
- package/lib/services/warning-service.js +98 -0
- package/lib/shared/ajv.js +14 -14
- package/lib/shared/assert.js +21 -0
- package/lib/shared/ast-utils.js +7 -6
- package/lib/shared/deep-merge-arrays.js +62 -0
- package/lib/shared/directives.js +3 -2
- package/lib/shared/flags.js +108 -0
- package/lib/shared/logging.js +24 -16
- package/lib/shared/naming.js +109 -0
- package/lib/shared/option-utils.js +63 -0
- package/lib/shared/relative-module-resolver.js +18 -40
- package/lib/shared/runtime-info.js +138 -128
- package/lib/shared/serialization.js +78 -0
- package/lib/shared/severity.js +22 -22
- package/lib/shared/stats.js +30 -0
- package/lib/shared/string-utils.js +19 -21
- package/lib/shared/text-table.js +68 -0
- package/lib/shared/translate-cli-options.js +281 -0
- package/lib/shared/traverser.js +153 -146
- package/lib/types/config-api.d.ts +12 -0
- package/lib/types/index.d.ts +1473 -0
- package/lib/types/rules.d.ts +5589 -0
- package/lib/types/universal.d.ts +6 -0
- package/lib/types/use-at-your-own-risk.d.ts +87 -0
- package/lib/universal.js +10 -0
- package/lib/unsupported-api.js +8 -9
- package/messages/all-files-ignored.js +3 -3
- package/messages/all-matched-files-ignored.js +21 -0
- package/messages/config-file-missing.js +16 -0
- package/messages/config-plugin-missing.js +14 -0
- package/messages/config-serialize-function.js +30 -0
- package/messages/eslintrc-incompat.js +35 -16
- package/messages/eslintrc-plugins.js +8 -5
- 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 +4 -4
- package/messages/plugin-conflict.js +9 -9
- package/messages/plugin-invalid.js +4 -4
- package/messages/plugin-missing.js +4 -4
- 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 +105 -60
- package/conf/config-schema.js +0 -93
- package/lib/cli-engine/formatters/checkstyle.js +0 -60
- package/lib/cli-engine/formatters/compact.js +0 -60
- package/lib/cli-engine/formatters/jslint-xml.js +0 -41
- package/lib/cli-engine/formatters/junit.js +0 -82
- package/lib/cli-engine/formatters/tap.js +0 -95
- package/lib/cli-engine/formatters/unix.js +0 -58
- package/lib/cli-engine/formatters/visualstudio.js +0 -63
- package/lib/cli-engine/xml-escape.js +0 -34
- package/lib/config/flat-config-helpers.js +0 -111
- package/lib/config/rule-validator.js +0 -158
- package/lib/eslint/flat-eslint.js +0 -1159
- package/lib/linter/config-comment-parser.js +0 -185
- package/lib/linter/node-event-generator.js +0 -354
- package/lib/linter/report-translator.js +0 -369
- package/lib/linter/safe-emitter.js +0 -52
- package/lib/rule-tester/flat-rule-tester.js +0 -1131
- package/lib/rules/require-jsdoc.js +0 -122
- package/lib/rules/utils/patterns/letters.js +0 -36
- package/lib/rules/valid-jsdoc.js +0 -516
- package/lib/shared/config-validator.js +0 -347
- package/lib/shared/deprecation-warnings.js +0 -58
- package/lib/shared/types.js +0 -216
- package/lib/source-code/index.js +0 -5
- package/lib/source-code/source-code.js +0 -1055
- package/lib/source-code/token-store/backward-token-comment-cursor.js +0 -57
- package/lib/source-code/token-store/backward-token-cursor.js +0 -58
- package/lib/source-code/token-store/cursors.js +0 -90
- package/lib/source-code/token-store/forward-token-comment-cursor.js +0 -57
- package/lib/source-code/token-store/forward-token-cursor.js +0 -63
- package/lib/source-code/token-store/index.js +0 -627
- package/lib/source-code/token-store/padded-token-cursor.js +0 -38
- package/lib/source-code/token-store/utils.js +0 -107
|
@@ -3,11 +3,26 @@
|
|
|
3
3
|
*/
|
|
4
4
|
"use strict";
|
|
5
5
|
|
|
6
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
CALL,
|
|
8
|
+
CONSTRUCT,
|
|
9
|
+
ReferenceTracker,
|
|
10
|
+
getStaticValue,
|
|
11
|
+
getStringIfConstant,
|
|
12
|
+
} = require("@eslint-community/eslint-utils");
|
|
7
13
|
const { RegExpParser, visitRegExpAST } = require("@eslint-community/regexpp");
|
|
8
|
-
const {
|
|
14
|
+
const {
|
|
15
|
+
isCombiningCharacter,
|
|
16
|
+
isEmojiModifier,
|
|
17
|
+
isRegionalIndicatorSymbol,
|
|
18
|
+
isSurrogatePair,
|
|
19
|
+
} = require("./utils/unicode");
|
|
9
20
|
const astUtils = require("./utils/ast-utils.js");
|
|
10
21
|
const { isValidWithUnicodeFlag } = require("./utils/regular-expressions");
|
|
22
|
+
const {
|
|
23
|
+
parseStringLiteral,
|
|
24
|
+
parseTemplateToken,
|
|
25
|
+
} = require("./utils/char-source");
|
|
11
26
|
|
|
12
27
|
//------------------------------------------------------------------------------
|
|
13
28
|
// Helpers
|
|
@@ -26,275 +41,555 @@ const { isValidWithUnicodeFlag } = require("./utils/regular-expressions");
|
|
|
26
41
|
* @param {CharacterClassElement[]} nodes The node list to iterate character sequences.
|
|
27
42
|
* @returns {IterableIterator<Character[]>} The list of character sequences.
|
|
28
43
|
*/
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
44
|
+
function* iterateCharacterSequence(nodes) {
|
|
45
|
+
/** @type {Character[]} */
|
|
46
|
+
let seq = [];
|
|
47
|
+
|
|
48
|
+
for (const node of nodes) {
|
|
49
|
+
switch (node.type) {
|
|
50
|
+
case "Character":
|
|
51
|
+
seq.push(node);
|
|
52
|
+
break;
|
|
53
|
+
|
|
54
|
+
case "CharacterClassRange":
|
|
55
|
+
seq.push(node.min);
|
|
56
|
+
yield seq;
|
|
57
|
+
seq = [node.max];
|
|
58
|
+
break;
|
|
59
|
+
|
|
60
|
+
case "CharacterSet":
|
|
61
|
+
case "CharacterClass": // [[]] nesting character class
|
|
62
|
+
case "ClassStringDisjunction": // \q{...}
|
|
63
|
+
case "ExpressionCharacterClass": // [A--B]
|
|
64
|
+
if (seq.length > 0) {
|
|
65
|
+
yield seq;
|
|
66
|
+
seq = [];
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
|
|
70
|
+
// no default
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (seq.length > 0) {
|
|
75
|
+
yield seq;
|
|
76
|
+
}
|
|
63
77
|
}
|
|
64
78
|
|
|
65
|
-
|
|
66
79
|
/**
|
|
67
80
|
* Checks whether the given character node is a Unicode code point escape or not.
|
|
68
81
|
* @param {Character} char the character node to check.
|
|
69
82
|
* @returns {boolean} `true` if the character node is a Unicode code point escape.
|
|
70
83
|
*/
|
|
71
84
|
function isUnicodeCodePointEscape(char) {
|
|
72
|
-
|
|
85
|
+
return /^\\u\{[\da-f]+\}$/iu.test(char.raw);
|
|
73
86
|
}
|
|
74
87
|
|
|
75
88
|
/**
|
|
76
|
-
* Each function returns
|
|
77
|
-
* @type {Record<string, (chars: Character[]) =>
|
|
89
|
+
* Each function returns matched characters if it detects that kind of problem.
|
|
90
|
+
* @type {Record<string, (chars: Character[]) => IterableIterator<Character[]>>}
|
|
78
91
|
*/
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
92
|
+
const findCharacterSequences = {
|
|
93
|
+
*surrogatePairWithoutUFlag(chars) {
|
|
94
|
+
for (const [index, char] of chars.entries()) {
|
|
95
|
+
const previous = chars[index - 1];
|
|
96
|
+
|
|
97
|
+
if (
|
|
98
|
+
previous &&
|
|
99
|
+
char &&
|
|
100
|
+
isSurrogatePair(previous.value, char.value) &&
|
|
101
|
+
!isUnicodeCodePointEscape(previous) &&
|
|
102
|
+
!isUnicodeCodePointEscape(char)
|
|
103
|
+
) {
|
|
104
|
+
yield [previous, char];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
*surrogatePair(chars) {
|
|
110
|
+
for (const [index, char] of chars.entries()) {
|
|
111
|
+
const previous = chars[index - 1];
|
|
112
|
+
|
|
113
|
+
if (
|
|
114
|
+
previous &&
|
|
115
|
+
char &&
|
|
116
|
+
isSurrogatePair(previous.value, char.value) &&
|
|
117
|
+
(isUnicodeCodePointEscape(previous) ||
|
|
118
|
+
isUnicodeCodePointEscape(char))
|
|
119
|
+
) {
|
|
120
|
+
yield [previous, char];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
*combiningClass(chars, unfilteredChars) {
|
|
126
|
+
/*
|
|
127
|
+
* When `allowEscape` is `true`, a combined character should only be allowed if the combining mark appears as an escape sequence.
|
|
128
|
+
* This means that the base character should be considered even if it's escaped.
|
|
129
|
+
*/
|
|
130
|
+
for (const [index, char] of chars.entries()) {
|
|
131
|
+
const previous = unfilteredChars[index - 1];
|
|
132
|
+
|
|
133
|
+
if (
|
|
134
|
+
previous &&
|
|
135
|
+
char &&
|
|
136
|
+
isCombiningCharacter(char.value) &&
|
|
137
|
+
!isCombiningCharacter(previous.value)
|
|
138
|
+
) {
|
|
139
|
+
yield [previous, char];
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
*emojiModifier(chars) {
|
|
145
|
+
for (const [index, char] of chars.entries()) {
|
|
146
|
+
const previous = chars[index - 1];
|
|
147
|
+
|
|
148
|
+
if (
|
|
149
|
+
previous &&
|
|
150
|
+
char &&
|
|
151
|
+
isEmojiModifier(char.value) &&
|
|
152
|
+
!isEmojiModifier(previous.value)
|
|
153
|
+
) {
|
|
154
|
+
yield [previous, char];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
*regionalIndicatorSymbol(chars) {
|
|
160
|
+
for (const [index, char] of chars.entries()) {
|
|
161
|
+
const previous = chars[index - 1];
|
|
162
|
+
|
|
163
|
+
if (
|
|
164
|
+
previous &&
|
|
165
|
+
char &&
|
|
166
|
+
isRegionalIndicatorSymbol(char.value) &&
|
|
167
|
+
isRegionalIndicatorSymbol(previous.value)
|
|
168
|
+
) {
|
|
169
|
+
yield [previous, char];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
*zwj(chars) {
|
|
175
|
+
let sequence = null;
|
|
176
|
+
|
|
177
|
+
for (const [index, char] of chars.entries()) {
|
|
178
|
+
const previous = chars[index - 1];
|
|
179
|
+
const next = chars[index + 1];
|
|
180
|
+
|
|
181
|
+
if (
|
|
182
|
+
previous &&
|
|
183
|
+
char &&
|
|
184
|
+
next &&
|
|
185
|
+
char.value === 0x200d &&
|
|
186
|
+
previous.value !== 0x200d &&
|
|
187
|
+
next.value !== 0x200d
|
|
188
|
+
) {
|
|
189
|
+
if (sequence) {
|
|
190
|
+
if (sequence.at(-1) === previous) {
|
|
191
|
+
sequence.push(char, next); // append to the sequence
|
|
192
|
+
} else {
|
|
193
|
+
yield sequence;
|
|
194
|
+
sequence = chars.slice(index - 1, index + 2);
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
sequence = chars.slice(index - 1, index + 2);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (sequence) {
|
|
203
|
+
yield sequence;
|
|
204
|
+
}
|
|
205
|
+
},
|
|
147
206
|
};
|
|
148
207
|
|
|
149
|
-
const kinds = Object.keys(
|
|
208
|
+
const kinds = Object.keys(findCharacterSequences);
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Gets the value of the given node if it's a static value other than a regular expression object,
|
|
212
|
+
* or the node's `regex` property.
|
|
213
|
+
* The purpose of this method is to provide a replacement for `getStaticValue` in environments where certain regular expressions cannot be evaluated.
|
|
214
|
+
* A known example is Node.js 18 which does not support the `v` flag.
|
|
215
|
+
* Calling `getStaticValue` on a regular expression node with the `v` flag on Node.js 18 always returns `null`.
|
|
216
|
+
* A limitation of this method is that it can only detect a regular expression if the specified node is itself a regular expression literal node.
|
|
217
|
+
* @param {ASTNode | undefined} node The node to be inspected.
|
|
218
|
+
* @param {Scope} initialScope Scope to start finding variables. This function tries to resolve identifier references which are in the given scope.
|
|
219
|
+
* @returns {{ value: any } | { regex: { pattern: string, flags: string } } | null} The static value of the node, or `null`.
|
|
220
|
+
*/
|
|
221
|
+
function getStaticValueOrRegex(node, initialScope) {
|
|
222
|
+
if (!node) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
if (node.type === "Literal" && node.regex) {
|
|
226
|
+
return { regex: node.regex };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const staticValue = getStaticValue(node, initialScope);
|
|
230
|
+
|
|
231
|
+
if (staticValue?.value instanceof RegExp) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
return staticValue;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Checks whether a specified regexpp character is represented as an acceptable escape sequence.
|
|
239
|
+
* This function requires the source text of the character to be known.
|
|
240
|
+
* @param {Character} char Character to check.
|
|
241
|
+
* @param {string} charSource Source text of the character to check.
|
|
242
|
+
* @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
|
|
243
|
+
*/
|
|
244
|
+
function checkForAcceptableEscape(char, charSource) {
|
|
245
|
+
if (!charSource.startsWith("\\")) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
const match = /(?<=^\\+).$/su.exec(charSource);
|
|
249
|
+
|
|
250
|
+
return match?.[0] !== String.fromCodePoint(char.value);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Checks whether a specified regexpp character is represented as an acceptable escape sequence.
|
|
255
|
+
* This function works with characters that are produced by a string or template literal.
|
|
256
|
+
* It requires the source text and the CodeUnit list of the literal to be known.
|
|
257
|
+
* @param {Character} char Character to check.
|
|
258
|
+
* @param {string} nodeSource Source text of the string or template literal that produces the character.
|
|
259
|
+
* @param {CodeUnit[]} codeUnits List of CodeUnit objects of the literal that produces the character.
|
|
260
|
+
* @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
|
|
261
|
+
*/
|
|
262
|
+
function checkForAcceptableEscapeInString(char, nodeSource, codeUnits) {
|
|
263
|
+
const firstIndex = char.start;
|
|
264
|
+
const lastIndex = char.end - 1;
|
|
265
|
+
const start = codeUnits[firstIndex].start;
|
|
266
|
+
const end = codeUnits[lastIndex].end;
|
|
267
|
+
const charSource = nodeSource.slice(start, end);
|
|
268
|
+
|
|
269
|
+
return checkForAcceptableEscape(char, charSource);
|
|
270
|
+
}
|
|
150
271
|
|
|
151
272
|
//------------------------------------------------------------------------------
|
|
152
273
|
// Rule Definition
|
|
153
274
|
//------------------------------------------------------------------------------
|
|
154
275
|
|
|
155
|
-
/** @type {import('../
|
|
276
|
+
/** @type {import('../types').Rule.RuleModule} */
|
|
156
277
|
module.exports = {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
278
|
+
meta: {
|
|
279
|
+
type: "problem",
|
|
280
|
+
|
|
281
|
+
defaultOptions: [
|
|
282
|
+
{
|
|
283
|
+
allowEscape: false,
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
|
|
287
|
+
docs: {
|
|
288
|
+
description:
|
|
289
|
+
"Disallow characters which are made with multiple code points in character class syntax",
|
|
290
|
+
recommended: true,
|
|
291
|
+
url: "https://eslint.org/docs/latest/rules/no-misleading-character-class",
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
hasSuggestions: true,
|
|
295
|
+
|
|
296
|
+
schema: [
|
|
297
|
+
{
|
|
298
|
+
type: "object",
|
|
299
|
+
properties: {
|
|
300
|
+
allowEscape: {
|
|
301
|
+
type: "boolean",
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
additionalProperties: false,
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
|
|
308
|
+
messages: {
|
|
309
|
+
surrogatePairWithoutUFlag:
|
|
310
|
+
"Unexpected surrogate pair in character class. Use 'u' flag.",
|
|
311
|
+
surrogatePair: "Unexpected surrogate pair in character class.",
|
|
312
|
+
combiningClass: "Unexpected combined character in character class.",
|
|
313
|
+
emojiModifier: "Unexpected modified Emoji in character class.",
|
|
314
|
+
regionalIndicatorSymbol:
|
|
315
|
+
"Unexpected national flag in character class.",
|
|
316
|
+
zwj: "Unexpected joined character sequence in character class.",
|
|
317
|
+
suggestUnicodeFlag: "Add unicode 'u' flag to regex.",
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
create(context) {
|
|
321
|
+
const [{ allowEscape }] = context.options;
|
|
322
|
+
const sourceCode = context.sourceCode;
|
|
323
|
+
const parser = new RegExpParser();
|
|
324
|
+
const checkedPatternNodes = new Set();
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Verify a given regular expression.
|
|
328
|
+
* @param {Node} node The node to report.
|
|
329
|
+
* @param {string} pattern The regular expression pattern to verify.
|
|
330
|
+
* @param {string} flags The flags of the regular expression.
|
|
331
|
+
* @param {Function} unicodeFixer Fixer for missing "u" flag.
|
|
332
|
+
* @returns {void}
|
|
333
|
+
*/
|
|
334
|
+
function verify(node, pattern, flags, unicodeFixer) {
|
|
335
|
+
let patternNode;
|
|
336
|
+
|
|
337
|
+
try {
|
|
338
|
+
patternNode = parser.parsePattern(pattern, 0, pattern.length, {
|
|
339
|
+
unicode: flags.includes("u"),
|
|
340
|
+
unicodeSets: flags.includes("v"),
|
|
341
|
+
});
|
|
342
|
+
} catch {
|
|
343
|
+
// Ignore regular expressions with syntax errors
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
let codeUnits = null;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Checks whether a specified regexpp character is represented as an acceptable escape sequence.
|
|
351
|
+
* For the purposes of this rule, an escape sequence is considered acceptable if it consists of one or more backslashes followed by the character being escaped.
|
|
352
|
+
* @param {Character} char Character to check.
|
|
353
|
+
* @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
|
|
354
|
+
*/
|
|
355
|
+
function isAcceptableEscapeSequence(char) {
|
|
356
|
+
if (node.type === "Literal" && node.regex) {
|
|
357
|
+
return checkForAcceptableEscape(char, char.raw);
|
|
358
|
+
}
|
|
359
|
+
if (node.type === "Literal" && typeof node.value === "string") {
|
|
360
|
+
const nodeSource = node.raw;
|
|
361
|
+
|
|
362
|
+
codeUnits ??= parseStringLiteral(nodeSource);
|
|
363
|
+
|
|
364
|
+
return checkForAcceptableEscapeInString(
|
|
365
|
+
char,
|
|
366
|
+
nodeSource,
|
|
367
|
+
codeUnits,
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
if (astUtils.isStaticTemplateLiteral(node)) {
|
|
371
|
+
const nodeSource = sourceCode.getText(node);
|
|
372
|
+
|
|
373
|
+
codeUnits ??= parseTemplateToken(nodeSource);
|
|
374
|
+
|
|
375
|
+
return checkForAcceptableEscapeInString(
|
|
376
|
+
char,
|
|
377
|
+
nodeSource,
|
|
378
|
+
codeUnits,
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const foundKindMatches = new Map();
|
|
385
|
+
|
|
386
|
+
visitRegExpAST(patternNode, {
|
|
387
|
+
onCharacterClassEnter(ccNode) {
|
|
388
|
+
for (const unfilteredChars of iterateCharacterSequence(
|
|
389
|
+
ccNode.elements,
|
|
390
|
+
)) {
|
|
391
|
+
let chars;
|
|
392
|
+
|
|
393
|
+
if (allowEscape) {
|
|
394
|
+
// Replace escape sequences with null to avoid having them flagged.
|
|
395
|
+
chars = unfilteredChars.map(char =>
|
|
396
|
+
isAcceptableEscapeSequence(char) ? null : char,
|
|
397
|
+
);
|
|
398
|
+
} else {
|
|
399
|
+
chars = unfilteredChars;
|
|
400
|
+
}
|
|
401
|
+
for (const kind of kinds) {
|
|
402
|
+
const matches = findCharacterSequences[kind](
|
|
403
|
+
chars,
|
|
404
|
+
unfilteredChars,
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
if (foundKindMatches.has(kind)) {
|
|
408
|
+
foundKindMatches.get(kind).push(...matches);
|
|
409
|
+
} else {
|
|
410
|
+
foundKindMatches.set(kind, [...matches]);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Finds the report loc(s) for a range of matches.
|
|
419
|
+
* Only literals and expression-less templates generate granular errors.
|
|
420
|
+
* @param {Character[][]} matches Lists of individual characters being reported on.
|
|
421
|
+
* @returns {Location[]} locs for context.report.
|
|
422
|
+
* @see https://github.com/eslint/eslint/pull/17515
|
|
423
|
+
*/
|
|
424
|
+
function getNodeReportLocations(matches) {
|
|
425
|
+
if (
|
|
426
|
+
!astUtils.isStaticTemplateLiteral(node) &&
|
|
427
|
+
node.type !== "Literal"
|
|
428
|
+
) {
|
|
429
|
+
return matches.length ? [node.loc] : [];
|
|
430
|
+
}
|
|
431
|
+
return matches.map(chars => {
|
|
432
|
+
const firstIndex = chars[0].start;
|
|
433
|
+
const lastIndex = chars.at(-1).end - 1;
|
|
434
|
+
let start;
|
|
435
|
+
let end;
|
|
436
|
+
|
|
437
|
+
if (node.type === "TemplateLiteral") {
|
|
438
|
+
const source = sourceCode.getText(node);
|
|
439
|
+
const offset = node.range[0];
|
|
440
|
+
|
|
441
|
+
codeUnits ??= parseTemplateToken(source);
|
|
442
|
+
start = offset + codeUnits[firstIndex].start;
|
|
443
|
+
end = offset + codeUnits[lastIndex].end;
|
|
444
|
+
} else if (typeof node.value === "string") {
|
|
445
|
+
// String Literal
|
|
446
|
+
const source = node.raw;
|
|
447
|
+
const offset = node.range[0];
|
|
448
|
+
|
|
449
|
+
codeUnits ??= parseStringLiteral(source);
|
|
450
|
+
start = offset + codeUnits[firstIndex].start;
|
|
451
|
+
end = offset + codeUnits[lastIndex].end;
|
|
452
|
+
} else {
|
|
453
|
+
// RegExp Literal
|
|
454
|
+
const offset = node.range[0] + 1; // Add 1 to skip the leading slash.
|
|
455
|
+
|
|
456
|
+
start = offset + firstIndex;
|
|
457
|
+
end = offset + lastIndex + 1;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return {
|
|
461
|
+
start: sourceCode.getLocFromIndex(start),
|
|
462
|
+
end: sourceCode.getLocFromIndex(end),
|
|
463
|
+
};
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
for (const [kind, matches] of foundKindMatches) {
|
|
468
|
+
let suggest;
|
|
469
|
+
|
|
470
|
+
if (kind === "surrogatePairWithoutUFlag") {
|
|
471
|
+
suggest = [
|
|
472
|
+
{
|
|
473
|
+
messageId: "suggestUnicodeFlag",
|
|
474
|
+
fix: unicodeFixer,
|
|
475
|
+
},
|
|
476
|
+
];
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const locs = getNodeReportLocations(matches);
|
|
480
|
+
|
|
481
|
+
for (const loc of locs) {
|
|
482
|
+
context.report({
|
|
483
|
+
node,
|
|
484
|
+
loc,
|
|
485
|
+
messageId: kind,
|
|
486
|
+
suggest,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return {
|
|
493
|
+
"Literal[regex]"(node) {
|
|
494
|
+
if (checkedPatternNodes.has(node)) {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
verify(node, node.regex.pattern, node.regex.flags, fixer => {
|
|
498
|
+
if (
|
|
499
|
+
!isValidWithUnicodeFlag(
|
|
500
|
+
context.languageOptions.ecmaVersion,
|
|
501
|
+
node.regex.pattern,
|
|
502
|
+
)
|
|
503
|
+
) {
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return fixer.insertTextAfter(node, "u");
|
|
508
|
+
});
|
|
509
|
+
},
|
|
510
|
+
Program(node) {
|
|
511
|
+
const scope = sourceCode.getScope(node);
|
|
512
|
+
const tracker = new ReferenceTracker(scope);
|
|
513
|
+
|
|
514
|
+
/*
|
|
515
|
+
* Iterate calls of RegExp.
|
|
516
|
+
* E.g., `new RegExp()`, `RegExp()`, `new window.RegExp()`,
|
|
517
|
+
* `const {RegExp: a} = window; new a()`, etc...
|
|
518
|
+
*/
|
|
519
|
+
for (const { node: refNode } of tracker.iterateGlobalReferences(
|
|
520
|
+
{
|
|
521
|
+
RegExp: { [CALL]: true, [CONSTRUCT]: true },
|
|
522
|
+
},
|
|
523
|
+
)) {
|
|
524
|
+
let pattern, flags;
|
|
525
|
+
const [patternNode, flagsNode] = refNode.arguments;
|
|
526
|
+
const evaluatedPattern = getStaticValueOrRegex(
|
|
527
|
+
patternNode,
|
|
528
|
+
scope,
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
if (!evaluatedPattern) {
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
if (flagsNode) {
|
|
535
|
+
if (evaluatedPattern.regex) {
|
|
536
|
+
pattern = evaluatedPattern.regex.pattern;
|
|
537
|
+
checkedPatternNodes.add(patternNode);
|
|
538
|
+
} else {
|
|
539
|
+
pattern = String(evaluatedPattern.value);
|
|
540
|
+
}
|
|
541
|
+
flags = getStringIfConstant(flagsNode, scope);
|
|
542
|
+
} else {
|
|
543
|
+
if (evaluatedPattern.regex) {
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
pattern = String(evaluatedPattern.value);
|
|
547
|
+
flags = "";
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (typeof flags === "string") {
|
|
551
|
+
verify(patternNode, pattern, flags, fixer => {
|
|
552
|
+
if (
|
|
553
|
+
!isValidWithUnicodeFlag(
|
|
554
|
+
context.languageOptions.ecmaVersion,
|
|
555
|
+
pattern,
|
|
556
|
+
)
|
|
557
|
+
) {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (refNode.arguments.length === 1) {
|
|
562
|
+
const penultimateToken =
|
|
563
|
+
sourceCode.getLastToken(refNode, {
|
|
564
|
+
skip: 1,
|
|
565
|
+
}); // skip closing parenthesis
|
|
566
|
+
|
|
567
|
+
return fixer.insertTextAfter(
|
|
568
|
+
penultimateToken,
|
|
569
|
+
astUtils.isCommaToken(penultimateToken)
|
|
570
|
+
? ' "u",'
|
|
571
|
+
: ', "u"',
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if (
|
|
576
|
+
(flagsNode.type === "Literal" &&
|
|
577
|
+
typeof flagsNode.value === "string") ||
|
|
578
|
+
flagsNode.type === "TemplateLiteral"
|
|
579
|
+
) {
|
|
580
|
+
const range = [
|
|
581
|
+
flagsNode.range[0],
|
|
582
|
+
flagsNode.range[1] - 1,
|
|
583
|
+
];
|
|
584
|
+
|
|
585
|
+
return fixer.insertTextAfterRange(range, "u");
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
return null;
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
},
|
|
593
|
+
};
|
|
594
|
+
},
|
|
300
595
|
};
|