Skip to content

Commit 4531014

Browse files
authored
feat(core): ComponentCollector adds options to skip the collection of… (#917)
1 parent 9391cf1 commit 4531014

File tree

17 files changed

+312
-132
lines changed

17 files changed

+312
-132
lines changed

packages/core/docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
## Interfaces
88

9+
- [ComponentCollectorOptions](interfaces/ComponentCollectorOptions.md)
910
- [ERClassComponent](interfaces/ERClassComponent.md)
1011
- [ERFunctionComponent](interfaces/ERFunctionComponent.md)
1112
- [ERHook](interfaces/ERHook.md)
@@ -30,6 +31,7 @@
3031

3132
## Variables
3233

34+
- [DEFAULT\_COMPONENT\_COLLECT\_OPTIONS](variables/DEFAULT_COMPONENT_COLLECT_OPTIONS.md)
3335
- [DEFAULT\_COMPONENT\_HINT](variables/DEFAULT_COMPONENT_HINT.md)
3436
- [ERClassComponentFlag](variables/ERClassComponentFlag.md)
3537
- [ERComponentHint](variables/ERComponentHint.md)

packages/core/docs/functions/useComponentCollector.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
# Function: useComponentCollector()
88

9-
> **useComponentCollector**(`context`, `hint`): `object`
9+
> **useComponentCollector**(`context`, `hint`, `options`): `object`
1010
1111
## Parameters
1212

@@ -18,6 +18,10 @@
1818

1919
`bigint` = `DEFAULT_COMPONENT_HINT`
2020

21+
### options
22+
23+
[`ComponentCollectorOptions`](../interfaces/ComponentCollectorOptions.md) = `DEFAULT_COMPONENT_COLLECT_OPTIONS`
24+
2125
## Returns
2226

2327
`object`
@@ -84,7 +88,7 @@
8488

8589
`void`
8690

87-
#### listeners.AssignmentExpression\[type\]\[operator='='\]\[left.type='MemberExpression'\]\[left.property.name='displayName'\]()
91+
#### listeners.AssignmentExpression\[type\]\[operator='='\]\[left.type='MemberExpression'\]\[left.property.name='displayName'\]()?
8892

8993
##### Parameters
9094

@@ -96,7 +100,7 @@
96100

97101
`void`
98102

99-
#### listeners.CallExpression\[type\]:exit()
103+
#### listeners.CallExpression\[type\]:exit()?
100104

101105
##### Parameters
102106

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[**@eslint-react/core**](../README.md)
2+
3+
***
4+
5+
[@eslint-react/core](../README.md) / ComponentCollectorOptions
6+
7+
# Interface: ComponentCollectorOptions
8+
9+
## Properties
10+
11+
### collectDisplayName
12+
13+
> **collectDisplayName**: `boolean`
14+
15+
***
16+
17+
### collectHookCalls
18+
19+
> **collectHookCalls**: `boolean`
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[**@eslint-react/core**](../README.md)
2+
3+
***
4+
5+
[@eslint-react/core](../README.md) / DEFAULT\_COMPONENT\_COLLECT\_OPTIONS
6+
7+
# Variable: DEFAULT\_COMPONENT\_COLLECT\_OPTIONS
8+
9+
> `const` **DEFAULT\_COMPONENT\_COLLECT\_OPTIONS**: [`ComponentCollectorOptions`](../interfaces/ComponentCollectorOptions.md)

packages/core/src/component/component-collector.ts

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-restricted-syntax */
12
import * as AST from "@eslint-react/ast";
23
import { _ } from "@eslint-react/eff";
34
import * as JSX from "@eslint-react/jsx";
@@ -57,10 +58,21 @@ function getComponentFlag(initPath: ERFunctionComponent["initPath"]) {
5758
return flag;
5859
}
5960

61+
export interface ComponentCollectorOptions {
62+
collectDisplayName?: boolean;
63+
collectHookCalls?: boolean;
64+
}
65+
66+
// dprint-ignore
67+
const displayNameAssignmentSelector = "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']";
68+
6069
export function useComponentCollector(
6170
context: RuleContext,
6271
hint = DEFAULT_COMPONENT_HINT,
72+
options: ComponentCollectorOptions = {},
6373
) {
74+
const { collectDisplayName = false, collectHookCalls = false } = options;
75+
6476
const jsxCtx = { getScope: (node: TSESTree.Node) => context.sourceCode.getScope(node) } as const;
6577
const components = new Map<string, ERFunctionComponent>();
6678
const functionEntries: {
@@ -69,6 +81,7 @@ export function useComponentCollector(
6981
hookCalls: TSESTree.CallExpression[];
7082
isComponent: boolean;
7183
}[] = [];
84+
7285
const getCurrentEntry = () => functionEntries.at(-1);
7386
const onFunctionEnter = (node: AST.TSESTreeFunction) => {
7487
const key = getId();
@@ -137,34 +150,36 @@ export function useComponentCollector(
137150
initPath,
138151
});
139152
},
140-
"AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"(
141-
node: TSESTree.AssignmentExpression & { left: TSESTree.MemberExpression },
142-
) {
143-
const { left, right } = node;
144-
const componentName = left.object.type === T.Identifier
145-
? left.object.name
146-
: _;
147-
const component = [...components.values()]
148-
.findLast(({ name }) => name != null && name === componentName);
149-
if (component == null) {
150-
return;
153+
...collectDisplayName
154+
? {
155+
[displayNameAssignmentSelector](node: TSESTree.AssignmentExpression & { left: TSESTree.MemberExpression }) {
156+
const { left, right } = node;
157+
const componentName = left.object.type === T.Identifier
158+
? left.object.name
159+
: _;
160+
const component = [...components.values()]
161+
.findLast(({ name }) => name != null && name === componentName);
162+
if (component == null) {
163+
return;
164+
}
165+
component.displayName = right;
166+
},
151167
}
152-
components.set(component.key, {
153-
...component,
154-
displayName: right,
155-
});
156-
},
157-
"CallExpression[type]:exit"(node: TSESTree.CallExpression) {
158-
if (!isReactHookCall(node)) {
159-
return;
168+
: {},
169+
...collectHookCalls
170+
? {
171+
"CallExpression[type]:exit"(node: TSESTree.CallExpression) {
172+
if (!isReactHookCall(node)) {
173+
return;
174+
}
175+
const entry = getCurrentEntry();
176+
if (entry == null) {
177+
return;
178+
}
179+
entry.hookCalls.push(node);
180+
},
160181
}
161-
const entry = getCurrentEntry();
162-
if (entry == null) {
163-
return;
164-
}
165-
functionEntries.pop();
166-
functionEntries.push({ ...entry, hookCalls: [...entry.hookCalls, node] });
167-
},
182+
: {},
168183
"ReturnStatement[type]"(node: TSESTree.ReturnStatement) {
169184
const entry = getCurrentEntry();
170185
if (entry == null) {

packages/core/src/hook/hook-collector.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,7 @@ export function useHookCollector() {
5757
if (hook == null) {
5858
return;
5959
}
60-
hooks.set(hook.key, {
61-
...hook,
62-
hookCalls: [
63-
...hook.hookCalls,
64-
node,
65-
],
66-
});
60+
hook.hookCalls.push(node);
6761
},
6862
} as const satisfies ESLintUtils.RuleListener;
6963
return { ctx, listeners } as const;

0 commit comments

Comments
 (0)