oxlint-plugin-eslint 1.52.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/LICENSE +22 -0
- package/README.md +36 -0
- package/common/ast-utils.cjs +5843 -0
- package/common/chunk.cjs +9 -0
- package/common/eslint-utils.cjs +1633 -0
- package/common/fix-tracker.cjs +89 -0
- package/common/ignore.cjs +123 -0
- package/common/keywords.cjs +15 -0
- package/common/regexpp.cjs +1720 -0
- package/common/regular-expressions.cjs +40 -0
- package/common/string-utils.cjs +39 -0
- package/index.js +7477 -0
- package/package.json +34 -0
- package/rules/accessor-pairs.cjs +233 -0
- package/rules/array-bracket-newline.cjs +172 -0
- package/rules/array-bracket-spacing.cjs +184 -0
- package/rules/array-callback-return.cjs +262 -0
- package/rules/array-element-newline.cjs +178 -0
- package/rules/arrow-body-style.cjs +135 -0
- package/rules/arrow-parens.cjs +130 -0
- package/rules/arrow-spacing.cjs +129 -0
- package/rules/block-scoped-var.cjs +101 -0
- package/rules/block-spacing.cjs +125 -0
- package/rules/brace-style.cjs +141 -0
- package/rules/callback-return.cjs +117 -0
- package/rules/camelcase.cjs +194 -0
- package/rules/capitalized-comments.cjs +168 -0
- package/rules/class-methods-use-this.cjs +155 -0
- package/rules/comma-dangle.cjs +274 -0
- package/rules/comma-spacing.cjs +111 -0
- package/rules/comma-style.cjs +180 -0
- package/rules/complexity.cjs +100 -0
- package/rules/computed-property-spacing.cjs +155 -0
- package/rules/consistent-return.cjs +113 -0
- package/rules/consistent-this.cjs +109 -0
- package/rules/constructor-super.cjs +207 -0
- package/rules/curly.cjs +173 -0
- package/rules/default-case-last.cjs +36 -0
- package/rules/default-case.cjs +50 -0
- package/rules/default-param-last.cjs +61 -0
- package/rules/dot-location.cjs +87 -0
- package/rules/dot-notation.cjs +77 -0
- package/rules/eol-last.cjs +91 -0
- package/rules/eqeqeq.cjs +127 -0
- package/rules/for-direction.cjs +94 -0
- package/rules/func-call-spacing.cjs +127 -0
- package/rules/func-name-matching.cjs +138 -0
- package/rules/func-names.cjs +121 -0
- package/rules/func-style.cjs +103 -0
- package/rules/function-call-argument-newline.cjs +109 -0
- package/rules/function-paren-newline.cjs +173 -0
- package/rules/generator-star-spacing.cjs +174 -0
- package/rules/getter-return.cjs +129 -0
- package/rules/global-require.cjs +84 -0
- package/rules/grouped-accessor-pairs.cjs +146 -0
- package/rules/guard-for-in.cjs +39 -0
- package/rules/handle-callback-err.cjs +86 -0
- package/rules/id-blacklist.cjs +135 -0
- package/rules/id-denylist.cjs +126 -0
- package/rules/id-length.cjs +119 -0
- package/rules/id-match.cjs +139 -0
- package/rules/implicit-arrow-linebreak.cjs +76 -0
- package/rules/indent-legacy.cjs +520 -0
- package/rules/indent.cjs +842 -0
- package/rules/init-declarations.cjs +88 -0
- package/rules/jsx-quotes.cjs +84 -0
- package/rules/key-spacing.cjs +399 -0
- package/rules/keyword-spacing.cjs +464 -0
- package/rules/line-comment-position.cjs +75 -0
- package/rules/linebreak-style.cjs +89 -0
- package/rules/lines-around-comment.cjs +290 -0
- package/rules/lines-around-directive.cjs +129 -0
- package/rules/lines-between-class-members.cjs +212 -0
- package/rules/logical-assignment-operators.cjs +305 -0
- package/rules/max-classes-per-file.cjs +61 -0
- package/rules/max-depth.cjs +117 -0
- package/rules/max-len.cjs +256 -0
- package/rules/max-lines-per-function.cjs +116 -0
- package/rules/max-lines.cjs +109 -0
- package/rules/max-nested-callbacks.cjs +78 -0
- package/rules/max-params.cjs +78 -0
- package/rules/max-statements-per-line.cjs +147 -0
- package/rules/max-statements.cjs +119 -0
- package/rules/multiline-comment-style.cjs +319 -0
- package/rules/multiline-ternary.cjs +106 -0
- package/rules/new-cap.cjs +139 -0
- package/rules/new-parens.cjs +70 -0
- package/rules/newline-after-var.cjs +159 -0
- package/rules/newline-before-return.cjs +128 -0
- package/rules/newline-per-chained-call.cjs +100 -0
- package/rules/no-alert.cjs +84 -0
- package/rules/no-array-constructor.cjs +91 -0
- package/rules/no-async-promise-executor.cjs +33 -0
- package/rules/no-await-in-loop.cjs +75 -0
- package/rules/no-bitwise.cjs +106 -0
- package/rules/no-buffer-constructor.cjs +51 -0
- package/rules/no-caller.cjs +34 -0
- package/rules/no-case-declarations.cjs +56 -0
- package/rules/no-catch-shadow.cjs +57 -0
- package/rules/no-class-assign.cjs +55 -0
- package/rules/no-compare-neg-zero.cjs +52 -0
- package/rules/no-cond-assign.cjs +104 -0
- package/rules/no-confusing-arrow.cjs +87 -0
- package/rules/no-console.cjs +138 -0
- package/rules/no-const-assign.cjs +50 -0
- package/rules/no-constant-binary-expression.cjs +284 -0
- package/rules/no-constant-condition.cjs +119 -0
- package/rules/no-constructor-return.cjs +43 -0
- package/rules/no-continue.cjs +33 -0
- package/rules/no-control-regex.cjs +74 -0
- package/rules/no-debugger.cjs +33 -0
- package/rules/no-delete-var.cjs +32 -0
- package/rules/no-div-regex.cjs +39 -0
- package/rules/no-dupe-args.cjs +61 -0
- package/rules/no-dupe-class-members.cjs +77 -0
- package/rules/no-dupe-else-if.cjs +74 -0
- package/rules/no-dupe-keys.cjs +88 -0
- package/rules/no-duplicate-case.cjs +49 -0
- package/rules/no-duplicate-imports.cjs +166 -0
- package/rules/no-else-return.cjs +182 -0
- package/rules/no-empty-character-class.cjs +47 -0
- package/rules/no-empty-function.cjs +141 -0
- package/rules/no-empty-pattern.cjs +50 -0
- package/rules/no-empty-static-block.cjs +50 -0
- package/rules/no-empty.cjs +78 -0
- package/rules/no-eq-null.cjs +34 -0
- package/rules/no-eval.cjs +165 -0
- package/rules/no-ex-assign.cjs +45 -0
- package/rules/no-extend-native.cjs +103 -0
- package/rules/no-extra-bind.cjs +127 -0
- package/rules/no-extra-boolean-cast.cjs +159 -0
- package/rules/no-extra-label.cjs +116 -0
- package/rules/no-extra-parens.cjs +665 -0
- package/rules/no-extra-semi.cjs +103 -0
- package/rules/no-fallthrough.cjs +136 -0
- package/rules/no-floating-decimal.cjs +66 -0
- package/rules/no-func-assign.cjs +63 -0
- package/rules/no-global-assign.cjs +62 -0
- package/rules/no-implicit-coercion.cjs +219 -0
- package/rules/no-implicit-globals.cjs +77 -0
- package/rules/no-implied-eval.cjs +87 -0
- package/rules/no-import-assign.cjs +123 -0
- package/rules/no-inline-comments.cjs +57 -0
- package/rules/no-inner-declarations.cjs +82 -0
- package/rules/no-invalid-regexp.cjs +130 -0
- package/rules/no-invalid-this.cjs +90 -0
- package/rules/no-irregular-whitespace.cjs +157 -0
- package/rules/no-iterator.cjs +34 -0
- package/rules/no-label-var.cjs +46 -0
- package/rules/no-labels.cjs +106 -0
- package/rules/no-lone-blocks.cjs +75 -0
- package/rules/no-lonely-if.cjs +42 -0
- package/rules/no-loop-func.cjs +143 -0
- package/rules/no-loss-of-precision.cjs +160 -0
- package/rules/no-magic-numbers.cjs +222 -0
- package/rules/no-misleading-character-class.cjs +500 -0
- package/rules/no-mixed-operators.cjs +197 -0
- package/rules/no-mixed-requires.cjs +117 -0
- package/rules/no-mixed-spaces-and-tabs.cjs +87 -0
- package/rules/no-multi-assign.cjs +38 -0
- package/rules/no-multi-spaces.cjs +95 -0
- package/rules/no-multi-str.cjs +44 -0
- package/rules/no-multiple-empty-lines.cjs +112 -0
- package/rules/no-native-reassign.cjs +72 -0
- package/rules/no-negated-condition.cjs +77 -0
- package/rules/no-negated-in-lhs.cjs +43 -0
- package/rules/no-nested-ternary.cjs +33 -0
- package/rules/no-new-func.cjs +50 -0
- package/rules/no-new-native-nonconstructor.cjs +42 -0
- package/rules/no-new-object.cjs +47 -0
- package/rules/no-new-require.cjs +50 -0
- package/rules/no-new-symbol.cjs +48 -0
- package/rules/no-new-wrappers.cjs +44 -0
- package/rules/no-new.cjs +33 -0
- package/rules/no-nonoctal-decimal-escape.cjs +80 -0
- package/rules/no-obj-calls.cjs +64 -0
- package/rules/no-object-constructor.cjs +69 -0
- package/rules/no-octal-escape.cjs +35 -0
- package/rules/no-octal.cjs +32 -0
- package/rules/no-param-reassign.cjs +135 -0
- package/rules/no-path-concat.cjs +52 -0
- package/rules/no-plusplus.cjs +64 -0
- package/rules/no-process-env.cjs +51 -0
- package/rules/no-process-exit.cjs +50 -0
- package/rules/no-promise-executor-return.cjs +131 -0
- package/rules/no-proto.cjs +34 -0
- package/rules/no-prototype-builtins.cjs +85 -0
- package/rules/no-redeclare.cjs +103 -0
- package/rules/no-regex-spaces.cjs +115 -0
- package/rules/no-restricted-exports.cjs +117 -0
- package/rules/no-restricted-globals.cjs +147 -0
- package/rules/no-restricted-imports.cjs +421 -0
- package/rules/no-restricted-modules.cjs +144 -0
- package/rules/no-restricted-properties.cjs +123 -0
- package/rules/no-restricted-syntax.cjs +49 -0
- package/rules/no-return-assign.cjs +45 -0
- package/rules/no-return-await.cjs +88 -0
- package/rules/no-script-url.cjs +49 -0
- package/rules/no-self-assign.cjs +88 -0
- package/rules/no-self-compare.cjs +53 -0
- package/rules/no-sequences.cjs +81 -0
- package/rules/no-setter-return.cjs +110 -0
- package/rules/no-shadow-restricted-names.cjs +60 -0
- package/rules/no-shadow.cjs +302 -0
- package/rules/no-spaced-func.cjs +69 -0
- package/rules/no-sparse-arrays.cjs +40 -0
- package/rules/no-sync.cjs +58 -0
- package/rules/no-tabs.cjs +73 -0
- package/rules/no-template-curly-in-string.cjs +33 -0
- package/rules/no-ternary.cjs +33 -0
- package/rules/no-this-before-super.cjs +177 -0
- package/rules/no-throw-literal.cjs +40 -0
- package/rules/no-trailing-spaces.cjs +123 -0
- package/rules/no-unassigned-vars.cjs +54 -0
- package/rules/no-undef-init.cjs +46 -0
- package/rules/no-undef.cjs +51 -0
- package/rules/no-undefined.cjs +58 -0
- package/rules/no-underscore-dangle.cjs +211 -0
- package/rules/no-unexpected-multiline.cjs +76 -0
- package/rules/no-unmodified-loop-condition.cjs +849 -0
- package/rules/no-unneeded-ternary.cjs +112 -0
- package/rules/no-unreachable-loop.cjs +128 -0
- package/rules/no-unreachable.cjs +195 -0
- package/rules/no-unsafe-finally.cjs +67 -0
- package/rules/no-unsafe-negation.cjs +86 -0
- package/rules/no-unsafe-optional-chaining.cjs +164 -0
- package/rules/no-unused-expressions.cjs +163 -0
- package/rules/no-unused-labels.cjs +97 -0
- package/rules/no-unused-private-class-members.cjs +69 -0
- package/rules/no-unused-vars.cjs +639 -0
- package/rules/no-use-before-define.cjs +245 -0
- package/rules/no-useless-assignment.cjs +250 -0
- package/rules/no-useless-backreference.cjs +137 -0
- package/rules/no-useless-call.cjs +57 -0
- package/rules/no-useless-catch.cjs +38 -0
- package/rules/no-useless-computed-key.cjs +106 -0
- package/rules/no-useless-concat.cjs +78 -0
- package/rules/no-useless-constructor.cjs +152 -0
- package/rules/no-useless-escape.cjs +164 -0
- package/rules/no-useless-rename.cjs +94 -0
- package/rules/no-useless-return.cjs +229 -0
- package/rules/no-var.cjs +235 -0
- package/rules/no-void.cjs +39 -0
- package/rules/no-warning-comments.cjs +112 -0
- package/rules/no-whitespace-before-property.cjs +72 -0
- package/rules/no-with.cjs +32 -0
- package/rules/nonblock-statement-body-position.cjs +107 -0
- package/rules/object-curly-newline.cjs +194 -0
- package/rules/object-curly-spacing.cjs +225 -0
- package/rules/object-property-newline.cjs +81 -0
- package/rules/object-shorthand.cjs +284 -0
- package/rules/one-var-declaration-per-line.cjs +75 -0
- package/rules/one-var.cjs +378 -0
- package/rules/operator-assignment.cjs +146 -0
- package/rules/operator-linebreak.cjs +150 -0
- package/rules/padded-blocks.cjs +192 -0
- package/rules/padding-line-between-statements.cjs +377 -0
- package/rules/prefer-arrow-callback.cjs +185 -0
- package/rules/prefer-const.cjs +240 -0
- package/rules/prefer-destructuring.cjs +188 -0
- package/rules/prefer-exponentiation-operator.cjs +100 -0
- package/rules/prefer-named-capture-group.cjs +111 -0
- package/rules/prefer-numeric-literals.cjs +75 -0
- package/rules/prefer-object-has-own.cjs +54 -0
- package/rules/prefer-object-spread.cjs +170 -0
- package/rules/prefer-promise-reject-errors.cjs +62 -0
- package/rules/prefer-reflect.cjs +100 -0
- package/rules/prefer-regex-literals.cjs +256 -0
- package/rules/prefer-rest-params.cjs +80 -0
- package/rules/prefer-spread.cjs +57 -0
- package/rules/prefer-template.cjs +147 -0
- package/rules/preserve-caught-error.cjs +196 -0
- package/rules/quote-props.cjs +224 -0
- package/rules/quotes.cjs +187 -0
- package/rules/radix.cjs +124 -0
- package/rules/require-atomic-updates.cjs +197 -0
- package/rules/require-await.cjs +90 -0
- package/rules/require-unicode-regexp.cjs +101 -0
- package/rules/require-yield.cjs +56 -0
- package/rules/rest-spread-spacing.cjs +99 -0
- package/rules/semi-spacing.cjs +215 -0
- package/rules/semi-style.cjs +116 -0
- package/rules/semi.cjs +239 -0
- package/rules/sort-imports.cjs +140 -0
- package/rules/sort-keys.cjs +165 -0
- package/rules/sort-vars.cjs +50 -0
- package/rules/space-before-blocks.cjs +132 -0
- package/rules/space-before-function-paren.cjs +126 -0
- package/rules/space-in-parens.cjs +175 -0
- package/rules/space-infix-ops.cjs +133 -0
- package/rules/space-unary-ops.cjs +237 -0
- package/rules/spaced-comment.cjs +233 -0
- package/rules/strict.cjs +206 -0
- package/rules/switch-colon-spacing.cjs +114 -0
- package/rules/symbol-description.cjs +49 -0
- package/rules/template-curly-spacing.cjs +112 -0
- package/rules/template-tag-spacing.cjs +82 -0
- package/rules/unicode-bom.cjs +52 -0
- package/rules/use-isnan.cjs +144 -0
- package/rules/valid-typeof.cjs +104 -0
- package/rules/vars-on-top.cjs +94 -0
- package/rules/wrap-iife.cjs +131 -0
- package/rules/wrap-regex.cjs +57 -0
- package/rules/yield-star-spacing.cjs +115 -0
- package/rules/yoda.cjs +185 -0
|
@@ -0,0 +1,1633 @@
|
|
|
1
|
+
const require_chunk = require("./chunk.cjs");
|
|
2
|
+
//#region ../../node_modules/.pnpm/eslint-visitor-keys@3.4.3/node_modules/eslint-visitor-keys/dist/eslint-visitor-keys.cjs
|
|
3
|
+
var require_eslint_visitor_keys = /* @__PURE__ */ require_chunk.t(((exports) => {
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* @type {VisitorKeys}
|
|
10
|
+
*/
|
|
11
|
+
let KEYS = {
|
|
12
|
+
ArrayExpression: ["elements"],
|
|
13
|
+
ArrayPattern: ["elements"],
|
|
14
|
+
ArrowFunctionExpression: ["params", "body"],
|
|
15
|
+
AssignmentExpression: ["left", "right"],
|
|
16
|
+
AssignmentPattern: ["left", "right"],
|
|
17
|
+
AwaitExpression: ["argument"],
|
|
18
|
+
BinaryExpression: ["left", "right"],
|
|
19
|
+
BlockStatement: ["body"],
|
|
20
|
+
BreakStatement: ["label"],
|
|
21
|
+
CallExpression: ["callee", "arguments"],
|
|
22
|
+
CatchClause: ["param", "body"],
|
|
23
|
+
ChainExpression: ["expression"],
|
|
24
|
+
ClassBody: ["body"],
|
|
25
|
+
ClassDeclaration: [
|
|
26
|
+
"id",
|
|
27
|
+
"superClass",
|
|
28
|
+
"body"
|
|
29
|
+
],
|
|
30
|
+
ClassExpression: [
|
|
31
|
+
"id",
|
|
32
|
+
"superClass",
|
|
33
|
+
"body"
|
|
34
|
+
],
|
|
35
|
+
ConditionalExpression: [
|
|
36
|
+
"test",
|
|
37
|
+
"consequent",
|
|
38
|
+
"alternate"
|
|
39
|
+
],
|
|
40
|
+
ContinueStatement: ["label"],
|
|
41
|
+
DebuggerStatement: [],
|
|
42
|
+
DoWhileStatement: ["body", "test"],
|
|
43
|
+
EmptyStatement: [],
|
|
44
|
+
ExperimentalRestProperty: ["argument"],
|
|
45
|
+
ExperimentalSpreadProperty: ["argument"],
|
|
46
|
+
ExportAllDeclaration: ["exported", "source"],
|
|
47
|
+
ExportDefaultDeclaration: ["declaration"],
|
|
48
|
+
ExportNamedDeclaration: [
|
|
49
|
+
"declaration",
|
|
50
|
+
"specifiers",
|
|
51
|
+
"source"
|
|
52
|
+
],
|
|
53
|
+
ExportSpecifier: ["exported", "local"],
|
|
54
|
+
ExpressionStatement: ["expression"],
|
|
55
|
+
ForInStatement: [
|
|
56
|
+
"left",
|
|
57
|
+
"right",
|
|
58
|
+
"body"
|
|
59
|
+
],
|
|
60
|
+
ForOfStatement: [
|
|
61
|
+
"left",
|
|
62
|
+
"right",
|
|
63
|
+
"body"
|
|
64
|
+
],
|
|
65
|
+
ForStatement: [
|
|
66
|
+
"init",
|
|
67
|
+
"test",
|
|
68
|
+
"update",
|
|
69
|
+
"body"
|
|
70
|
+
],
|
|
71
|
+
FunctionDeclaration: [
|
|
72
|
+
"id",
|
|
73
|
+
"params",
|
|
74
|
+
"body"
|
|
75
|
+
],
|
|
76
|
+
FunctionExpression: [
|
|
77
|
+
"id",
|
|
78
|
+
"params",
|
|
79
|
+
"body"
|
|
80
|
+
],
|
|
81
|
+
Identifier: [],
|
|
82
|
+
IfStatement: [
|
|
83
|
+
"test",
|
|
84
|
+
"consequent",
|
|
85
|
+
"alternate"
|
|
86
|
+
],
|
|
87
|
+
ImportDeclaration: ["specifiers", "source"],
|
|
88
|
+
ImportDefaultSpecifier: ["local"],
|
|
89
|
+
ImportExpression: ["source"],
|
|
90
|
+
ImportNamespaceSpecifier: ["local"],
|
|
91
|
+
ImportSpecifier: ["imported", "local"],
|
|
92
|
+
JSXAttribute: ["name", "value"],
|
|
93
|
+
JSXClosingElement: ["name"],
|
|
94
|
+
JSXClosingFragment: [],
|
|
95
|
+
JSXElement: [
|
|
96
|
+
"openingElement",
|
|
97
|
+
"children",
|
|
98
|
+
"closingElement"
|
|
99
|
+
],
|
|
100
|
+
JSXEmptyExpression: [],
|
|
101
|
+
JSXExpressionContainer: ["expression"],
|
|
102
|
+
JSXFragment: [
|
|
103
|
+
"openingFragment",
|
|
104
|
+
"children",
|
|
105
|
+
"closingFragment"
|
|
106
|
+
],
|
|
107
|
+
JSXIdentifier: [],
|
|
108
|
+
JSXMemberExpression: ["object", "property"],
|
|
109
|
+
JSXNamespacedName: ["namespace", "name"],
|
|
110
|
+
JSXOpeningElement: ["name", "attributes"],
|
|
111
|
+
JSXOpeningFragment: [],
|
|
112
|
+
JSXSpreadAttribute: ["argument"],
|
|
113
|
+
JSXSpreadChild: ["expression"],
|
|
114
|
+
JSXText: [],
|
|
115
|
+
LabeledStatement: ["label", "body"],
|
|
116
|
+
Literal: [],
|
|
117
|
+
LogicalExpression: ["left", "right"],
|
|
118
|
+
MemberExpression: ["object", "property"],
|
|
119
|
+
MetaProperty: ["meta", "property"],
|
|
120
|
+
MethodDefinition: ["key", "value"],
|
|
121
|
+
NewExpression: ["callee", "arguments"],
|
|
122
|
+
ObjectExpression: ["properties"],
|
|
123
|
+
ObjectPattern: ["properties"],
|
|
124
|
+
PrivateIdentifier: [],
|
|
125
|
+
Program: ["body"],
|
|
126
|
+
Property: ["key", "value"],
|
|
127
|
+
PropertyDefinition: ["key", "value"],
|
|
128
|
+
RestElement: ["argument"],
|
|
129
|
+
ReturnStatement: ["argument"],
|
|
130
|
+
SequenceExpression: ["expressions"],
|
|
131
|
+
SpreadElement: ["argument"],
|
|
132
|
+
StaticBlock: ["body"],
|
|
133
|
+
Super: [],
|
|
134
|
+
SwitchCase: ["test", "consequent"],
|
|
135
|
+
SwitchStatement: ["discriminant", "cases"],
|
|
136
|
+
TaggedTemplateExpression: ["tag", "quasi"],
|
|
137
|
+
TemplateElement: [],
|
|
138
|
+
TemplateLiteral: ["quasis", "expressions"],
|
|
139
|
+
ThisExpression: [],
|
|
140
|
+
ThrowStatement: ["argument"],
|
|
141
|
+
TryStatement: [
|
|
142
|
+
"block",
|
|
143
|
+
"handler",
|
|
144
|
+
"finalizer"
|
|
145
|
+
],
|
|
146
|
+
UnaryExpression: ["argument"],
|
|
147
|
+
UpdateExpression: ["argument"],
|
|
148
|
+
VariableDeclaration: ["declarations"],
|
|
149
|
+
VariableDeclarator: ["id", "init"],
|
|
150
|
+
WhileStatement: ["test", "body"],
|
|
151
|
+
WithStatement: ["object", "body"],
|
|
152
|
+
YieldExpression: ["argument"]
|
|
153
|
+
}, NODE_TYPES = Object.keys(KEYS);
|
|
154
|
+
for (let type of NODE_TYPES) Object.freeze(KEYS[type]);
|
|
155
|
+
Object.freeze(KEYS);
|
|
156
|
+
/**
|
|
157
|
+
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
158
|
+
* See LICENSE file in root directory for full license.
|
|
159
|
+
*/
|
|
160
|
+
/**
|
|
161
|
+
* @typedef {import('./visitor-keys.js').VisitorKeys} VisitorKeys
|
|
162
|
+
*/
|
|
163
|
+
let KEY_BLACKLIST = new Set([
|
|
164
|
+
"parent",
|
|
165
|
+
"leadingComments",
|
|
166
|
+
"trailingComments"
|
|
167
|
+
]);
|
|
168
|
+
/**
|
|
169
|
+
* Check whether a given key should be used or not.
|
|
170
|
+
* @param {string} key The key to check.
|
|
171
|
+
* @returns {boolean} `true` if the key should be used.
|
|
172
|
+
*/
|
|
173
|
+
function filterKey(key) {
|
|
174
|
+
return !KEY_BLACKLIST.has(key) && key[0] !== "_";
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get visitor keys of a given node.
|
|
178
|
+
* @param {object} node The AST node to get keys.
|
|
179
|
+
* @returns {readonly string[]} Visitor keys of the node.
|
|
180
|
+
*/
|
|
181
|
+
function getKeys(node) {
|
|
182
|
+
return Object.keys(node).filter(filterKey);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Make the union set with `KEYS` and given keys.
|
|
186
|
+
* @param {VisitorKeys} additionalKeys The additional keys.
|
|
187
|
+
* @returns {VisitorKeys} The union set.
|
|
188
|
+
*/
|
|
189
|
+
function unionWith(additionalKeys) {
|
|
190
|
+
let retv = Object.assign({}, KEYS);
|
|
191
|
+
for (let type of Object.keys(additionalKeys)) if (Object.prototype.hasOwnProperty.call(retv, type)) {
|
|
192
|
+
let keys = new Set(additionalKeys[type]);
|
|
193
|
+
for (let key of retv[type]) keys.add(key);
|
|
194
|
+
retv[type] = Object.freeze(Array.from(keys));
|
|
195
|
+
} else retv[type] = Object.freeze(Array.from(additionalKeys[type]));
|
|
196
|
+
return Object.freeze(retv);
|
|
197
|
+
}
|
|
198
|
+
exports.KEYS = KEYS, exports.getKeys = getKeys, exports.unionWith = unionWith;
|
|
199
|
+
})), require_eslint_utils = /* @__PURE__ */ require_chunk.t(((exports) => {
|
|
200
|
+
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
201
|
+
var eslintVisitorKeys = require_eslint_visitor_keys();
|
|
202
|
+
/** @typedef {import("eslint").Scope.Scope} Scope */
|
|
203
|
+
/** @typedef {import("estree").Node} Node */
|
|
204
|
+
/**
|
|
205
|
+
* Get the innermost scope which contains a given location.
|
|
206
|
+
* @param {Scope} initialScope The initial scope to search.
|
|
207
|
+
* @param {Node} node The location to search.
|
|
208
|
+
* @returns {Scope} The innermost scope.
|
|
209
|
+
*/
|
|
210
|
+
function getInnermostScope(initialScope, node) {
|
|
211
|
+
let location = node.range[0], scope = initialScope, found = !1;
|
|
212
|
+
do {
|
|
213
|
+
found = !1;
|
|
214
|
+
for (let childScope of scope.childScopes) {
|
|
215
|
+
let range = childScope.block.range;
|
|
216
|
+
if (range[0] <= location && location < range[1]) {
|
|
217
|
+
scope = childScope, found = !0;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
} while (found);
|
|
222
|
+
return scope;
|
|
223
|
+
}
|
|
224
|
+
/** @typedef {import("eslint").Scope.Scope} Scope */
|
|
225
|
+
/** @typedef {import("eslint").Scope.Variable} Variable */
|
|
226
|
+
/** @typedef {import("estree").Identifier} Identifier */
|
|
227
|
+
/**
|
|
228
|
+
* Find the variable of a given name.
|
|
229
|
+
* @param {Scope} initialScope The scope to start finding.
|
|
230
|
+
* @param {string|Identifier} nameOrNode The variable name to find. If this is a Node object then it should be an Identifier node.
|
|
231
|
+
* @returns {Variable|null} The found variable or null.
|
|
232
|
+
*/
|
|
233
|
+
function findVariable(initialScope, nameOrNode) {
|
|
234
|
+
let name = "", scope = initialScope;
|
|
235
|
+
for (typeof nameOrNode == "string" ? name = nameOrNode : (name = nameOrNode.name, scope = getInnermostScope(scope, nameOrNode)); scope != null;) {
|
|
236
|
+
let variable = scope.set.get(name);
|
|
237
|
+
if (variable != null) return variable;
|
|
238
|
+
scope = scope.upper;
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
/** @typedef {import("eslint").AST.Token} Token */
|
|
243
|
+
/** @typedef {import("estree").Comment} Comment */
|
|
244
|
+
/** @typedef {import("./types.mjs").ArrowToken} ArrowToken */
|
|
245
|
+
/** @typedef {import("./types.mjs").CommaToken} CommaToken */
|
|
246
|
+
/** @typedef {import("./types.mjs").SemicolonToken} SemicolonToken */
|
|
247
|
+
/** @typedef {import("./types.mjs").ColonToken} ColonToken */
|
|
248
|
+
/** @typedef {import("./types.mjs").OpeningParenToken} OpeningParenToken */
|
|
249
|
+
/** @typedef {import("./types.mjs").ClosingParenToken} ClosingParenToken */
|
|
250
|
+
/** @typedef {import("./types.mjs").OpeningBracketToken} OpeningBracketToken */
|
|
251
|
+
/** @typedef {import("./types.mjs").ClosingBracketToken} ClosingBracketToken */
|
|
252
|
+
/** @typedef {import("./types.mjs").OpeningBraceToken} OpeningBraceToken */
|
|
253
|
+
/** @typedef {import("./types.mjs").ClosingBraceToken} ClosingBraceToken */
|
|
254
|
+
/**
|
|
255
|
+
* @template {string} Value
|
|
256
|
+
* @typedef {import("./types.mjs").PunctuatorToken<Value>} PunctuatorToken
|
|
257
|
+
*/
|
|
258
|
+
/** @typedef {Comment | Token} CommentOrToken */
|
|
259
|
+
/**
|
|
260
|
+
* Creates the negate function of the given function.
|
|
261
|
+
* @param {function(CommentOrToken):boolean} f - The function to negate.
|
|
262
|
+
* @returns {function(CommentOrToken):boolean} Negated function.
|
|
263
|
+
*/
|
|
264
|
+
function negate(f) {
|
|
265
|
+
return (token) => !f(token);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Checks if the given token is a PunctuatorToken with the given value
|
|
269
|
+
* @template {string} Value
|
|
270
|
+
* @param {CommentOrToken} token - The token to check.
|
|
271
|
+
* @param {Value} value - The value to check.
|
|
272
|
+
* @returns {token is PunctuatorToken<Value>} `true` if the token is a PunctuatorToken with the given value.
|
|
273
|
+
*/
|
|
274
|
+
function isPunctuatorTokenWithValue(token, value) {
|
|
275
|
+
return token.type === "Punctuator" && token.value === value;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Checks if the given token is an arrow token or not.
|
|
279
|
+
* @param {CommentOrToken} token - The token to check.
|
|
280
|
+
* @returns {token is ArrowToken} `true` if the token is an arrow token.
|
|
281
|
+
*/
|
|
282
|
+
function isArrowToken(token) {
|
|
283
|
+
return isPunctuatorTokenWithValue(token, "=>");
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Checks if the given token is a comma token or not.
|
|
287
|
+
* @param {CommentOrToken} token - The token to check.
|
|
288
|
+
* @returns {token is CommaToken} `true` if the token is a comma token.
|
|
289
|
+
*/
|
|
290
|
+
function isCommaToken(token) {
|
|
291
|
+
return isPunctuatorTokenWithValue(token, ",");
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Checks if the given token is a semicolon token or not.
|
|
295
|
+
* @param {CommentOrToken} token - The token to check.
|
|
296
|
+
* @returns {token is SemicolonToken} `true` if the token is a semicolon token.
|
|
297
|
+
*/
|
|
298
|
+
function isSemicolonToken(token) {
|
|
299
|
+
return isPunctuatorTokenWithValue(token, ";");
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Checks if the given token is a colon token or not.
|
|
303
|
+
* @param {CommentOrToken} token - The token to check.
|
|
304
|
+
* @returns {token is ColonToken} `true` if the token is a colon token.
|
|
305
|
+
*/
|
|
306
|
+
function isColonToken(token) {
|
|
307
|
+
return isPunctuatorTokenWithValue(token, ":");
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Checks if the given token is an opening parenthesis token or not.
|
|
311
|
+
* @param {CommentOrToken} token - The token to check.
|
|
312
|
+
* @returns {token is OpeningParenToken} `true` if the token is an opening parenthesis token.
|
|
313
|
+
*/
|
|
314
|
+
function isOpeningParenToken(token) {
|
|
315
|
+
return isPunctuatorTokenWithValue(token, "(");
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Checks if the given token is a closing parenthesis token or not.
|
|
319
|
+
* @param {CommentOrToken} token - The token to check.
|
|
320
|
+
* @returns {token is ClosingParenToken} `true` if the token is a closing parenthesis token.
|
|
321
|
+
*/
|
|
322
|
+
function isClosingParenToken(token) {
|
|
323
|
+
return isPunctuatorTokenWithValue(token, ")");
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Checks if the given token is an opening square bracket token or not.
|
|
327
|
+
* @param {CommentOrToken} token - The token to check.
|
|
328
|
+
* @returns {token is OpeningBracketToken} `true` if the token is an opening square bracket token.
|
|
329
|
+
*/
|
|
330
|
+
function isOpeningBracketToken(token) {
|
|
331
|
+
return isPunctuatorTokenWithValue(token, "[");
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Checks if the given token is a closing square bracket token or not.
|
|
335
|
+
* @param {CommentOrToken} token - The token to check.
|
|
336
|
+
* @returns {token is ClosingBracketToken} `true` if the token is a closing square bracket token.
|
|
337
|
+
*/
|
|
338
|
+
function isClosingBracketToken(token) {
|
|
339
|
+
return isPunctuatorTokenWithValue(token, "]");
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Checks if the given token is an opening brace token or not.
|
|
343
|
+
* @param {CommentOrToken} token - The token to check.
|
|
344
|
+
* @returns {token is OpeningBraceToken} `true` if the token is an opening brace token.
|
|
345
|
+
*/
|
|
346
|
+
function isOpeningBraceToken(token) {
|
|
347
|
+
return isPunctuatorTokenWithValue(token, "{");
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Checks if the given token is a closing brace token or not.
|
|
351
|
+
* @param {CommentOrToken} token - The token to check.
|
|
352
|
+
* @returns {token is ClosingBraceToken} `true` if the token is a closing brace token.
|
|
353
|
+
*/
|
|
354
|
+
function isClosingBraceToken(token) {
|
|
355
|
+
return isPunctuatorTokenWithValue(token, "}");
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Checks if the given token is a comment token or not.
|
|
359
|
+
* @param {CommentOrToken} token - The token to check.
|
|
360
|
+
* @returns {token is Comment} `true` if the token is a comment token.
|
|
361
|
+
*/
|
|
362
|
+
function isCommentToken(token) {
|
|
363
|
+
return [
|
|
364
|
+
"Block",
|
|
365
|
+
"Line",
|
|
366
|
+
"Shebang"
|
|
367
|
+
].includes(token.type);
|
|
368
|
+
}
|
|
369
|
+
let isNotArrowToken = negate(isArrowToken), isNotCommaToken = negate(isCommaToken), isNotSemicolonToken = negate(isSemicolonToken), isNotColonToken = negate(isColonToken), isNotOpeningParenToken = negate(isOpeningParenToken), isNotClosingParenToken = negate(isClosingParenToken), isNotOpeningBracketToken = negate(isOpeningBracketToken), isNotClosingBracketToken = negate(isClosingBracketToken), isNotOpeningBraceToken = negate(isOpeningBraceToken), isNotClosingBraceToken = negate(isClosingBraceToken), isNotCommentToken = negate(isCommentToken);
|
|
370
|
+
/** @typedef {import("eslint").Rule.Node} RuleNode */
|
|
371
|
+
/** @typedef {import("eslint").SourceCode} SourceCode */
|
|
372
|
+
/** @typedef {import("eslint").AST.Token} Token */
|
|
373
|
+
/** @typedef {import("estree").Function} FunctionNode */
|
|
374
|
+
/** @typedef {import("estree").FunctionDeclaration} FunctionDeclaration */
|
|
375
|
+
/** @typedef {import("estree").FunctionExpression} FunctionExpression */
|
|
376
|
+
/** @typedef {import("estree").SourceLocation} SourceLocation */
|
|
377
|
+
/** @typedef {import("estree").Position} Position */
|
|
378
|
+
/**
|
|
379
|
+
* Get the `(` token of the given function node.
|
|
380
|
+
* @param {FunctionExpression | FunctionDeclaration} node - The function node to get.
|
|
381
|
+
* @param {SourceCode} sourceCode - The source code object to get tokens.
|
|
382
|
+
* @returns {Token} `(` token.
|
|
383
|
+
*/
|
|
384
|
+
function getOpeningParenOfParams(node, sourceCode) {
|
|
385
|
+
return node.id ? sourceCode.getTokenAfter(node.id, isOpeningParenToken) : sourceCode.getFirstToken(node, isOpeningParenToken);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Get the location of the given function node for reporting.
|
|
389
|
+
* @param {FunctionNode} node - The function node to get.
|
|
390
|
+
* @param {SourceCode} sourceCode - The source code object to get tokens.
|
|
391
|
+
* @returns {SourceLocation|null} The location of the function node for reporting.
|
|
392
|
+
*/
|
|
393
|
+
function getFunctionHeadLocation(node, sourceCode) {
|
|
394
|
+
let parent = node.parent, start = null, end = null;
|
|
395
|
+
if (node.type === "ArrowFunctionExpression") {
|
|
396
|
+
let arrowToken = sourceCode.getTokenBefore(node.body, isArrowToken);
|
|
397
|
+
start = arrowToken.loc.start, end = arrowToken.loc.end;
|
|
398
|
+
} else parent && (parent.type === "Property" || parent.type === "MethodDefinition" || parent.type === "PropertyDefinition") ? (start = parent.loc.start, end = getOpeningParenOfParams(node, sourceCode).loc.start) : (start = node.loc.start, end = getOpeningParenOfParams(node, sourceCode).loc.start);
|
|
399
|
+
return {
|
|
400
|
+
start: { ...start },
|
|
401
|
+
end: { ...end }
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
/** @typedef {import("./types.mjs").StaticValue} StaticValue */
|
|
405
|
+
/** @typedef {import("eslint").Scope.Scope} Scope */
|
|
406
|
+
/** @typedef {import("eslint").Scope.Variable} Variable */
|
|
407
|
+
/** @typedef {import("estree").Node} Node */
|
|
408
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.Node} TSESTreeNode */
|
|
409
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.AST_NODE_TYPES} TSESTreeNodeTypes */
|
|
410
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.MemberExpression} MemberExpression */
|
|
411
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.Property} Property */
|
|
412
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.RegExpLiteral} RegExpLiteral */
|
|
413
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.BigIntLiteral} BigIntLiteral */
|
|
414
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.Literal} Literal */
|
|
415
|
+
let globalObject = typeof globalThis < "u" ? globalThis : typeof self < "u" ? self : typeof window < "u" ? window : typeof global < "u" ? global : {}, builtinNames = Object.freeze(new Set(/* @__PURE__ */ "Array.ArrayBuffer.BigInt.BigInt64Array.BigUint64Array.Boolean.DataView.Date.decodeURI.decodeURIComponent.encodeURI.encodeURIComponent.escape.Float32Array.Float64Array.Function.Infinity.Int16Array.Int32Array.Int8Array.isFinite.isNaN.isPrototypeOf.JSON.Map.Math.NaN.Number.Object.parseFloat.parseInt.Promise.Proxy.Reflect.RegExp.Set.String.Symbol.Uint16Array.Uint32Array.Uint8Array.Uint8ClampedArray.undefined.unescape.WeakMap.WeakSet".split("."))), callAllowed = new Set([
|
|
416
|
+
Array.isArray,
|
|
417
|
+
Array.of,
|
|
418
|
+
Array.prototype.at,
|
|
419
|
+
Array.prototype.concat,
|
|
420
|
+
Array.prototype.entries,
|
|
421
|
+
Array.prototype.every,
|
|
422
|
+
Array.prototype.filter,
|
|
423
|
+
Array.prototype.find,
|
|
424
|
+
Array.prototype.findIndex,
|
|
425
|
+
Array.prototype.flat,
|
|
426
|
+
Array.prototype.includes,
|
|
427
|
+
Array.prototype.indexOf,
|
|
428
|
+
Array.prototype.join,
|
|
429
|
+
Array.prototype.keys,
|
|
430
|
+
Array.prototype.lastIndexOf,
|
|
431
|
+
Array.prototype.slice,
|
|
432
|
+
Array.prototype.some,
|
|
433
|
+
Array.prototype.toString,
|
|
434
|
+
Array.prototype.values,
|
|
435
|
+
typeof BigInt == "function" ? BigInt : void 0,
|
|
436
|
+
Boolean,
|
|
437
|
+
Date,
|
|
438
|
+
Date.parse,
|
|
439
|
+
decodeURI,
|
|
440
|
+
decodeURIComponent,
|
|
441
|
+
encodeURI,
|
|
442
|
+
encodeURIComponent,
|
|
443
|
+
escape,
|
|
444
|
+
isFinite,
|
|
445
|
+
isNaN,
|
|
446
|
+
isPrototypeOf,
|
|
447
|
+
Map,
|
|
448
|
+
Map.prototype.entries,
|
|
449
|
+
Map.prototype.get,
|
|
450
|
+
Map.prototype.has,
|
|
451
|
+
Map.prototype.keys,
|
|
452
|
+
Map.prototype.values,
|
|
453
|
+
...Object.getOwnPropertyNames(Math).filter((k) => k !== "random").map((k) => Math[k]).filter((f) => typeof f == "function"),
|
|
454
|
+
Number,
|
|
455
|
+
Number.isFinite,
|
|
456
|
+
Number.isNaN,
|
|
457
|
+
Number.parseFloat,
|
|
458
|
+
Number.parseInt,
|
|
459
|
+
Number.prototype.toExponential,
|
|
460
|
+
Number.prototype.toFixed,
|
|
461
|
+
Number.prototype.toPrecision,
|
|
462
|
+
Number.prototype.toString,
|
|
463
|
+
Object,
|
|
464
|
+
Object.entries,
|
|
465
|
+
Object.is,
|
|
466
|
+
Object.isExtensible,
|
|
467
|
+
Object.isFrozen,
|
|
468
|
+
Object.isSealed,
|
|
469
|
+
Object.keys,
|
|
470
|
+
Object.values,
|
|
471
|
+
parseFloat,
|
|
472
|
+
parseInt,
|
|
473
|
+
RegExp,
|
|
474
|
+
Set,
|
|
475
|
+
Set.prototype.entries,
|
|
476
|
+
Set.prototype.has,
|
|
477
|
+
Set.prototype.keys,
|
|
478
|
+
Set.prototype.values,
|
|
479
|
+
String,
|
|
480
|
+
String.fromCharCode,
|
|
481
|
+
String.fromCodePoint,
|
|
482
|
+
String.raw,
|
|
483
|
+
String.prototype.at,
|
|
484
|
+
String.prototype.charAt,
|
|
485
|
+
String.prototype.charCodeAt,
|
|
486
|
+
String.prototype.codePointAt,
|
|
487
|
+
String.prototype.concat,
|
|
488
|
+
String.prototype.endsWith,
|
|
489
|
+
String.prototype.includes,
|
|
490
|
+
String.prototype.indexOf,
|
|
491
|
+
String.prototype.lastIndexOf,
|
|
492
|
+
String.prototype.normalize,
|
|
493
|
+
String.prototype.padEnd,
|
|
494
|
+
String.prototype.padStart,
|
|
495
|
+
String.prototype.slice,
|
|
496
|
+
String.prototype.startsWith,
|
|
497
|
+
String.prototype.substr,
|
|
498
|
+
String.prototype.substring,
|
|
499
|
+
String.prototype.toLowerCase,
|
|
500
|
+
String.prototype.toString,
|
|
501
|
+
String.prototype.toUpperCase,
|
|
502
|
+
String.prototype.trim,
|
|
503
|
+
String.prototype.trimEnd,
|
|
504
|
+
String.prototype.trimLeft,
|
|
505
|
+
String.prototype.trimRight,
|
|
506
|
+
String.prototype.trimStart,
|
|
507
|
+
Symbol.for,
|
|
508
|
+
Symbol.keyFor,
|
|
509
|
+
unescape
|
|
510
|
+
].filter((f) => typeof f == "function")), callPassThrough = new Set([
|
|
511
|
+
Object.freeze,
|
|
512
|
+
Object.preventExtensions,
|
|
513
|
+
Object.seal
|
|
514
|
+
]), getterAllowed = [
|
|
515
|
+
[Map, new Set(["size"])],
|
|
516
|
+
[RegExp, new Set([
|
|
517
|
+
"dotAll",
|
|
518
|
+
"flags",
|
|
519
|
+
"global",
|
|
520
|
+
"hasIndices",
|
|
521
|
+
"ignoreCase",
|
|
522
|
+
"multiline",
|
|
523
|
+
"source",
|
|
524
|
+
"sticky",
|
|
525
|
+
"unicode"
|
|
526
|
+
])],
|
|
527
|
+
[Set, new Set(["size"])]
|
|
528
|
+
];
|
|
529
|
+
/**
|
|
530
|
+
* Get the property descriptor.
|
|
531
|
+
* @param {object} object The object to get.
|
|
532
|
+
* @param {string|number|symbol} name The property name to get.
|
|
533
|
+
*/
|
|
534
|
+
function getPropertyDescriptor(object, name) {
|
|
535
|
+
let x = object;
|
|
536
|
+
for (; (typeof x == "object" || typeof x == "function") && x !== null;) {
|
|
537
|
+
let d = Object.getOwnPropertyDescriptor(x, name);
|
|
538
|
+
if (d) return d;
|
|
539
|
+
x = Object.getPrototypeOf(x);
|
|
540
|
+
}
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Check if a property is getter or not.
|
|
545
|
+
* @param {object} object The object to check.
|
|
546
|
+
* @param {string|number|symbol} name The property name to check.
|
|
547
|
+
*/
|
|
548
|
+
function isGetter(object, name) {
|
|
549
|
+
let d = getPropertyDescriptor(object, name);
|
|
550
|
+
return d != null && d.get != null;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Get the element values of a given node list.
|
|
554
|
+
* @param {(Node|TSESTreeNode|null)[]} nodeList The node list to get values.
|
|
555
|
+
* @param {Scope|undefined|null} initialScope The initial scope to find variables.
|
|
556
|
+
* @returns {any[]|null} The value list if all nodes are constant. Otherwise, null.
|
|
557
|
+
*/
|
|
558
|
+
function getElementValues(nodeList, initialScope) {
|
|
559
|
+
let valueList = [];
|
|
560
|
+
for (let i = 0; i < nodeList.length; ++i) {
|
|
561
|
+
let elementNode = nodeList[i];
|
|
562
|
+
if (elementNode == null) valueList.length = i + 1;
|
|
563
|
+
else if (elementNode.type === "SpreadElement") {
|
|
564
|
+
let argument = getStaticValueR(elementNode.argument, initialScope);
|
|
565
|
+
if (argument == null) return null;
|
|
566
|
+
valueList.push(...argument.value);
|
|
567
|
+
} else {
|
|
568
|
+
let element = getStaticValueR(elementNode, initialScope);
|
|
569
|
+
if (element == null) return null;
|
|
570
|
+
valueList.push(element.value);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return valueList;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Checks if a variable is a built-in global.
|
|
577
|
+
* @param {Variable|null} variable The variable to check.
|
|
578
|
+
* @returns {variable is Variable & {defs:[]}}
|
|
579
|
+
*/
|
|
580
|
+
function isBuiltinGlobal(variable) {
|
|
581
|
+
return variable != null && variable.defs.length === 0 && builtinNames.has(variable.name) && variable.name in globalObject;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Checks if a variable can be considered as a constant.
|
|
585
|
+
* @param {Variable} variable
|
|
586
|
+
* @returns {variable is Variable & {defs: [import("eslint").Scope.Definition & { type: "Variable" }]}} True if the variable can be considered as a constant.
|
|
587
|
+
*/
|
|
588
|
+
function canBeConsideredConst(variable) {
|
|
589
|
+
if (variable.defs.length !== 1) return !1;
|
|
590
|
+
let def = variable.defs[0];
|
|
591
|
+
return !!(def.parent && def.type === "Variable" && (def.parent.kind === "const" || isEffectivelyConst(variable)));
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Returns whether the given variable is never written to after initialization.
|
|
595
|
+
* @param {Variable} variable
|
|
596
|
+
* @returns {boolean}
|
|
597
|
+
*/
|
|
598
|
+
function isEffectivelyConst(variable) {
|
|
599
|
+
let refs = variable.references, inits = refs.filter((r) => r.init).length, reads = refs.filter((r) => r.isReadOnly()).length;
|
|
600
|
+
return inits === 1 && reads + inits === refs.length;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Checks if a variable has mutation in its property.
|
|
604
|
+
* @param {Variable} variable The variable to check.
|
|
605
|
+
* @param {Scope|null} initialScope The scope to start finding variable. Optional. If the node is a computed property node and this scope was given, this checks the computed property name by the `getStringIfConstant` function with the scope, and returns the value of it.
|
|
606
|
+
* @returns {boolean} True if the variable has mutation in its property.
|
|
607
|
+
*/
|
|
608
|
+
function hasMutationInProperty(variable, initialScope) {
|
|
609
|
+
for (let ref of variable.references) {
|
|
610
|
+
let node = ref.identifier;
|
|
611
|
+
for (; node && node.parent && node.parent.type === "MemberExpression";) node = node.parent;
|
|
612
|
+
if (!(!node || !node.parent) && (node.parent.type === "AssignmentExpression" && node.parent.left === node || node.parent.type === "UpdateExpression" && node.parent.argument === node || node.parent.type === "CallExpression" && node.parent.callee === node && node.type === "MemberExpression" && isNameOfMutationArrayMethod(getStaticPropertyNameValue(node, initialScope)))) return !0;
|
|
613
|
+
}
|
|
614
|
+
return !1;
|
|
615
|
+
/**
|
|
616
|
+
* Checks if a method name is one of the mutation array methods.
|
|
617
|
+
* @param {StaticValue|null} methodName The method name to check.
|
|
618
|
+
* @returns {boolean} True if the method name is a mutation array method.
|
|
619
|
+
*/
|
|
620
|
+
function isNameOfMutationArrayMethod(methodName) {
|
|
621
|
+
if (methodName == null || methodName.value == null) return !1;
|
|
622
|
+
let name = methodName.value;
|
|
623
|
+
return name === "copyWithin" || name === "fill" || name === "pop" || name === "push" || name === "reverse" || name === "shift" || name === "sort" || name === "splice" || name === "unshift";
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* @template {TSESTreeNodeTypes} T
|
|
628
|
+
* @callback VisitorCallback
|
|
629
|
+
* @param {TSESTreeNode & { type: T }} node
|
|
630
|
+
* @param {Scope|undefined|null} initialScope
|
|
631
|
+
* @returns {StaticValue | null}
|
|
632
|
+
*/
|
|
633
|
+
/**
|
|
634
|
+
* @typedef { { [K in TSESTreeNodeTypes]?: VisitorCallback<K> } } Operations
|
|
635
|
+
*/
|
|
636
|
+
/**
|
|
637
|
+
* @type {Operations}
|
|
638
|
+
*/
|
|
639
|
+
let operations = Object.freeze({
|
|
640
|
+
ArrayExpression(node, initialScope) {
|
|
641
|
+
let elements = getElementValues(node.elements, initialScope);
|
|
642
|
+
return elements == null ? null : { value: elements };
|
|
643
|
+
},
|
|
644
|
+
AssignmentExpression(node, initialScope) {
|
|
645
|
+
return node.operator === "=" ? getStaticValueR(node.right, initialScope) : null;
|
|
646
|
+
},
|
|
647
|
+
BinaryExpression(node, initialScope) {
|
|
648
|
+
if (node.operator === "in" || node.operator === "instanceof") return null;
|
|
649
|
+
let left = getStaticValueR(node.left, initialScope), right = getStaticValueR(node.right, initialScope);
|
|
650
|
+
if (left != null && right != null) switch (node.operator) {
|
|
651
|
+
case "==": return { value: left.value == right.value };
|
|
652
|
+
case "!=": return { value: left.value != right.value };
|
|
653
|
+
case "===": return { value: left.value === right.value };
|
|
654
|
+
case "!==": return { value: left.value !== right.value };
|
|
655
|
+
case "<": return { value: left.value < right.value };
|
|
656
|
+
case "<=": return { value: left.value <= right.value };
|
|
657
|
+
case ">": return { value: left.value > right.value };
|
|
658
|
+
case ">=": return { value: left.value >= right.value };
|
|
659
|
+
case "<<": return { value: left.value << right.value };
|
|
660
|
+
case ">>": return { value: left.value >> right.value };
|
|
661
|
+
case ">>>": return { value: left.value >>> right.value };
|
|
662
|
+
case "+": return { value: left.value + right.value };
|
|
663
|
+
case "-": return { value: left.value - right.value };
|
|
664
|
+
case "*": return { value: left.value * right.value };
|
|
665
|
+
case "/": return { value: left.value / right.value };
|
|
666
|
+
case "%": return { value: left.value % right.value };
|
|
667
|
+
case "**": return { value: left.value ** right.value };
|
|
668
|
+
case "|": return { value: left.value | right.value };
|
|
669
|
+
case "^": return { value: left.value ^ right.value };
|
|
670
|
+
case "&": return { value: left.value & right.value };
|
|
671
|
+
}
|
|
672
|
+
return null;
|
|
673
|
+
},
|
|
674
|
+
CallExpression(node, initialScope) {
|
|
675
|
+
let calleeNode = node.callee, args = getElementValues(node.arguments, initialScope);
|
|
676
|
+
if (args != null) if (calleeNode.type === "MemberExpression") {
|
|
677
|
+
if (calleeNode.property.type === "PrivateIdentifier") return null;
|
|
678
|
+
let object = getStaticValueR(calleeNode.object, initialScope);
|
|
679
|
+
if (object != null) {
|
|
680
|
+
if (object.value == null && (object.optional || node.optional)) return {
|
|
681
|
+
value: void 0,
|
|
682
|
+
optional: !0
|
|
683
|
+
};
|
|
684
|
+
let property = getStaticPropertyNameValue(calleeNode, initialScope);
|
|
685
|
+
if (property != null) {
|
|
686
|
+
let receiver = object.value, methodName = property.value;
|
|
687
|
+
if (callAllowed.has(receiver[methodName])) return { value: receiver[methodName](...args) };
|
|
688
|
+
if (callPassThrough.has(receiver[methodName])) return { value: args[0] };
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
} else {
|
|
692
|
+
let callee = getStaticValueR(calleeNode, initialScope);
|
|
693
|
+
if (callee != null) {
|
|
694
|
+
if (callee.value == null && node.optional) return {
|
|
695
|
+
value: void 0,
|
|
696
|
+
optional: !0
|
|
697
|
+
};
|
|
698
|
+
let func = callee.value;
|
|
699
|
+
if (callAllowed.has(func)) return { value: func(...args) };
|
|
700
|
+
if (callPassThrough.has(func)) return { value: args[0] };
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
return null;
|
|
704
|
+
},
|
|
705
|
+
ConditionalExpression(node, initialScope) {
|
|
706
|
+
let test = getStaticValueR(node.test, initialScope);
|
|
707
|
+
return test == null ? null : test.value ? getStaticValueR(node.consequent, initialScope) : getStaticValueR(node.alternate, initialScope);
|
|
708
|
+
},
|
|
709
|
+
ExpressionStatement(node, initialScope) {
|
|
710
|
+
return getStaticValueR(node.expression, initialScope);
|
|
711
|
+
},
|
|
712
|
+
Identifier(node, initialScope) {
|
|
713
|
+
if (initialScope != null) {
|
|
714
|
+
let variable = findVariable(initialScope, node);
|
|
715
|
+
if (variable != null) {
|
|
716
|
+
if (isBuiltinGlobal(variable)) return { value: globalObject[variable.name] };
|
|
717
|
+
if (canBeConsideredConst(variable)) {
|
|
718
|
+
let def = variable.defs[0];
|
|
719
|
+
if (def.node.id.type === "Identifier") {
|
|
720
|
+
let init = getStaticValueR(def.node.init, initialScope);
|
|
721
|
+
return init && typeof init.value == "object" && init.value !== null && hasMutationInProperty(variable, initialScope) ? null : init;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return null;
|
|
727
|
+
},
|
|
728
|
+
Literal(node) {
|
|
729
|
+
let literal = node;
|
|
730
|
+
return (literal.regex != null || literal.bigint != null) && literal.value == null ? null : { value: literal.value };
|
|
731
|
+
},
|
|
732
|
+
LogicalExpression(node, initialScope) {
|
|
733
|
+
let left = getStaticValueR(node.left, initialScope);
|
|
734
|
+
if (left != null) {
|
|
735
|
+
if (node.operator === "||" && left.value || node.operator === "&&" && !left.value || node.operator === "??" && left.value != null) return left;
|
|
736
|
+
let right = getStaticValueR(node.right, initialScope);
|
|
737
|
+
if (right != null) return right;
|
|
738
|
+
}
|
|
739
|
+
return null;
|
|
740
|
+
},
|
|
741
|
+
MemberExpression(node, initialScope) {
|
|
742
|
+
if (node.property.type === "PrivateIdentifier") return null;
|
|
743
|
+
let object = getStaticValueR(node.object, initialScope);
|
|
744
|
+
if (object != null) {
|
|
745
|
+
if (object.value == null && (object.optional || node.optional)) return {
|
|
746
|
+
value: void 0,
|
|
747
|
+
optional: !0
|
|
748
|
+
};
|
|
749
|
+
let property = getStaticPropertyNameValue(node, initialScope);
|
|
750
|
+
if (property != null) {
|
|
751
|
+
if (!isGetter(object.value, property.value)) return { value: object.value[property.value] };
|
|
752
|
+
for (let [classFn, allowed] of getterAllowed) if (object.value instanceof classFn && allowed.has(property.value)) return { value: object.value[property.value] };
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
return null;
|
|
756
|
+
},
|
|
757
|
+
ChainExpression(node, initialScope) {
|
|
758
|
+
let expression = getStaticValueR(node.expression, initialScope);
|
|
759
|
+
return expression == null ? null : { value: expression.value };
|
|
760
|
+
},
|
|
761
|
+
NewExpression(node, initialScope) {
|
|
762
|
+
let callee = getStaticValueR(node.callee, initialScope), args = getElementValues(node.arguments, initialScope);
|
|
763
|
+
if (callee != null && args != null) {
|
|
764
|
+
let Func = callee.value;
|
|
765
|
+
if (callAllowed.has(Func)) return { value: new Func(...args) };
|
|
766
|
+
}
|
|
767
|
+
return null;
|
|
768
|
+
},
|
|
769
|
+
ObjectExpression(node, initialScope) {
|
|
770
|
+
/** @type {Record<PropertyKey, unknown>} */
|
|
771
|
+
let object = {};
|
|
772
|
+
for (let propertyNode of node.properties) if (propertyNode.type === "Property") {
|
|
773
|
+
if (propertyNode.kind !== "init") return null;
|
|
774
|
+
let key = getStaticPropertyNameValue(propertyNode, initialScope), value = getStaticValueR(propertyNode.value, initialScope);
|
|
775
|
+
if (key == null || value == null) return null;
|
|
776
|
+
object[key.value] = value.value;
|
|
777
|
+
} else if (propertyNode.type === "SpreadElement" || propertyNode.type === "ExperimentalSpreadProperty") {
|
|
778
|
+
let argument = getStaticValueR(propertyNode.argument, initialScope);
|
|
779
|
+
if (argument == null) return null;
|
|
780
|
+
Object.assign(object, argument.value);
|
|
781
|
+
} else return null;
|
|
782
|
+
return { value: object };
|
|
783
|
+
},
|
|
784
|
+
SequenceExpression(node, initialScope) {
|
|
785
|
+
let last = node.expressions[node.expressions.length - 1];
|
|
786
|
+
return getStaticValueR(last, initialScope);
|
|
787
|
+
},
|
|
788
|
+
TaggedTemplateExpression(node, initialScope) {
|
|
789
|
+
let tag = getStaticValueR(node.tag, initialScope), expressions = getElementValues(node.quasi.expressions, initialScope);
|
|
790
|
+
if (tag != null && expressions != null) {
|
|
791
|
+
let func = tag.value, strings = node.quasi.quasis.map((q) => q.value.cooked);
|
|
792
|
+
if (strings.raw = node.quasi.quasis.map((q) => q.value.raw), func === String.raw) return { value: func(strings, ...expressions) };
|
|
793
|
+
}
|
|
794
|
+
return null;
|
|
795
|
+
},
|
|
796
|
+
TemplateLiteral(node, initialScope) {
|
|
797
|
+
let expressions = getElementValues(node.expressions, initialScope);
|
|
798
|
+
if (expressions != null) {
|
|
799
|
+
let value = node.quasis[0].value.cooked;
|
|
800
|
+
for (let i = 0; i < expressions.length; ++i) value += expressions[i], value += node.quasis[i + 1].value.cooked;
|
|
801
|
+
return { value };
|
|
802
|
+
}
|
|
803
|
+
return null;
|
|
804
|
+
},
|
|
805
|
+
UnaryExpression(node, initialScope) {
|
|
806
|
+
if (node.operator === "delete") return null;
|
|
807
|
+
if (node.operator === "void") return { value: void 0 };
|
|
808
|
+
let arg = getStaticValueR(node.argument, initialScope);
|
|
809
|
+
if (arg != null) switch (node.operator) {
|
|
810
|
+
case "-": return { value: -arg.value };
|
|
811
|
+
case "+": return { value: +arg.value };
|
|
812
|
+
case "!": return { value: !arg.value };
|
|
813
|
+
case "~": return { value: ~arg.value };
|
|
814
|
+
case "typeof": return { value: typeof arg.value };
|
|
815
|
+
}
|
|
816
|
+
return null;
|
|
817
|
+
},
|
|
818
|
+
TSAsExpression(node, initialScope) {
|
|
819
|
+
return getStaticValueR(node.expression, initialScope);
|
|
820
|
+
},
|
|
821
|
+
TSSatisfiesExpression(node, initialScope) {
|
|
822
|
+
return getStaticValueR(node.expression, initialScope);
|
|
823
|
+
},
|
|
824
|
+
TSTypeAssertion(node, initialScope) {
|
|
825
|
+
return getStaticValueR(node.expression, initialScope);
|
|
826
|
+
},
|
|
827
|
+
TSNonNullExpression(node, initialScope) {
|
|
828
|
+
return getStaticValueR(node.expression, initialScope);
|
|
829
|
+
},
|
|
830
|
+
TSInstantiationExpression(node, initialScope) {
|
|
831
|
+
return getStaticValueR(node.expression, initialScope);
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
/**
|
|
835
|
+
* Get the value of a given node if it's a static value.
|
|
836
|
+
* @param {Node|TSESTreeNode|null|undefined} node The node to get.
|
|
837
|
+
* @param {Scope|undefined|null} initialScope The scope to start finding variable.
|
|
838
|
+
* @returns {StaticValue|null} The static value of the node, or `null`.
|
|
839
|
+
*/
|
|
840
|
+
function getStaticValueR(node, initialScope) {
|
|
841
|
+
return node != null && Object.hasOwnProperty.call(operations, node.type) ? operations[node.type](node, initialScope) : null;
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Get the static value of property name from a MemberExpression node or a Property node.
|
|
845
|
+
* @param {MemberExpression|Property} node The node to get.
|
|
846
|
+
* @param {Scope|null} [initialScope] The scope to start finding variable. Optional. If the node is a computed property node and this scope was given, this checks the computed property name by the `getStringIfConstant` function with the scope, and returns the value of it.
|
|
847
|
+
* @returns {StaticValue|null} The static value of the property name of the node, or `null`.
|
|
848
|
+
*/
|
|
849
|
+
function getStaticPropertyNameValue(node, initialScope) {
|
|
850
|
+
let nameNode = node.type === "Property" ? node.key : node.property;
|
|
851
|
+
return node.computed ? getStaticValueR(nameNode, initialScope) : nameNode.type === "Identifier" ? { value: nameNode.name } : nameNode.type === "Literal" ? nameNode.bigint ? { value: nameNode.bigint } : { value: String(nameNode.value) } : null;
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Get the value of a given node if it's a static value.
|
|
855
|
+
* @param {Node} node The node to get.
|
|
856
|
+
* @param {Scope|null} [initialScope] The scope to start finding variable. Optional. If this scope was given, this tries to resolve identifier references which are in the given node as much as possible.
|
|
857
|
+
* @returns {StaticValue | null} The static value of the node, or `null`.
|
|
858
|
+
*/
|
|
859
|
+
function getStaticValue(node, initialScope = null) {
|
|
860
|
+
try {
|
|
861
|
+
return getStaticValueR(node, initialScope);
|
|
862
|
+
} catch {
|
|
863
|
+
return null;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
/** @typedef {import("eslint").Scope.Scope} Scope */
|
|
867
|
+
/** @typedef {import("estree").Node} Node */
|
|
868
|
+
/** @typedef {import("estree").RegExpLiteral} RegExpLiteral */
|
|
869
|
+
/** @typedef {import("estree").BigIntLiteral} BigIntLiteral */
|
|
870
|
+
/** @typedef {import("estree").SimpleLiteral} SimpleLiteral */
|
|
871
|
+
/**
|
|
872
|
+
* Get the value of a given node if it's a literal or a template literal.
|
|
873
|
+
* @param {Node} node The node to get.
|
|
874
|
+
* @param {Scope|null} [initialScope] The scope to start finding variable. Optional. If the node is an Identifier node and this scope was given, this checks the variable of the identifier, and returns the value of it if the variable is a constant.
|
|
875
|
+
* @returns {string|null} The value of the node, or `null`.
|
|
876
|
+
*/
|
|
877
|
+
function getStringIfConstant(node, initialScope = null) {
|
|
878
|
+
if (node && node.type === "Literal" && node.value === null) {
|
|
879
|
+
let literal = node;
|
|
880
|
+
if (literal.regex) return `/${literal.regex.pattern}/${literal.regex.flags}`;
|
|
881
|
+
if (literal.bigint) return literal.bigint;
|
|
882
|
+
}
|
|
883
|
+
let evaluated = getStaticValue(node, initialScope);
|
|
884
|
+
if (evaluated) try {
|
|
885
|
+
return String(evaluated.value);
|
|
886
|
+
} catch {}
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
/** @typedef {import("eslint").Scope.Scope} Scope */
|
|
890
|
+
/** @typedef {import("estree").MemberExpression} MemberExpression */
|
|
891
|
+
/** @typedef {import("estree").MethodDefinition} MethodDefinition */
|
|
892
|
+
/** @typedef {import("estree").Property} Property */
|
|
893
|
+
/** @typedef {import("estree").PropertyDefinition} PropertyDefinition */
|
|
894
|
+
/** @typedef {import("estree").Identifier} Identifier */
|
|
895
|
+
/**
|
|
896
|
+
* Get the property name from a MemberExpression node or a Property node.
|
|
897
|
+
* @param {MemberExpression | MethodDefinition | Property | PropertyDefinition} node The node to get.
|
|
898
|
+
* @param {Scope} [initialScope] The scope to start finding variable. Optional. If the node is a computed property node and this scope was given, this checks the computed property name by the `getStringIfConstant` function with the scope, and returns the value of it.
|
|
899
|
+
* @returns {string|null|undefined} The property name of the node.
|
|
900
|
+
*/
|
|
901
|
+
function getPropertyName(node, initialScope) {
|
|
902
|
+
switch (node.type) {
|
|
903
|
+
case "MemberExpression": return node.computed ? getStringIfConstant(node.property, initialScope) : node.property.type === "PrivateIdentifier" ? null : node.property.name;
|
|
904
|
+
case "Property":
|
|
905
|
+
case "MethodDefinition":
|
|
906
|
+
case "PropertyDefinition": return node.computed ? getStringIfConstant(node.key, initialScope) : node.key.type === "Literal" ? String(node.key.value) : node.key.type === "PrivateIdentifier" ? null : node.key.name;
|
|
907
|
+
}
|
|
908
|
+
return null;
|
|
909
|
+
}
|
|
910
|
+
/** @typedef {import("eslint").Rule.Node} RuleNode */
|
|
911
|
+
/** @typedef {import("eslint").SourceCode} SourceCode */
|
|
912
|
+
/** @typedef {import("estree").Function} FunctionNode */
|
|
913
|
+
/** @typedef {import("estree").FunctionDeclaration} FunctionDeclaration */
|
|
914
|
+
/** @typedef {import("estree").FunctionExpression} FunctionExpression */
|
|
915
|
+
/** @typedef {import("estree").Identifier} Identifier */
|
|
916
|
+
/**
|
|
917
|
+
* Get the name and kind of the given function node.
|
|
918
|
+
* @param {FunctionNode} node - The function node to get.
|
|
919
|
+
* @param {SourceCode} [sourceCode] The source code object to get the code of computed property keys.
|
|
920
|
+
* @returns {string} The name and kind of the function node.
|
|
921
|
+
*/
|
|
922
|
+
function getFunctionNameWithKind(node, sourceCode) {
|
|
923
|
+
let parent = node.parent;
|
|
924
|
+
if (!parent) return "";
|
|
925
|
+
let tokens = [], isObjectMethod = parent.type === "Property" && parent.value === node, isClassMethod = parent.type === "MethodDefinition" && parent.value === node, isClassFieldMethod = parent.type === "PropertyDefinition" && parent.value === node;
|
|
926
|
+
if ((isClassMethod || isClassFieldMethod) && (parent.static && tokens.push("static"), parent.key.type === "PrivateIdentifier" && tokens.push("private")), node.async && tokens.push("async"), node.generator && tokens.push("generator"), isObjectMethod || isClassMethod) {
|
|
927
|
+
if (parent.kind === "constructor") return "constructor";
|
|
928
|
+
parent.kind === "get" ? tokens.push("getter") : parent.kind === "set" ? tokens.push("setter") : tokens.push("method");
|
|
929
|
+
} else isClassFieldMethod ? tokens.push("method") : (node.type === "ArrowFunctionExpression" && tokens.push("arrow"), tokens.push("function"));
|
|
930
|
+
if (isObjectMethod || isClassMethod || isClassFieldMethod) if (parent.key.type === "PrivateIdentifier") tokens.push(`#${parent.key.name}`);
|
|
931
|
+
else {
|
|
932
|
+
let name = getPropertyName(parent);
|
|
933
|
+
if (name) tokens.push(`'${name}'`);
|
|
934
|
+
else if (sourceCode) {
|
|
935
|
+
let keyText = sourceCode.getText(parent.key);
|
|
936
|
+
keyText.includes("\n") || tokens.push(`[${keyText}]`);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
else hasId(node) ? tokens.push(`'${node.id.name}'`) : parent.type === "VariableDeclarator" && parent.id && parent.id.type === "Identifier" ? tokens.push(`'${parent.id.name}'`) : (parent.type === "AssignmentExpression" || parent.type === "AssignmentPattern") && parent.left && parent.left.type === "Identifier" ? tokens.push(`'${parent.left.name}'`) : parent.type === "ExportDefaultDeclaration" && parent.declaration === node && tokens.push("'default'");
|
|
940
|
+
return tokens.join(" ");
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* @param {FunctionNode} node
|
|
944
|
+
* @returns {node is FunctionDeclaration | FunctionExpression & { id: Identifier }}
|
|
945
|
+
*/
|
|
946
|
+
function hasId(node) {
|
|
947
|
+
return !!node.id;
|
|
948
|
+
}
|
|
949
|
+
/** @typedef {import("estree").Node} Node */
|
|
950
|
+
/** @typedef {import("eslint").SourceCode} SourceCode */
|
|
951
|
+
/** @typedef {import("./types.mjs").HasSideEffectOptions} HasSideEffectOptions */
|
|
952
|
+
/** @typedef {import("estree").BinaryExpression} BinaryExpression */
|
|
953
|
+
/** @typedef {import("estree").MemberExpression} MemberExpression */
|
|
954
|
+
/** @typedef {import("estree").MethodDefinition} MethodDefinition */
|
|
955
|
+
/** @typedef {import("estree").Property} Property */
|
|
956
|
+
/** @typedef {import("estree").PropertyDefinition} PropertyDefinition */
|
|
957
|
+
/** @typedef {import("estree").UnaryExpression} UnaryExpression */
|
|
958
|
+
let typeConversionBinaryOps = Object.freeze(new Set([
|
|
959
|
+
"==",
|
|
960
|
+
"!=",
|
|
961
|
+
"<",
|
|
962
|
+
"<=",
|
|
963
|
+
">",
|
|
964
|
+
">=",
|
|
965
|
+
"<<",
|
|
966
|
+
">>",
|
|
967
|
+
">>>",
|
|
968
|
+
"+",
|
|
969
|
+
"-",
|
|
970
|
+
"*",
|
|
971
|
+
"/",
|
|
972
|
+
"%",
|
|
973
|
+
"|",
|
|
974
|
+
"^",
|
|
975
|
+
"&",
|
|
976
|
+
"in"
|
|
977
|
+
])), typeConversionUnaryOps = Object.freeze(new Set([
|
|
978
|
+
"-",
|
|
979
|
+
"+",
|
|
980
|
+
"!",
|
|
981
|
+
"~"
|
|
982
|
+
]));
|
|
983
|
+
/**
|
|
984
|
+
* Check whether the given value is an ASTNode or not.
|
|
985
|
+
* @param {any} x The value to check.
|
|
986
|
+
* @returns {x is Node} `true` if the value is an ASTNode.
|
|
987
|
+
*/
|
|
988
|
+
function isNode(x) {
|
|
989
|
+
return typeof x == "object" && !!x && typeof x.type == "string";
|
|
990
|
+
}
|
|
991
|
+
let visitor = Object.freeze(Object.assign(Object.create(null), {
|
|
992
|
+
$visit(node, options, visitorKeys) {
|
|
993
|
+
let { type } = node;
|
|
994
|
+
return typeof this[type] == "function" ? this[type](node, options, visitorKeys) : this.$visitChildren(node, options, visitorKeys);
|
|
995
|
+
},
|
|
996
|
+
$visitChildren(node, options, visitorKeys) {
|
|
997
|
+
let { type } = node;
|
|
998
|
+
for (let key of visitorKeys[type] || eslintVisitorKeys.getKeys(node)) {
|
|
999
|
+
let value = node[key];
|
|
1000
|
+
if (Array.isArray(value)) {
|
|
1001
|
+
for (let element of value) if (isNode(element) && this.$visit(element, options, visitorKeys)) return !0;
|
|
1002
|
+
} else if (isNode(value) && this.$visit(value, options, visitorKeys)) return !0;
|
|
1003
|
+
}
|
|
1004
|
+
return !1;
|
|
1005
|
+
},
|
|
1006
|
+
ArrowFunctionExpression() {
|
|
1007
|
+
return !1;
|
|
1008
|
+
},
|
|
1009
|
+
AssignmentExpression() {
|
|
1010
|
+
return !0;
|
|
1011
|
+
},
|
|
1012
|
+
AwaitExpression() {
|
|
1013
|
+
return !0;
|
|
1014
|
+
},
|
|
1015
|
+
BinaryExpression(node, options, visitorKeys) {
|
|
1016
|
+
return options.considerImplicitTypeConversion && typeConversionBinaryOps.has(node.operator) && (node.left.type !== "Literal" || node.right.type !== "Literal") ? !0 : this.$visitChildren(node, options, visitorKeys);
|
|
1017
|
+
},
|
|
1018
|
+
CallExpression() {
|
|
1019
|
+
return !0;
|
|
1020
|
+
},
|
|
1021
|
+
FunctionExpression() {
|
|
1022
|
+
return !1;
|
|
1023
|
+
},
|
|
1024
|
+
ImportExpression() {
|
|
1025
|
+
return !0;
|
|
1026
|
+
},
|
|
1027
|
+
MemberExpression(node, options, visitorKeys) {
|
|
1028
|
+
return options.considerGetters || options.considerImplicitTypeConversion && node.computed && node.property.type !== "Literal" ? !0 : this.$visitChildren(node, options, visitorKeys);
|
|
1029
|
+
},
|
|
1030
|
+
MethodDefinition(node, options, visitorKeys) {
|
|
1031
|
+
return options.considerImplicitTypeConversion && node.computed && node.key.type !== "Literal" ? !0 : this.$visitChildren(node, options, visitorKeys);
|
|
1032
|
+
},
|
|
1033
|
+
NewExpression() {
|
|
1034
|
+
return !0;
|
|
1035
|
+
},
|
|
1036
|
+
Property(node, options, visitorKeys) {
|
|
1037
|
+
return options.considerImplicitTypeConversion && node.computed && node.key.type !== "Literal" ? !0 : this.$visitChildren(node, options, visitorKeys);
|
|
1038
|
+
},
|
|
1039
|
+
PropertyDefinition(node, options, visitorKeys) {
|
|
1040
|
+
return options.considerImplicitTypeConversion && node.computed && node.key.type !== "Literal" ? !0 : this.$visitChildren(node, options, visitorKeys);
|
|
1041
|
+
},
|
|
1042
|
+
UnaryExpression(node, options, visitorKeys) {
|
|
1043
|
+
return node.operator === "delete" || options.considerImplicitTypeConversion && typeConversionUnaryOps.has(node.operator) && node.argument.type !== "Literal" ? !0 : this.$visitChildren(node, options, visitorKeys);
|
|
1044
|
+
},
|
|
1045
|
+
UpdateExpression() {
|
|
1046
|
+
return !0;
|
|
1047
|
+
},
|
|
1048
|
+
YieldExpression() {
|
|
1049
|
+
return !0;
|
|
1050
|
+
}
|
|
1051
|
+
}));
|
|
1052
|
+
/**
|
|
1053
|
+
* Check whether a given node has any side effect or not.
|
|
1054
|
+
* @param {Node} node The node to get.
|
|
1055
|
+
* @param {SourceCode} sourceCode The source code object.
|
|
1056
|
+
* @param {HasSideEffectOptions} [options] The option object.
|
|
1057
|
+
* @returns {boolean} `true` if the node has a certain side effect.
|
|
1058
|
+
*/
|
|
1059
|
+
function hasSideEffect(node, sourceCode, options = {}) {
|
|
1060
|
+
let { considerGetters = !1, considerImplicitTypeConversion = !1 } = options;
|
|
1061
|
+
return visitor.$visit(node, {
|
|
1062
|
+
considerGetters,
|
|
1063
|
+
considerImplicitTypeConversion
|
|
1064
|
+
}, sourceCode.visitorKeys || eslintVisitorKeys.KEYS);
|
|
1065
|
+
}
|
|
1066
|
+
/** @typedef {import("estree").Node} Node */
|
|
1067
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.NewExpression} TSNewExpression */
|
|
1068
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.CallExpression} TSCallExpression */
|
|
1069
|
+
/** @typedef {import("eslint").SourceCode} SourceCode */
|
|
1070
|
+
/** @typedef {import("eslint").AST.Token} Token */
|
|
1071
|
+
/** @typedef {import("eslint").Rule.Node} RuleNode */
|
|
1072
|
+
/**
|
|
1073
|
+
* Get the left parenthesis of the parent node syntax if it exists.
|
|
1074
|
+
* E.g., `if (a) {}` then the `(`.
|
|
1075
|
+
* @param {Node} node The AST node to check.
|
|
1076
|
+
* @param {SourceCode} sourceCode The source code object to get tokens.
|
|
1077
|
+
* @returns {Token|null} The left parenthesis of the parent node syntax
|
|
1078
|
+
*/
|
|
1079
|
+
function getParentSyntaxParen(node, sourceCode) {
|
|
1080
|
+
let parent = node.parent;
|
|
1081
|
+
if (!parent) return null;
|
|
1082
|
+
switch (parent.type) {
|
|
1083
|
+
case "CallExpression":
|
|
1084
|
+
case "NewExpression": return parent.arguments.length === 1 && parent.arguments[0] === node ? sourceCode.getTokenAfter(parent.typeArguments || parent.typeParameters || parent.callee, isOpeningParenToken) : null;
|
|
1085
|
+
case "DoWhileStatement": return parent.test === node ? sourceCode.getTokenAfter(parent.body, isOpeningParenToken) : null;
|
|
1086
|
+
case "IfStatement":
|
|
1087
|
+
case "WhileStatement": return parent.test === node ? sourceCode.getFirstToken(parent, 1) : null;
|
|
1088
|
+
case "ImportExpression": return parent.source === node ? sourceCode.getFirstToken(parent, 1) : null;
|
|
1089
|
+
case "SwitchStatement": return parent.discriminant === node ? sourceCode.getFirstToken(parent, 1) : null;
|
|
1090
|
+
case "WithStatement": return parent.object === node ? sourceCode.getFirstToken(parent, 1) : null;
|
|
1091
|
+
default: return null;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Check whether a given node is parenthesized or not.
|
|
1096
|
+
* @param {number} times The number of parantheses.
|
|
1097
|
+
* @param {Node} node The AST node to check.
|
|
1098
|
+
* @param {SourceCode} sourceCode The source code object to get tokens.
|
|
1099
|
+
* @returns {boolean} `true` if the node is parenthesized the given times.
|
|
1100
|
+
*/
|
|
1101
|
+
/**
|
|
1102
|
+
* Check whether a given node is parenthesized or not.
|
|
1103
|
+
* @param {Node} node The AST node to check.
|
|
1104
|
+
* @param {SourceCode} sourceCode The source code object to get tokens.
|
|
1105
|
+
* @returns {boolean} `true` if the node is parenthesized.
|
|
1106
|
+
*/
|
|
1107
|
+
/**
|
|
1108
|
+
* Check whether a given node is parenthesized or not.
|
|
1109
|
+
* @param {Node|number} timesOrNode The first parameter.
|
|
1110
|
+
* @param {Node|SourceCode} nodeOrSourceCode The second parameter.
|
|
1111
|
+
* @param {SourceCode} [optionalSourceCode] The third parameter.
|
|
1112
|
+
* @returns {boolean} `true` if the node is parenthesized.
|
|
1113
|
+
*/
|
|
1114
|
+
function isParenthesized(timesOrNode, nodeOrSourceCode, optionalSourceCode) {
|
|
1115
|
+
/** @type {number} */
|
|
1116
|
+
let times, node, sourceCode, maybeLeftParen, maybeRightParen;
|
|
1117
|
+
if (typeof timesOrNode == "number") {
|
|
1118
|
+
if (times = timesOrNode | 0, node = nodeOrSourceCode, sourceCode = optionalSourceCode, !(times >= 1)) throw TypeError("'times' should be a positive integer.");
|
|
1119
|
+
} else times = 1, node = timesOrNode, sourceCode = nodeOrSourceCode;
|
|
1120
|
+
if (node == null || node.parent == null || node.parent.type === "CatchClause" && node.parent.param === node) return !1;
|
|
1121
|
+
maybeLeftParen = maybeRightParen = node;
|
|
1122
|
+
do
|
|
1123
|
+
maybeLeftParen = sourceCode.getTokenBefore(maybeLeftParen), maybeRightParen = sourceCode.getTokenAfter(maybeRightParen);
|
|
1124
|
+
while (maybeLeftParen != null && maybeRightParen != null && isOpeningParenToken(maybeLeftParen) && isClosingParenToken(maybeRightParen) && maybeLeftParen !== getParentSyntaxParen(node, sourceCode) && --times > 0);
|
|
1125
|
+
return times === 0;
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* @author Toru Nagashima <https://github.com/mysticatea>
|
|
1129
|
+
* See LICENSE file in root directory for full license.
|
|
1130
|
+
*/
|
|
1131
|
+
let placeholder = /\$(?:[$&`']|[1-9][0-9]?)/gu, internal = /* @__PURE__ */ new WeakMap();
|
|
1132
|
+
/**
|
|
1133
|
+
* Check whether a given character is escaped or not.
|
|
1134
|
+
* @param {string} str The string to check.
|
|
1135
|
+
* @param {number} index The location of the character to check.
|
|
1136
|
+
* @returns {boolean} `true` if the character is escaped.
|
|
1137
|
+
*/
|
|
1138
|
+
function isEscaped(str, index) {
|
|
1139
|
+
let escaped = !1;
|
|
1140
|
+
for (let i = index - 1; i >= 0 && str.charCodeAt(i) === 92; --i) escaped = !escaped;
|
|
1141
|
+
return escaped;
|
|
1142
|
+
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Replace a given string by a given matcher.
|
|
1145
|
+
* @param {PatternMatcher} matcher The pattern matcher.
|
|
1146
|
+
* @param {string} str The string to be replaced.
|
|
1147
|
+
* @param {string} replacement The new substring to replace each matched part.
|
|
1148
|
+
* @returns {string} The replaced string.
|
|
1149
|
+
*/
|
|
1150
|
+
function replaceS(matcher, str, replacement) {
|
|
1151
|
+
let chunks = [], index = 0;
|
|
1152
|
+
/**
|
|
1153
|
+
* @param {string} key The placeholder.
|
|
1154
|
+
* @param {RegExpExecArray} match The matched information.
|
|
1155
|
+
* @returns {string} The replaced string.
|
|
1156
|
+
*/
|
|
1157
|
+
function replacer(key, match) {
|
|
1158
|
+
switch (key) {
|
|
1159
|
+
case "$$": return "$";
|
|
1160
|
+
case "$&": return match[0];
|
|
1161
|
+
case "$`": return str.slice(0, match.index);
|
|
1162
|
+
case "$'": return str.slice(match.index + match[0].length);
|
|
1163
|
+
default: {
|
|
1164
|
+
let i = key.slice(1);
|
|
1165
|
+
return i in match ? match[i] : key;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
for (let match of matcher.execAll(str)) chunks.push(str.slice(index, match.index)), chunks.push(replacement.replace(placeholder, (key) => replacer(key, match))), index = match.index + match[0].length;
|
|
1170
|
+
return chunks.push(str.slice(index)), chunks.join("");
|
|
1171
|
+
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Replace a given string by a given matcher.
|
|
1174
|
+
* @param {PatternMatcher} matcher The pattern matcher.
|
|
1175
|
+
* @param {string} str The string to be replaced.
|
|
1176
|
+
* @param {(substring: string, ...args: any[]) => string} replace The function to replace each matched part.
|
|
1177
|
+
* @returns {string} The replaced string.
|
|
1178
|
+
*/
|
|
1179
|
+
function replaceF(matcher, str, replace) {
|
|
1180
|
+
let chunks = [], index = 0;
|
|
1181
|
+
for (let match of matcher.execAll(str)) chunks.push(str.slice(index, match.index)), chunks.push(String(replace(...match, match.index, match.input))), index = match.index + match[0].length;
|
|
1182
|
+
return chunks.push(str.slice(index)), chunks.join("");
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1185
|
+
* The class to find patterns as considering escape sequences.
|
|
1186
|
+
*/
|
|
1187
|
+
var PatternMatcher = class {
|
|
1188
|
+
/**
|
|
1189
|
+
* Initialize this matcher.
|
|
1190
|
+
* @param {RegExp} pattern The pattern to match.
|
|
1191
|
+
* @param {{escaped?:boolean}} [options] The options.
|
|
1192
|
+
*/
|
|
1193
|
+
constructor(pattern, options = {}) {
|
|
1194
|
+
let { escaped = !1 } = options;
|
|
1195
|
+
if (!(pattern instanceof RegExp)) throw TypeError("'pattern' should be a RegExp instance.");
|
|
1196
|
+
if (!pattern.flags.includes("g")) throw Error("'pattern' should contains 'g' flag.");
|
|
1197
|
+
internal.set(this, {
|
|
1198
|
+
pattern: new RegExp(pattern.source, pattern.flags),
|
|
1199
|
+
escaped: !!escaped
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Find the pattern in a given string.
|
|
1204
|
+
* @param {string} str The string to find.
|
|
1205
|
+
* @returns {IterableIterator<RegExpExecArray>} The iterator which iterate the matched information.
|
|
1206
|
+
*/
|
|
1207
|
+
*execAll(str) {
|
|
1208
|
+
let { pattern, escaped } = internal.get(this), match = null, lastIndex = 0;
|
|
1209
|
+
for (pattern.lastIndex = 0; (match = pattern.exec(str)) != null;) (escaped || !isEscaped(str, match.index)) && (lastIndex = pattern.lastIndex, yield match, pattern.lastIndex = lastIndex);
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* Check whether the pattern is found in a given string.
|
|
1213
|
+
* @param {string} str The string to check.
|
|
1214
|
+
* @returns {boolean} `true` if the pattern was found in the string.
|
|
1215
|
+
*/
|
|
1216
|
+
test(str) {
|
|
1217
|
+
return !this.execAll(str).next().done;
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Replace a given string.
|
|
1221
|
+
* @param {string} str The string to be replaced.
|
|
1222
|
+
* @param {(string|((...strs:string[])=>string))} replacer The string or function to replace. This is the same as the 2nd argument of `String.prototype.replace`.
|
|
1223
|
+
* @returns {string} The replaced string.
|
|
1224
|
+
*/
|
|
1225
|
+
[Symbol.replace](str, replacer) {
|
|
1226
|
+
return typeof replacer == "function" ? replaceF(this, String(str), replacer) : replaceS(this, String(str), String(replacer));
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1229
|
+
/** @typedef {import("eslint").Scope.Scope} Scope */
|
|
1230
|
+
/** @typedef {import("eslint").Scope.Variable} Variable */
|
|
1231
|
+
/** @typedef {import("eslint").Rule.Node} RuleNode */
|
|
1232
|
+
/** @typedef {import("estree").Node} Node */
|
|
1233
|
+
/** @typedef {import("estree").Expression} Expression */
|
|
1234
|
+
/** @typedef {import("estree").Pattern} Pattern */
|
|
1235
|
+
/** @typedef {import("estree").Identifier} Identifier */
|
|
1236
|
+
/** @typedef {import("estree").SimpleCallExpression} CallExpression */
|
|
1237
|
+
/** @typedef {import("estree").Program} Program */
|
|
1238
|
+
/** @typedef {import("estree").ImportDeclaration} ImportDeclaration */
|
|
1239
|
+
/** @typedef {import("estree").ExportAllDeclaration} ExportAllDeclaration */
|
|
1240
|
+
/** @typedef {import("estree").ExportDefaultDeclaration} ExportDefaultDeclaration */
|
|
1241
|
+
/** @typedef {import("estree").ExportNamedDeclaration} ExportNamedDeclaration */
|
|
1242
|
+
/** @typedef {import("estree").ImportSpecifier} ImportSpecifier */
|
|
1243
|
+
/** @typedef {import("estree").ImportDefaultSpecifier} ImportDefaultSpecifier */
|
|
1244
|
+
/** @typedef {import("estree").ImportNamespaceSpecifier} ImportNamespaceSpecifier */
|
|
1245
|
+
/** @typedef {import("estree").ExportSpecifier} ExportSpecifier */
|
|
1246
|
+
/** @typedef {import("estree").Property} Property */
|
|
1247
|
+
/** @typedef {import("estree").AssignmentProperty} AssignmentProperty */
|
|
1248
|
+
/** @typedef {import("estree").Literal} Literal */
|
|
1249
|
+
/** @typedef {import("@typescript-eslint/types").TSESTree.Node} TSESTreeNode */
|
|
1250
|
+
/** @typedef {import("./types.mjs").ReferenceTrackerOptions} ReferenceTrackerOptions */
|
|
1251
|
+
/**
|
|
1252
|
+
* @template T
|
|
1253
|
+
* @typedef {import("./types.mjs").TraceMap<T>} TraceMap
|
|
1254
|
+
*/
|
|
1255
|
+
/**
|
|
1256
|
+
* @template T
|
|
1257
|
+
* @typedef {import("./types.mjs").TraceMapObject<T>} TraceMapObject
|
|
1258
|
+
*/
|
|
1259
|
+
/**
|
|
1260
|
+
* @template T
|
|
1261
|
+
* @typedef {import("./types.mjs").TrackedReferences<T>} TrackedReferences
|
|
1262
|
+
*/
|
|
1263
|
+
let IMPORT_TYPE = /^(?:Import|Export(?:All|Default|Named))Declaration$/u;
|
|
1264
|
+
/**
|
|
1265
|
+
* Check whether a given node is an import node or not.
|
|
1266
|
+
* @param {Node} node
|
|
1267
|
+
* @returns {node is ImportDeclaration|ExportAllDeclaration|ExportNamedDeclaration&{source: Literal}} `true` if the node is an import node.
|
|
1268
|
+
*/
|
|
1269
|
+
function isHasSource(node) {
|
|
1270
|
+
return IMPORT_TYPE.test(node.type) && node.source != null;
|
|
1271
|
+
}
|
|
1272
|
+
let has = Function.call.bind(Object.hasOwnProperty), READ = Symbol("read"), CALL = Symbol("call"), CONSTRUCT = Symbol("construct"), ESM = Symbol("esm"), requireCall = { require: { [CALL]: !0 } };
|
|
1273
|
+
/**
|
|
1274
|
+
* Check whether a given variable is modified or not.
|
|
1275
|
+
* @param {Variable|undefined} variable The variable to check.
|
|
1276
|
+
* @returns {boolean} `true` if the variable is modified.
|
|
1277
|
+
*/
|
|
1278
|
+
function isModifiedGlobal(variable) {
|
|
1279
|
+
return variable == null || variable.defs.length !== 0 || variable.references.some((r) => r.isWrite());
|
|
1280
|
+
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Check if the value of a given node is passed through to the parent syntax as-is.
|
|
1283
|
+
* For example, `a` and `b` in (`a || b` and `c ? a : b`) are passed through.
|
|
1284
|
+
* @param {Node} node A node to check.
|
|
1285
|
+
* @returns {node is RuleNode & {parent: Expression}} `true` if the node is passed through.
|
|
1286
|
+
*/
|
|
1287
|
+
function isPassThrough(node) {
|
|
1288
|
+
let parent = node.parent;
|
|
1289
|
+
if (parent) switch (parent.type) {
|
|
1290
|
+
case "ConditionalExpression": return parent.consequent === node || parent.alternate === node;
|
|
1291
|
+
case "LogicalExpression": return !0;
|
|
1292
|
+
case "SequenceExpression": return parent.expressions[parent.expressions.length - 1] === node;
|
|
1293
|
+
case "ChainExpression": return !0;
|
|
1294
|
+
case "TSAsExpression":
|
|
1295
|
+
case "TSSatisfiesExpression":
|
|
1296
|
+
case "TSTypeAssertion":
|
|
1297
|
+
case "TSNonNullExpression":
|
|
1298
|
+
case "TSInstantiationExpression": return !0;
|
|
1299
|
+
default: return !1;
|
|
1300
|
+
}
|
|
1301
|
+
return !1;
|
|
1302
|
+
}
|
|
1303
|
+
/**
|
|
1304
|
+
* The reference tracker.
|
|
1305
|
+
*/
|
|
1306
|
+
var ReferenceTracker = class {
|
|
1307
|
+
/**
|
|
1308
|
+
* Initialize this tracker.
|
|
1309
|
+
* @param {Scope} globalScope The global scope.
|
|
1310
|
+
* @param {object} [options] The options.
|
|
1311
|
+
* @param {"legacy"|"strict"} [options.mode="strict"] The mode to determine the ImportDeclaration's behavior for CJS modules.
|
|
1312
|
+
* @param {string[]} [options.globalObjectNames=["global","globalThis","self","window"]] The variable names for Global Object.
|
|
1313
|
+
*/
|
|
1314
|
+
constructor(globalScope, options = {}) {
|
|
1315
|
+
let { mode = "strict", globalObjectNames = [
|
|
1316
|
+
"global",
|
|
1317
|
+
"globalThis",
|
|
1318
|
+
"self",
|
|
1319
|
+
"window"
|
|
1320
|
+
] } = options;
|
|
1321
|
+
/** @private */
|
|
1322
|
+
this.variableStack = [], this.globalScope = globalScope, this.mode = mode, this.globalObjectNames = globalObjectNames.slice(0);
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* Iterate the references of global variables.
|
|
1326
|
+
* @template T
|
|
1327
|
+
* @param {TraceMap<T>} traceMap The trace map.
|
|
1328
|
+
* @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
|
|
1329
|
+
*/
|
|
1330
|
+
*iterateGlobalReferences(traceMap) {
|
|
1331
|
+
for (let key of Object.keys(traceMap)) {
|
|
1332
|
+
let nextTraceMap = traceMap[key], path = [key], variable = this.globalScope.set.get(key);
|
|
1333
|
+
isModifiedGlobal(variable) || (yield* this._iterateVariableReferences(variable, path, nextTraceMap, !0));
|
|
1334
|
+
}
|
|
1335
|
+
for (let key of this.globalObjectNames) {
|
|
1336
|
+
/** @type {string[]} */
|
|
1337
|
+
let path = [], variable = this.globalScope.set.get(key);
|
|
1338
|
+
isModifiedGlobal(variable) || (yield* this._iterateVariableReferences(variable, path, traceMap, !1));
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Iterate the references of CommonJS modules.
|
|
1343
|
+
* @template T
|
|
1344
|
+
* @param {TraceMap<T>} traceMap The trace map.
|
|
1345
|
+
* @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
|
|
1346
|
+
*/
|
|
1347
|
+
*iterateCjsReferences(traceMap) {
|
|
1348
|
+
for (let { node } of this.iterateGlobalReferences(requireCall)) {
|
|
1349
|
+
let key = getStringIfConstant(
|
|
1350
|
+
/** @type {CallExpression} */
|
|
1351
|
+
node.arguments[0]
|
|
1352
|
+
);
|
|
1353
|
+
if (key == null || !has(traceMap, key)) continue;
|
|
1354
|
+
let nextTraceMap = traceMap[key], path = [key];
|
|
1355
|
+
nextTraceMap[READ] && (yield {
|
|
1356
|
+
node,
|
|
1357
|
+
path,
|
|
1358
|
+
type: READ,
|
|
1359
|
+
info: nextTraceMap[READ]
|
|
1360
|
+
}), yield* this._iteratePropertyReferences(node, path, nextTraceMap);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Iterate the references of ES modules.
|
|
1365
|
+
* @template T
|
|
1366
|
+
* @param {TraceMap<T>} traceMap The trace map.
|
|
1367
|
+
* @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
|
|
1368
|
+
*/
|
|
1369
|
+
*iterateEsmReferences(traceMap) {
|
|
1370
|
+
let programNode = this.globalScope.block;
|
|
1371
|
+
for (let node of programNode.body) {
|
|
1372
|
+
if (!isHasSource(node)) continue;
|
|
1373
|
+
let moduleId = node.source.value;
|
|
1374
|
+
if (!has(traceMap, moduleId)) continue;
|
|
1375
|
+
let nextTraceMap = traceMap[moduleId], path = [moduleId];
|
|
1376
|
+
if (nextTraceMap[READ] && (yield {
|
|
1377
|
+
node,
|
|
1378
|
+
path,
|
|
1379
|
+
type: READ,
|
|
1380
|
+
info: nextTraceMap[READ]
|
|
1381
|
+
}), node.type === "ExportAllDeclaration") for (let key of Object.keys(nextTraceMap)) {
|
|
1382
|
+
let exportTraceMap = nextTraceMap[key];
|
|
1383
|
+
exportTraceMap[READ] && (yield {
|
|
1384
|
+
node,
|
|
1385
|
+
path: path.concat(key),
|
|
1386
|
+
type: READ,
|
|
1387
|
+
info: exportTraceMap[READ]
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
else for (let specifier of node.specifiers) {
|
|
1391
|
+
let esm = has(nextTraceMap, ESM), it = this._iterateImportReferences(specifier, path, esm ? nextTraceMap : this.mode === "legacy" ? {
|
|
1392
|
+
default: nextTraceMap,
|
|
1393
|
+
...nextTraceMap
|
|
1394
|
+
} : { default: nextTraceMap });
|
|
1395
|
+
if (esm) yield* it;
|
|
1396
|
+
else for (let report of it) report.path = report.path.filter(exceptDefault), (report.path.length >= 2 || report.type !== READ) && (yield report);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1401
|
+
* Iterate the property references for a given expression AST node.
|
|
1402
|
+
* @template T
|
|
1403
|
+
* @param {Expression} node The expression AST node to iterate property references.
|
|
1404
|
+
* @param {TraceMap<T>} traceMap The trace map.
|
|
1405
|
+
* @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate property references.
|
|
1406
|
+
*/
|
|
1407
|
+
*iteratePropertyReferences(node, traceMap) {
|
|
1408
|
+
yield* this._iteratePropertyReferences(node, [], traceMap);
|
|
1409
|
+
}
|
|
1410
|
+
/**
|
|
1411
|
+
* Iterate the references for a given variable.
|
|
1412
|
+
* @private
|
|
1413
|
+
* @template T
|
|
1414
|
+
* @param {Variable} variable The variable to iterate that references.
|
|
1415
|
+
* @param {string[]} path The current path.
|
|
1416
|
+
* @param {TraceMapObject<T>} traceMap The trace map.
|
|
1417
|
+
* @param {boolean} shouldReport = The flag to report those references.
|
|
1418
|
+
* @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
|
|
1419
|
+
*/
|
|
1420
|
+
*_iterateVariableReferences(variable, path, traceMap, shouldReport) {
|
|
1421
|
+
if (!this.variableStack.includes(variable)) {
|
|
1422
|
+
this.variableStack.push(variable);
|
|
1423
|
+
try {
|
|
1424
|
+
for (let reference of variable.references) {
|
|
1425
|
+
if (!reference.isRead()) continue;
|
|
1426
|
+
let node = reference.identifier;
|
|
1427
|
+
shouldReport && traceMap[READ] && (yield {
|
|
1428
|
+
node,
|
|
1429
|
+
path,
|
|
1430
|
+
type: READ,
|
|
1431
|
+
info: traceMap[READ]
|
|
1432
|
+
}), yield* this._iteratePropertyReferences(node, path, traceMap);
|
|
1433
|
+
}
|
|
1434
|
+
} finally {
|
|
1435
|
+
this.variableStack.pop();
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Iterate the references for a given AST node.
|
|
1441
|
+
* @private
|
|
1442
|
+
* @template T
|
|
1443
|
+
* @param {Expression} rootNode The AST node to iterate references.
|
|
1444
|
+
* @param {string[]} path The current path.
|
|
1445
|
+
* @param {TraceMapObject<T>} traceMap The trace map.
|
|
1446
|
+
* @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
|
|
1447
|
+
*/
|
|
1448
|
+
*_iteratePropertyReferences(rootNode, path, traceMap) {
|
|
1449
|
+
let node = rootNode;
|
|
1450
|
+
for (; isPassThrough(node);) node = node.parent;
|
|
1451
|
+
let parent = node.parent;
|
|
1452
|
+
if (parent) {
|
|
1453
|
+
if (parent.type === "MemberExpression") {
|
|
1454
|
+
if (parent.object === node) {
|
|
1455
|
+
let key = getPropertyName(parent);
|
|
1456
|
+
if (key == null || !has(traceMap, key)) return;
|
|
1457
|
+
path = path.concat(key);
|
|
1458
|
+
let nextTraceMap = traceMap[key];
|
|
1459
|
+
nextTraceMap[READ] && (yield {
|
|
1460
|
+
node: parent,
|
|
1461
|
+
path,
|
|
1462
|
+
type: READ,
|
|
1463
|
+
info: nextTraceMap[READ]
|
|
1464
|
+
}), yield* this._iteratePropertyReferences(parent, path, nextTraceMap);
|
|
1465
|
+
}
|
|
1466
|
+
return;
|
|
1467
|
+
}
|
|
1468
|
+
if (parent.type === "CallExpression") {
|
|
1469
|
+
parent.callee === node && traceMap[CALL] && (yield {
|
|
1470
|
+
node: parent,
|
|
1471
|
+
path,
|
|
1472
|
+
type: CALL,
|
|
1473
|
+
info: traceMap[CALL]
|
|
1474
|
+
});
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
if (parent.type === "NewExpression") {
|
|
1478
|
+
parent.callee === node && traceMap[CONSTRUCT] && (yield {
|
|
1479
|
+
node: parent,
|
|
1480
|
+
path,
|
|
1481
|
+
type: CONSTRUCT,
|
|
1482
|
+
info: traceMap[CONSTRUCT]
|
|
1483
|
+
});
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1486
|
+
if (parent.type === "AssignmentExpression") {
|
|
1487
|
+
parent.right === node && (yield* this._iterateLhsReferences(parent.left, path, traceMap), yield* this._iteratePropertyReferences(parent, path, traceMap));
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
if (parent.type === "AssignmentPattern") {
|
|
1491
|
+
parent.right === node && (yield* this._iterateLhsReferences(parent.left, path, traceMap));
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1494
|
+
parent.type === "VariableDeclarator" && parent.init === node && (yield* this._iterateLhsReferences(parent.id, path, traceMap));
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Iterate the references for a given Pattern node.
|
|
1499
|
+
* @private
|
|
1500
|
+
* @template T
|
|
1501
|
+
* @param {Pattern} patternNode The Pattern node to iterate references.
|
|
1502
|
+
* @param {string[]} path The current path.
|
|
1503
|
+
* @param {TraceMapObject<T>} traceMap The trace map.
|
|
1504
|
+
* @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
|
|
1505
|
+
*/
|
|
1506
|
+
*_iterateLhsReferences(patternNode, path, traceMap) {
|
|
1507
|
+
if (patternNode.type === "Identifier") {
|
|
1508
|
+
let variable = findVariable(this.globalScope, patternNode);
|
|
1509
|
+
variable != null && (yield* this._iterateVariableReferences(variable, path, traceMap, !1));
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
1512
|
+
if (patternNode.type === "ObjectPattern") {
|
|
1513
|
+
for (let property of patternNode.properties) {
|
|
1514
|
+
let key = getPropertyName(property);
|
|
1515
|
+
if (key == null || !has(traceMap, key)) continue;
|
|
1516
|
+
let nextPath = path.concat(key), nextTraceMap = traceMap[key];
|
|
1517
|
+
nextTraceMap[READ] && (yield {
|
|
1518
|
+
node: property,
|
|
1519
|
+
path: nextPath,
|
|
1520
|
+
type: READ,
|
|
1521
|
+
info: nextTraceMap[READ]
|
|
1522
|
+
}), yield* this._iterateLhsReferences(
|
|
1523
|
+
/** @type {AssignmentProperty} */
|
|
1524
|
+
property.value,
|
|
1525
|
+
nextPath,
|
|
1526
|
+
nextTraceMap
|
|
1527
|
+
);
|
|
1528
|
+
}
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
patternNode.type === "AssignmentPattern" && (yield* this._iterateLhsReferences(patternNode.left, path, traceMap));
|
|
1532
|
+
}
|
|
1533
|
+
/**
|
|
1534
|
+
* Iterate the references for a given ModuleSpecifier node.
|
|
1535
|
+
* @private
|
|
1536
|
+
* @template T
|
|
1537
|
+
* @param {ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier} specifierNode The ModuleSpecifier node to iterate references.
|
|
1538
|
+
* @param {string[]} path The current path.
|
|
1539
|
+
* @param {TraceMapObject<T>} traceMap The trace map.
|
|
1540
|
+
* @returns {IterableIterator<TrackedReferences<T>>} The iterator to iterate references.
|
|
1541
|
+
*/
|
|
1542
|
+
*_iterateImportReferences(specifierNode, path, traceMap) {
|
|
1543
|
+
let type = specifierNode.type;
|
|
1544
|
+
if (type === "ImportSpecifier" || type === "ImportDefaultSpecifier") {
|
|
1545
|
+
let key = type === "ImportDefaultSpecifier" ? "default" : specifierNode.imported.type === "Identifier" ? specifierNode.imported.name : specifierNode.imported.value;
|
|
1546
|
+
if (!has(traceMap, key)) return;
|
|
1547
|
+
path = path.concat(key);
|
|
1548
|
+
let nextTraceMap = traceMap[key];
|
|
1549
|
+
nextTraceMap[READ] && (yield {
|
|
1550
|
+
node: specifierNode,
|
|
1551
|
+
path,
|
|
1552
|
+
type: READ,
|
|
1553
|
+
info: nextTraceMap[READ]
|
|
1554
|
+
}), yield* this._iterateVariableReferences(findVariable(this.globalScope, specifierNode.local), path, nextTraceMap, !1);
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
if (type === "ImportNamespaceSpecifier") {
|
|
1558
|
+
yield* this._iterateVariableReferences(findVariable(this.globalScope, specifierNode.local), path, traceMap, !1);
|
|
1559
|
+
return;
|
|
1560
|
+
}
|
|
1561
|
+
if (type === "ExportSpecifier") {
|
|
1562
|
+
let key = specifierNode.local.type === "Identifier" ? specifierNode.local.name : specifierNode.local.value;
|
|
1563
|
+
if (!has(traceMap, key)) return;
|
|
1564
|
+
path = path.concat(key);
|
|
1565
|
+
let nextTraceMap = traceMap[key];
|
|
1566
|
+
nextTraceMap[READ] && (yield {
|
|
1567
|
+
node: specifierNode,
|
|
1568
|
+
path,
|
|
1569
|
+
type: READ,
|
|
1570
|
+
info: nextTraceMap[READ]
|
|
1571
|
+
});
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
};
|
|
1575
|
+
ReferenceTracker.READ = READ, ReferenceTracker.CALL = CALL, ReferenceTracker.CONSTRUCT = CONSTRUCT, ReferenceTracker.ESM = ESM;
|
|
1576
|
+
/**
|
|
1577
|
+
* This is a predicate function for Array#filter.
|
|
1578
|
+
* @param {string} name A name part.
|
|
1579
|
+
* @param {number} index The index of the name.
|
|
1580
|
+
* @returns {boolean} `false` if it's default.
|
|
1581
|
+
*/
|
|
1582
|
+
function exceptDefault(name, index) {
|
|
1583
|
+
return !(index === 1 && name === "default");
|
|
1584
|
+
}
|
|
1585
|
+
/** @typedef {import("./types.mjs").StaticValue} StaticValue */
|
|
1586
|
+
var index = {
|
|
1587
|
+
CALL,
|
|
1588
|
+
CONSTRUCT,
|
|
1589
|
+
ESM,
|
|
1590
|
+
findVariable,
|
|
1591
|
+
getFunctionHeadLocation,
|
|
1592
|
+
getFunctionNameWithKind,
|
|
1593
|
+
getInnermostScope,
|
|
1594
|
+
getPropertyName,
|
|
1595
|
+
getStaticValue,
|
|
1596
|
+
getStringIfConstant,
|
|
1597
|
+
hasSideEffect,
|
|
1598
|
+
isArrowToken,
|
|
1599
|
+
isClosingBraceToken,
|
|
1600
|
+
isClosingBracketToken,
|
|
1601
|
+
isClosingParenToken,
|
|
1602
|
+
isColonToken,
|
|
1603
|
+
isCommaToken,
|
|
1604
|
+
isCommentToken,
|
|
1605
|
+
isNotArrowToken,
|
|
1606
|
+
isNotClosingBraceToken,
|
|
1607
|
+
isNotClosingBracketToken,
|
|
1608
|
+
isNotClosingParenToken,
|
|
1609
|
+
isNotColonToken,
|
|
1610
|
+
isNotCommaToken,
|
|
1611
|
+
isNotCommentToken,
|
|
1612
|
+
isNotOpeningBraceToken,
|
|
1613
|
+
isNotOpeningBracketToken,
|
|
1614
|
+
isNotOpeningParenToken,
|
|
1615
|
+
isNotSemicolonToken,
|
|
1616
|
+
isOpeningBraceToken,
|
|
1617
|
+
isOpeningBracketToken,
|
|
1618
|
+
isOpeningParenToken,
|
|
1619
|
+
isParenthesized,
|
|
1620
|
+
isSemicolonToken,
|
|
1621
|
+
PatternMatcher,
|
|
1622
|
+
READ,
|
|
1623
|
+
ReferenceTracker
|
|
1624
|
+
};
|
|
1625
|
+
exports.CALL = CALL, exports.CONSTRUCT = CONSTRUCT, exports.ESM = ESM, exports.PatternMatcher = PatternMatcher, exports.READ = READ, exports.ReferenceTracker = ReferenceTracker, exports.default = index, exports.findVariable = findVariable, exports.getFunctionHeadLocation = getFunctionHeadLocation, exports.getFunctionNameWithKind = getFunctionNameWithKind, exports.getInnermostScope = getInnermostScope, exports.getPropertyName = getPropertyName, exports.getStaticValue = getStaticValue, exports.getStringIfConstant = getStringIfConstant, exports.hasSideEffect = hasSideEffect, exports.isArrowToken = isArrowToken, exports.isClosingBraceToken = isClosingBraceToken, exports.isClosingBracketToken = isClosingBracketToken, exports.isClosingParenToken = isClosingParenToken, exports.isColonToken = isColonToken, exports.isCommaToken = isCommaToken, exports.isCommentToken = isCommentToken, exports.isNotArrowToken = isNotArrowToken, exports.isNotClosingBraceToken = isNotClosingBraceToken, exports.isNotClosingBracketToken = isNotClosingBracketToken, exports.isNotClosingParenToken = isNotClosingParenToken, exports.isNotColonToken = isNotColonToken, exports.isNotCommaToken = isNotCommaToken, exports.isNotCommentToken = isNotCommentToken, exports.isNotOpeningBraceToken = isNotOpeningBraceToken, exports.isNotOpeningBracketToken = isNotOpeningBracketToken, exports.isNotOpeningParenToken = isNotOpeningParenToken, exports.isNotSemicolonToken = isNotSemicolonToken, exports.isOpeningBraceToken = isOpeningBraceToken, exports.isOpeningBracketToken = isOpeningBracketToken, exports.isOpeningParenToken = isOpeningParenToken, exports.isParenthesized = isParenthesized, exports.isSemicolonToken = isSemicolonToken;
|
|
1626
|
+
}));
|
|
1627
|
+
//#endregion
|
|
1628
|
+
Object.defineProperty(exports, "t", {
|
|
1629
|
+
enumerable: !0,
|
|
1630
|
+
get: function() {
|
|
1631
|
+
return require_eslint_utils;
|
|
1632
|
+
}
|
|
1633
|
+
});
|