forked from sveltejs/eslint-plugin-svelte
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathderived-has-same-inputs-outputs.ts
107 lines (101 loc) · 3.28 KB
/
derived-has-same-inputs-outputs.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import type * as ESTree from "estree"
import { createRule } from "../utils"
import type { RuleContext } from "../types"
import { extractStoreReferences } from "./reference-helpers/svelte-store"
export default createRule("derived-has-same-inputs-outputs", {
meta: {
docs: {
description:
"derived store should use same variable names between values and callback",
category: "Stylistic Issues",
recommended: false,
conflictWithPrettier: false,
},
schema: [],
messages: {
unexpected: "The argument name should be '{{name}}'.",
},
type: "suggestion",
},
create(context) {
/** check node type */
function isIdentifierOrArrayExpression(
node: ESTree.SpreadElement | ESTree.Expression,
): node is ESTree.Identifier | ESTree.ArrayExpression {
return ["Identifier", "ArrayExpression"].includes(node.type)
}
type ArrowFunctionExpressionOrFunctionExpression =
| ESTree.ArrowFunctionExpression
| ESTree.FunctionExpression
/** check node type */
function isFunctionExpression(
node: ESTree.SpreadElement | ESTree.Expression,
): node is ArrowFunctionExpressionOrFunctionExpression {
return ["ArrowFunctionExpression", "FunctionExpression"].includes(
node.type,
)
}
/**
* Check for identifier type.
* e.g. derived(a, ($a) => {});
*/
function checkIdentifier(
context: RuleContext,
args: ESTree.Identifier,
fn: ArrowFunctionExpressionOrFunctionExpression,
) {
const fnParam = fn.params[0]
if (fnParam.type !== "Identifier") return
const expectedName = `$${args.name}`
if (expectedName !== fnParam.name) {
context.report({
node: fn,
loc: fnParam.loc!,
messageId: "unexpected",
data: { name: expectedName },
})
}
}
/**
* Check for array type.
* e.g. derived([ a, b ], ([ $a, $b ]) => {})
*/
function checkArrayExpression(
context: RuleContext,
args: ESTree.ArrayExpression,
fn: ArrowFunctionExpressionOrFunctionExpression,
) {
const fnParam = fn.params[0]
if (fnParam.type !== "ArrayPattern") return
const argNames = args.elements.map((element) => {
return element && element.type === "Identifier" ? element.name : null
})
fnParam.elements.forEach((element, index) => {
const argName = argNames[index]
if (element && element.type === "Identifier" && argName) {
const expectedName = `$${argName}`
if (expectedName !== element.name) {
context.report({
node: fn,
loc: element.loc!,
messageId: "unexpected",
data: { name: expectedName },
})
}
}
})
}
return {
Program() {
for (const { node } of extractStoreReferences(context, ["derived"])) {
const [args, fn] = node.arguments
if (!args || !isIdentifierOrArrayExpression(args)) continue
if (!fn || !isFunctionExpression(fn)) continue
if (!fn.params || fn.params.length === 0) continue
if (args.type === "Identifier") checkIdentifier(context, args, fn)
else checkArrayExpression(context, args, fn)
}
},
}
},
})