1
1
import path from "path" ;
2
2
import ts from "typescript" ;
3
+ import { alias } from "../alias" ;
3
4
import { upsert } from "../util/upsert" ;
4
5
import { projectDir } from "./projectDir" ;
5
6
@@ -24,7 +25,7 @@ export function generate(
24
25
25
26
let result = "" ;
26
27
27
- const replacementTargets = scanBetterFile ( libFile ) ;
28
+ const replacementTargets = scanBetterFile ( printer , libFile ) ;
28
29
29
30
if ( replacementTargets . size === 0 ) {
30
31
for ( const statement of originalFile . statements ) {
@@ -188,7 +189,10 @@ type ReplacementTarget = (
188
189
/**
189
190
* Scan better lib file to determine which statements need to be replaced.
190
191
*/
191
- function scanBetterFile ( libFile : string ) : Map < string , ReplacementTarget [ ] > {
192
+ function scanBetterFile (
193
+ printer : ts . Printer ,
194
+ libFile : string
195
+ ) : Map < string , ReplacementTarget [ ] > {
192
196
const replacementTargets = new Map < string , ReplacementTarget [ ] > ( ) ;
193
197
{
194
198
const betterLibFile = path . join ( betterLibDir , `lib.${ libFile } ` ) ;
@@ -198,43 +202,58 @@ function scanBetterFile(libFile: string): Map<string, ReplacementTarget[]> {
198
202
// Scan better file to determine which statements need to be replaced.
199
203
for ( const statement of betterFile . statements ) {
200
204
const name = getStatementDeclName ( statement ) ?? "" ;
201
- if ( ts . isInterfaceDeclaration ( statement ) ) {
202
- const members = new Map <
203
- string ,
204
- {
205
- member : ts . TypeElement ;
206
- text : string ;
207
- } [ ]
208
- > ( ) ;
209
- for ( const member of statement . members ) {
210
- const memberName = member . name ?. getText ( betterFile ) ?? "" ;
211
- upsert ( members , memberName , ( members = [ ] ) => {
212
- members . push ( {
213
- member,
214
- text : member . getFullText ( betterFile ) ,
205
+ const aliasesMap =
206
+ alias . get ( name ) ?? new Map ( [ [ name , new Map < string , string > ( ) ] ] ) ;
207
+ for ( const [ targetName , typeMap ] of aliasesMap ) {
208
+ const transformedStatement = replaceAliases ( statement , typeMap ) ;
209
+ if ( ts . isInterfaceDeclaration ( transformedStatement ) ) {
210
+ const members = new Map <
211
+ string ,
212
+ {
213
+ member : ts . TypeElement ;
214
+ text : string ;
215
+ } [ ]
216
+ > ( ) ;
217
+ for ( const member of transformedStatement . members ) {
218
+ const memberName = member . name ?. getText ( betterFile ) ?? "" ;
219
+ upsert ( members , memberName , ( members = [ ] ) => {
220
+ const leadingSpacesMatch = / ^ \s * / . exec (
221
+ member . getFullText ( betterFile )
222
+ ) ;
223
+ const leadingSpaces =
224
+ leadingSpacesMatch !== null ? leadingSpacesMatch [ 0 ] : "" ;
225
+ members . push ( {
226
+ member,
227
+ text :
228
+ leadingSpaces +
229
+ printer . printNode (
230
+ ts . EmitHint . Unspecified ,
231
+ member ,
232
+ betterFile
233
+ ) ,
234
+ } ) ;
235
+ return members ;
215
236
} ) ;
216
- return members ;
217
- } ) ;
218
- }
219
-
220
- upsert ( replacementTargets , name , ( targets = [ ] ) => {
221
- targets . push ( {
222
- type : "interface" ,
223
- members,
224
- originalStatement : statement ,
225
- sourceFile : betterFile ,
237
+ }
238
+ upsert ( replacementTargets , targetName , ( targets = [ ] ) => {
239
+ targets . push ( {
240
+ type : "interface" ,
241
+ members,
242
+ originalStatement : transformedStatement ,
243
+ sourceFile : betterFile ,
244
+ } ) ;
245
+ return targets ;
226
246
} ) ;
227
- return targets ;
228
- } ) ;
229
- } else {
230
- upsert ( replacementTargets , name , ( statements = [ ] ) => {
231
- statements . push ( {
232
- type : "non-interface" ,
233
- statement ,
234
- sourceFile : betterFile ,
247
+ } else {
248
+ upsert ( replacementTargets , targetName , ( statements = [ ] ) => {
249
+ statements . push ( {
250
+ type : "non-interface" ,
251
+ statement : transformedStatement ,
252
+ sourceFile : betterFile ,
253
+ } ) ;
254
+ return statements ;
235
255
} ) ;
236
- return statements ;
237
- } ) ;
256
+ }
238
257
}
239
258
}
240
259
}
@@ -372,3 +391,29 @@ function commentOut(code: string): string {
372
391
const result = lines . map ( ( line ) => `// ${ line } ` ) ;
373
392
return result . join ( "\n" ) + "\n" ;
374
393
}
394
+
395
+ function replaceAliases (
396
+ statement : ts . Statement ,
397
+ typeMap : Map < string , string >
398
+ ) : ts . Statement {
399
+ if ( typeMap . size === 0 ) return statement ;
400
+ return ts . transform ( statement , [
401
+ ( context ) => ( sourceStatement ) => {
402
+ const visitor = ( node : ts . Node ) : ts . Node => {
403
+ if ( ts . isTypeReferenceNode ( node ) && ts . isIdentifier ( node . typeName ) ) {
404
+ const replacementType = typeMap . get ( node . typeName . text ) ;
405
+ if ( replacementType === undefined ) {
406
+ return node ;
407
+ }
408
+ return ts . factory . updateTypeReferenceNode (
409
+ node ,
410
+ ts . factory . createIdentifier ( replacementType ) ,
411
+ node . typeArguments
412
+ ) ;
413
+ }
414
+ return ts . visitEachChild ( node , visitor , context ) ;
415
+ } ;
416
+ return ts . visitNode ( sourceStatement , visitor ) ;
417
+ } ,
418
+ ] ) . transformed [ 0 ] ;
419
+ }
0 commit comments