Skip to content

Commit 6d8134e

Browse files
TypeScript BotAndarist
TypeScript Bot
andauthored
🤖 Pick PR #57637 (Fixed a regression related to deter...) into release-5.4 (#57987)
Co-authored-by: Mateusz BurzyÅ„ski <[email protected]>
1 parent 1c25c7f commit 6d8134e

8 files changed

+982
-67
lines changed

‎src/services/completions.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -3126,8 +3126,7 @@ function getContextualType(previousToken: Node, position: number, sourceFile: So
31263126
default:
31273127
const argInfo = SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile, checker);
31283128
return argInfo ?
3129-
// At `,`, treat this as the next argument after the comma.
3130-
checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === SyntaxKind.CommaToken ? 1 : 0)) :
3129+
checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex) :
31313130
isEqualityOperatorKind(previousToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind) ?
31323131
// completion at `x ===/**/` should be for the right side
31333132
checker.getTypeAtLocation(parent.left) :

‎src/services/signatureHelp.ts

+46-57
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
canHaveSymbol,
77
CheckFlags,
88
contains,
9-
countWhere,
109
createPrinterWithRemoveComments,
1110
createTextSpan,
1211
createTextSpanFromBounds,
@@ -60,7 +59,6 @@ import {
6059
JsxTagNameExpression,
6160
last,
6261
lastOrUndefined,
63-
length,
6462
ListFormat,
6563
map,
6664
mapToDisplayParts,
@@ -288,7 +286,7 @@ function getArgumentOrParameterListInfo(node: Node, position: number, sourceFile
288286
if (!info) return undefined;
289287
const { list, argumentIndex } = info;
290288

291-
const argumentCount = getArgumentCount(list, /*ignoreTrailingComma*/ isInString(sourceFile, position, node), checker);
289+
const argumentCount = getArgumentCount(checker, list);
292290
if (argumentIndex !== 0) {
293291
Debug.assertLessThan(argumentIndex, argumentCount);
294292
}
@@ -309,7 +307,7 @@ function getArgumentOrParameterListAndIndex(node: Node, sourceFile: SourceFile,
309307
// - On the target of the call (parent.func)
310308
// - On the 'new' keyword in a 'new' expression
311309
const list = findContainingList(node);
312-
return list && { list, argumentIndex: getArgumentIndex(list, node, checker) };
310+
return list && { list, argumentIndex: getArgumentIndex(checker, list, node) };
313311
}
314312
}
315313

@@ -481,37 +479,6 @@ function chooseBetterSymbol(s: Symbol): Symbol {
481479
: s;
482480
}
483481

484-
function getArgumentIndex(argumentsList: Node, node: Node, checker: TypeChecker) {
485-
// The list we got back can include commas. In the presence of errors it may
486-
// also just have nodes without commas. For example "Foo(a b c)" will have 3
487-
// args without commas. We want to find what index we're at. So we count
488-
// forward until we hit ourselves, only incrementing the index if it isn't a
489-
// comma.
490-
//
491-
// Note: the subtlety around trailing commas (in getArgumentCount) does not apply
492-
// here. That's because we're only walking forward until we hit the node we're
493-
// on. In that case, even if we're after the trailing comma, we'll still see
494-
// that trailing comma in the list, and we'll have generated the appropriate
495-
// arg index.
496-
const args = argumentsList.getChildren();
497-
let argumentIndex = 0;
498-
for (let pos = 0; pos < length(args); pos++) {
499-
const child = args[pos];
500-
if (child === node) {
501-
break;
502-
}
503-
if (isSpreadElement(child)) {
504-
argumentIndex = argumentIndex + getSpreadElementCount(child, checker) + (pos > 0 ? pos : 0);
505-
}
506-
else {
507-
if (child.kind !== SyntaxKind.CommaToken) {
508-
argumentIndex++;
509-
}
510-
}
511-
}
512-
return argumentIndex;
513-
}
514-
515482
function getSpreadElementCount(node: SpreadElement, checker: TypeChecker) {
516483
const spreadType = checker.getTypeAtLocation(node.expression);
517484
if (checker.isTupleType(spreadType)) {
@@ -525,32 +492,54 @@ function getSpreadElementCount(node: SpreadElement, checker: TypeChecker) {
525492
return 0;
526493
}
527494

528-
function getArgumentCount(argumentsList: Node, ignoreTrailingComma: boolean, checker: TypeChecker) {
529-
// The argument count for a list is normally the number of non-comma children it has.
530-
// For example, if you have "Foo(a,b)" then there will be three children of the arg
531-
// list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
532-
// is a small subtlety. If you have "Foo(a,)", then the child list will just have
533-
// 'a' '<comma>'. So, in the case where the last child is a comma, we increase the
534-
// arg count by one to compensate.
535-
//
536-
// Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
537-
// we'll have: 'a' '<comma>' '<missing>'
538-
// That will give us 2 non-commas. We then add one for the last comma, giving us an
539-
// arg count of 3.
540-
const listChildren = argumentsList.getChildren();
541-
542-
let argumentCount = 0;
543-
for (const child of listChildren) {
495+
function getArgumentIndex(checker: TypeChecker, argumentsList: Node, node: Node) {
496+
return getArgumentIndexOrCount(checker, argumentsList, node);
497+
}
498+
499+
function getArgumentCount(checker: TypeChecker, argumentsList: Node) {
500+
return getArgumentIndexOrCount(checker, argumentsList, /*node*/ undefined);
501+
}
502+
503+
function getArgumentIndexOrCount(checker: TypeChecker, argumentsList: Node, node: Node | undefined) {
504+
// The list we got back can include commas. In the presence of errors it may
505+
// also just have nodes without commas. For example "Foo(a b c)" will have 3
506+
// args without commas.
507+
const args = argumentsList.getChildren();
508+
let argumentIndex = 0;
509+
let skipComma = false;
510+
for (const child of args) {
511+
if (node && child === node) {
512+
if (!skipComma && child.kind === SyntaxKind.CommaToken) {
513+
argumentIndex++;
514+
}
515+
return argumentIndex;
516+
}
544517
if (isSpreadElement(child)) {
545-
argumentCount = argumentCount + getSpreadElementCount(child, checker);
518+
argumentIndex += getSpreadElementCount(child, checker);
519+
skipComma = true;
520+
continue;
521+
}
522+
if (child.kind !== SyntaxKind.CommaToken) {
523+
argumentIndex++;
524+
skipComma = true;
525+
continue;
526+
}
527+
if (skipComma) {
528+
skipComma = false;
529+
continue;
546530
}
531+
argumentIndex++;
547532
}
548-
549-
argumentCount = argumentCount + countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken);
550-
if (!ignoreTrailingComma && listChildren.length > 0 && last(listChildren).kind === SyntaxKind.CommaToken) {
551-
argumentCount++;
533+
if (node) {
534+
return argumentIndex;
552535
}
553-
return argumentCount;
536+
// The argument count for a list is normally the number of non-comma children it has.
537+
// For example, if you have "Foo(a,b)" then there will be three children of the arg
538+
// list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
539+
// is a small subtlety. If you have "Foo(a,)", then the child list will just have
540+
// 'a' '<comma>'. So, in the case where the last child is a comma, we increase the
541+
// arg count by one to compensate.
542+
return args.length && last(args).kind === SyntaxKind.CommaToken ? argumentIndex + 1 : argumentIndex;
554543
}
555544

556545
// spanIndex is either the index for a given template span.

‎tests/baselines/reference/signatureHelpRestArgs.baseline ‎tests/baselines/reference/signatureHelpRestArgs1.baseline

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// === SignatureHelp ===
2-
=== /tests/cases/fourslash/signatureHelpRestArgs.ts ===
2+
=== /tests/cases/fourslash/signatureHelpRestArgs1.ts ===
33
// function fn(a: number, b: number, c: number) {}
44
// const a = [1, 2] as const;
55
// const b = [1] as const;
@@ -33,7 +33,7 @@
3333
[
3434
{
3535
"marker": {
36-
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
36+
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
3737
"position": 109,
3838
"name": "1"
3939
},
@@ -163,12 +163,12 @@
163163
},
164164
"selectedItemIndex": 0,
165165
"argumentIndex": 2,
166-
"argumentCount": 4
166+
"argumentCount": 3
167167
}
168168
},
169169
{
170170
"marker": {
171-
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
171+
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
172172
"position": 115,
173173
"name": "2"
174174
},
@@ -303,7 +303,7 @@
303303
},
304304
{
305305
"marker": {
306-
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
306+
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
307307
"position": 134,
308308
"name": "3"
309309
},
@@ -433,12 +433,12 @@
433433
},
434434
"selectedItemIndex": 0,
435435
"argumentIndex": 1,
436-
"argumentCount": 3
436+
"argumentCount": 2
437437
}
438438
},
439439
{
440440
"marker": {
441-
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
441+
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
442442
"position": 140,
443443
"name": "4"
444444
},
@@ -573,7 +573,7 @@
573573
},
574574
{
575575
"marker": {
576-
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
576+
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
577577
"position": 148,
578578
"name": "5"
579579
},

0 commit comments

Comments
 (0)