@@ -14,6 +14,7 @@ import {ReflectionHost} from '../../reflection';
14
14
15
15
import { Context } from './context' ;
16
16
import { ImportManager } from './import_manager' ;
17
+ import { TypeEmitter } from './type_emitter' ;
17
18
18
19
19
20
export function translateType (
@@ -79,12 +80,13 @@ class TypeTranslatorVisitor implements o.ExpressionVisitor, o.TypeVisitor {
79
80
return ts . factory . createTypeLiteralNode ( [ indexSignature ] ) ;
80
81
}
81
82
82
- visitTransplantedType ( ast : o . TransplantedType < ts . Node > , context : any ) {
83
+ visitTransplantedType ( ast : o . TransplantedType < ts . Node > , context : Context ) {
83
84
if ( ! ts . isTypeNode ( ast . type ) ) {
84
85
throw new Error ( `A TransplantedType must wrap a TypeNode` ) ;
85
86
}
86
87
87
- return this . translateTransplantedTypeNode ( ast . type , context ) ;
88
+ const emitter = new TypeEmitter ( typeRef => this . translateTypeReference ( typeRef , context ) ) ;
89
+ return emitter . emitType ( ast . type ) ;
88
90
}
89
91
90
92
visitReadVarExpr ( ast : o . ReadVarExpr , context : Context ) : ts . TypeQueryNode {
@@ -253,70 +255,28 @@ class TypeTranslatorVisitor implements o.ExpressionVisitor, o.TypeVisitor {
253
255
return typeNode ;
254
256
}
255
257
256
- /**
257
- * Translates a type reference node so that all of its references
258
- * are imported into the context file.
259
- */
260
- private translateTransplantedTypeReferenceNode (
261
- node : ts . TypeReferenceNode & { typeName : ts . Identifier } , context : any ) : ts . TypeReferenceNode {
262
- const declaration = this . reflector . getDeclarationOfIdentifier ( node . typeName ) ;
263
-
258
+ private translateTypeReference ( type : ts . TypeReferenceNode , context : Context ) : ts . TypeReferenceNode
259
+ | null {
260
+ const target = ts . isIdentifier ( type . typeName ) ? type . typeName : type . typeName . right ;
261
+ const declaration = this . reflector . getDeclarationOfIdentifier ( target ) ;
264
262
if ( declaration === null ) {
265
263
throw new Error (
266
- `Unable to statically determine the declaration file of type node ${ node . typeName . text } ` ) ;
264
+ `Unable to statically determine the declaration file of type node ${ target . text } ` ) ;
267
265
}
268
266
269
267
const emittedType = this . refEmitter . emit (
270
268
new Reference ( declaration . node ) , this . contextFile ,
271
269
ImportFlags . NoAliasing | ImportFlags . AllowTypeImports |
272
270
ImportFlags . AllowRelativeDtsImports ) ;
273
271
274
- assertSuccessfulReferenceEmit ( emittedType , node , 'type' ) ;
275
-
276
- const result = emittedType . expression . visitExpression ( this , context ) ;
272
+ assertSuccessfulReferenceEmit ( emittedType , target , 'type' ) ;
277
273
278
- if ( ! ts . isTypeReferenceNode ( result ) ) {
279
- throw new Error ( `Expected TypeReferenceNode when referencing the type for ${
280
- node . typeName . text } , but received ${ ts . SyntaxKind [ result . kind ] } `) ;
281
- }
274
+ const typeNode = this . translateExpression ( emittedType . expression , context ) ;
282
275
283
- // If the original node doesn't have any generic parameters we return the results.
284
- if ( node . typeArguments === undefined || node . typeArguments . length === 0 ) {
285
- return result ;
276
+ if ( ! ts . isTypeReferenceNode ( typeNode ) ) {
277
+ throw new Error (
278
+ `Expected TypeReferenceNode for emitted reference, got ${ ts . SyntaxKind [ typeNode . kind ] } .` ) ;
286
279
}
287
-
288
- // If there are any generics, we have to reflect them as well.
289
- const translatedArgs =
290
- node . typeArguments . map ( arg => this . translateTransplantedTypeNode ( arg , context ) ) ;
291
-
292
- return ts . factory . updateTypeReferenceNode (
293
- result , result . typeName , ts . factory . createNodeArray ( translatedArgs ) ) ;
294
- }
295
-
296
- /**
297
- * Translates a type node so that all of the type references it
298
- * contains are imported and can be referenced in the context file.
299
- */
300
- private translateTransplantedTypeNode ( rootNode : ts . TypeNode , context : any ) : ts . TypeNode {
301
- const factory : ts . TransformerFactory < ts . Node > = transformContext => root => {
302
- const walk = ( node : ts . Node ) : ts . Node => {
303
- if ( ts . isTypeReferenceNode ( node ) && ts . isIdentifier ( node . typeName ) ) {
304
- const translated =
305
- this . translateTransplantedTypeReferenceNode ( node as ts . TypeReferenceNode & {
306
- typeName : ts . Identifier ;
307
- } , context ) ;
308
-
309
- if ( translated !== node ) {
310
- return translated ;
311
- }
312
- }
313
-
314
- return ts . visitEachChild ( node , walk , transformContext ) ;
315
- } ;
316
-
317
- return ts . visitNode ( root , walk ) ;
318
- } ;
319
-
320
- return ts . transform ( rootNode , [ factory ] ) . transformed [ 0 ] as ts . TypeNode ;
280
+ return typeNode ;
321
281
}
322
282
}
0 commit comments