@@ -731,110 +731,158 @@ export class Resolver extends DiagnosticEmitter {
731
731
732
732
// infer generic call if type arguments have been omitted
733
733
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
+ }
735
749
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
+ ) ;
769
811
}
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
+ ) ;
782
825
}
783
826
}
827
+ }
784
828
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 ;
816
849
}
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
824
856
) ;
857
+ if ( ! resolvedDefaultType ) return null ;
858
+ resolvedTypeArguments [ i ] = resolvedDefaultType ;
859
+ continue ;
825
860
}
826
- return null ;
827
861
}
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 ;
834
883
}
835
884
836
- // otherwise resolve the non-generic call as usual
837
- return this . resolveFunction ( prototype , null , new Map ( ) , reportMode ) ;
885
+ return resolvedTypeArguments ;
838
886
}
839
887
840
888
/** Updates contextual types with a possibly encapsulated inferred type. */
@@ -3644,15 +3692,34 @@ export class Resolver extends DiagnosticEmitter {
3644
3692
3645
3693
// Resolve type arguments if generic
3646
3694
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
+
3656
3723
if ( ! resolvedTypeArguments ) return null ;
3657
3724
3658
3725
// Otherwise make sure that no type arguments have been specified
0 commit comments