Skip to content

Commit

Permalink
🤖 Pick PR #57637 (Fixed a regression related to deter...) into releas…
Browse files Browse the repository at this point in the history
…e-5.4 (#57987)

Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
  • Loading branch information
TypeScript Bot and Andarist authored Mar 28, 2024
1 parent 1c25c7f commit 6d8134e
Show file tree
Hide file tree
Showing 8 changed files with 982 additions and 67 deletions.
3 changes: 1 addition & 2 deletions src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3126,8 +3126,7 @@ function getContextualType(previousToken: Node, position: number, sourceFile: So
default:
const argInfo = SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile, checker);
return argInfo ?
// At `,`, treat this as the next argument after the comma.
checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === SyntaxKind.CommaToken ? 1 : 0)) :
checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex) :
isEqualityOperatorKind(previousToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind) ?
// completion at `x ===/**/` should be for the right side
checker.getTypeAtLocation(parent.left) :
Expand Down
103 changes: 46 additions & 57 deletions src/services/signatureHelp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
canHaveSymbol,
CheckFlags,
contains,
countWhere,
createPrinterWithRemoveComments,
createTextSpan,
createTextSpanFromBounds,
Expand Down Expand Up @@ -60,7 +59,6 @@ import {
JsxTagNameExpression,
last,
lastOrUndefined,
length,
ListFormat,
map,
mapToDisplayParts,
Expand Down Expand Up @@ -288,7 +286,7 @@ function getArgumentOrParameterListInfo(node: Node, position: number, sourceFile
if (!info) return undefined;
const { list, argumentIndex } = info;

const argumentCount = getArgumentCount(list, /*ignoreTrailingComma*/ isInString(sourceFile, position, node), checker);
const argumentCount = getArgumentCount(checker, list);
if (argumentIndex !== 0) {
Debug.assertLessThan(argumentIndex, argumentCount);
}
Expand All @@ -309,7 +307,7 @@ function getArgumentOrParameterListAndIndex(node: Node, sourceFile: SourceFile,
// - On the target of the call (parent.func)
// - On the 'new' keyword in a 'new' expression
const list = findContainingList(node);
return list && { list, argumentIndex: getArgumentIndex(list, node, checker) };
return list && { list, argumentIndex: getArgumentIndex(checker, list, node) };
}
}

Expand Down Expand Up @@ -481,37 +479,6 @@ function chooseBetterSymbol(s: Symbol): Symbol {
: s;
}

function getArgumentIndex(argumentsList: Node, node: Node, checker: TypeChecker) {
// The list we got back can include commas. In the presence of errors it may
// also just have nodes without commas. For example "Foo(a b c)" will have 3
// args without commas. We want to find what index we're at. So we count
// forward until we hit ourselves, only incrementing the index if it isn't a
// comma.
//
// Note: the subtlety around trailing commas (in getArgumentCount) does not apply
// here. That's because we're only walking forward until we hit the node we're
// on. In that case, even if we're after the trailing comma, we'll still see
// that trailing comma in the list, and we'll have generated the appropriate
// arg index.
const args = argumentsList.getChildren();
let argumentIndex = 0;
for (let pos = 0; pos < length(args); pos++) {
const child = args[pos];
if (child === node) {
break;
}
if (isSpreadElement(child)) {
argumentIndex = argumentIndex + getSpreadElementCount(child, checker) + (pos > 0 ? pos : 0);
}
else {
if (child.kind !== SyntaxKind.CommaToken) {
argumentIndex++;
}
}
}
return argumentIndex;
}

function getSpreadElementCount(node: SpreadElement, checker: TypeChecker) {
const spreadType = checker.getTypeAtLocation(node.expression);
if (checker.isTupleType(spreadType)) {
Expand All @@ -525,32 +492,54 @@ function getSpreadElementCount(node: SpreadElement, checker: TypeChecker) {
return 0;
}

function getArgumentCount(argumentsList: Node, ignoreTrailingComma: boolean, checker: TypeChecker) {
// The argument count for a list is normally the number of non-comma children it has.
// For example, if you have "Foo(a,b)" then there will be three children of the arg
// list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
// is a small subtlety. If you have "Foo(a,)", then the child list will just have
// 'a' '<comma>'. So, in the case where the last child is a comma, we increase the
// arg count by one to compensate.
//
// Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
// we'll have: 'a' '<comma>' '<missing>'
// That will give us 2 non-commas. We then add one for the last comma, giving us an
// arg count of 3.
const listChildren = argumentsList.getChildren();

let argumentCount = 0;
for (const child of listChildren) {
function getArgumentIndex(checker: TypeChecker, argumentsList: Node, node: Node) {
return getArgumentIndexOrCount(checker, argumentsList, node);
}

function getArgumentCount(checker: TypeChecker, argumentsList: Node) {
return getArgumentIndexOrCount(checker, argumentsList, /*node*/ undefined);
}

function getArgumentIndexOrCount(checker: TypeChecker, argumentsList: Node, node: Node | undefined) {
// The list we got back can include commas. In the presence of errors it may
// also just have nodes without commas. For example "Foo(a b c)" will have 3
// args without commas.
const args = argumentsList.getChildren();
let argumentIndex = 0;
let skipComma = false;
for (const child of args) {
if (node && child === node) {
if (!skipComma && child.kind === SyntaxKind.CommaToken) {
argumentIndex++;
}
return argumentIndex;
}
if (isSpreadElement(child)) {
argumentCount = argumentCount + getSpreadElementCount(child, checker);
argumentIndex += getSpreadElementCount(child, checker);
skipComma = true;
continue;
}
if (child.kind !== SyntaxKind.CommaToken) {
argumentIndex++;
skipComma = true;
continue;
}
if (skipComma) {
skipComma = false;
continue;
}
argumentIndex++;
}

argumentCount = argumentCount + countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken);
if (!ignoreTrailingComma && listChildren.length > 0 && last(listChildren).kind === SyntaxKind.CommaToken) {
argumentCount++;
if (node) {
return argumentIndex;
}
return argumentCount;
// The argument count for a list is normally the number of non-comma children it has.
// For example, if you have "Foo(a,b)" then there will be three children of the arg
// list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
// is a small subtlety. If you have "Foo(a,)", then the child list will just have
// 'a' '<comma>'. So, in the case where the last child is a comma, we increase the
// arg count by one to compensate.
return args.length && last(args).kind === SyntaxKind.CommaToken ? argumentIndex + 1 : argumentIndex;
}

// spanIndex is either the index for a given template span.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// === SignatureHelp ===
=== /tests/cases/fourslash/signatureHelpRestArgs.ts ===
=== /tests/cases/fourslash/signatureHelpRestArgs1.ts ===
// function fn(a: number, b: number, c: number) {}
// const a = [1, 2] as const;
// const b = [1] as const;
Expand Down Expand Up @@ -33,7 +33,7 @@
[
{
"marker": {
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
"position": 109,
"name": "1"
},
Expand Down Expand Up @@ -163,12 +163,12 @@
},
"selectedItemIndex": 0,
"argumentIndex": 2,
"argumentCount": 4
"argumentCount": 3
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
"position": 115,
"name": "2"
},
Expand Down Expand Up @@ -303,7 +303,7 @@
},
{
"marker": {
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
"position": 134,
"name": "3"
},
Expand Down Expand Up @@ -433,12 +433,12 @@
},
"selectedItemIndex": 0,
"argumentIndex": 1,
"argumentCount": 3
"argumentCount": 2
}
},
{
"marker": {
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
"position": 140,
"name": "4"
},
Expand Down Expand Up @@ -573,7 +573,7 @@
},
{
"marker": {
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs.ts",
"fileName": "/tests/cases/fourslash/signatureHelpRestArgs1.ts",
"position": 148,
"name": "5"
},
Expand Down
Loading

0 comments on commit 6d8134e

Please sign in to comment.