Skip to content

Commit 415293b

Browse files
committed
refactor: update component and hook collectors to return arrays instead of maps
- Changed `getAllComponents` in `useComponentCollector` and `useComponentCollectorLegacy` to return arrays of components instead of maps. - Updated documentation to reflect the new return types. - Adjusted all usages of `getAllComponents` and `getAllHooks` across the codebase to accommodate the new array structure. - Cleaned up related rules in the ESLint plugins to ensure compatibility with the updated collectors.
1 parent 6f16966 commit 415293b

29 files changed

+94
-142
lines changed

packages/core/docs/@eslint-react/namespaces/useComponentCollector/type-aliases/ReturnType.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
```ts
66
type ReturnType = {
77
ctx: {
8-
getAllComponents: (node: TSESTree.Program) => Map<string, FunctionComponent>;
8+
getAllComponents: (node: TSESTree.Program) => FunctionComponent[];
99
getCurrentEntries: () => FunctionEntry[];
1010
getCurrentEntry: () => FunctionEntry | unit;
1111
};
@@ -17,8 +17,8 @@ type ReturnType = {
1717

1818
| Property | Type |
1919
| ------ | ------ |
20-
| <a id="ctx"></a> `ctx` | \{ `getAllComponents`: (`node`: `TSESTree.Program`) => [`Map`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)\<`string`, [`FunctionComponent`](../../../../interfaces/FunctionComponent.md)\>; `getCurrentEntries`: () => `FunctionEntry`[]; `getCurrentEntry`: () => `FunctionEntry` \| `unit`; \} |
21-
| `ctx.getAllComponents` | (`node`: `TSESTree.Program`) => [`Map`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)\<`string`, [`FunctionComponent`](../../../../interfaces/FunctionComponent.md)\> |
20+
| <a id="ctx"></a> `ctx` | \{ `getAllComponents`: (`node`: `TSESTree.Program`) => [`FunctionComponent`](../../../../interfaces/FunctionComponent.md)[]; `getCurrentEntries`: () => `FunctionEntry`[]; `getCurrentEntry`: () => `FunctionEntry` \| `unit`; \} |
21+
| `ctx.getAllComponents` | (`node`: `TSESTree.Program`) => [`FunctionComponent`](../../../../interfaces/FunctionComponent.md)[] |
2222
| `ctx.getCurrentEntries` | () => `FunctionEntry`[] |
2323
| `ctx.getCurrentEntry` | () => `FunctionEntry` \| `unit` |
2424
| <a id="listeners"></a> `listeners` | `ESLintUtils.RuleListener` |

packages/core/docs/@eslint-react/namespaces/useComponentCollectorLegacy/type-aliases/ReturnType.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
```ts
66
type ReturnType = {
77
ctx: {
8-
getAllComponents: (node: TSESTree.Program) => Map<string, ClassComponent>;
8+
getAllComponents: (node: TSESTree.Program) => ClassComponent[];
99
};
1010
listeners: ESLintUtils.RuleListener;
1111
};
@@ -15,6 +15,6 @@ type ReturnType = {
1515

1616
| Property | Type |
1717
| ------ | ------ |
18-
| <a id="ctx"></a> `ctx` | \{ `getAllComponents`: (`node`: `TSESTree.Program`) => [`Map`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)\<`string`, [`ClassComponent`](../../../../interfaces/ClassComponent.md)\>; \} |
19-
| `ctx.getAllComponents` | (`node`: `TSESTree.Program`) => [`Map`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)\<`string`, [`ClassComponent`](../../../../interfaces/ClassComponent.md)\> |
18+
| <a id="ctx"></a> `ctx` | \{ `getAllComponents`: (`node`: `TSESTree.Program`) => [`ClassComponent`](../../../../interfaces/ClassComponent.md)[]; \} |
19+
| `ctx.getAllComponents` | (`node`: `TSESTree.Program`) => [`ClassComponent`](../../../../interfaces/ClassComponent.md)[] |
2020
| <a id="listeners"></a> `listeners` | `ESLintUtils.RuleListener` |

packages/core/docs/@eslint-react/namespaces/useHookCollector/type-aliases/ReturnType.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
```ts
66
type ReturnType = {
77
ctx: {
8-
getAllHooks: Map<string, Hook>;
8+
getAllHooks: Hook[];
99
};
1010
listeners: ESLintUtils.RuleListener;
1111
};
@@ -15,6 +15,6 @@ type ReturnType = {
1515

1616
| Property | Type |
1717
| ------ | ------ |
18-
| <a id="ctx"></a> `ctx` | \{ `getAllHooks`: [`Map`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)\<`string`, [`Hook`](../../../../interfaces/Hook.md)\>; \} |
19-
| `ctx.getAllHooks` | [`Map`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)\<`string`, [`Hook`](../../../../interfaces/Hook.md)\> |
18+
| <a id="ctx"></a> `ctx` | \{ `getAllHooks`: [`Hook`](../../../../interfaces/Hook.md)[]; \} |
19+
| `ctx.getAllHooks` | [`Hook`](../../../../interfaces/Hook.md)[] |
2020
| <a id="listeners"></a> `listeners` | `ESLintUtils.RuleListener` |

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const idGen = new IdGenerator("class_component_");
1212
export declare namespace useComponentCollectorLegacy {
1313
type ReturnType = {
1414
ctx: {
15-
getAllComponents: (node: TSESTree.Program) => Map<string, ClassComponent>;
15+
getAllComponents: (node: TSESTree.Program) => ClassComponent[];
1616
};
1717
listeners: ESLintUtils.RuleListener;
1818
};
@@ -27,8 +27,8 @@ export function useComponentCollectorLegacy(): useComponentCollectorLegacy.Retur
2727

2828
const ctx = {
2929
// eslint-disable-next-line @typescript-eslint/no-unused-vars
30-
getAllComponents(node: TSESTree.Program): typeof components {
31-
return components;
30+
getAllComponents(node: TSESTree.Program) {
31+
return [...components.values()];
3232
},
3333
} as const;
3434

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

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export declare namespace useComponentCollector {
3333
};
3434
type ReturnType = {
3535
ctx: {
36-
getAllComponents: (node: TSESTree.Program) => Map<string, FunctionComponent>;
36+
getAllComponents: (node: TSESTree.Program) => FunctionComponent[];
3737
getCurrentEntries: () => FunctionEntry[];
3838
getCurrentEntry: () => FunctionEntry | unit;
3939
};
@@ -57,37 +57,22 @@ export function useComponentCollector(
5757
hint = DEFAULT_COMPONENT_DETECTION_HINT,
5858
} = options;
5959

60-
const components = new Map<string, FunctionComponent>();
6160
const functionEntries: FunctionEntry[] = [];
61+
const components = new Map<string, FunctionComponent>();
6262

6363
const getCurrentEntry = () => functionEntries.at(-1);
6464
const onFunctionEnter = (node: AST.TSESTreeFunction) => {
6565
const key = idGen.next();
6666
functionEntries.push({ key, node, hookCalls: [], isComponent: false });
6767
};
6868
const onFunctionExit = () => {
69-
const entry = functionEntries.at(-1);
70-
if (entry == null) return;
71-
if (!entry.isComponent) return functionEntries.pop();
72-
const rets = AST.getNestedReturnStatements(entry.node.body);
73-
for (let i = rets.length - 1; i >= 0; i--) {
74-
const ret = rets[i];
75-
if (ret == null) continue;
76-
const shouldDrop = context.sourceCode.getScope(ret).block === entry.node
77-
&& ret.argument != null
78-
&& !isJsxLike(context.sourceCode, ret.argument, hint);
79-
if (shouldDrop) {
80-
components.delete(entry.key);
81-
break;
82-
}
83-
}
8469
return functionEntries.pop();
8570
};
8671

8772
const ctx = {
8873
// eslint-disable-next-line @typescript-eslint/no-unused-vars
89-
getAllComponents(node: TSESTree.Program): typeof components {
90-
return components;
74+
getAllComponents(node: TSESTree.Program) {
75+
return [...components.values()];
9176
},
9277
getCurrentEntries() {
9378
return [...functionEntries];
@@ -131,8 +116,7 @@ export function useComponentCollector(
131116
const componentName = left.object.type === T.Identifier
132117
? left.object.name
133118
: unit;
134-
const component = [...components.values()]
135-
.findLast(({ name }) => name != null && name === componentName);
119+
const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
136120
if (component == null) return;
137121
component.displayName = right;
138122
},
@@ -158,10 +142,11 @@ export function useComponentCollector(
158142
entry.isComponent = true;
159143
const initPath = AST.getFunctionInitPath(entry.node);
160144
const id = getFunctionComponentId(context, entry.node);
145+
const key = entry.key;
161146
const name = getComponentNameFromId(id);
162-
components.set(entry.key, {
147+
components.set(key, {
163148
id,
164-
key: entry.key,
149+
key,
165150
kind: "function",
166151
name,
167152
node: entry.node,

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ type FunctionEntry = {
1717
export declare namespace useHookCollector {
1818
type ReturnType = {
1919
ctx: {
20-
getAllHooks(node: TSESTree.Program): Map<string, Hook>;
20+
getAllHooks(node: TSESTree.Program): Hook[];
2121
};
2222
listeners: ESLintUtils.RuleListener;
2323
};
@@ -51,8 +51,8 @@ export function useHookCollector(): useHookCollector.ReturnType {
5151
};
5252
const ctx = {
5353
// eslint-disable-next-line @typescript-eslint/no-unused-vars
54-
getAllHooks(node: TSESTree.Program): typeof hooks {
55-
return hooks;
54+
getAllHooks(node: TSESTree.Program) {
55+
return [...hooks.values()];
5656
},
5757
} as const;
5858
const listeners = {

packages/plugins/eslint-plugin-react-debug/src/rules/class-component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ export function create(context: RuleContext<MessageID, []>): RuleListener {
3535
return {
3636
...listeners,
3737
"Program:exit"(program) {
38-
const components = ctx.getAllComponents(program);
39-
for (const { name = "anonymous", node: component } of components.values()) {
38+
for (const { name = "anonymous", node: component } of ctx.getAllComponents(program)) {
4039
context.report({
4140
messageId: "classComponent",
4241
node: component,

packages/plugins/eslint-plugin-react-debug/src/rules/function-component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ export function create(context: RuleContext<MessageID, []>): RuleListener {
4343
return {
4444
...listeners,
4545
"Program:exit"(program) {
46-
const components = ctx.getAllComponents(program);
47-
for (const { name = "anonymous", node, displayName, flag, hookCalls } of components.values()) {
46+
for (const { name = "anonymous", node, displayName, flag, hookCalls } of ctx.getAllComponents(program)) {
4847
context.report({
4948
messageId: "functionComponent",
5049
node,

packages/plugins/eslint-plugin-react-debug/src/rules/hook.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@ export function create(context: RuleContext<MessageID, []>): RuleListener {
3636
return {
3737
...listeners,
3838
"Program:exit"(program) {
39-
const allHooks = ctx.getAllHooks(program);
40-
41-
for (const { name, node, hookCalls } of allHooks.values()) {
39+
for (const { name, node, hookCalls } of ctx.getAllHooks(program)) {
4240
context.report({
4341
messageId: "hook",
4442
node,

packages/plugins/eslint-plugin-react-naming-convention/src/rules/component-name.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,14 @@ export default createRule<Options, MessageID>({
8282
export function create(context: RuleContext<MessageID, Options>): RuleListener {
8383
const options = normalizeOptions(context.options);
8484
const { rule } = options;
85-
const collector = useComponentCollector(context);
86-
const collectorLegacy = useComponentCollectorLegacy();
85+
const fCollector = useComponentCollector(context);
86+
const cCollector = useComponentCollectorLegacy();
8787

8888
return {
89-
...collector.listeners,
90-
...collectorLegacy.listeners,
89+
...fCollector.listeners,
90+
...cCollector.listeners,
9191
"Program:exit"(program) {
92-
const functionComponents = collector.ctx.getAllComponents(program);
93-
const classComponents = collectorLegacy.ctx.getAllComponents(program);
94-
for (const { node: component } of functionComponents.values()) {
92+
for (const { node: component } of fCollector.ctx.getAllComponents(program)) {
9593
const id = AST.getFunctionId(component);
9694
if (id?.name == null) continue;
9795
const name = id.name;
@@ -102,7 +100,7 @@ export function create(context: RuleContext<MessageID, Options>): RuleListener {
102100
data: { name, rule },
103101
});
104102
}
105-
for (const { node: component } of classComponents.values()) {
103+
for (const { node: component } of cCollector.ctx.getAllComponents(program)) {
106104
const id = AST.getClassId(component);
107105
if (id?.name == null) continue;
108106
const name = id.name;

0 commit comments

Comments
 (0)