@eslint-react/var 1.23.1-beta.2 → 1.23.1-beta.6
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/dist/index.d.mts +46 -457
- package/dist/index.d.ts +46 -457
- package/dist/index.js +117 -125
- package/dist/index.mjs +116 -123
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var AST2 = require('@eslint-react/ast');
|
|
4
3
|
var eff = require('@eslint-react/eff');
|
|
4
|
+
var ASTUtils = require('@typescript-eslint/utils/ast-utils');
|
|
5
5
|
var types = require('@typescript-eslint/types');
|
|
6
|
-
var
|
|
6
|
+
var AST3 = require('@eslint-react/ast');
|
|
7
7
|
var scopeManager = require('@typescript-eslint/scope-manager');
|
|
8
|
-
var
|
|
8
|
+
var tsPattern = require('ts-pattern');
|
|
9
9
|
|
|
10
10
|
function _interopNamespace(e) {
|
|
11
11
|
if (e && e.__esModule) return e;
|
|
@@ -25,117 +25,10 @@ function _interopNamespace(e) {
|
|
|
25
25
|
return Object.freeze(n);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
var AST2__namespace = /*#__PURE__*/_interopNamespace(AST2);
|
|
29
28
|
var ASTUtils__namespace = /*#__PURE__*/_interopNamespace(ASTUtils);
|
|
29
|
+
var AST3__namespace = /*#__PURE__*/_interopNamespace(AST3);
|
|
30
30
|
|
|
31
|
-
// src/
|
|
32
|
-
function getVariableNode(at) {
|
|
33
|
-
return (variable) => {
|
|
34
|
-
return eff.F.pipe(
|
|
35
|
-
eff.O.some(variable),
|
|
36
|
-
eff.O.flatMapNullable((v) => v.defs.at(at)),
|
|
37
|
-
eff.O.flatMapNullable((def) => {
|
|
38
|
-
switch (true) {
|
|
39
|
-
case (def.type === scopeManager.DefinitionType.FunctionName && def.node.type === types.AST_NODE_TYPES.FunctionDeclaration):
|
|
40
|
-
return def.node;
|
|
41
|
-
case (def.type === scopeManager.DefinitionType.ClassName && def.node.type === types.AST_NODE_TYPES.ClassDeclaration):
|
|
42
|
-
return def.node;
|
|
43
|
-
case (def.type === scopeManager.DefinitionType.Parameter && AST2__namespace.isFunction(def.node)):
|
|
44
|
-
return def.node;
|
|
45
|
-
case ("init" in def.node && def.node.init && !("declarations" in def.node.init)):
|
|
46
|
-
return def.node.init;
|
|
47
|
-
default:
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
);
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// src/construction.ts
|
|
56
|
-
var Construction = eff.Data.taggedEnum();
|
|
57
|
-
var ConstructionHint = {
|
|
58
|
-
None: 0n,
|
|
59
|
-
StrictCallExpression: 1n << 0n
|
|
60
|
-
};
|
|
61
|
-
function inspectConstruction(node, initialScope, hint = ConstructionHint.None) {
|
|
62
|
-
const detect = (node2) => {
|
|
63
|
-
return tsPattern.match(node2).when(AST2__namespace.is(types.AST_NODE_TYPES.ArrayExpression), (node3) => Construction.Array({ node: node3, usage: eff.O.none() })).when(AST2__namespace.is(types.AST_NODE_TYPES.ObjectExpression), (node3) => Construction.ObjectExpression({ node: node3, usage: eff.O.none() })).when(AST2__namespace.is(types.AST_NODE_TYPES.ClassExpression), (node3) => Construction.ClassExpression({ node: node3, usage: eff.O.none() })).when(AST2__namespace.is(types.AST_NODE_TYPES.JSXElement), (node3) => Construction.JSXElement({ node: node3, usage: eff.O.none() })).when(AST2__namespace.is(types.AST_NODE_TYPES.JSXFragment), (node3) => Construction.JSXFragment({ node: node3, usage: eff.O.none() })).when(AST2__namespace.is(types.AST_NODE_TYPES.CallExpression), (node3) => {
|
|
64
|
-
if (hint & ConstructionHint.StrictCallExpression) {
|
|
65
|
-
return Construction.CallExpression({ node: node3, usage: eff.O.none() });
|
|
66
|
-
}
|
|
67
|
-
return Construction.None({ node: node3, usage: eff.O.none() });
|
|
68
|
-
}).when(AST2__namespace.is(types.AST_NODE_TYPES.NewExpression), (node3) => Construction.NewExpression({ node: node3, usage: eff.O.none() })).when(
|
|
69
|
-
AST2__namespace.isOneOf([
|
|
70
|
-
types.AST_NODE_TYPES.FunctionExpression,
|
|
71
|
-
types.AST_NODE_TYPES.ArrowFunctionExpression
|
|
72
|
-
]),
|
|
73
|
-
(node3) => {
|
|
74
|
-
return Construction.FunctionExpression({ node: node3, usage: eff.O.none() });
|
|
75
|
-
}
|
|
76
|
-
).when(AST2__namespace.is(types.AST_NODE_TYPES.MemberExpression), (node3) => {
|
|
77
|
-
if (!("object" in node3)) return Construction.None({ node: node3, usage: eff.O.none() });
|
|
78
|
-
const object = detect(node3.object);
|
|
79
|
-
if (object._tag === "None") return object;
|
|
80
|
-
return {
|
|
81
|
-
...object,
|
|
82
|
-
usage: eff.O.some(node3.object)
|
|
83
|
-
};
|
|
84
|
-
}).when(AST2__namespace.is(types.AST_NODE_TYPES.AssignmentExpression), (node3) => {
|
|
85
|
-
if (!("right" in node3)) return Construction.None({ node: node3, usage: eff.O.none() });
|
|
86
|
-
const right = detect(node3.right);
|
|
87
|
-
if (right._tag === "None") return right;
|
|
88
|
-
return Construction.AssignmentExpression({
|
|
89
|
-
node: right.node,
|
|
90
|
-
usage: eff.O.some(node3)
|
|
91
|
-
});
|
|
92
|
-
}).when(AST2__namespace.is(types.AST_NODE_TYPES.AssignmentPattern), (node3) => {
|
|
93
|
-
if (!("right" in node3)) return Construction.None({ node: node3, usage: eff.O.none() });
|
|
94
|
-
const right = detect(node3.right);
|
|
95
|
-
if (right._tag === "None") return right;
|
|
96
|
-
return Construction.AssignmentPattern({
|
|
97
|
-
node: right.node,
|
|
98
|
-
usage: eff.O.some(node3)
|
|
99
|
-
});
|
|
100
|
-
}).when(AST2__namespace.is(types.AST_NODE_TYPES.LogicalExpression), (node3) => {
|
|
101
|
-
if (!("left" in node3 && "right" in node3)) return Construction.None({ node: node3, usage: eff.O.none() });
|
|
102
|
-
const left = detect(node3.left);
|
|
103
|
-
if (left._tag !== "None") return left;
|
|
104
|
-
return detect(node3.right);
|
|
105
|
-
}).when(AST2__namespace.is(types.AST_NODE_TYPES.ConditionalExpression), (node3) => {
|
|
106
|
-
if (!("consequent" in node3 && "alternate" in node3 && !eff.isNullable(node3.alternate))) {
|
|
107
|
-
return Construction.None({ node: node3, usage: eff.O.none() });
|
|
108
|
-
}
|
|
109
|
-
const consequent = detect(node3.consequent);
|
|
110
|
-
if (consequent._tag !== "None") return Construction.None({ node: node3, usage: eff.O.none() });
|
|
111
|
-
return detect(node3.alternate);
|
|
112
|
-
}).when(AST2__namespace.is(types.AST_NODE_TYPES.Identifier), (node3) => {
|
|
113
|
-
if (!("name" in node3 && eff.isString(node3.name))) return Construction.None({ node: node3, usage: eff.O.none() });
|
|
114
|
-
const construction = eff.F.pipe(
|
|
115
|
-
eff.O.fromNullable(initialScope.set.get(node3.name)),
|
|
116
|
-
eff.O.flatMap(getVariableNode(-1)),
|
|
117
|
-
eff.O.map(detect),
|
|
118
|
-
eff.O.filter(eff.not(Construction.$is("None")))
|
|
119
|
-
);
|
|
120
|
-
if (eff.O.isNone(construction)) return Construction.None({ node: node3, usage: eff.O.none() });
|
|
121
|
-
return {
|
|
122
|
-
...construction.value,
|
|
123
|
-
usage: eff.O.some(node3)
|
|
124
|
-
};
|
|
125
|
-
}).when(AST2__namespace.is(types.AST_NODE_TYPES.Literal), (node3) => {
|
|
126
|
-
if ("regex" in node3) {
|
|
127
|
-
return Construction.RegExpLiteral({ node: node3, usage: eff.O.none() });
|
|
128
|
-
}
|
|
129
|
-
return Construction.None({ node: node3, usage: eff.O.none() });
|
|
130
|
-
}).when(AST2__namespace.isTypeExpression, () => {
|
|
131
|
-
if (!("expression" in node2) || !eff.isObject(node2.expression)) {
|
|
132
|
-
return Construction.None({ node: node2, usage: eff.O.none() });
|
|
133
|
-
}
|
|
134
|
-
return detect(node2.expression);
|
|
135
|
-
}).otherwise(() => Construction.None({ node: node2, usage: eff.O.none() }));
|
|
136
|
-
};
|
|
137
|
-
return detect(node);
|
|
138
|
-
}
|
|
31
|
+
// src/find-variable.ts
|
|
139
32
|
var findVariable2 = eff.F.dual(2, (nameOrNode, initialScope) => {
|
|
140
33
|
return eff.O.fromNullable(ASTUtils__namespace.findVariable(initialScope, nameOrNode));
|
|
141
34
|
});
|
|
@@ -170,6 +63,28 @@ function getVariableDeclaratorID(node, prev) {
|
|
|
170
63
|
return getVariableDeclaratorID(node.parent, node);
|
|
171
64
|
}
|
|
172
65
|
}
|
|
66
|
+
function getVariableNode(at) {
|
|
67
|
+
return (variable) => {
|
|
68
|
+
return eff.F.pipe(
|
|
69
|
+
eff.O.some(variable),
|
|
70
|
+
eff.O.flatMapNullable((v) => v.defs.at(at)),
|
|
71
|
+
eff.O.flatMapNullable((def) => {
|
|
72
|
+
switch (true) {
|
|
73
|
+
case (def.type === scopeManager.DefinitionType.FunctionName && def.node.type === types.AST_NODE_TYPES.FunctionDeclaration):
|
|
74
|
+
return def.node;
|
|
75
|
+
case (def.type === scopeManager.DefinitionType.ClassName && def.node.type === types.AST_NODE_TYPES.ClassDeclaration):
|
|
76
|
+
return def.node;
|
|
77
|
+
case (def.type === scopeManager.DefinitionType.Parameter && AST3__namespace.isFunction(def.node)):
|
|
78
|
+
return def.node;
|
|
79
|
+
case ("init" in def.node && def.node.init && !("declarations" in def.node.init)):
|
|
80
|
+
return def.node.init;
|
|
81
|
+
default:
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
}
|
|
173
88
|
function getVariables(initialScope) {
|
|
174
89
|
let scope = initialScope;
|
|
175
90
|
const variables = [...scope.variables];
|
|
@@ -194,7 +109,7 @@ function isInitializedFromSource(name, source, initialScope) {
|
|
|
194
109
|
return eff.F.pipe(
|
|
195
110
|
getRequireExpressionArguments(init),
|
|
196
111
|
eff.O.flatMapNullable((args) => args[0]),
|
|
197
|
-
eff.O.filter(
|
|
112
|
+
eff.O.filter(AST3__namespace.isStringLiteral),
|
|
198
113
|
// check for: `require('source')` or `require('source/...')`
|
|
199
114
|
eff.O.exists((arg) => arg.value === source || arg.value.startsWith(`${source}/`))
|
|
200
115
|
);
|
|
@@ -244,25 +159,25 @@ function isNodeValueEqual(a, b, initialScopes) {
|
|
|
244
159
|
const aDefParentParent = eff.O.flatMapNullable(aDef, (d) => d.parent?.parent);
|
|
245
160
|
const bDefParentParent = eff.O.flatMapNullable(bDef, (d) => d.parent?.parent);
|
|
246
161
|
switch (true) {
|
|
247
|
-
case (eff.O.exists(aVarNodeParent,
|
|
162
|
+
case (eff.O.exists(aVarNodeParent, AST3__namespace.is(types.AST_NODE_TYPES.CallExpression)) && eff.O.exists(bVarNodeParent, AST3__namespace.is(types.AST_NODE_TYPES.CallExpression)) && eff.O.exists(aVarNode, AST3__namespace.isFunction) && eff.O.exists(bVarNode, AST3__namespace.isFunction)): {
|
|
248
163
|
const hasSameCallee = eff.F.pipe(
|
|
249
164
|
eff.O.Do,
|
|
250
165
|
eff.O.bind("aCallee", () => eff.O.map(aVarNodeParent, (n) => n.callee)),
|
|
251
166
|
eff.O.bind("bCallee", () => eff.O.map(bVarNodeParent, (n) => n.callee)),
|
|
252
|
-
eff.O.exists(({ aCallee, bCallee }) =>
|
|
167
|
+
eff.O.exists(({ aCallee, bCallee }) => AST3__namespace.isNodeEqual(aCallee, bCallee))
|
|
253
168
|
);
|
|
254
169
|
if (!hasSameCallee) return false;
|
|
255
170
|
return eff.F.pipe(
|
|
256
171
|
eff.O.Do,
|
|
257
172
|
eff.O.bind("aParams", () => eff.O.map(aVarNode, (n) => n.params)),
|
|
258
173
|
eff.O.bind("bParams", () => eff.O.map(bVarNode, (n) => n.params)),
|
|
259
|
-
eff.O.let("aPos", ({ aParams }) => aParams.findIndex(
|
|
260
|
-
eff.O.let("bPos", ({ bParams }) => bParams.findIndex(
|
|
174
|
+
eff.O.let("aPos", ({ aParams }) => aParams.findIndex(AST3__namespace.isNodeEqual(a))),
|
|
175
|
+
eff.O.let("bPos", ({ bParams }) => bParams.findIndex(AST3__namespace.isNodeEqual(b))),
|
|
261
176
|
eff.O.filter(({ aPos, bPos }) => aPos !== -1 && bPos !== -1),
|
|
262
177
|
eff.O.exists(({ aPos, bPos }) => aPos === bPos)
|
|
263
178
|
);
|
|
264
179
|
}
|
|
265
|
-
case (eff.O.exists(aDefParentParent,
|
|
180
|
+
case (eff.O.exists(aDefParentParent, AST3__namespace.is(types.AST_NODE_TYPES.ForOfStatement)) && eff.O.exists(bDefParentParent, AST3__namespace.is(types.AST_NODE_TYPES.ForOfStatement))): {
|
|
266
181
|
return eff.F.pipe(
|
|
267
182
|
eff.O.Do,
|
|
268
183
|
eff.O.bind("aLeft", () => eff.O.map(aDefParentParent, (d) => d.left)),
|
|
@@ -270,7 +185,7 @@ function isNodeValueEqual(a, b, initialScopes) {
|
|
|
270
185
|
eff.O.filter(({ aLeft, bLeft }) => aLeft.type === bLeft.type),
|
|
271
186
|
eff.O.bind("aRight", () => eff.O.map(aDefParentParent, (d) => d.right)),
|
|
272
187
|
eff.O.bind("bRight", () => eff.O.map(bDefParentParent, (d) => d.right)),
|
|
273
|
-
eff.O.exists(({ aRight, bRight }) =>
|
|
188
|
+
eff.O.exists(({ aRight, bRight }) => AST3__namespace.isNodeEqual(aRight, bRight))
|
|
274
189
|
);
|
|
275
190
|
}
|
|
276
191
|
default: {
|
|
@@ -279,14 +194,14 @@ function isNodeValueEqual(a, b, initialScopes) {
|
|
|
279
194
|
}
|
|
280
195
|
}
|
|
281
196
|
case (a.type === types.AST_NODE_TYPES.MemberExpression && b.type === types.AST_NODE_TYPES.MemberExpression): {
|
|
282
|
-
return
|
|
197
|
+
return AST3__namespace.isNodeEqual(a.property, b.property) && isNodeValueEqual(a.object, b.object, initialScopes);
|
|
283
198
|
}
|
|
284
199
|
case (a.type === types.AST_NODE_TYPES.ThisExpression && b.type === types.AST_NODE_TYPES.ThisExpression): {
|
|
285
200
|
if (aScope.block === bScope.block) return true;
|
|
286
201
|
return eff.F.pipe(
|
|
287
202
|
eff.O.Do,
|
|
288
|
-
eff.O.bind("aFunction", () =>
|
|
289
|
-
eff.O.bind("bFunction", () =>
|
|
203
|
+
eff.O.bind("aFunction", () => AST3__namespace.traverseUp(a, AST3__namespace.isOneOf(thisBlockTypes))),
|
|
204
|
+
eff.O.bind("bFunction", () => AST3__namespace.traverseUp(b, AST3__namespace.isOneOf(thisBlockTypes))),
|
|
290
205
|
eff.O.exists(({ aFunction, bFunction }) => aFunction === bFunction)
|
|
291
206
|
);
|
|
292
207
|
}
|
|
@@ -300,16 +215,93 @@ function isNodeValueEqual(a, b, initialScopes) {
|
|
|
300
215
|
}
|
|
301
216
|
}
|
|
302
217
|
}
|
|
218
|
+
var ValueConstructionHint = {
|
|
219
|
+
None: 0n,
|
|
220
|
+
StrictCallExpression: 1n << 0n
|
|
221
|
+
};
|
|
222
|
+
function getValueConstruction(node, initialScope, hint = ValueConstructionHint.None) {
|
|
223
|
+
switch (node.type) {
|
|
224
|
+
case types.AST_NODE_TYPES.JSXElement:
|
|
225
|
+
case types.AST_NODE_TYPES.JSXFragment: {
|
|
226
|
+
return { kind: "JSXElement", node };
|
|
227
|
+
}
|
|
228
|
+
case types.AST_NODE_TYPES.ArrayExpression: {
|
|
229
|
+
return { kind: "ArrayExpression", node };
|
|
230
|
+
}
|
|
231
|
+
case types.AST_NODE_TYPES.ObjectExpression: {
|
|
232
|
+
return { kind: "ObjectExpression", node };
|
|
233
|
+
}
|
|
234
|
+
case types.AST_NODE_TYPES.ClassExpression: {
|
|
235
|
+
return { kind: "ClassExpression", node };
|
|
236
|
+
}
|
|
237
|
+
case types.AST_NODE_TYPES.NewExpression: {
|
|
238
|
+
return { kind: "NewExpression", node };
|
|
239
|
+
}
|
|
240
|
+
case types.AST_NODE_TYPES.FunctionExpression:
|
|
241
|
+
case types.AST_NODE_TYPES.ArrowFunctionExpression: {
|
|
242
|
+
return { kind: "FunctionExpression", node };
|
|
243
|
+
}
|
|
244
|
+
case types.AST_NODE_TYPES.CallExpression: {
|
|
245
|
+
if (hint & ValueConstructionHint.StrictCallExpression) {
|
|
246
|
+
return { kind: "CallExpression", node };
|
|
247
|
+
}
|
|
248
|
+
return { kind: "None", node };
|
|
249
|
+
}
|
|
250
|
+
case types.AST_NODE_TYPES.MemberExpression: {
|
|
251
|
+
if (!("object" in node)) return { kind: "None", node };
|
|
252
|
+
return getValueConstruction(node.object, initialScope, hint);
|
|
253
|
+
}
|
|
254
|
+
case types.AST_NODE_TYPES.AssignmentExpression:
|
|
255
|
+
case types.AST_NODE_TYPES.AssignmentPattern: {
|
|
256
|
+
if (!("right" in node)) return { kind: "None", node };
|
|
257
|
+
return getValueConstruction(node.right, initialScope, hint);
|
|
258
|
+
}
|
|
259
|
+
case types.AST_NODE_TYPES.LogicalExpression: {
|
|
260
|
+
const lvc = getValueConstruction(node.left, initialScope, hint);
|
|
261
|
+
if (lvc.kind !== "None") return lvc;
|
|
262
|
+
return getValueConstruction(node.right, initialScope, hint);
|
|
263
|
+
}
|
|
264
|
+
case types.AST_NODE_TYPES.ConditionalExpression: {
|
|
265
|
+
const cvc = getValueConstruction(node.consequent, initialScope, hint);
|
|
266
|
+
if (cvc.kind !== "None") return cvc;
|
|
267
|
+
return getValueConstruction(node.alternate, initialScope, hint);
|
|
268
|
+
}
|
|
269
|
+
case types.AST_NODE_TYPES.Identifier: {
|
|
270
|
+
if (!("name" in node && eff.isString(node.name))) return { kind: "None", node };
|
|
271
|
+
const construction = eff.F.pipe(
|
|
272
|
+
eff.O.fromNullable(initialScope.set.get(node.name)),
|
|
273
|
+
eff.O.flatMap(getVariableNode(-1)),
|
|
274
|
+
eff.O.map((node2) => getValueConstruction(node2, initialScope, hint)),
|
|
275
|
+
eff.O.filter((vc) => vc.kind !== "None")
|
|
276
|
+
);
|
|
277
|
+
if (eff.O.isNone(construction)) return { kind: "None", node };
|
|
278
|
+
return {
|
|
279
|
+
...construction.value
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
case types.AST_NODE_TYPES.Literal: {
|
|
283
|
+
if ("regex" in node) {
|
|
284
|
+
return { kind: "RegExpLiteral", node };
|
|
285
|
+
}
|
|
286
|
+
return { kind: "None", node };
|
|
287
|
+
}
|
|
288
|
+
default: {
|
|
289
|
+
if (!("expression" in node && eff.isObject(node.expression))) {
|
|
290
|
+
return { kind: "None", node };
|
|
291
|
+
}
|
|
292
|
+
return getValueConstruction(node.expression, initialScope, hint);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
303
296
|
|
|
304
|
-
exports.
|
|
305
|
-
exports.ConstructionHint = ConstructionHint;
|
|
297
|
+
exports.ValueConstructionHint = ValueConstructionHint;
|
|
306
298
|
exports.findVariable = findVariable2;
|
|
307
299
|
exports.getChidScopes = getChidScopes;
|
|
308
300
|
exports.getScope = getScope;
|
|
309
301
|
exports.getStaticValue = getStaticValue2;
|
|
302
|
+
exports.getValueConstruction = getValueConstruction;
|
|
310
303
|
exports.getVariableDeclaratorID = getVariableDeclaratorID;
|
|
311
304
|
exports.getVariableNode = getVariableNode;
|
|
312
305
|
exports.getVariables = getVariables;
|
|
313
|
-
exports.inspectConstruction = inspectConstruction;
|
|
314
306
|
exports.isInitializedFromSource = isInitializedFromSource;
|
|
315
307
|
exports.isNodeValueEqual = isNodeValueEqual;
|
package/dist/index.mjs
CHANGED
|
@@ -1,118 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { F, O, Equal, isObject, isString } from '@eslint-react/eff';
|
|
2
|
+
import * as ASTUtils from '@typescript-eslint/utils/ast-utils';
|
|
3
3
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
4
|
-
import
|
|
4
|
+
import * as AST3 from '@eslint-react/ast';
|
|
5
5
|
import { DefinitionType, ScopeType } from '@typescript-eslint/scope-manager';
|
|
6
|
-
import
|
|
6
|
+
import { isMatching } from 'ts-pattern';
|
|
7
7
|
|
|
8
|
-
// src/
|
|
9
|
-
function getVariableNode(at) {
|
|
10
|
-
return (variable) => {
|
|
11
|
-
return F.pipe(
|
|
12
|
-
O.some(variable),
|
|
13
|
-
O.flatMapNullable((v) => v.defs.at(at)),
|
|
14
|
-
O.flatMapNullable((def) => {
|
|
15
|
-
switch (true) {
|
|
16
|
-
case (def.type === DefinitionType.FunctionName && def.node.type === AST_NODE_TYPES.FunctionDeclaration):
|
|
17
|
-
return def.node;
|
|
18
|
-
case (def.type === DefinitionType.ClassName && def.node.type === AST_NODE_TYPES.ClassDeclaration):
|
|
19
|
-
return def.node;
|
|
20
|
-
case (def.type === DefinitionType.Parameter && AST2.isFunction(def.node)):
|
|
21
|
-
return def.node;
|
|
22
|
-
case ("init" in def.node && def.node.init && !("declarations" in def.node.init)):
|
|
23
|
-
return def.node.init;
|
|
24
|
-
default:
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
);
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// src/construction.ts
|
|
33
|
-
var Construction = Data.taggedEnum();
|
|
34
|
-
var ConstructionHint = {
|
|
35
|
-
None: 0n,
|
|
36
|
-
StrictCallExpression: 1n << 0n
|
|
37
|
-
};
|
|
38
|
-
function inspectConstruction(node, initialScope, hint = ConstructionHint.None) {
|
|
39
|
-
const detect = (node2) => {
|
|
40
|
-
return match(node2).when(AST2.is(AST_NODE_TYPES.ArrayExpression), (node3) => Construction.Array({ node: node3, usage: O.none() })).when(AST2.is(AST_NODE_TYPES.ObjectExpression), (node3) => Construction.ObjectExpression({ node: node3, usage: O.none() })).when(AST2.is(AST_NODE_TYPES.ClassExpression), (node3) => Construction.ClassExpression({ node: node3, usage: O.none() })).when(AST2.is(AST_NODE_TYPES.JSXElement), (node3) => Construction.JSXElement({ node: node3, usage: O.none() })).when(AST2.is(AST_NODE_TYPES.JSXFragment), (node3) => Construction.JSXFragment({ node: node3, usage: O.none() })).when(AST2.is(AST_NODE_TYPES.CallExpression), (node3) => {
|
|
41
|
-
if (hint & ConstructionHint.StrictCallExpression) {
|
|
42
|
-
return Construction.CallExpression({ node: node3, usage: O.none() });
|
|
43
|
-
}
|
|
44
|
-
return Construction.None({ node: node3, usage: O.none() });
|
|
45
|
-
}).when(AST2.is(AST_NODE_TYPES.NewExpression), (node3) => Construction.NewExpression({ node: node3, usage: O.none() })).when(
|
|
46
|
-
AST2.isOneOf([
|
|
47
|
-
AST_NODE_TYPES.FunctionExpression,
|
|
48
|
-
AST_NODE_TYPES.ArrowFunctionExpression
|
|
49
|
-
]),
|
|
50
|
-
(node3) => {
|
|
51
|
-
return Construction.FunctionExpression({ node: node3, usage: O.none() });
|
|
52
|
-
}
|
|
53
|
-
).when(AST2.is(AST_NODE_TYPES.MemberExpression), (node3) => {
|
|
54
|
-
if (!("object" in node3)) return Construction.None({ node: node3, usage: O.none() });
|
|
55
|
-
const object = detect(node3.object);
|
|
56
|
-
if (object._tag === "None") return object;
|
|
57
|
-
return {
|
|
58
|
-
...object,
|
|
59
|
-
usage: O.some(node3.object)
|
|
60
|
-
};
|
|
61
|
-
}).when(AST2.is(AST_NODE_TYPES.AssignmentExpression), (node3) => {
|
|
62
|
-
if (!("right" in node3)) return Construction.None({ node: node3, usage: O.none() });
|
|
63
|
-
const right = detect(node3.right);
|
|
64
|
-
if (right._tag === "None") return right;
|
|
65
|
-
return Construction.AssignmentExpression({
|
|
66
|
-
node: right.node,
|
|
67
|
-
usage: O.some(node3)
|
|
68
|
-
});
|
|
69
|
-
}).when(AST2.is(AST_NODE_TYPES.AssignmentPattern), (node3) => {
|
|
70
|
-
if (!("right" in node3)) return Construction.None({ node: node3, usage: O.none() });
|
|
71
|
-
const right = detect(node3.right);
|
|
72
|
-
if (right._tag === "None") return right;
|
|
73
|
-
return Construction.AssignmentPattern({
|
|
74
|
-
node: right.node,
|
|
75
|
-
usage: O.some(node3)
|
|
76
|
-
});
|
|
77
|
-
}).when(AST2.is(AST_NODE_TYPES.LogicalExpression), (node3) => {
|
|
78
|
-
if (!("left" in node3 && "right" in node3)) return Construction.None({ node: node3, usage: O.none() });
|
|
79
|
-
const left = detect(node3.left);
|
|
80
|
-
if (left._tag !== "None") return left;
|
|
81
|
-
return detect(node3.right);
|
|
82
|
-
}).when(AST2.is(AST_NODE_TYPES.ConditionalExpression), (node3) => {
|
|
83
|
-
if (!("consequent" in node3 && "alternate" in node3 && !isNullable(node3.alternate))) {
|
|
84
|
-
return Construction.None({ node: node3, usage: O.none() });
|
|
85
|
-
}
|
|
86
|
-
const consequent = detect(node3.consequent);
|
|
87
|
-
if (consequent._tag !== "None") return Construction.None({ node: node3, usage: O.none() });
|
|
88
|
-
return detect(node3.alternate);
|
|
89
|
-
}).when(AST2.is(AST_NODE_TYPES.Identifier), (node3) => {
|
|
90
|
-
if (!("name" in node3 && isString(node3.name))) return Construction.None({ node: node3, usage: O.none() });
|
|
91
|
-
const construction = F.pipe(
|
|
92
|
-
O.fromNullable(initialScope.set.get(node3.name)),
|
|
93
|
-
O.flatMap(getVariableNode(-1)),
|
|
94
|
-
O.map(detect),
|
|
95
|
-
O.filter(not(Construction.$is("None")))
|
|
96
|
-
);
|
|
97
|
-
if (O.isNone(construction)) return Construction.None({ node: node3, usage: O.none() });
|
|
98
|
-
return {
|
|
99
|
-
...construction.value,
|
|
100
|
-
usage: O.some(node3)
|
|
101
|
-
};
|
|
102
|
-
}).when(AST2.is(AST_NODE_TYPES.Literal), (node3) => {
|
|
103
|
-
if ("regex" in node3) {
|
|
104
|
-
return Construction.RegExpLiteral({ node: node3, usage: O.none() });
|
|
105
|
-
}
|
|
106
|
-
return Construction.None({ node: node3, usage: O.none() });
|
|
107
|
-
}).when(AST2.isTypeExpression, () => {
|
|
108
|
-
if (!("expression" in node2) || !isObject(node2.expression)) {
|
|
109
|
-
return Construction.None({ node: node2, usage: O.none() });
|
|
110
|
-
}
|
|
111
|
-
return detect(node2.expression);
|
|
112
|
-
}).otherwise(() => Construction.None({ node: node2, usage: O.none() }));
|
|
113
|
-
};
|
|
114
|
-
return detect(node);
|
|
115
|
-
}
|
|
8
|
+
// src/find-variable.ts
|
|
116
9
|
var findVariable2 = F.dual(2, (nameOrNode, initialScope) => {
|
|
117
10
|
return O.fromNullable(ASTUtils.findVariable(initialScope, nameOrNode));
|
|
118
11
|
});
|
|
@@ -147,6 +40,28 @@ function getVariableDeclaratorID(node, prev) {
|
|
|
147
40
|
return getVariableDeclaratorID(node.parent, node);
|
|
148
41
|
}
|
|
149
42
|
}
|
|
43
|
+
function getVariableNode(at) {
|
|
44
|
+
return (variable) => {
|
|
45
|
+
return F.pipe(
|
|
46
|
+
O.some(variable),
|
|
47
|
+
O.flatMapNullable((v) => v.defs.at(at)),
|
|
48
|
+
O.flatMapNullable((def) => {
|
|
49
|
+
switch (true) {
|
|
50
|
+
case (def.type === DefinitionType.FunctionName && def.node.type === AST_NODE_TYPES.FunctionDeclaration):
|
|
51
|
+
return def.node;
|
|
52
|
+
case (def.type === DefinitionType.ClassName && def.node.type === AST_NODE_TYPES.ClassDeclaration):
|
|
53
|
+
return def.node;
|
|
54
|
+
case (def.type === DefinitionType.Parameter && AST3.isFunction(def.node)):
|
|
55
|
+
return def.node;
|
|
56
|
+
case ("init" in def.node && def.node.init && !("declarations" in def.node.init)):
|
|
57
|
+
return def.node.init;
|
|
58
|
+
default:
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
150
65
|
function getVariables(initialScope) {
|
|
151
66
|
let scope = initialScope;
|
|
152
67
|
const variables = [...scope.variables];
|
|
@@ -171,7 +86,7 @@ function isInitializedFromSource(name, source, initialScope) {
|
|
|
171
86
|
return F.pipe(
|
|
172
87
|
getRequireExpressionArguments(init),
|
|
173
88
|
O.flatMapNullable((args) => args[0]),
|
|
174
|
-
O.filter(
|
|
89
|
+
O.filter(AST3.isStringLiteral),
|
|
175
90
|
// check for: `require('source')` or `require('source/...')`
|
|
176
91
|
O.exists((arg) => arg.value === source || arg.value.startsWith(`${source}/`))
|
|
177
92
|
);
|
|
@@ -221,25 +136,25 @@ function isNodeValueEqual(a, b, initialScopes) {
|
|
|
221
136
|
const aDefParentParent = O.flatMapNullable(aDef, (d) => d.parent?.parent);
|
|
222
137
|
const bDefParentParent = O.flatMapNullable(bDef, (d) => d.parent?.parent);
|
|
223
138
|
switch (true) {
|
|
224
|
-
case (O.exists(aVarNodeParent,
|
|
139
|
+
case (O.exists(aVarNodeParent, AST3.is(AST_NODE_TYPES.CallExpression)) && O.exists(bVarNodeParent, AST3.is(AST_NODE_TYPES.CallExpression)) && O.exists(aVarNode, AST3.isFunction) && O.exists(bVarNode, AST3.isFunction)): {
|
|
225
140
|
const hasSameCallee = F.pipe(
|
|
226
141
|
O.Do,
|
|
227
142
|
O.bind("aCallee", () => O.map(aVarNodeParent, (n) => n.callee)),
|
|
228
143
|
O.bind("bCallee", () => O.map(bVarNodeParent, (n) => n.callee)),
|
|
229
|
-
O.exists(({ aCallee, bCallee }) =>
|
|
144
|
+
O.exists(({ aCallee, bCallee }) => AST3.isNodeEqual(aCallee, bCallee))
|
|
230
145
|
);
|
|
231
146
|
if (!hasSameCallee) return false;
|
|
232
147
|
return F.pipe(
|
|
233
148
|
O.Do,
|
|
234
149
|
O.bind("aParams", () => O.map(aVarNode, (n) => n.params)),
|
|
235
150
|
O.bind("bParams", () => O.map(bVarNode, (n) => n.params)),
|
|
236
|
-
O.let("aPos", ({ aParams }) => aParams.findIndex(
|
|
237
|
-
O.let("bPos", ({ bParams }) => bParams.findIndex(
|
|
151
|
+
O.let("aPos", ({ aParams }) => aParams.findIndex(AST3.isNodeEqual(a))),
|
|
152
|
+
O.let("bPos", ({ bParams }) => bParams.findIndex(AST3.isNodeEqual(b))),
|
|
238
153
|
O.filter(({ aPos, bPos }) => aPos !== -1 && bPos !== -1),
|
|
239
154
|
O.exists(({ aPos, bPos }) => aPos === bPos)
|
|
240
155
|
);
|
|
241
156
|
}
|
|
242
|
-
case (O.exists(aDefParentParent,
|
|
157
|
+
case (O.exists(aDefParentParent, AST3.is(AST_NODE_TYPES.ForOfStatement)) && O.exists(bDefParentParent, AST3.is(AST_NODE_TYPES.ForOfStatement))): {
|
|
243
158
|
return F.pipe(
|
|
244
159
|
O.Do,
|
|
245
160
|
O.bind("aLeft", () => O.map(aDefParentParent, (d) => d.left)),
|
|
@@ -247,7 +162,7 @@ function isNodeValueEqual(a, b, initialScopes) {
|
|
|
247
162
|
O.filter(({ aLeft, bLeft }) => aLeft.type === bLeft.type),
|
|
248
163
|
O.bind("aRight", () => O.map(aDefParentParent, (d) => d.right)),
|
|
249
164
|
O.bind("bRight", () => O.map(bDefParentParent, (d) => d.right)),
|
|
250
|
-
O.exists(({ aRight, bRight }) =>
|
|
165
|
+
O.exists(({ aRight, bRight }) => AST3.isNodeEqual(aRight, bRight))
|
|
251
166
|
);
|
|
252
167
|
}
|
|
253
168
|
default: {
|
|
@@ -256,14 +171,14 @@ function isNodeValueEqual(a, b, initialScopes) {
|
|
|
256
171
|
}
|
|
257
172
|
}
|
|
258
173
|
case (a.type === AST_NODE_TYPES.MemberExpression && b.type === AST_NODE_TYPES.MemberExpression): {
|
|
259
|
-
return
|
|
174
|
+
return AST3.isNodeEqual(a.property, b.property) && isNodeValueEqual(a.object, b.object, initialScopes);
|
|
260
175
|
}
|
|
261
176
|
case (a.type === AST_NODE_TYPES.ThisExpression && b.type === AST_NODE_TYPES.ThisExpression): {
|
|
262
177
|
if (aScope.block === bScope.block) return true;
|
|
263
178
|
return F.pipe(
|
|
264
179
|
O.Do,
|
|
265
|
-
O.bind("aFunction", () =>
|
|
266
|
-
O.bind("bFunction", () =>
|
|
180
|
+
O.bind("aFunction", () => AST3.traverseUp(a, AST3.isOneOf(thisBlockTypes))),
|
|
181
|
+
O.bind("bFunction", () => AST3.traverseUp(b, AST3.isOneOf(thisBlockTypes))),
|
|
267
182
|
O.exists(({ aFunction, bFunction }) => aFunction === bFunction)
|
|
268
183
|
);
|
|
269
184
|
}
|
|
@@ -277,5 +192,83 @@ function isNodeValueEqual(a, b, initialScopes) {
|
|
|
277
192
|
}
|
|
278
193
|
}
|
|
279
194
|
}
|
|
195
|
+
var ValueConstructionHint = {
|
|
196
|
+
None: 0n,
|
|
197
|
+
StrictCallExpression: 1n << 0n
|
|
198
|
+
};
|
|
199
|
+
function getValueConstruction(node, initialScope, hint = ValueConstructionHint.None) {
|
|
200
|
+
switch (node.type) {
|
|
201
|
+
case AST_NODE_TYPES.JSXElement:
|
|
202
|
+
case AST_NODE_TYPES.JSXFragment: {
|
|
203
|
+
return { kind: "JSXElement", node };
|
|
204
|
+
}
|
|
205
|
+
case AST_NODE_TYPES.ArrayExpression: {
|
|
206
|
+
return { kind: "ArrayExpression", node };
|
|
207
|
+
}
|
|
208
|
+
case AST_NODE_TYPES.ObjectExpression: {
|
|
209
|
+
return { kind: "ObjectExpression", node };
|
|
210
|
+
}
|
|
211
|
+
case AST_NODE_TYPES.ClassExpression: {
|
|
212
|
+
return { kind: "ClassExpression", node };
|
|
213
|
+
}
|
|
214
|
+
case AST_NODE_TYPES.NewExpression: {
|
|
215
|
+
return { kind: "NewExpression", node };
|
|
216
|
+
}
|
|
217
|
+
case AST_NODE_TYPES.FunctionExpression:
|
|
218
|
+
case AST_NODE_TYPES.ArrowFunctionExpression: {
|
|
219
|
+
return { kind: "FunctionExpression", node };
|
|
220
|
+
}
|
|
221
|
+
case AST_NODE_TYPES.CallExpression: {
|
|
222
|
+
if (hint & ValueConstructionHint.StrictCallExpression) {
|
|
223
|
+
return { kind: "CallExpression", node };
|
|
224
|
+
}
|
|
225
|
+
return { kind: "None", node };
|
|
226
|
+
}
|
|
227
|
+
case AST_NODE_TYPES.MemberExpression: {
|
|
228
|
+
if (!("object" in node)) return { kind: "None", node };
|
|
229
|
+
return getValueConstruction(node.object, initialScope, hint);
|
|
230
|
+
}
|
|
231
|
+
case AST_NODE_TYPES.AssignmentExpression:
|
|
232
|
+
case AST_NODE_TYPES.AssignmentPattern: {
|
|
233
|
+
if (!("right" in node)) return { kind: "None", node };
|
|
234
|
+
return getValueConstruction(node.right, initialScope, hint);
|
|
235
|
+
}
|
|
236
|
+
case AST_NODE_TYPES.LogicalExpression: {
|
|
237
|
+
const lvc = getValueConstruction(node.left, initialScope, hint);
|
|
238
|
+
if (lvc.kind !== "None") return lvc;
|
|
239
|
+
return getValueConstruction(node.right, initialScope, hint);
|
|
240
|
+
}
|
|
241
|
+
case AST_NODE_TYPES.ConditionalExpression: {
|
|
242
|
+
const cvc = getValueConstruction(node.consequent, initialScope, hint);
|
|
243
|
+
if (cvc.kind !== "None") return cvc;
|
|
244
|
+
return getValueConstruction(node.alternate, initialScope, hint);
|
|
245
|
+
}
|
|
246
|
+
case AST_NODE_TYPES.Identifier: {
|
|
247
|
+
if (!("name" in node && isString(node.name))) return { kind: "None", node };
|
|
248
|
+
const construction = F.pipe(
|
|
249
|
+
O.fromNullable(initialScope.set.get(node.name)),
|
|
250
|
+
O.flatMap(getVariableNode(-1)),
|
|
251
|
+
O.map((node2) => getValueConstruction(node2, initialScope, hint)),
|
|
252
|
+
O.filter((vc) => vc.kind !== "None")
|
|
253
|
+
);
|
|
254
|
+
if (O.isNone(construction)) return { kind: "None", node };
|
|
255
|
+
return {
|
|
256
|
+
...construction.value
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
case AST_NODE_TYPES.Literal: {
|
|
260
|
+
if ("regex" in node) {
|
|
261
|
+
return { kind: "RegExpLiteral", node };
|
|
262
|
+
}
|
|
263
|
+
return { kind: "None", node };
|
|
264
|
+
}
|
|
265
|
+
default: {
|
|
266
|
+
if (!("expression" in node && isObject(node.expression))) {
|
|
267
|
+
return { kind: "None", node };
|
|
268
|
+
}
|
|
269
|
+
return getValueConstruction(node.expression, initialScope, hint);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
280
273
|
|
|
281
|
-
export {
|
|
274
|
+
export { ValueConstructionHint, findVariable2 as findVariable, getChidScopes, getScope, getStaticValue2 as getStaticValue, getValueConstruction, getVariableDeclaratorID, getVariableNode, getVariables, isInitializedFromSource, isNodeValueEqual };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/var",
|
|
3
|
-
"version": "1.23.1-beta.
|
|
3
|
+
"version": "1.23.1-beta.6",
|
|
4
4
|
"description": "ESLint React's TSESTree AST utility module for static analysis of variables",
|
|
5
5
|
"homepage": "https://github.com/rEl1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"@typescript-eslint/utils": "^8.19.0",
|
|
39
39
|
"string-ts": "^2.2.0",
|
|
40
40
|
"ts-pattern": "^5.6.0",
|
|
41
|
-
"@eslint-react/ast": "1.23.1-beta.
|
|
42
|
-
"@eslint-react/eff": "1.23.1-beta.
|
|
43
|
-
"@eslint-react/types": "1.23.1-beta.
|
|
41
|
+
"@eslint-react/ast": "1.23.1-beta.6",
|
|
42
|
+
"@eslint-react/eff": "1.23.1-beta.6",
|
|
43
|
+
"@eslint-react/types": "1.23.1-beta.6"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"tsup": "^8.3.5",
|