@@ -731,110 +731,145 @@ export class Resolver extends DiagnosticEmitter {
731731
732732 // infer generic call if type arguments have been omitted
733733 if ( prototype . is ( CommonFlags . Generic ) ) {
734- let contextualTypeArguments = cloneMap ( ctxFlow . contextualTypeArguments ) ;
734+ let resolvedTypeArguments = this . inferGenericTypesArguments (
735+ node ,
736+ prototype ,
737+ prototype . typeParameterNodes ,
738+ ctxFlow ,
739+ reportMode ,
740+ ) ;
741+
742+ return this . resolveFunction (
743+ prototype ,
744+ resolvedTypeArguments ,
745+ cloneMap ( ctxFlow . contextualTypeArguments ) ,
746+ reportMode
747+ ) ;
748+ }
735749
736- // fill up contextual types with auto for each generic component
737- let typeParameterNodes = assert ( prototype . typeParameterNodes ) ;
738- let numTypeParameters = typeParameterNodes . length ;
739- let typeParameterNames = new Set < string > ( ) ;
740- for ( let i = 0 ; i < numTypeParameters ; ++ i ) {
741- let name = typeParameterNodes [ i ] . name . text ;
742- contextualTypeArguments . set ( name , Type . auto ) ;
743- typeParameterNames . add ( name ) ;
744- }
745-
746- let parameterNodes = prototype . functionTypeNode . parameters ;
747- let numParameters = parameterNodes . length ;
748- let argumentNodes = node . args ;
749- let numArguments = argumentNodes . length ;
750-
751- // infer types with generic components while updating contextual types
752- for ( let i = 0 ; i < numParameters ; ++ i ) {
753- let argumentExpression = i < numArguments
754- ? argumentNodes [ i ]
755- : parameterNodes [ i ] . initializer ;
756- if ( ! argumentExpression ) {
757- // optional but not have initializer should be handled in the other place
758- if ( parameterNodes [ i ] . parameterKind == ParameterKind . Optional ) {
759- continue ;
760- }
761- // missing initializer -> too few arguments
762- if ( reportMode == ReportMode . Report ) {
763- this . error (
764- DiagnosticCode . Expected_0_arguments_but_got_1 ,
765- node . range , numParameters . toString ( ) , numArguments . toString ( )
766- ) ;
767- }
768- return null ;
750+ // otherwise resolve the non-generic call as usual
751+ return this . resolveFunction ( prototype , null , new Map ( ) , reportMode ) ;
752+ }
753+
754+ inferGenericTypesArguments (
755+ node : CallExpression | NewExpression ,
756+ prototype : FunctionPrototype ,
757+ typeParameterNodes : TypeParameterNode [ ] | null ,
758+ ctxFlow : Flow ,
759+ reportMode : ReportMode = ReportMode . Report ,
760+ ) : Type [ ] | null {
761+
762+ if ( ! typeParameterNodes ) {
763+ return null ;
764+ }
765+
766+ let contextualTypeArguments = cloneMap ( ctxFlow . contextualTypeArguments ) ;
767+
768+ // fill up contextual types with auto for each generic component
769+ let numTypeParameters = typeParameterNodes . length ;
770+ let typeParameterNames = new Set < string > ( ) ;
771+ for ( let i = 0 ; i < numTypeParameters ; ++ i ) {
772+ let name = typeParameterNodes [ i ] . name . text ;
773+ contextualTypeArguments . set ( name , Type . auto ) ;
774+ typeParameterNames . add ( name ) ;
775+ }
776+
777+ let parameterNodes = prototype . functionTypeNode . parameters ;
778+ let numParameters = parameterNodes . length ;
779+ let argumentNodes = node . args ;
780+ let numArguments = argumentNodes . length ;
781+
782+ // infer types with generic components while updating contextual types
783+ for ( let i = 0 ; i < numParameters ; ++ i ) {
784+ let argumentExpression = i < numArguments
785+ ? argumentNodes [ i ]
786+ : parameterNodes [ i ] . initializer ;
787+ if ( ! argumentExpression ) {
788+ // optional but not have initializer should be handled in the other place
789+ if ( parameterNodes [ i ] . parameterKind == ParameterKind . Optional ) {
790+ continue ;
791+ }
792+ // missing initializer -> too few arguments
793+ if ( reportMode == ReportMode . Report ) {
794+ this . error (
795+ DiagnosticCode . Expected_0_arguments_but_got_1 ,
796+ node . range , numParameters . toString ( ) , numArguments . toString ( )
797+ ) ;
769798 }
770- let typeNode = parameterNodes [ i ] . type ;
771- if ( typeNode . hasGenericComponent ( typeParameterNodes ) ) {
772- let type = this . resolveExpression ( argumentExpression , ctxFlow , Type . auto , ReportMode . Swallow ) ;
773- if ( type ) {
774- this . propagateInferredGenericTypes (
775- typeNode ,
776- type ,
777- prototype ,
778- contextualTypeArguments ,
779- typeParameterNames
780- ) ;
781- }
799+ return null ;
800+ }
801+ let typeNode = parameterNodes [ i ] . type ;
802+ if ( typeNode . hasGenericComponent ( typeParameterNodes ) ) {
803+ let type = this . resolveExpression ( argumentExpression , ctxFlow , Type . auto , ReportMode . Swallow ) ;
804+ if ( type ) {
805+ this . propagateInferredGenericTypes (
806+ typeNode ,
807+ type ,
808+ prototype ,
809+ contextualTypeArguments ,
810+ typeParameterNames
811+ ) ;
782812 }
783813 }
814+ }
784815
785- // apply concrete types to the generic function signature
786- let resolvedTypeArguments = new Array < Type > ( numTypeParameters ) ;
787- for ( let i = 0 ; i < numTypeParameters ; ++ i ) {
788- let typeParameterNode = typeParameterNodes [ i ] ;
789- let name = typeParameterNode . name . text ;
790- if ( contextualTypeArguments . has ( name ) ) {
791- let inferredType = assert ( contextualTypeArguments . get ( name ) ) ;
792- if ( inferredType != Type . auto ) {
793- resolvedTypeArguments [ i ] = inferredType ;
794- continue ;
816+ // apply concrete types to the generic function signature
817+ let resolvedTypeArguments = new Array < Type > ( numTypeParameters ) ;
818+ for ( let i = 0 ; i < numTypeParameters ; ++ i ) {
819+ let typeParameterNode = typeParameterNodes [ i ] ;
820+ let name = typeParameterNode . name . text ;
821+ if ( contextualTypeArguments . has ( name ) ) {
822+ let inferredType = assert ( contextualTypeArguments . get ( name ) ) ;
823+ if ( inferredType != Type . auto ) {
824+ resolvedTypeArguments [ i ] = inferredType ;
825+ continue ;
826+ }
827+ let defaultType = typeParameterNode . defaultType ;
828+ if ( defaultType ) {
829+ // Default parameters are resolved in context of the called function, not the calling function
830+ let parent = prototype . parent ;
831+ let defaultTypeContextualTypeArguments : Map < string , Type > | null = null ;
832+ if ( parent . kind == ElementKind . Class ) {
833+ defaultTypeContextualTypeArguments = ( < Class > parent ) . contextualTypeArguments ;
834+ } else if ( parent . kind == ElementKind . Function ) {
835+ defaultTypeContextualTypeArguments = ( < Function > parent ) . contextualTypeArguments ;
795836 }
796- let defaultType = typeParameterNode . defaultType ;
797- if ( defaultType ) {
798- // Default parameters are resolved in context of the called function, not the calling function
799- let parent = prototype . parent ;
800- let defaultTypeContextualTypeArguments : Map < string , Type > | null = null ;
801- if ( parent . kind == ElementKind . Class ) {
802- defaultTypeContextualTypeArguments = ( < Class > parent ) . contextualTypeArguments ;
803- } else if ( parent . kind == ElementKind . Function ) {
804- defaultTypeContextualTypeArguments = ( < Function > parent ) . contextualTypeArguments ;
805- }
806- let resolvedDefaultType = this . resolveType (
807- defaultType ,
808- null ,
809- prototype ,
810- defaultTypeContextualTypeArguments ,
811- reportMode
812- ) ;
813- if ( ! resolvedDefaultType ) return null ;
814- resolvedTypeArguments [ i ] = resolvedDefaultType ;
815- continue ;
816- }
817- }
818- // unused template, e.g. `function test<T>(): void {...}` called as `test()`
819- // invalid because the type is effectively unknown inside the function body
820- if ( reportMode == ReportMode . Report ) {
821- this . error (
822- DiagnosticCode . Type_argument_expected ,
823- node . expression . range . atEnd
837+ let resolvedDefaultType = this . resolveType (
838+ defaultType ,
839+ null ,
840+ prototype ,
841+ defaultTypeContextualTypeArguments ,
842+ reportMode
824843 ) ;
844+ if ( ! resolvedDefaultType ) return null ;
845+ resolvedTypeArguments [ i ] = resolvedDefaultType ;
846+ continue ;
825847 }
826- return null ;
827848 }
828- return this . resolveFunction (
829- prototype ,
830- resolvedTypeArguments ,
831- cloneMap ( ctxFlow . contextualTypeArguments ) ,
832- reportMode
833- ) ;
849+ // unused template, e.g. `function test<T>(): void {...}` called as `test()`
850+ // invalid because the type is effectively unknown inside the function body
851+ if ( reportMode == ReportMode . Report ) {
852+ let range : Range ;
853+ switch ( node . kind ) {
854+ case NodeKind . Call :
855+ range = ( < CallExpression > node ) . expression . range ;
856+ break ;
857+ case NodeKind . New :
858+ range = ( < NewExpression > node ) . typeName . range ;
859+ break ;
860+ default :
861+ assert ( false ) ;
862+ return null ;
863+ }
864+ this . error (
865+ DiagnosticCode . Type_argument_expected ,
866+ range . atEnd
867+ ) ;
868+ }
869+ return null ;
834870 }
835871
836- // otherwise resolve the non-generic call as usual
837- return this . resolveFunction ( prototype , null , new Map ( ) , reportMode ) ;
872+ return resolvedTypeArguments ;
838873 }
839874
840875 /** Updates contextual types with a possibly encapsulated inferred type. */
0 commit comments