fork of hey-api/openapi-ts because I need some additional things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: language-aware declaration sharing check

Lubos 86c71151 01095085

+68 -7
+5
.changeset/stale-spiders-sleep.md
··· 1 + --- 2 + "@hey-api/codegen-core": patch 3 + --- 4 + 5 + **planner**: language-aware declaration sharing check
+43
packages/codegen-core/src/__tests__/project.test.ts
··· 1 + import { canDeclarationsShareIdentifier } from '../project/namespace'; 1 2 import { Project } from '../project/project'; 3 + import type { SymbolKind } from '../symbols/types'; 2 4 3 5 // Mock Planner so we control what files appear in project.files 4 6 vi.mock('../planner/planner', () => { ··· 54 56 }); 55 57 }); 56 58 }); 59 + 60 + describe('canDeclarationsShareIdentifier', () => { 61 + const kinds: ReadonlyArray<SymbolKind> = [ 62 + 'class', 63 + 'enum', 64 + 'function', 65 + 'interface', 66 + 'namespace', 67 + 'type', 68 + 'var', 69 + ]; 70 + 71 + it('matches TypeScript declaration merging matrix', () => { 72 + const allowed = new Set([ 73 + 'interface|interface', 74 + 'class|interface', 75 + 'class|namespace', 76 + 'enum|namespace', 77 + 'function|namespace', 78 + 'namespace|namespace', 79 + 'function|type', 80 + 'type|var', 81 + ]); 82 + 83 + for (const a of kinds) { 84 + for (const b of kinds) { 85 + expect(canDeclarationsShareIdentifier('typescript', a, b)).toBe( 86 + allowed.has([a, b].sort().join('|')), 87 + ); 88 + } 89 + } 90 + }); 91 + 92 + it('returns false for Python declaration pairs', () => { 93 + for (const a of kinds) { 94 + for (const b of kinds) { 95 + expect(canDeclarationsShareIdentifier('python', a, b)).toBe(false); 96 + } 97 + } 98 + }); 99 + });
+4 -4
packages/codegen-core/src/planner/planner.ts
··· 4 4 import type { IProjectRenderMeta } from '../extensions'; 5 5 import type { File } from '../files/file'; 6 6 import type { INode } from '../nodes/node'; 7 - import { canShareName } from '../project/namespace'; 7 + import { canDeclarationsShareIdentifier } from '../project/namespace'; 8 8 import type { IProject } from '../project/types'; 9 9 import { fromRef } from '../refs/refs'; 10 10 import type { RenderContext } from '../renderer'; ··· 417 417 418 418 const localNames = ctx.localNames(scope); 419 419 while (true) { 420 + const language = node?.language || symbol.node?.language || file.language; 421 + 420 422 const kinds = [...(localNames.get(finalName) ?? [])]; 421 423 422 - // TODO: adjust canShareName for language 423 - const ok = kinds.every((kind) => canShareName(symbol.kind, kind)); 424 + const ok = kinds.every((kind) => canDeclarationsShareIdentifier(language, symbol.kind, kind)); 424 425 if (ok) break; 425 426 426 - const language = node?.language || symbol.node?.language || file.language; 427 427 const resolver = 428 428 (language ? this.project.nameConflictResolvers[language] : undefined) ?? 429 429 this.project.defaultNameConflictResolver;
+16 -3
packages/codegen-core/src/project/namespace.ts
··· 1 + import type { Language } from '../languages/types'; 1 2 import type { SymbolKind } from '../symbols/types'; 2 3 3 - const kindRank: Record<SymbolKind, number> = { 4 + const typescriptMergeKindRank: Record<SymbolKind, number> = { 4 5 class: 3, 5 6 enum: 4, 6 7 function: 5, ··· 14 15 * Returns true if two declarations of given kinds 15 16 * are allowed to share the same identifier in TypeScript. 16 17 */ 17 - export function canShareName(a: SymbolKind, b: SymbolKind): boolean { 18 + function canTypeScriptDeclarationsShareIdentifier(a: SymbolKind, b: SymbolKind): boolean { 18 19 // sort based on TypeScript merge precedence so `a` is always the weaker merge candidate 19 20 // ensures that asymmetric merges like `type + var` are correctly handled 20 - if (kindRank[a] > kindRank[b]) { 21 + if (typescriptMergeKindRank[a] > typescriptMergeKindRank[b]) { 21 22 [a, b] = [b, a]; 22 23 } 23 24 ··· 33 34 return false; 34 35 } 35 36 } 37 + 38 + export function canDeclarationsShareIdentifier( 39 + language: Language | undefined, 40 + a: SymbolKind, 41 + b: SymbolKind, 42 + ): boolean { 43 + if (language === 'typescript') { 44 + return canTypeScriptDeclarationsShareIdentifier(a, b); 45 + } 46 + 47 + return false; 48 + }