@@ -38,14 +38,42 @@ namespace ts.codefix {
38
38
39
39
case SyntaxKind . MethodSignature :
40
40
case SyntaxKind . MethodDeclaration :
41
+ // The signature for the implementation appears as an entry in `signatures` iff
42
+ // there is only one signature.
43
+ // If there are overloads and an implementation signature, it appears as an
44
+ // extra declaration that isn't a signature for `type`.
45
+ // If there is more than one overload but no implementation signature
46
+ // (eg: an abstract method or interface declaration), there is a 1-1
47
+ // correspondence of declarations and signatures.
41
48
const signatures = checker . getSignaturesOfType ( type , SignatureKind . Call ) ;
42
49
if ( ! ( signatures && signatures . length > 0 ) ) {
43
50
return "" ;
44
51
}
45
- // TODO: (arozga) Deal with multiple signatures.
46
- const sigString = checker . signatureToString ( signatures [ 0 ] , enclosingDeclaration , TypeFormatFlags . SuppressAnyReturnType , SignatureKind . Call ) ;
52
+ if ( declarations . length === 1 ) {
53
+ Debug . assert ( signatures . length === 1 ) ;
54
+ const sigString = checker . signatureToString ( signatures [ 0 ] , enclosingDeclaration , TypeFormatFlags . SuppressAnyReturnType , SignatureKind . Call ) ;
55
+ return `${ visibility } ${ name } ${ sigString } ${ getMethodBodyStub ( newlineChar ) } ` ;
56
+ }
57
+
58
+ let result = "" ;
59
+ for ( let i = 0 ; i < signatures . length ; i ++ ) {
60
+ const sigString = checker . signatureToString ( signatures [ i ] , enclosingDeclaration , TypeFormatFlags . SuppressAnyReturnType , SignatureKind . Call ) ;
61
+ result += `${ visibility } ${ name } ${ sigString } ;${ newlineChar } ` ;
62
+ }
63
+
64
+ // If there is a declaration with a body, it is the last declaration,
65
+ // and it isn't caught by `getSignaturesOfType`.
66
+ let bodySig : Signature | undefined = undefined ;
67
+ if ( declarations . length > signatures . length ) {
68
+ bodySig = checker . getSignatureFromDeclaration ( declarations [ declarations . length - 1 ] as SignatureDeclaration ) ;
69
+ }
70
+ else {
71
+ bodySig = createBodyDeclarationSignatureWithAnyTypes ( declarations as SignatureDeclaration [ ] , signatures , enclosingDeclaration , checker ) ;
72
+ }
73
+ const sigString = checker . signatureToString ( bodySig , enclosingDeclaration , TypeFormatFlags . SuppressAnyReturnType , SignatureKind . Call ) ;
74
+ result += `${ visibility } ${ name } ${ sigString } ${ getMethodBodyStub ( newlineChar ) } ` ;
47
75
48
- return ` ${ visibility } ${ name } ${ sigString } ${ getMethodBodyStub ( newlineChar ) } ` ;
76
+ return result ;
49
77
case SyntaxKind . ComputedPropertyName :
50
78
if ( hasDynamicName ( node ) ) {
51
79
return "" ;
@@ -59,8 +87,73 @@ namespace ts.codefix {
59
87
}
60
88
}
61
89
90
+ function createBodyDeclarationSignatureWithAnyTypes ( signatureDecls : SignatureDeclaration [ ] , signatures : Signature [ ] , enclosingDeclaration : ClassLikeDeclaration , checker : TypeChecker ) : Signature {
91
+ Debug . assert ( signatureDecls . length === signatures . length ) ;
92
+
93
+ const newSignatureDeclaration = createNode ( SyntaxKind . CallSignature ) as SignatureDeclaration ;
94
+ newSignatureDeclaration . parent = enclosingDeclaration ;
95
+ newSignatureDeclaration . name = signatureDecls [ 0 ] . name ;
96
+
97
+ let maxArgs = - 1 , maxArgsIndex = 0 ;
98
+ let minArgumentCount = signatures [ 0 ] . minArgumentCount ;
99
+ let hasRestParameter = false ;
100
+ for ( let i = 0 ; i < signatures . length ; i ++ ) {
101
+ const sig = signatures [ i ] ;
102
+ minArgumentCount = Math . min ( sig . minArgumentCount , minArgumentCount ) ;
103
+ if ( sig . parameters . length > maxArgs ) {
104
+ maxArgs = sig . parameters . length ;
105
+ maxArgsIndex = i ;
106
+ }
107
+ hasRestParameter = hasRestParameter || sig . hasRestParameter ;
108
+ }
109
+
110
+ const anyTypeNode : TypeNode = createNode ( SyntaxKind . AnyKeyword ) as TypeNode ;
111
+ const optionalToken = createToken ( SyntaxKind . QuestionToken ) ;
112
+
113
+ newSignatureDeclaration . parameters = createNodeArray < ParameterDeclaration > ( ) ;
114
+ for ( let i = 0 ; i < maxArgs - 1 ; i ++ ) {
115
+ const newParameter = createParameterDeclaration ( i , minArgumentCount , newSignatureDeclaration ) ;
116
+ newSignatureDeclaration . parameters . push ( newParameter ) ;
117
+ }
118
+
119
+ const lastParameter = createParameterDeclaration ( maxArgs - 1 , minArgumentCount , newSignatureDeclaration ) ;
120
+ if ( hasRestParameter ) {
121
+ lastParameter . dotDotDotToken = createToken ( SyntaxKind . DotDotDotToken ) ;
122
+
123
+ let allMaxArgsAreRest = true ;
124
+ for ( const sig of signatures ) {
125
+ allMaxArgsAreRest = allMaxArgsAreRest && sig . parameters [ maxArgs - 1 ] && sig . hasRestParameter ;
126
+ }
127
+ if ( ! allMaxArgsAreRest ) {
128
+ const newParameter = createParameterDeclaration ( maxArgs - 1 , minArgumentCount , newSignatureDeclaration ) ;
129
+ newSignatureDeclaration . parameters . push ( newParameter ) ;
130
+ }
131
+ }
132
+
133
+ newSignatureDeclaration . parameters . push ( lastParameter ) ;
134
+
135
+ newSignatureDeclaration . type = anyTypeNode ;
136
+ newSignatureDeclaration . type . parent = newSignatureDeclaration ;
137
+
138
+ return checker . getSignatureFromDeclaration ( newSignatureDeclaration ) ;
139
+
140
+ function createParameterDeclaration ( index : number , minArgCount : number , enclosingSignature : SignatureDeclaration ) : ParameterDeclaration {
141
+ const newParameter = createNode ( SyntaxKind . Parameter ) as ParameterDeclaration ;
142
+ newParameter . symbol = checker . createSymbol ( SymbolFlags . FunctionScopedVariable , "arg" + index ) ;
143
+ newParameter . symbol . valueDeclaration = newParameter ;
144
+ newParameter . symbol . declarations = [ newParameter ] ;
145
+ newParameter . type = anyTypeNode ;
146
+ newParameter . parent = enclosingSignature ;
147
+ if ( index >= minArgCount ) {
148
+ newParameter . questionToken = optionalToken ;
149
+ }
150
+
151
+ return newParameter ;
152
+ }
153
+ }
154
+
62
155
function getMethodBodyStub ( newLineChar : string ) {
63
- return `{${ newLineChar } throw new Error('Method not implemented.');${ newLineChar } }${ newLineChar } ` ;
156
+ return ` {${ newLineChar } throw new Error('Method not implemented.');${ newLineChar } }${ newLineChar } ` ;
64
157
}
65
158
66
159
function getVisibilityPrefix ( flags : ModifierFlags ) : string {
0 commit comments