-
-
Notifications
You must be signed in to change notification settings - Fork 28
/
tree.ts
124 lines (113 loc) · 2.92 KB
/
tree.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import type { TSESTree } from "@typescript-eslint/experimental-utils";
import {
isCallExpression,
isClassLike,
isFunctionExpressionLike,
isFunctionLike,
isIdentifier,
isMemberExpression,
isMethodDefinition,
isProperty,
isTSInterfaceBody,
isTSTypeAliasDeclaration,
} from "./typeguard";
/**
* Return the first ancestor that meets the given check criteria.
*/
function getAncestorOfType<T extends TSESTree.Node>(
checker: (node: TSESTree.Node, child: TSESTree.Node | null) => node is T,
node: TSESTree.Node,
child: TSESTree.Node | null = null
): T | null {
return checker(node, child)
? node
: node.parent === null || node.parent === undefined
? null
: getAncestorOfType(checker, node.parent, node);
}
/**
* Test if the given node is in a function's body.
*/
export function inFunctionBody(node: TSESTree.Node): boolean {
return (
getAncestorOfType(
(n, c): n is TSESTree.Node => isFunctionLike(n) && n.body === c,
node
) !== null
);
}
/**
* Test if the given node is in a class.
*/
export function inClass(node: TSESTree.Node): boolean {
return getAncestorOfType(isClassLike, node) !== null;
}
/**
* Test if the given node is in a TS Property Signature.
*/
export function inInterface(node: TSESTree.Node): boolean {
return getAncestorOfType(isTSInterfaceBody, node) !== null;
}
/**
* Test if the given node is in a Constructor.
*/
export function inConstructor(node: TSESTree.Node): boolean {
const methodDefinition = getAncestorOfType(isMethodDefinition, node);
return (
methodDefinition !== null &&
isIdentifier(methodDefinition.key) &&
methodDefinition.key.name === "constructor"
);
}
/**
* Is the given node in the return type.
*/
export function isInReturnType(node: TSESTree.Node): boolean {
return (
getAncestorOfType(
(n): n is TSESTree.Node =>
n.parent !== undefined &&
n.parent !== null &&
isFunctionLike(n.parent) &&
n.parent.returnType === n,
node
) !== null
);
}
/**
* Is the given node in a TS Type Alias Declaration.
*/
export function isInTSTypeAliasDeclaration(node: TSESTree.Node): boolean {
return getAncestorOfType(isTSTypeAliasDeclaration, node) !== null;
}
/**
* Is the given identifier a property of an object?
*/
export function isPropertyAccess(node: TSESTree.Identifier): boolean {
return (
node.parent !== undefined &&
isMemberExpression(node.parent) &&
node.parent.property === node
);
}
/**
* Is the given identifier a property name?
*/
export function isPropertyName(node: TSESTree.Identifier): boolean {
return (
node.parent !== undefined &&
isProperty(node.parent) &&
node.parent.key === node
);
}
/**
* Is the given function an IIFE?
*/
export function isIIFE(node: TSESTree.Node): boolean {
return (
isFunctionExpressionLike(node) &&
node.parent !== undefined &&
isCallExpression(node.parent) &&
node.parent.callee === node
);
}