diff --git a/packages/core/src/component/component-collector-legacy.ts b/packages/core/src/component/component-collector-legacy.ts index 00e2bd308..f7aa70a55 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 4780582bb..f72e9abc8 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 624422592..2e1a0c789 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 b58878438..e42702595 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 000000000..5ac19227c --- /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 03cbd699a..ec8fdbdc6 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 an id. + * @returns A generated id. + */ + next() { + this.n = 1n + this.n; + return this.prefix + this.n.toString(16); + } +} + +export { IdGenerator };