Skip to content

Commit b2bca72

Browse files
committed
Fix argumentCount and selectedItemIndex
1 parent 23843ff commit b2bca72

File tree

4 files changed

+55
-20
lines changed

4 files changed

+55
-20
lines changed

src/harness/fourslash.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,13 @@ module FourSlash {
891891
assert.equal(actual, expected);
892892
}
893893

894+
public verifySignatureHelpArgumentCount(expected: number) {
895+
this.taoInvalidReason = 'verifySignatureHelpArgumentCount NYI';
896+
var signatureHelpItems = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
897+
var actual = signatureHelpItems.argumentCount;
898+
assert.equal(actual, expected);
899+
}
900+
894901
public verifySignatureHelpPresent(shouldBePresent = true) {
895902
this.taoInvalidReason = 'verifySignatureHelpPresent NYI';
896903

@@ -946,22 +953,14 @@ module FourSlash {
946953

947954
private getActiveSignatureHelpItem() {
948955
var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
949-
950-
// If the signature hasn't been narrowed down yet (e.g. no parameters have yet been entered),
951-
// 'activeFormal' will be -1 (even if there is only 1 signature). Signature help will show the
952-
// first signature in the signature group, so go with that
953-
var index = help.selectedItemIndex < 0 ? 0 : help.selectedItemIndex;
954-
956+
var index = help.selectedItemIndex;
955957
return help.items[index];
956958
}
957959

958960
private getActiveParameter(): ts.SignatureHelpParameter {
959961
var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
960-
961962
var item = help.items[help.selectedItemIndex];
962-
963-
// Same logic as in getActiveSignatureHelp - this value might be -1 until a parameter value actually gets typed
964-
var currentParam = help.argumentIndex < 0 ? 0 : help.argumentIndex;
963+
var currentParam = help.argumentIndex;
965964
return item.parameters[currentParam];
966965
}
967966

src/services/signatureHelp.ts

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,33 @@ module ts.SignatureHelp {
252252
return undefined;
253253
}
254254

255+
/**
256+
* The selectedItemIndex could be negative for several reasons.
257+
* 1. There are too many arguments for all of the overloads
258+
* 2. None of the overloads were type compatible
259+
* The solution here is to try to pick the best overload by picking
260+
* either the first one that has an appropriate number of parameters,
261+
* or the one with the most parameters.
262+
*/
263+
function selectBestInvalidOverloadIndex(candidates: Signature[], argumentCount: number): number {
264+
var maxParamsSignatureIndex = -1;
265+
var maxParams = -1;
266+
for (var i = 0; i < candidates.length; i++) {
267+
var candidate = candidates[i];
268+
269+
if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) {
270+
return i;
271+
}
272+
273+
if (candidate.parameters.length > maxParams) {
274+
maxParams = candidate.parameters.length;
275+
maxParamsSignatureIndex = i;
276+
}
277+
}
278+
279+
return maxParamsSignatureIndex;
280+
}
281+
255282
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentInfoOrTypeArgumentInfo: ListItemInfo): SignatureHelpItems {
256283
var argumentListOrTypeArgumentList = argumentInfoOrTypeArgumentInfo.list;
257284
var items: SignatureHelpItem[] = map(candidates, candidateSignature => {
@@ -326,11 +353,6 @@ module ts.SignatureHelp {
326353
};
327354
});
328355

329-
var selectedItemIndex = candidates.indexOf(bestSignature);
330-
if (selectedItemIndex < 0) {
331-
selectedItemIndex = 0;
332-
}
333-
334356
// We use full start and skip trivia on the end because we want to include trivia on
335357
// both sides. For example,
336358
//
@@ -353,8 +375,18 @@ module ts.SignatureHelp {
353375
// But if we are on a comma, we also want to pretend we are on the argument *following*
354376
// the comma. That amounts to taking the ceiling of half the index.
355377
var argumentIndex = (argumentInfoOrTypeArgumentInfo.listItemIndex + 1) >> 1;
356-
var numberOfCommas = countWhere(argumentListOrTypeArgumentList.getChildren(), arg => arg.kind === SyntaxKind.CommaToken);
357-
var argumentCount = numberOfCommas + 1;
378+
379+
// argumentCount is the number of commas plus one, unless the list is completely empty,
380+
// in which case there are 0.
381+
var argumentCount = argumentListOrTypeArgumentList.getChildCount() === 0
382+
? 0
383+
: 1 + countWhere(argumentListOrTypeArgumentList.getChildren(), arg => arg.kind === SyntaxKind.CommaToken);
384+
385+
var selectedItemIndex = candidates.indexOf(bestSignature);
386+
if (selectedItemIndex < 0) {
387+
selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount);
388+
}
389+
358390
return {
359391
items: items,
360392
applicableSpan: applicableSpan,

tests/cases/fourslash/fourslash.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ module FourSlashInterface {
294294
FourSlash.currentTestState.verifySignatureHelpCount(expected);
295295
}
296296

297+
public signatureHelpArgumentCountIs(expected: number) {
298+
FourSlash.currentTestState.verifySignatureHelpArgumentCount(expected);
299+
}
300+
297301
public currentSignatureParamterCountIs(expected: number) {
298302
FourSlash.currentTestState.verifyCurrentSignatureHelpParameterCount(expected);
299303
}

tests/cases/fourslash/signatureHelpOnOverloadsDifferentArity3.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ goTo.marker();
1111
verify.signatureHelpCountIs(4);
1212
verify.currentSignatureHelpIs("f(): any");
1313
verify.currentSignatureParamterCountIs(0);
14+
verify.signatureHelpArgumentCountIs(0);
1415

1516
edit.insert(", ");
1617
verify.signatureHelpCountIs(4);
@@ -19,8 +20,7 @@ verify.currentSignatureParamterCountIs(2);
1920
verify.currentParameterHelpArgumentNameIs("b");
2021
verify.currentParameterSpanIs("b: boolean");
2122

22-
// What should the intended behavior be if there are too many arguments?
2323
edit.insert(", ");
2424
verify.signatureHelpCountIs(4);
25-
verify.currentSignatureHelpIs("f(): any");
26-
verify.currentSignatureParamterCountIs(0);
25+
verify.currentSignatureHelpIs("f(s: string, b: boolean): any");
26+
verify.currentSignatureParamterCountIs(2);

0 commit comments

Comments
 (0)