From fbf0526c8bdaed968b5ac54e8d147614128fa5ac Mon Sep 17 00:00:00 2001 From: Rel1cx Date: Tue, 4 Nov 2025 16:13:21 +0800 Subject: [PATCH 1/3] Replace getId with IdGenerator across collectors --- .../component/component-collector-legacy.ts | 6 ++- .../core/src/component/component-collector.ts | 8 ++-- packages/core/src/hook/hook-collector.ts | 6 ++- packages/shared/docs/README.md | 4 ++ packages/shared/docs/classes/IdGenerator.md | 41 +++++++++++++++++++ packages/shared/src/_id.ts | 28 +++++++++++-- 6 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 packages/shared/docs/classes/IdGenerator.md diff --git a/packages/core/src/component/component-collector-legacy.ts b/packages/core/src/component/component-collector-legacy.ts index 00e2bd308b..f7aa70a55c 100644 --- a/packages/core/src/component/component-collector-legacy.ts +++ b/packages/core/src/component/component-collector-legacy.ts @@ -3,10 +3,12 @@ import { unit } from "@eslint-react/eff"; import type { ESLintUtils, TSESTree } from "@typescript-eslint/utils"; import type { ClassComponent } from "./component-semantic-node"; -import { getId } from "@eslint-react/shared"; +import { IdGenerator } from "@eslint-react/shared"; import { ComponentFlag } from "./component-flag"; import { isClassComponent, isPureComponent } from "./component-is"; +const idGen = new IdGenerator("class_component_"); + export declare namespace useComponentCollectorLegacy { type ReturnType = { ctx: { @@ -35,7 +37,7 @@ export function useComponentCollectorLegacy(): useComponentCollectorLegacy.Retur return; } const id = AST.getClassId(node); - const key = getId(); + const key = idGen.next(); const flag = isPureComponent(node) ? ComponentFlag.PureComponent : ComponentFlag.None; diff --git a/packages/core/src/component/component-collector.ts b/packages/core/src/component/component-collector.ts index 4780582bb2..f72e9abc8f 100644 --- a/packages/core/src/component/component-collector.ts +++ b/packages/core/src/component/component-collector.ts @@ -1,7 +1,7 @@ import * as AST from "@eslint-react/ast"; import { unit } from "@eslint-react/eff"; import { type RuleContext } from "@eslint-react/shared"; -import { getId } from "@eslint-react/shared"; +import { IdGenerator } from "@eslint-react/shared"; import type { TSESTree } from "@typescript-eslint/types"; import { AST_NODE_TYPES as T } from "@typescript-eslint/types"; import type { ESLintUtils } from "@typescript-eslint/utils"; @@ -16,6 +16,8 @@ import { getFunctionComponentId } from "./component-id"; import { getComponentFlagFromInitPath } from "./component-init-path"; import { getComponentNameFromId, hasNoneOrLooseComponentName } from "./component-name"; +const idGen = new IdGenerator("function_component_"); + type FunctionEntry = { key: string; node: AST.TSESTreeFunction; @@ -60,7 +62,7 @@ export function useComponentCollector( const getCurrentEntry = () => functionEntries.at(-1); const onFunctionEnter = (node: AST.TSESTreeFunction) => { - const key = getId(); + const key = idGen.next(); functionEntries.push({ key, node, hookCalls: [], isComponent: false }); }; const onFunctionExit = () => { @@ -106,8 +108,8 @@ export function useComponentCollector( if (!isComponent) return; const initPath = AST.getFunctionInitPath(entry.node); const id = getFunctionComponentId(context, entry.node); + const key = entry.key; const name = getComponentNameFromId(id); - const key = getId(); components.set(key, { id, key, diff --git a/packages/core/src/hook/hook-collector.ts b/packages/core/src/hook/hook-collector.ts index 624422592c..2e1a0c7890 100644 --- a/packages/core/src/hook/hook-collector.ts +++ b/packages/core/src/hook/hook-collector.ts @@ -2,10 +2,12 @@ import * as AST from "@eslint-react/ast"; import type { ESLintUtils, TSESTree } from "@typescript-eslint/utils"; import type { Hook } from "./hook-semantic-node"; -import { getId } from "@eslint-react/shared"; +import { IdGenerator } from "@eslint-react/shared"; import { isReactHookCall } from "./hook-is"; import { isReactHookName } from "./hook-name"; +const idGen = new IdGenerator("hook_"); + type FunctionEntry = { key: string; node: AST.TSESTreeFunction; @@ -26,7 +28,7 @@ export function useHookCollector(): useHookCollector.ReturnType { const functionEntries: FunctionEntry[] = []; const onFunctionEnter = (node: AST.TSESTreeFunction) => { const id = AST.getFunctionId(node); - const key = getId(); + const key = idGen.next(); const name = id?.name; if (name != null && isReactHookName(name)) { functionEntries.push({ key, node, isHook: true }); diff --git a/packages/shared/docs/README.md b/packages/shared/docs/README.md index b588784385..e427025951 100644 --- a/packages/shared/docs/README.md +++ b/packages/shared/docs/README.md @@ -4,6 +4,10 @@ # @eslint-react/shared +## Classes + +- [IdGenerator](classes/IdGenerator.md) + ## Interfaces - [CompatibleConfig](interfaces/CompatibleConfig.md) diff --git a/packages/shared/docs/classes/IdGenerator.md b/packages/shared/docs/classes/IdGenerator.md new file mode 100644 index 0000000000..5ac19227c3 --- /dev/null +++ b/packages/shared/docs/classes/IdGenerator.md @@ -0,0 +1,41 @@ +[**@eslint-react/shared**](../README.md) + +*** + +[@eslint-react/shared](../README.md) / IdGenerator + +# Class: IdGenerator + +A generator for unique ids. + +## Constructors + +### Constructor + +> **new IdGenerator**(`prefix`): `IdGenerator` + +#### Parameters + +##### prefix + +`string` = `"id_"` + +Optional. A prefix of generated ids. + +#### Returns + +`IdGenerator` + +## Methods + +### next() + +> **next**(): `string` + +Generates id. + +#### Returns + +`string` + +A generated id. diff --git a/packages/shared/src/_id.ts b/packages/shared/src/_id.ts index 03cbd699ad..699bef4ad8 100644 --- a/packages/shared/src/_id.ts +++ b/packages/shared/src/_id.ts @@ -1,6 +1,28 @@ -let id = 0n; +// ------------------------------------------------------------------------------ +// Public Interface +// ------------------------------------------------------------------------------ /** - * @internal + * A generator for unique ids. */ -export const getId = () => (id++).toString(); +class IdGenerator { + private n: bigint; + private prefix: string; + /** + * @param prefix Optional. A prefix of generated ids. + */ + constructor(prefix: string = "id_") { + this.prefix = prefix; + this.n = 0n; + } + /** + * Generates id. + * @returns A generated id. + */ + next() { + this.n = (1n + this.n) | 0n; + return this.prefix + this.n.toString(16); + } +} + +export { IdGenerator }; From dba5967f36e5a19c3e40b53d7780c1b6fec09c6e Mon Sep 17 00:00:00 2001 From: REL1CX Date: Tue, 4 Nov 2025 16:18:29 +0800 Subject: [PATCH 2/3] Update packages/shared/src/_id.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: REL1CX --- packages/shared/src/_id.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/src/_id.ts b/packages/shared/src/_id.ts index 699bef4ad8..6addc80910 100644 --- a/packages/shared/src/_id.ts +++ b/packages/shared/src/_id.ts @@ -16,7 +16,7 @@ class IdGenerator { this.n = 0n; } /** - * Generates id. + * Generates an id. * @returns A generated id. */ next() { From d9e5b0fe61b8e00d501ed0d1957077440fa7095f Mon Sep 17 00:00:00 2001 From: REL1CX Date: Tue, 4 Nov 2025 16:19:05 +0800 Subject: [PATCH 3/3] Update packages/shared/src/_id.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: REL1CX --- packages/shared/src/_id.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/src/_id.ts b/packages/shared/src/_id.ts index 6addc80910..ec8fdbdc62 100644 --- a/packages/shared/src/_id.ts +++ b/packages/shared/src/_id.ts @@ -20,7 +20,7 @@ class IdGenerator { * @returns A generated id. */ next() { - this.n = (1n + this.n) | 0n; + this.n = 1n + this.n; return this.prefix + this.n.toString(16); } }