@@ -15,6 +15,7 @@ import {
1515 TcbInputMapping ,
1616 TcbPipeMetadata ,
1717 TypeCheckableDirectiveMeta ,
18+ TcbTypeParameter ,
1819} from '../api' ;
1920import { Environment } from './environment' ;
2021import { ImportFlags , ReferenceEmitKind , Reference } from '../../imports' ;
@@ -35,6 +36,7 @@ import {generateTcbTypeParameters} from './tcb_util';
3536import { TypeParameterEmitter } from './type_parameter_emitter' ;
3637import { ClassDeclaration } from '../../reflection' ;
3738import ts from 'typescript' ;
39+ import { TcbGenericContextBehavior } from './ops/context' ;
3840
3941/**
4042 * Adapts the compiler's `TypeCheckBlockMetadata` (which includes full TS AST nodes)
@@ -44,8 +46,11 @@ export function adaptTypeCheckBlockMetadata(
4446 ref : Reference < ClassDeclaration < ts . ClassDeclaration > > ,
4547 meta : TypeCheckBlockMetadata ,
4648 env : Environment ,
49+ genericContextBehavior : TcbGenericContextBehavior ,
4750) : { tcbMeta : TcbTypeCheckBlockMetadata ; component : TcbComponentMetadata } {
4851 const refCache = new Map < Reference < ClassDeclaration > , TcbReferenceMetadata > ( ) ;
52+ const dirCache = new Map < TypeCheckableDirectiveMeta , TcbDirectiveMetadata > ( ) ;
53+
4954 const extractRef = ( ref : Reference < ClassDeclaration > ) => {
5055 if ( refCache . has ( ref ) ) {
5156 return refCache . get ( ref ) ! ;
@@ -55,8 +60,6 @@ export function adaptTypeCheckBlockMetadata(
5560 return result ;
5661 } ;
5762
58- const dirCache = new Map < TypeCheckableDirectiveMeta , TcbDirectiveMetadata > ( ) ;
59-
6063 const convertDir = ( dir : TypeCheckableDirectiveMeta ) : TcbDirectiveMetadata => {
6164 if ( dirCache . has ( dir ) ) return dirCache . get ( dir ) ! ;
6265
@@ -110,45 +113,33 @@ export function adaptTypeCheckBlockMetadata(
110113
111114 ref : extractRef ( dir . ref as Reference < ClassDeclaration > ) ,
112115 isGeneric : dir . isGeneric ,
113-
114- typeParameters : ( ( ) => {
115- const node = dir . ref . node as ClassDeclaration < ts . ClassDeclaration > ;
116- if ( ! node . typeParameters ) {
117- return null ;
118- }
119- const emitter = new TypeParameterEmitter ( node . typeParameters , env . reflector ) ;
120- let emitted : ts . TypeParameterDeclaration [ ] | undefined ;
121- if ( ! emitter . canEmit ( ( ref ) => env . canReferenceType ( ref ) ) ) {
122- emitted = [ ...node . typeParameters ] as ts . TypeParameterDeclaration [ ] ;
123- } else {
124- emitted = emitter . emit ( ( ref ) => env . referenceType ( ref ) ) ;
125- }
126- return generateTcbTypeParameters ( emitted || [ ] , env . contextFile ) ;
127- } ) ( ) ,
128- hasRequiresInlineTypeCtor : requiresInlineTypeCtor (
116+ requiresInlineTypeCtor : requiresInlineTypeCtor (
129117 dir . ref . node as ClassDeclaration < ts . ClassDeclaration > ,
130118 env . reflector ,
131119 env ,
132120 ) ,
121+ ...adaptGenerics (
122+ dir . ref . node as ClassDeclaration < ts . ClassDeclaration > ,
123+ env ,
124+ TcbGenericContextBehavior . UseEmitter ,
125+ ) ,
133126 } ;
134127
135128 dirCache . set ( dir , tcbDir ) ;
136129 return tcbDir ;
137130 } ;
138131
132+ const originalBoundTarget = meta . boundTarget . target ;
139133 const adaptedBoundTarget : BoundTarget < TcbDirectiveMetadata > = {
140- target : ( ( ) => {
141- const originalTarget = meta . boundTarget . target ;
142- return {
143- template : originalTarget . template ,
144- host : originalTarget . host
145- ? {
146- node : originalTarget . host . node ,
147- directives : originalTarget . host . directives . map ( convertDir ) ,
148- }
149- : undefined ,
150- } ;
151- } ) ( ) ,
134+ target : {
135+ template : originalBoundTarget . template ,
136+ host : originalBoundTarget . host
137+ ? {
138+ node : originalBoundTarget . host . node ,
139+ directives : originalBoundTarget . host . directives . map ( convertDir ) ,
140+ }
141+ : undefined ,
142+ } ,
152143 getUsedDirectives : ( ) => meta . boundTarget . getUsedDirectives ( ) . map ( convertDir ) ,
153144 getEagerlyUsedDirectives : ( ) => meta . boundTarget . getEagerlyUsedDirectives ( ) . map ( convertDir ) ,
154145 getUsedPipes : ( ) => meta . boundTarget . getUsedPipes ( ) ,
@@ -208,25 +199,59 @@ export function adaptTypeCheckBlockMetadata(
208199 isStandalone : meta . isStandalone ,
209200 preserveWhitespaces : meta . preserveWhitespaces ,
210201 } ,
211- component : ( ( ) => {
212- return {
213- ref : extractRef ( ref as Reference < ClassDeclaration > ) ,
214- typeParameters : ( ( ) => {
215- if ( ! ref . node . typeParameters ) return null ;
216- const emitter = new TypeParameterEmitter ( ref . node . typeParameters , env . reflector ) ;
217- let emitted : ts . TypeParameterDeclaration [ ] | undefined ;
218- if ( ! emitter . canEmit ( ( r ) => env . canReferenceType ( r ) ) ) {
219- emitted = [ ...ref . node . typeParameters ] as ts . TypeParameterDeclaration [ ] ;
220- } else {
221- emitted = emitter . emit ( ( r ) => env . referenceType ( r ) ) ;
222- }
223- return generateTcbTypeParameters ( emitted || [ ] , env . contextFile ) ;
224- } ) ( ) ,
225- } ;
226- } ) ( ) ,
202+ component : {
203+ ref : extractRef ( ref as Reference < ClassDeclaration > ) ,
204+ ...adaptGenerics (
205+ ref . node ,
206+ env ,
207+ env . config . useContextGenericType
208+ ? genericContextBehavior
209+ : TcbGenericContextBehavior . FallbackToAny ,
210+ ) ,
211+ } ,
227212 } ;
228213}
229214
215+ function adaptGenerics (
216+ node : ClassDeclaration < ts . ClassDeclaration > ,
217+ env : Environment ,
218+ genericContextBehavior : TcbGenericContextBehavior ,
219+ ) : {
220+ typeParameters : TcbTypeParameter [ ] | null ;
221+ typeArguments : string [ ] | null ;
222+ } {
223+ let typeParameters : TcbTypeParameter [ ] | null ;
224+ let typeArguments : string [ ] | null ;
225+
226+ if ( node . typeParameters !== undefined && node . typeParameters . length > 0 ) {
227+ switch ( genericContextBehavior ) {
228+ case TcbGenericContextBehavior . UseEmitter :
229+ const emitter = new TypeParameterEmitter ( node . typeParameters , env . reflector ) ;
230+ const emittedParams = emitter . canEmit ( ( r ) => env . canReferenceType ( r ) )
231+ ? emitter . emit ( ( typeRef ) => env . referenceType ( typeRef ) )
232+ : undefined ;
233+ typeParameters = generateTcbTypeParameters (
234+ emittedParams || node . typeParameters ,
235+ env . contextFile ,
236+ ) ;
237+ typeArguments = typeParameters . map ( ( param ) => param . name ) ;
238+ break ;
239+ case TcbGenericContextBehavior . CopyClassNodes :
240+ typeParameters = generateTcbTypeParameters ( node . typeParameters , env . contextFile ) ;
241+ typeArguments = typeParameters . map ( ( param ) => param . name ) ;
242+ break ;
243+ case TcbGenericContextBehavior . FallbackToAny :
244+ typeParameters = generateTcbTypeParameters ( node . typeParameters , env . contextFile ) ;
245+ typeArguments = new Array < string > ( node . typeParameters . length ) . fill ( 'any' ) ;
246+ break ;
247+ }
248+ } else {
249+ typeParameters = typeArguments = null ;
250+ }
251+
252+ return { typeParameters, typeArguments} ;
253+ }
254+
230255function extractReferenceMetadata (
231256 ref : Reference < ClassDeclaration > ,
232257 env : Environment ,
0 commit comments