eslint-plugin-effector 0.7.1 → 0.7.4
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
|
@@ -2,6 +2,7 @@ const { createLinkToRule } = require("../../utils/create-link-to-rule");
|
|
|
2
2
|
const { isInsideReactComponent } = require("../../utils/react");
|
|
3
3
|
const { nodeTypeIs } = require("../../utils/node-type-is");
|
|
4
4
|
const { traverseParentByType } = require("../../utils/traverse-parent-by-type");
|
|
5
|
+
const { nodeIsType } = require("../../utils/node-is-type");
|
|
5
6
|
|
|
6
7
|
module.exports = {
|
|
7
8
|
meta: {
|
|
@@ -23,34 +24,44 @@ module.exports = {
|
|
|
23
24
|
const parserServices = context.parserServices;
|
|
24
25
|
|
|
25
26
|
// TypeScript-only rule, since units can be imported from anywhere
|
|
26
|
-
if (parserServices.hasFullTypeInformation) {
|
|
27
|
-
return {
|
|
28
|
-
Identifier(node) {
|
|
29
|
-
if (isInsideReactComponent(node)) {
|
|
30
|
-
if (
|
|
31
|
-
nodeTypeIs.effect({ node, context }) ||
|
|
32
|
-
nodeTypeIs.event({ node, context })
|
|
33
|
-
) {
|
|
34
|
-
if (!isInsideUseEventCall({ node, context })) {
|
|
35
|
-
context.report({
|
|
36
|
-
node,
|
|
37
|
-
messageId: "useEventNeeded",
|
|
38
|
-
data: {
|
|
39
|
-
unitName: node.name,
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
};
|
|
27
|
+
if (!parserServices.hasFullTypeInformation) {
|
|
28
|
+
return {};
|
|
47
29
|
}
|
|
48
30
|
|
|
49
|
-
return {
|
|
31
|
+
return {
|
|
32
|
+
Identifier(node) {
|
|
33
|
+
if (!isInsideReactComponent(node)) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (nodeIsType({ node })) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
nodeTypeIs.not.effect({ node, context }) &&
|
|
43
|
+
nodeTypeIs.not.event({ node, context })
|
|
44
|
+
) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (isInsideEffectorHook({ node, context })) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
context.report({
|
|
53
|
+
node,
|
|
54
|
+
messageId: "useEventNeeded",
|
|
55
|
+
data: {
|
|
56
|
+
unitName: node.name,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
};
|
|
50
61
|
},
|
|
51
62
|
};
|
|
52
63
|
|
|
53
|
-
function
|
|
64
|
+
function isInsideEffectorHook({ node, context }) {
|
|
54
65
|
const calleeParentNode = traverseParentByType(node.parent, "CallExpression");
|
|
55
66
|
|
|
56
67
|
if (!calleeParentNode?.callee) return false;
|
|
@@ -58,6 +69,6 @@ function isInsideUseEventCall({ node, context }) {
|
|
|
58
69
|
return nodeTypeIs.effectorReactHook({
|
|
59
70
|
node: calleeParentNode.callee,
|
|
60
71
|
context,
|
|
61
|
-
hook: ["useEvent", "useUnit"],
|
|
72
|
+
hook: ["useEvent", "useUnit", "useStore"],
|
|
62
73
|
});
|
|
63
74
|
}
|
package/utils/extract-config.js
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
function extractConfig(fields, { node }) {
|
|
2
2
|
const config = {};
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
config
|
|
6
|
-
|
|
7
|
-
);
|
|
8
|
-
|
|
4
|
+
if (isObject(node.arguments?.[0])) {
|
|
5
|
+
extractConfigFromObject(config, fields, node.arguments?.[0]);
|
|
6
|
+
} else if (isObject(node.arguments?.[1])) {
|
|
7
|
+
extractConfigFromObject(config, fields, node.arguments?.[1]);
|
|
8
|
+
if (fields.includes("clock")) {
|
|
9
|
+
config.clock = { value: node.arguments?.[0] };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
9
12
|
|
|
10
13
|
return config;
|
|
11
14
|
}
|
|
12
15
|
|
|
16
|
+
function isObject(node) {
|
|
17
|
+
return Boolean(node?.properties);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function extractConfigFromObject(config, fields, node) {
|
|
21
|
+
fields.forEach((field) => {
|
|
22
|
+
config[field] = node?.properties?.find((n) => n.key?.name === field);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
module.exports = { extractConfig };
|
package/utils/react.js
CHANGED
|
@@ -90,11 +90,41 @@ function isInsideReactComponent(node) {
|
|
|
90
90
|
if (isForwardRefCallback(node) || isMemoCallback(node)) {
|
|
91
91
|
return true;
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
if (isClass(node) && !isClassComponent(node)) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (isClassComponent(node)) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
93
102
|
node = node.parent;
|
|
94
103
|
}
|
|
95
104
|
return false;
|
|
96
105
|
}
|
|
97
106
|
|
|
107
|
+
function isClass(node) {
|
|
108
|
+
return node?.type === "ClassDeclaration";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function isClassComponent(node) {
|
|
112
|
+
if (!node?.superClass) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
if (node?.superClass?.type === "MemberExpression") {
|
|
116
|
+
return (
|
|
117
|
+
node?.superClass?.object?.name === "React" &&
|
|
118
|
+
/^(Pure)?Component$/.test(node?.superClass?.property?.name)
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
if (node?.superClass?.type === "Identifier") {
|
|
122
|
+
return /^(Pure)?Component$/.test(node?.superClass?.name);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
|
|
98
128
|
function isInsideReactHook(node) {
|
|
99
129
|
while (node) {
|
|
100
130
|
const functionName = getFunctionName(node);
|
package/utils/read-example.js
CHANGED
|
@@ -7,8 +7,8 @@ function readExample(dirname, exampleName) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
function getCorrectExamples(dirname, config = {}) {
|
|
10
|
-
const { ext
|
|
11
|
-
const pattern = `correct-*.${ext}`;
|
|
10
|
+
const { ext, namesOnly = true } = config;
|
|
11
|
+
const pattern = `correct-*.${resolveExtension(ext)}`;
|
|
12
12
|
const correct = glob.sync(join(dirname, "examples", pattern));
|
|
13
13
|
|
|
14
14
|
let result = correct;
|
|
@@ -24,9 +24,27 @@ function getCorrectExamples(dirname, config = {}) {
|
|
|
24
24
|
return result;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function resolveExtension(ext) {
|
|
28
|
+
const DEFAULT_EXT = "js";
|
|
29
|
+
|
|
30
|
+
if (Array.isArray(ext)) {
|
|
31
|
+
if (ext.length === 0) {
|
|
32
|
+
return DEFAULT_EXT;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (ext.length === 1) {
|
|
36
|
+
return ext[0];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return `{${ext.join(",")}}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return ext ?? DEFAULT_EXT;
|
|
43
|
+
}
|
|
44
|
+
|
|
27
45
|
function getIncorrectExamples(dirname, config = {}) {
|
|
28
|
-
const { ext
|
|
29
|
-
const pattern = `incorrect-*.${ext}`;
|
|
46
|
+
const { ext, namesOnly = true } = config;
|
|
47
|
+
const pattern = `incorrect-*.${resolveExtension(ext)}`;
|
|
30
48
|
const incorrect = glob.sync(join(dirname, "examples", pattern));
|
|
31
49
|
|
|
32
50
|
let result = incorrect;
|