Skip to content

Commit 85627b8

Browse files
ocavuesxzz
andauthored
fix: handle type parameters with the same name (#126)
Co-authored-by: Kevin Deng <sxzz@sxzz.moe>
1 parent b4077ba commit 85627b8

File tree

4 files changed

+68
-50
lines changed

4 files changed

+68
-50
lines changed

src/fake-js.ts

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,19 @@ import type { Plugin, RenderedChunk } from 'rolldown'
2525
// export declare function x$1(xx: X$1): void
2626

2727
type Dep = t.Expression & { replace?: (newNode: t.Node) => void }
28+
29+
/**
30+
* A collection of type parameters grouped by parameter name
31+
*/
32+
type GroupedTypeParams = Array<{
33+
name: string
34+
typeParams: t.TSTypeParameter[]
35+
}>
36+
2837
interface SymbolInfo {
2938
decl: t.Declaration
3039
bindings: t.Identifier[]
31-
params: t.TSTypeParameter[]
40+
params: GroupedTypeParams
3241
deps: Dep[]
3342
}
3443

@@ -179,11 +188,7 @@ export function createFakeJsPlugin({
179188
decl.id = binding
180189
}
181190

182-
const params: t.TSTypeParameter[] =
183-
'typeParameters' in decl &&
184-
decl.typeParameters?.type === 'TSTypeParameterDeclaration'
185-
? decl.typeParameters.params
186-
: []
191+
const params: GroupedTypeParams = collectParams(decl)
187192

188193
const deps = collectDependencies(decl, namespaceStmts)
189194

@@ -200,7 +205,7 @@ export function createFakeJsPlugin({
200205

201206
const symbolIdNode = t.numericLiteral(symbolId)
202207
const depsNode = t.arrowFunctionExpression(
203-
params.map((param) => t.identifier(param.name)),
208+
params.map(({ name }) => t.identifier(name)),
204209
t.arrayExpression(deps),
205210
)
206211
const sideEffectNode =
@@ -312,10 +317,12 @@ export function createFakeJsPlugin({
312317
}
313318

314319
const transformedParams = depsFn.params as t.Identifier[]
315-
for (let i = 0; i < original.params.length; i++) {
316-
const originalParam = original.params[i]
317-
const transformedParam = transformedParams[i]
318-
originalParam.name = transformedParam.name
320+
321+
for (const [i, transformedParam] of transformedParams.entries()) {
322+
const transformedName = transformedParam.name
323+
for (const originalTypeParam of original.params[i].typeParams) {
324+
originalTypeParam.name = transformedName
325+
}
319326
}
320327

321328
const transformedDeps = (depsFn.body as t.ArrayExpression)
@@ -385,6 +392,42 @@ export function createFakeJsPlugin({
385392
return symbolMap.get(symbolId)!
386393
}
387394

395+
/**
396+
* Collects all TSTypeParameter nodes from the given node and groups them by
397+
* their name. One name can associate with one or more type parameters. These
398+
* names will be used as the parameter name in the generated JavaScript
399+
* dependency function.
400+
*/
401+
function collectParams(node: t.Node): GroupedTypeParams {
402+
const typeParams: t.TSTypeParameter[] = []
403+
;(walk as any)(node, {
404+
leave(node: t.Node) {
405+
if (
406+
'typeParameters' in node &&
407+
node.typeParameters?.type === 'TSTypeParameterDeclaration'
408+
) {
409+
typeParams.push(...node.typeParameters.params)
410+
}
411+
},
412+
})
413+
414+
const paramMap = new Map<string, t.TSTypeParameter[]>()
415+
for (const typeParam of typeParams) {
416+
const name = typeParam.name
417+
const group = paramMap.get(name)
418+
if (group) {
419+
group.push(typeParam)
420+
} else {
421+
paramMap.set(name, [typeParam])
422+
}
423+
}
424+
425+
return Array.from(paramMap.entries()).map(([name, typeParams]) => ({
426+
name,
427+
typeParams,
428+
}))
429+
}
430+
388431
function collectDependencies(
389432
node: t.Node,
390433
namespaceStmts: NamespaceMap,

tests/__snapshots__/index.test.ts.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ export = _default;"
8181
`;
8282
8383
exports[`cyclic import 1`] = `
84-
"// a-xNP_tEJE.d.ts
84+
"// a-C1hvFFD1.d.ts
8585
//#region b.d.ts
8686
declare class SomeClass<T$1 extends SomeInterface<number>> {
8787
value: T$1;
8888
constructor(value: T$1);
89-
doSomething<T extends SomeInterface<number>>(value: T$1): T$1;
89+
doSomething<T$1 extends SomeInterface<number>>(value: T$1): T$1;
9090
}
9191
type SomeBoolean = boolean;
9292
//#endregion
@@ -98,10 +98,10 @@ type T = SomeBoolean;
9898
//#endregion
9999
export { SomeClass as i, T as n, SomeBoolean as r, SomeInterface as t };
100100
// a.d.ts
101-
import { n as T, t as SomeInterface } from "./a-xNP_tEJE.js";
101+
import { n as T, t as SomeInterface } from "./a-C1hvFFD1.js";
102102
export { SomeInterface, T };
103103
// b.d.ts
104-
import { i as SomeClass, r as SomeBoolean } from "./a-xNP_tEJE.js";
104+
import { i as SomeClass, r as SomeBoolean } from "./a-C1hvFFD1.js";
105105
export { SomeBoolean, SomeClass };"
106106
`;
107107

tests/rollup-plugin-dts/generics/known-diff.patch

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,8 @@ Index: diff.patch
22
===================================================================
33
--- diff.patch
44
+++ diff.patch
5-
@@ -13,23 +13,22 @@
6-
interface M {}
7-
interface N {}
8-
interface O {}
9-
interface P {}
10-
-declare type Gen<T> = T
11-
-interface I1<T = A> {
12-
- a: T
13-
+declare type Gen<T$1> = T$1
14-
+interface I1<T$1 = A> {
15-
+ a: T$1
16-
b: Gen<B>
17-
}
18-
-declare type Ty<T = C> = {
19-
- c: T
20-
+declare type Ty<T$1 = C> = {
21-
+ c: T$1
22-
d: Gen<D>
23-
}
24-
-declare class Cl<T = E> {
25-
- e: T
26-
+declare class Cl<T$1 = E> {
27-
+ e: T$1
28-
f: Gen<F>
29-
}
30-
-declare function fn<T = G>(g: T, h: Gen<H>): void
31-
+declare function fn<T$1 = G>(g: T$1, h: Gen<H>): void
5+
@@ -30,6 +30,5 @@
6+
declare function fn<T = G>(g: T, h: Gen<H>): void
327
declare type TyFn = <T = J>(j: T, k: Gen<K>) => L
338
declare type TyCtor = new <T = M>(m: T, n: Gen<N>) => O
349
interface I2 extends Gen<P> {}

tests/rollup-plugin-dts/generics/snapshot.d.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ interface M {}
1515
interface N {}
1616
interface O {}
1717
interface P {}
18-
declare type Gen<T$1> = T$1;
19-
interface I1<T$1 = A> {
20-
a: T$1;
18+
declare type Gen<T> = T;
19+
interface I1<T = A> {
20+
a: T;
2121
b: Gen<B>;
2222
}
23-
declare type Ty<T$1 = C> = {
24-
c: T$1;
23+
declare type Ty<T = C> = {
24+
c: T;
2525
d: Gen<D>;
2626
};
27-
declare class Cl<T$1 = E> {
28-
e: T$1;
27+
declare class Cl<T = E> {
28+
e: T;
2929
f: Gen<F>;
3030
}
31-
declare function fn<T$1 = G>(g: T$1, h: Gen<H>): void;
31+
declare function fn<T = G>(g: T, h: Gen<H>): void;
3232
declare type TyFn = <T = J>(j: T, k: Gen<K>) => L;
3333
declare type TyCtor = new <T = M>(m: T, n: Gen<N>) => O;
3434
interface I2 extends Gen<P> {}

0 commit comments

Comments
 (0)