eslint-plugin-no-mistakes 0.61.0 → 0.61.2
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/package.json
CHANGED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { unwrapExpression } = require("./async-ast");
|
|
4
|
+
const { propertyName, literalString } = require("./module-mock-helpers");
|
|
5
|
+
|
|
6
|
+
const UNSTABLE_BINDING_DEF_TYPES = new Set(["Parameter", "CatchClause", "FunctionName"]);
|
|
7
|
+
|
|
8
|
+
function findVariable(scope, name) {
|
|
9
|
+
while (scope) {
|
|
10
|
+
const variable = scope.variables.find((candidate) => candidate.name === name);
|
|
11
|
+
if (variable) return variable;
|
|
12
|
+
scope = scope.upper;
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function resolveVariable(node, context) {
|
|
18
|
+
return findVariable(context.sourceCode.getScope(node), node.name);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isLocalRequire(id, context) {
|
|
22
|
+
const variable = resolveVariable(id, context);
|
|
23
|
+
return Boolean(variable?.defs.some((def) => def.type && def.type !== "ImplicitGlobalVariable"));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isReassigned(id, context) {
|
|
27
|
+
const variable = resolveVariable(id, context);
|
|
28
|
+
if (!variable) return false;
|
|
29
|
+
const writes = variable.references.filter((reference) => reference.isWrite());
|
|
30
|
+
const initializationSites = new Set(
|
|
31
|
+
writes.filter((reference) => reference.init).map((reference) => reference.identifier),
|
|
32
|
+
);
|
|
33
|
+
const isVar = variable.defs.some(
|
|
34
|
+
(definition) => definition.type === "Variable" && definition.parent?.kind === "var",
|
|
35
|
+
);
|
|
36
|
+
return (
|
|
37
|
+
writes.some((reference) => !reference.init) ||
|
|
38
|
+
(isVar && initializationSites.size > 1) ||
|
|
39
|
+
variable.defs.some((definition) => UNSTABLE_BINDING_DEF_TYPES.has(definition.type))
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function bindingIdentifier(node) {
|
|
44
|
+
if (node?.type === "Identifier") return node;
|
|
45
|
+
return node?.type === "AssignmentPattern" && node.left.type === "Identifier" ? node.left : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function staticComputedPropertyName(node) {
|
|
49
|
+
return literalString(unwrapExpression(node));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function memberPropertyName(node) {
|
|
53
|
+
if (!node.computed) return propertyName(node.property);
|
|
54
|
+
return staticComputedPropertyName(node.property);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function recordObjectPatternBindings(pattern, source, recordDirect) {
|
|
58
|
+
for (const property of pattern.properties) {
|
|
59
|
+
if (property.type !== "Property") continue;
|
|
60
|
+
const name = property.computed
|
|
61
|
+
? staticComputedPropertyName(property.key)
|
|
62
|
+
: propertyName(property.key);
|
|
63
|
+
if (name) recordDirect(bindingIdentifier(property.value), source, name);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function namespaceSourceFromInit(init, context, namespaceBindings) {
|
|
68
|
+
const expression = unwrapExpression(init);
|
|
69
|
+
if (expression?.type !== "Identifier") return null;
|
|
70
|
+
return namespaceBindings.get(resolveVariable(expression, context)) || null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = {
|
|
74
|
+
isLocalRequire,
|
|
75
|
+
isReassigned,
|
|
76
|
+
memberPropertyName,
|
|
77
|
+
namespaceSourceFromInit,
|
|
78
|
+
recordObjectPatternBindings,
|
|
79
|
+
resolveVariable,
|
|
80
|
+
};
|
|
@@ -1,32 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const { unwrapExpression } = require("./async-ast");
|
|
4
|
+
const {
|
|
5
|
+
isLocalRequire,
|
|
6
|
+
isReassigned,
|
|
7
|
+
memberPropertyName,
|
|
8
|
+
namespaceSourceFromInit,
|
|
9
|
+
recordObjectPatternBindings,
|
|
10
|
+
resolveVariable,
|
|
11
|
+
} = require("./async-target-bindings");
|
|
4
12
|
const { compileTargets, matchesAny, targetMatches } = require("./async-patterns");
|
|
5
|
-
const {
|
|
6
|
-
|
|
7
|
-
function findVariable(scope, name) {
|
|
8
|
-
while (scope) {
|
|
9
|
-
const variable = scope.variables.find((candidate) => candidate.name === name);
|
|
10
|
-
if (variable) return variable;
|
|
11
|
-
scope = scope.upper;
|
|
12
|
-
}
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function resolveVariable(node, context) {
|
|
17
|
-
return findVariable(context.sourceCode.getScope(node), node.name);
|
|
18
|
-
}
|
|
13
|
+
const { literalString } = require("./module-mock-helpers");
|
|
19
14
|
|
|
20
15
|
function importSpecifierName(specifier) {
|
|
21
16
|
const imported = specifier.imported;
|
|
22
17
|
return imported.type === "Literal" ? String(imported.value) : imported.name;
|
|
23
18
|
}
|
|
24
19
|
|
|
25
|
-
function isLocalRequire(id, context) {
|
|
26
|
-
const variable = resolveVariable(id, context);
|
|
27
|
-
return Boolean(variable?.defs.some((def) => def.type && def.type !== "ImplicitGlobalVariable"));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
20
|
function requireSource(node, context) {
|
|
31
21
|
const expression = unwrapExpression(node);
|
|
32
22
|
const source = literalString(unwrapExpression(expression?.arguments?.[0]));
|
|
@@ -42,42 +32,16 @@ function requireSource(node, context) {
|
|
|
42
32
|
return source;
|
|
43
33
|
}
|
|
44
34
|
|
|
45
|
-
function bindingIdentifier(node) {
|
|
46
|
-
if (node?.type === "Identifier") return node;
|
|
47
|
-
return node?.type === "AssignmentPattern" && node.left.type === "Identifier" ? node.left : null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function memberPropertyName(node) {
|
|
51
|
-
if (!node.computed) return propertyName(node.property);
|
|
52
|
-
return staticComputedPropertyName(node.property);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function staticComputedPropertyName(node) {
|
|
56
|
-
return literalString(unwrapExpression(node));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
35
|
function createTargetMatcher(context, optionKey = "targets") {
|
|
60
36
|
const targets = compileTargets(context.options?.[0] || {}, optionKey);
|
|
61
37
|
const sourceSpecifierPatterns = targets.flatMap((target) => target.sourceSpecifierPatterns);
|
|
62
38
|
const directBindings = new Map();
|
|
63
39
|
const namespaceBindings = new Map();
|
|
64
40
|
|
|
65
|
-
function isReassigned(id) {
|
|
66
|
-
const variable = resolveVariable(id, context);
|
|
67
|
-
const writes = variable?.references.filter((reference) => reference.isWrite()) || [];
|
|
68
|
-
const initializationSites = new Set(
|
|
69
|
-
writes.filter((reference) => reference.init).map((reference) => reference.identifier),
|
|
70
|
-
);
|
|
71
|
-
const isVar = variable?.defs.some(
|
|
72
|
-
(definition) => definition.type === "Variable" && definition.parent?.kind === "var",
|
|
73
|
-
);
|
|
74
|
-
return writes.some((reference) => !reference.init) || (isVar && initializationSites.size > 1);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
41
|
function recordDirect(id, source, calleeName) {
|
|
78
42
|
if (
|
|
79
43
|
id?.type !== "Identifier" ||
|
|
80
|
-
isReassigned(id) ||
|
|
44
|
+
isReassigned(id, context) ||
|
|
81
45
|
!targetMatches(targets, source, calleeName)
|
|
82
46
|
) {
|
|
83
47
|
return;
|
|
@@ -89,7 +53,7 @@ function createTargetMatcher(context, optionKey = "targets") {
|
|
|
89
53
|
function recordNamespace(id, source) {
|
|
90
54
|
if (
|
|
91
55
|
id.type !== "Identifier" ||
|
|
92
|
-
isReassigned(id) ||
|
|
56
|
+
isReassigned(id, context) ||
|
|
93
57
|
!matchesAny(source, sourceSpecifierPatterns)
|
|
94
58
|
) {
|
|
95
59
|
return;
|
|
@@ -108,21 +72,20 @@ function createTargetMatcher(context, optionKey = "targets") {
|
|
|
108
72
|
return;
|
|
109
73
|
}
|
|
110
74
|
if (node.id.type === "ObjectPattern") {
|
|
111
|
-
|
|
112
|
-
if (property.type !== "Property") continue;
|
|
113
|
-
const name = property.computed
|
|
114
|
-
? staticComputedPropertyName(property.key)
|
|
115
|
-
: propertyName(property.key);
|
|
116
|
-
if (name) recordDirect(bindingIdentifier(property.value), source, name);
|
|
117
|
-
}
|
|
75
|
+
recordObjectPatternBindings(node.id, source, recordDirect);
|
|
118
76
|
}
|
|
119
77
|
return;
|
|
120
78
|
}
|
|
121
79
|
const member = unwrapExpression(node.init);
|
|
122
|
-
if (member?.type
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
80
|
+
if (member?.type === "MemberExpression" && node.id.type === "Identifier") {
|
|
81
|
+
const memberSource = requireSource(member.object, context);
|
|
82
|
+
const name = memberPropertyName(member);
|
|
83
|
+
if (memberSource && name) recordDirect(node.id, memberSource, name);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (node.id.type !== "ObjectPattern") return;
|
|
87
|
+
const nsSource = namespaceSourceFromInit(node.init, context, namespaceBindings);
|
|
88
|
+
if (nsSource) recordObjectPatternBindings(node.id, nsSource, recordDirect);
|
|
126
89
|
}
|
|
127
90
|
|
|
128
91
|
function recordImportEquals(node) {
|
|
@@ -170,7 +133,9 @@ function createTargetMatcher(context, optionKey = "targets") {
|
|
|
170
133
|
walk(node, (child) => {
|
|
171
134
|
if (child.type === "ImportDeclaration") recordImportDeclaration(child);
|
|
172
135
|
else if (child.type === "TSImportEqualsDeclaration") recordImportEquals(child);
|
|
173
|
-
|
|
136
|
+
});
|
|
137
|
+
walk(node, (child) => {
|
|
138
|
+
if (child.type === "VariableDeclarator") recordRequireDeclarator(child);
|
|
174
139
|
});
|
|
175
140
|
}
|
|
176
141
|
|