@@ -238,7 +238,7 @@ module ts.SignatureHelp {
238
238
invocation : callExpression ,
239
239
argumentsSpan : getApplicableSpanForArguments ( list ) ,
240
240
argumentIndex : 0 ,
241
- argumentCount : getCommaBasedArgCount ( list )
241
+ argumentCount : getArgumentCount ( list )
242
242
} ;
243
243
}
244
244
@@ -253,20 +253,11 @@ module ts.SignatureHelp {
253
253
var list = listItemInfo . list ;
254
254
var isTypeArgList = callExpression . typeArguments && callExpression . typeArguments . pos === list . pos ;
255
255
256
- // The listItemIndex we got back includes commas. Our goal is to return the index of the proper
257
- // item (not including commas). Here are some examples:
258
- // 1. foo(a, b, c #) -> the listItemIndex is 4, we want to return 2
259
- // 2. foo(a, b, # c) -> listItemIndex is 3, we want to return 2
260
- // 3. foo(#a) -> listItemIndex is 0, we want to return 0
261
- //
262
- // In general, we want to subtract the number of commas before the current index.
263
- // But if we are on a comma, we also want to pretend we are on the argument *following*
264
- // the comma. That amounts to taking the ceiling of half the index.
265
- var argumentIndex = ( listItemInfo . listItemIndex + 1 ) >> 1 ;
256
+ var argumentIndex = getArgumentIndex ( list , node ) ;
257
+ var argumentCount = getArgumentCount ( list ) ;
266
258
267
- var argumentCount = getCommaBasedArgCount ( list ) ;
268
-
269
- Debug . assert ( argumentIndex === 0 || argumentIndex < argumentCount , `argumentCount < argumentIndex, ${ argumentCount } < ${ argumentIndex } ` ) ;
259
+ Debug . assert ( argumentIndex === 0 || argumentIndex < argumentCount ,
260
+ `argumentCount < argumentIndex, ${ argumentCount } < ${ argumentIndex } ` ) ;
270
261
271
262
return {
272
263
kind : isTypeArgList ? ArgumentListKind . TypeArguments : ArgumentListKind . CallArguments ,
@@ -313,12 +304,53 @@ module ts.SignatureHelp {
313
304
return undefined ;
314
305
}
315
306
316
- function getCommaBasedArgCount ( argumentsList : Node ) {
317
- // The number of arguments is the number of commas plus one, unless the list
318
- // is completely empty, in which case there are 0 arguments.
319
- return argumentsList . getChildCount ( ) === 0
320
- ? 0
321
- : 1 + countWhere ( argumentsList . getChildren ( ) , arg => arg . kind === SyntaxKind . CommaToken ) ;
307
+ function getArgumentIndex ( argumentsList : Node , node : Node ) {
308
+ // The list we got back can include commas. In the presence of errors it may
309
+ // also just have nodes without commas. For example "Foo(a b c)" will have 3
310
+ // args without commas. We want to find what index we're at. So we count
311
+ // forward until we hit ourselves, only incrementing the index if it isn't a
312
+ // comma.
313
+ //
314
+ // Note: the subtlety around trailing commas (in getArgumentCount) does not apply
315
+ // here. That's because we're only walking forward until we hit the node we're
316
+ // on. In that case, even if we're after the trailing comma, we'll still see
317
+ // that trailing comma in the list, and we'll have generated the appropriate
318
+ // arg index.
319
+ var argumentIndex = 0 ;
320
+ var listChildren = argumentsList . getChildren ( ) ;
321
+ for ( var i = 0 , n = listChildren . length ; i < n ; i ++ ) {
322
+ var child = listChildren [ i ] ;
323
+ if ( child === node ) {
324
+ break ;
325
+ }
326
+ if ( child . kind !== SyntaxKind . CommaToken ) {
327
+ argumentIndex ++ ;
328
+ }
329
+ }
330
+
331
+ return argumentIndex ;
332
+ }
333
+
334
+ function getArgumentCount ( argumentsList : Node ) {
335
+ // The argument count for a list is normally the number of non-comma children it has.
336
+ // For example, if you have "Foo(a,b)" then there will be three children of the arg
337
+ // list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
338
+ // is a small subtlety. If you have "Foo(a,)", then the child list will just have
339
+ // 'a' '<comma>'. So, in the case where the last child is a comma, we increase the
340
+ // arg count by one to compensate.
341
+ //
342
+ // Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
343
+ // we'll have: 'a' '<comma>' '<missing>'
344
+ // That will give us 2 non-commas. We then add one for the last comma, givin us an
345
+ // arg count of 3.
346
+ var listChildren = argumentsList . getChildren ( ) ;
347
+
348
+ var argumentCount = countWhere ( listChildren , arg => arg . kind !== SyntaxKind . CommaToken ) ;
349
+ if ( listChildren . length > 0 && lastOrUndefined ( listChildren ) . kind === SyntaxKind . CommaToken ) {
350
+ argumentCount ++ ;
351
+ }
352
+
353
+ return argumentCount ;
322
354
}
323
355
324
356
// spanIndex is either the index for a given template span.
0 commit comments