Skip to content

Commit 5eb5f5d

Browse files
committed
chore: format
1 parent 06728f5 commit 5eb5f5d

2 files changed

Lines changed: 87 additions & 84 deletions

File tree

packages/codegen-core/src/planner/planner.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ export class Planner {
418418
while (true) {
419419
const language = node?.language || symbol.node?.language || file.language;
420420

421-
const ok = this.nameIsAvailable(scope, finalName, language, symbol.kind);
421+
const ok = this.nameIsAvailable({ kind: symbol.kind, language, name: finalName, scope });
422422
if (ok) break;
423423

424424
const resolver =
@@ -451,12 +451,17 @@ export class Planner {
451451
* that name is compatible (i.e., can share the same identifier) with `kind`.
452452
* This avoids copying the entire accumulated name map on every call.
453453
*/
454-
private nameIsAvailable(
455-
scope: Scope,
456-
name: string,
457-
language: string | undefined,
458-
kind: SymbolKind,
459-
): boolean {
454+
private nameIsAvailable({
455+
kind,
456+
language,
457+
name,
458+
scope,
459+
}: {
460+
kind: SymbolKind;
461+
language: string | undefined;
462+
name: string;
463+
scope: Scope;
464+
}): boolean {
460465
let current: Scope | undefined = scope;
461466
while (current) {
462467
const kinds = current.localNames.get(name);

packages/codegen-core/src/symbols/registry.ts

Lines changed: 75 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ type QueryCacheKey = string;
88
type SymbolId = number;
99

1010
export class SymbolRegistry implements ISymbolRegistry {
11+
/** Forward index: cache key → serialized entries it depends on. */
12+
private _cacheDependencies: Map<QueryCacheKey, ReadonlyArray<string>> = new Map();
13+
/** Reverse index: serialized index entry → set of cache keys that depend on it. */
14+
private _dependencyToCache: Map<QueryCacheKey, Set<QueryCacheKey>> = new Map();
1115
private _id: SymbolId = 0;
1216
private _indices: Map<IndexEntry[0], Map<IndexEntry[1], Set<SymbolId>>> = new Map();
1317
private _queryCache: Map<QueryCacheKey, ReadonlyArray<Symbol>> = new Map();
14-
/** Reverse index: serialized index entry → set of cache keys that depend on it. */
15-
private _dependencyToCache: Map<QueryCacheKey, Set<QueryCacheKey>> = new Map();
16-
/** Forward index: cache key → serialized entries it depends on, for clean eviction. */
17-
private _cacheDependencies: Map<QueryCacheKey, ReadonlyArray<string>> = new Map();
1818
private _registered: Set<SymbolId> = new Set();
1919
private _stubs: Set<SymbolId> = new Set();
2020
private _stubCache: Map<QueryCacheKey, SymbolId> = new Map();
@@ -80,6 +80,73 @@ export class SymbolRegistry implements ISymbolRegistry {
8080
}
8181
}
8282

83+
private buildIndexKeySpace(meta: ISymbolMeta, prefix = ''): IndexKeySpace {
84+
const entries: Array<IndexEntry> = [];
85+
for (const [key, value] of Object.entries(meta)) {
86+
const path = prefix ? `${prefix}.${key}` : key;
87+
if (value && typeof value === 'object' && !Array.isArray(value)) {
88+
entries.push(...this.buildIndexKeySpace(value as ISymbolMeta, path));
89+
} else {
90+
entries.push([path, value]);
91+
}
92+
}
93+
return entries;
94+
}
95+
96+
/**
97+
* Derives a stable, order-insensitive cache key from a pre-built key space.
98+
* Avoids rebuilding the key space when it's already available.
99+
*/
100+
private cacheKeyFromKeySpace(indexKeySpace: IndexKeySpace): QueryCacheKey {
101+
return indexKeySpace
102+
.map((indexEntry) => this.serializeIndexEntry(indexEntry))
103+
.sort() // ensure order-insensitivity
104+
.join('|');
105+
}
106+
107+
private indexSymbol(symbolId: SymbolId, indexKeySpace: IndexKeySpace): void {
108+
for (const [key, value] of indexKeySpace) {
109+
if (!this._indices.has(key)) this._indices.set(key, new Map());
110+
const values = this._indices.get(key)!;
111+
const set = values.get(value) ?? new Set();
112+
set.add(symbolId);
113+
values.set(value, set);
114+
}
115+
}
116+
117+
private invalidateCache(indexKeySpace: IndexKeySpace): void {
118+
for (const indexEntry of indexKeySpace) {
119+
const serialized = this.serializeIndexEntry(indexEntry);
120+
const cacheKeys = this._dependencyToCache.get(serialized);
121+
if (!cacheKeys) continue;
122+
for (const cacheKey of cacheKeys) {
123+
this._queryCache.delete(cacheKey);
124+
// Clean up stale reverse-index references so _dependencyToCache doesn't
125+
// accumulate orphaned entries for evicted cache keys.
126+
const deps = this._cacheDependencies.get(cacheKey);
127+
if (deps) {
128+
for (const dep of deps) {
129+
if (dep !== serialized) {
130+
this._dependencyToCache.get(dep)?.delete(cacheKey);
131+
}
132+
}
133+
this._cacheDependencies.delete(cacheKey);
134+
}
135+
}
136+
this._dependencyToCache.delete(serialized);
137+
}
138+
}
139+
140+
private isSubset(sub: IndexKeySpace, sup: IndexKeySpace): boolean {
141+
const supMap = new Map(sup);
142+
for (const [key, value] of sub) {
143+
if (!supMap.has(key) || supMap.get(key) !== value) {
144+
return false;
145+
}
146+
}
147+
return true;
148+
}
149+
83150
private queryByKeySpace(
84151
indexKeySpace: IndexKeySpace,
85152
cacheKey: QueryCacheKey,
@@ -109,14 +176,12 @@ export class SymbolRegistry implements ISymbolRegistry {
109176
return [];
110177
}
111178

112-
// We are basically trying to do Set intersection here. But with large OpenAPI spec
113-
// we may get a few very large sets.
114-
//
115-
// The flamegraph/profiling shows that the Set operations (has, delete) became
116-
// a very huge bottleneck.
179+
// We want to do a Set intersection, but large inputs may contain a few very
180+
// large sets. The profiling showed that Set operations became a huge bottleneck
181+
// on such inputs.
117182
//
118183
// To avoid iterating over large sets multiple times, we sort the sets by size
119-
// and use the smallest set as the base to minimise iterations and deletions.
184+
// and use the smallest set as the base to minimize iterations and deletions.
120185
sets.sort((a, b) => a.size - b.size);
121186
const result = new Set(sets[0]);
122187
for (let i = 1; i < sets.length; i++) {
@@ -132,17 +197,6 @@ export class SymbolRegistry implements ISymbolRegistry {
132197
return symbols;
133198
}
134199

135-
/**
136-
* Derives a stable, order-insensitive cache key from a pre-built key space.
137-
* Avoids rebuilding the key space when it's already available.
138-
*/
139-
private cacheKeyFromKeySpace(indexKeySpace: IndexKeySpace): QueryCacheKey {
140-
return indexKeySpace
141-
.map((indexEntry) => this.serializeIndexEntry(indexEntry))
142-
.sort() // ensure order-insensitivity
143-
.join('|');
144-
}
145-
146200
/**
147201
* Registers reverse-index entries so that when any of the given index entries
148202
* are invalidated, the cache key is evicted in O(1) per entry.
@@ -162,62 +216,6 @@ export class SymbolRegistry implements ISymbolRegistry {
162216
this._cacheDependencies.set(cacheKey, serializedEntries);
163217
}
164218

165-
private buildIndexKeySpace(meta: ISymbolMeta, prefix = ''): IndexKeySpace {
166-
const entries: Array<IndexEntry> = [];
167-
for (const [key, value] of Object.entries(meta)) {
168-
const path = prefix ? `${prefix}.${key}` : key;
169-
if (value && typeof value === 'object' && !Array.isArray(value)) {
170-
entries.push(...this.buildIndexKeySpace(value as ISymbolMeta, path));
171-
} else {
172-
entries.push([path, value]);
173-
}
174-
}
175-
return entries;
176-
}
177-
178-
private indexSymbol(symbolId: SymbolId, indexKeySpace: IndexKeySpace): void {
179-
for (const [key, value] of indexKeySpace) {
180-
if (!this._indices.has(key)) this._indices.set(key, new Map());
181-
const values = this._indices.get(key)!;
182-
const set = values.get(value) ?? new Set();
183-
set.add(symbolId);
184-
values.set(value, set);
185-
}
186-
}
187-
188-
private invalidateCache(indexKeySpace: IndexKeySpace): void {
189-
for (const indexEntry of indexKeySpace) {
190-
const serialized = this.serializeIndexEntry(indexEntry);
191-
const cacheKeys = this._dependencyToCache.get(serialized);
192-
if (!cacheKeys) continue;
193-
for (const cacheKey of cacheKeys) {
194-
this._queryCache.delete(cacheKey);
195-
// Clean up stale reverse-index references so _dependencyToCache doesn't
196-
// accumulate orphaned entries for evicted cache keys.
197-
const deps = this._cacheDependencies.get(cacheKey);
198-
if (deps) {
199-
for (const dep of deps) {
200-
if (dep !== serialized) {
201-
this._dependencyToCache.get(dep)?.delete(cacheKey);
202-
}
203-
}
204-
this._cacheDependencies.delete(cacheKey);
205-
}
206-
}
207-
this._dependencyToCache.delete(serialized);
208-
}
209-
}
210-
211-
private isSubset(sub: IndexKeySpace, sup: IndexKeySpace): boolean {
212-
const supMap = new Map(sup);
213-
for (const [key, value] of sub) {
214-
if (!supMap.has(key) || supMap.get(key) !== value) {
215-
return false;
216-
}
217-
}
218-
return true;
219-
}
220-
221219
private replaceStubs(symbol: Symbol, indexKeySpace: IndexKeySpace): void {
222220
for (const stubId of this._stubs.values()) {
223221
const stub = this._values.get(stubId);

0 commit comments

Comments
 (0)