-
Notifications
You must be signed in to change notification settings - Fork 7
/
common.ts
91 lines (84 loc) · 2.47 KB
/
common.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
import { Rule } from "eslint";
import { TSESTree } from "@typescript-eslint/types";
const componentNameRegex = /^[^a-z]/;
export function isComplexComponent(node: TSESTree.JSXOpeningElement) {
if (node.type !== "JSXOpeningElement") return false;
if (node.name.type !== "JSXIdentifier") return false;
return componentNameRegex.test(node.name.name);
}
export enum MemoStatus {
Memoized,
UnmemoizedObject,
UnmemoizedArray,
UnmemoizedNew,
UnmemoizedFunction,
UnmemoizedFunctionCall,
UnmemoizedJSX,
UnmemoizedOther,
}
function isCallExpression(
node: TSESTree.CallExpression,
name: "useMemo" | "useCallback"
) {
if (node.callee.type === "MemberExpression") {
const {
callee: { object, property },
} = node;
if (
object.type === "Identifier" &&
property.type === "Identifier" &&
object.name === "React" &&
property.name === name
) {
return true;
}
} else if (node.callee.type === "Identifier" && node.callee.name === name) {
return true;
}
return false;
}
function getIdentifierMemoStatus(
context: Rule.RuleContext,
{ name }: TSESTree.Identifier
): MemoStatus {
const variable = context.getScope().variables.find((v) => v.name === name);
if (variable === undefined) return MemoStatus.Memoized;
const [{ node }] = variable.defs;
if (node.type !== "VariableDeclarator") return MemoStatus.Memoized;
if (node.parent.kind === "let") {
context.report({ node, messageId: "usememo-const" });
}
return getExpressionMemoStatus(context, node.init);
}
export function getExpressionMemoStatus(
context: Rule.RuleContext,
expression: TSESTree.Expression
): MemoStatus {
switch (expression.type) {
case "ObjectExpression":
return MemoStatus.UnmemoizedObject;
case "ArrayExpression":
return MemoStatus.UnmemoizedArray;
case "NewExpression":
return MemoStatus.UnmemoizedNew;
case "FunctionExpression":
case "ArrowFunctionExpression":
return MemoStatus.UnmemoizedFunction;
case "JSXElement":
return MemoStatus.UnmemoizedJSX;
case "CallExpression":
if (
isCallExpression(expression, "useMemo") ||
isCallExpression(expression, "useCallback")
) {
return MemoStatus.Memoized;
}
return MemoStatus.UnmemoizedFunctionCall;
case "Identifier":
return getIdentifierMemoStatus(context, expression);
case "BinaryExpression":
return MemoStatus.Memoized;
default:
return MemoStatus.UnmemoizedOther;
}
}