@@ -731,110 +731,158 @@ 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 . inferGenericTypeArguments (
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+ private inferGenericTypeArguments (
755+ node : Expression ,
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+
780+ let argumentNodes : Expression [ ] ;
781+ switch ( node . kind ) {
782+ case NodeKind . Call :
783+ argumentNodes = ( < CallExpression > node ) . args ;
784+ break ;
785+ case NodeKind . New :
786+ argumentNodes = ( < NewExpression > node ) . args ;
787+ break ;
788+ default :
789+ assert ( false ) ;
790+ return null ;
791+ }
792+
793+ let numArguments = argumentNodes . length ;
794+
795+ // infer types with generic components while updating contextual types
796+ for ( let i = 0 ; i < numParameters ; ++ i ) {
797+ let argumentExpression = i < numArguments
798+ ? argumentNodes [ i ]
799+ : parameterNodes [ i ] . initializer ;
800+ if ( ! argumentExpression ) {
801+ // optional but not have initializer should be handled in the other place
802+ if ( parameterNodes [ i ] . parameterKind == ParameterKind . Optional ) {
803+ continue ;
804+ }
805+ // missing initializer -> too few arguments
806+ if ( reportMode == ReportMode . Report ) {
807+ this . error (
808+ DiagnosticCode . Expected_0_arguments_but_got_1 ,
809+ node . range , numParameters . toString ( ) , numArguments . toString ( )
810+ ) ;
769811 }
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- }
812+ return null ;
813+ }
814+ let typeNode = parameterNodes [ i ] . type ;
815+ if ( typeNode . hasGenericComponent ( typeParameterNodes ) ) {
816+ let type = this . resolveExpression ( argumentExpression , ctxFlow , Type . auto , ReportMode . Swallow ) ;
817+ if ( type ) {
818+ this . propagateInferredGenericTypes (
819+ typeNode ,
820+ type ,
821+ prototype ,
822+ contextualTypeArguments ,
823+ typeParameterNames
824+ ) ;
782825 }
783826 }
827+ }
784828
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 ;
795- }
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 ;
829+ // apply concrete types to the generic function signature
830+ let resolvedTypeArguments = new Array < Type > ( numTypeParameters ) ;
831+ for ( let i = 0 ; i < numTypeParameters ; ++ i ) {
832+ let typeParameterNode = typeParameterNodes [ i ] ;
833+ let name = typeParameterNode . name . text ;
834+ if ( contextualTypeArguments . has ( name ) ) {
835+ let inferredType = assert ( contextualTypeArguments . get ( name ) ) ;
836+ if ( inferredType != Type . auto ) {
837+ resolvedTypeArguments [ i ] = inferredType ;
838+ continue ;
839+ }
840+ let defaultType = typeParameterNode . defaultType ;
841+ if ( defaultType ) {
842+ // Default parameters are resolved in context of the called function, not the calling function
843+ let parent = prototype . parent ;
844+ let defaultTypeContextualTypeArguments : Map < string , Type > | null = null ;
845+ if ( parent . kind == ElementKind . Class ) {
846+ defaultTypeContextualTypeArguments = ( < Class > parent ) . contextualTypeArguments ;
847+ } else if ( parent . kind == ElementKind . Function ) {
848+ defaultTypeContextualTypeArguments = ( < Function > parent ) . contextualTypeArguments ;
816849 }
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
850+ let resolvedDefaultType = this . resolveType (
851+ defaultType ,
852+ null ,
853+ prototype ,
854+ defaultTypeContextualTypeArguments ,
855+ reportMode
824856 ) ;
857+ if ( ! resolvedDefaultType ) return null ;
858+ resolvedTypeArguments [ i ] = resolvedDefaultType ;
859+ continue ;
825860 }
826- return null ;
827861 }
828- return this . resolveFunction (
829- prototype ,
830- resolvedTypeArguments ,
831- cloneMap ( ctxFlow . contextualTypeArguments ) ,
832- reportMode
833- ) ;
862+ // unused template, e.g. `function test<T>(): void {...}` called as `test()`
863+ // invalid because the type is effectively unknown inside the function body
864+ if ( reportMode == ReportMode . Report ) {
865+ let range : Range ;
866+ switch ( node . kind ) {
867+ case NodeKind . Call :
868+ range = ( < CallExpression > node ) . expression . range ;
869+ break ;
870+ case NodeKind . New :
871+ range = ( < NewExpression > node ) . typeName . range ;
872+ break ;
873+ default :
874+ assert ( false ) ;
875+ return null ;
876+ }
877+ this . error (
878+ DiagnosticCode . Type_argument_expected ,
879+ range . atEnd
880+ ) ;
881+ }
882+ return null ;
834883 }
835884
836- // otherwise resolve the non-generic call as usual
837- return this . resolveFunction ( prototype , null , new Map ( ) , reportMode ) ;
885+ return resolvedTypeArguments ;
838886 }
839887
840888 /** Updates contextual types with a possibly encapsulated inferred type. */
@@ -3644,15 +3692,34 @@ export class Resolver extends DiagnosticEmitter {
36443692
36453693 // Resolve type arguments if generic
36463694 if ( prototype . is ( CommonFlags . Generic ) ) {
3647- resolvedTypeArguments = this . resolveTypeArguments ( // reports
3648- assert ( prototype . typeParameterNodes ) , // must be present if generic
3649- typeArgumentNodes ,
3650- flow ,
3651- ctxElement ,
3652- ctxTypes , // update
3653- reportNode ,
3654- reportMode
3655- ) ;
3695+
3696+ // find the constructor prototype, which may be on a base class
3697+ let constructorPrototype : FunctionPrototype | null = null ;
3698+ for ( let p : ClassPrototype | null = prototype ; p && ! constructorPrototype ; p = p . basePrototype ) {
3699+ constructorPrototype = p . constructorPrototype ;
3700+ }
3701+
3702+ // if no type arguments are provided, try to infer them from the constructor call
3703+ if ( ! typeArgumentNodes && constructorPrototype && flow && ctxTypes . size == 0 ) {
3704+ resolvedTypeArguments = this . inferGenericTypeArguments (
3705+ reportNode as NewExpression ,
3706+ constructorPrototype ,
3707+ prototype . typeParameterNodes ,
3708+ flow ,
3709+ ) ;
3710+ } else {
3711+ // resolve them from the provided type argument nodes
3712+ resolvedTypeArguments = this . resolveTypeArguments ( // reports
3713+ assert ( prototype . typeParameterNodes ) , // must be present if generic
3714+ typeArgumentNodes ,
3715+ flow ,
3716+ ctxElement ,
3717+ ctxTypes , // update
3718+ reportNode ,
3719+ reportMode
3720+ ) ;
3721+ }
3722+
36563723 if ( ! resolvedTypeArguments ) return null ;
36573724
36583725 // Otherwise make sure that no type arguments have been specified
0 commit comments