Fix signature help
This commit is contained in:
parent
8b0974a77e
commit
2fc2f5c4b9
|
@ -10321,7 +10321,7 @@ namespace ts {
|
|||
return -1;
|
||||
}
|
||||
|
||||
function hasCorrectArity(node: CallLikeExpression, args: Expression[], signature: Signature) {
|
||||
function hasCorrectArity(node: CallLikeExpression, args: Expression[], signature: Signature, signatureHelpTrailingComma = false) {
|
||||
let argCount: number; // Apparent number of arguments we will have in this call
|
||||
let typeArguments: NodeArray<TypeNode>; // Type arguments (undefined if none)
|
||||
let callIsIncomplete: boolean; // In incomplete call we want to be lenient when we have too few arguments
|
||||
|
@ -10367,7 +10367,7 @@ namespace ts {
|
|||
return signature.minArgumentCount === 0;
|
||||
}
|
||||
|
||||
argCount = args.length;
|
||||
argCount = signatureHelpTrailingComma ? args.length + 1 : args.length;
|
||||
|
||||
// If we are missing the close paren, the call is incomplete.
|
||||
callIsIncomplete = (<CallExpression>callExpression).arguments.end === callExpression.end;
|
||||
|
@ -10968,6 +10968,11 @@ namespace ts {
|
|||
let resultOfFailedInference: InferenceContext;
|
||||
let result: Signature;
|
||||
|
||||
// If we are in signature help, a trailing comma indicates that we intend to provide another argument,
|
||||
// so we will only accept overloads with arity at least 1 higher than the current number of provided arguments.
|
||||
const signatureHelpTrailingComma =
|
||||
candidatesOutArray && node.kind === SyntaxKind.CallExpression && (<CallExpression>node).arguments.hasTrailingComma;
|
||||
|
||||
// Section 4.12.1:
|
||||
// if the candidate list contains one or more signatures for which the type of each argument
|
||||
// expression is a subtype of each corresponding parameter type, the return type of the first
|
||||
|
@ -10979,14 +10984,14 @@ namespace ts {
|
|||
// is just important for choosing the best signature. So in the case where there is only one
|
||||
// signature, the subtype pass is useless. So skipping it is an optimization.
|
||||
if (candidates.length > 1) {
|
||||
result = chooseOverload(candidates, subtypeRelation);
|
||||
result = chooseOverload(candidates, subtypeRelation, signatureHelpTrailingComma);
|
||||
}
|
||||
if (!result) {
|
||||
// Reinitialize these pointers for round two
|
||||
candidateForArgumentError = undefined;
|
||||
candidateForTypeArgumentError = undefined;
|
||||
resultOfFailedInference = undefined;
|
||||
result = chooseOverload(candidates, assignableRelation);
|
||||
result = chooseOverload(candidates, assignableRelation, signatureHelpTrailingComma);
|
||||
}
|
||||
if (result) {
|
||||
return result;
|
||||
|
@ -11057,9 +11062,9 @@ namespace ts {
|
|||
diagnostics.add(createDiagnosticForNodeFromMessageChain(node, errorInfo));
|
||||
}
|
||||
|
||||
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>) {
|
||||
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
|
||||
for (const originalCandidate of candidates) {
|
||||
if (!hasCorrectArity(node, args, originalCandidate)) {
|
||||
if (!hasCorrectArity(node, args, originalCandidate, signatureHelpTrailingComma)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,19 @@ f1(1,);
|
|||
function f2(...args,) {}
|
||||
|
||||
f2(...[],);
|
||||
|
||||
// Not confused by overloads
|
||||
declare function f3(x, ): number;
|
||||
declare function f3(x, y,): string;
|
||||
|
||||
<number>f3(1,);
|
||||
<string>f3(1, 2,);
|
||||
|
||||
// Works for constructors too
|
||||
class X {
|
||||
constructor(a,) { }
|
||||
}
|
||||
new X(1,);
|
||||
|
||||
|
||||
//// [trailingCommasInFunctionParametersAndArguments.js]
|
||||
|
@ -18,3 +31,12 @@ function f2() {
|
|||
}
|
||||
}
|
||||
f2.apply(void 0, []);
|
||||
f3(1);
|
||||
f3(1, 2);
|
||||
// Works for constructors too
|
||||
var X = (function () {
|
||||
function X(a) {
|
||||
}
|
||||
return X;
|
||||
}());
|
||||
new X(1);
|
||||
|
|
|
@ -13,3 +13,29 @@ function f2(...args,) {}
|
|||
f2(...[],);
|
||||
>f2 : Symbol(f2, Decl(trailingCommasInFunctionParametersAndArguments.ts, 2, 7))
|
||||
|
||||
// Not confused by overloads
|
||||
declare function f3(x, ): number;
|
||||
>f3 : Symbol(f3, Decl(trailingCommasInFunctionParametersAndArguments.ts, 6, 11), Decl(trailingCommasInFunctionParametersAndArguments.ts, 9, 33))
|
||||
>x : Symbol(x, Decl(trailingCommasInFunctionParametersAndArguments.ts, 9, 20))
|
||||
|
||||
declare function f3(x, y,): string;
|
||||
>f3 : Symbol(f3, Decl(trailingCommasInFunctionParametersAndArguments.ts, 6, 11), Decl(trailingCommasInFunctionParametersAndArguments.ts, 9, 33))
|
||||
>x : Symbol(x, Decl(trailingCommasInFunctionParametersAndArguments.ts, 10, 20))
|
||||
>y : Symbol(y, Decl(trailingCommasInFunctionParametersAndArguments.ts, 10, 22))
|
||||
|
||||
<number>f3(1,);
|
||||
>f3 : Symbol(f3, Decl(trailingCommasInFunctionParametersAndArguments.ts, 6, 11), Decl(trailingCommasInFunctionParametersAndArguments.ts, 9, 33))
|
||||
|
||||
<string>f3(1, 2,);
|
||||
>f3 : Symbol(f3, Decl(trailingCommasInFunctionParametersAndArguments.ts, 6, 11), Decl(trailingCommasInFunctionParametersAndArguments.ts, 9, 33))
|
||||
|
||||
// Works for constructors too
|
||||
class X {
|
||||
>X : Symbol(X, Decl(trailingCommasInFunctionParametersAndArguments.ts, 13, 18))
|
||||
|
||||
constructor(a,) { }
|
||||
>a : Symbol(a, Decl(trailingCommasInFunctionParametersAndArguments.ts, 17, 16))
|
||||
}
|
||||
new X(1,);
|
||||
>X : Symbol(X, Decl(trailingCommasInFunctionParametersAndArguments.ts, 13, 18))
|
||||
|
||||
|
|
|
@ -18,3 +18,38 @@ f2(...[],);
|
|||
>...[] : undefined
|
||||
>[] : undefined[]
|
||||
|
||||
// Not confused by overloads
|
||||
declare function f3(x, ): number;
|
||||
>f3 : { (x: any): number; (x: any, y: any): string; }
|
||||
>x : any
|
||||
|
||||
declare function f3(x, y,): string;
|
||||
>f3 : { (x: any): number; (x: any, y: any): string; }
|
||||
>x : any
|
||||
>y : any
|
||||
|
||||
<number>f3(1,);
|
||||
><number>f3(1,) : number
|
||||
>f3(1,) : number
|
||||
>f3 : { (x: any): number; (x: any, y: any): string; }
|
||||
>1 : number
|
||||
|
||||
<string>f3(1, 2,);
|
||||
><string>f3(1, 2,) : string
|
||||
>f3(1, 2,) : string
|
||||
>f3 : { (x: any): number; (x: any, y: any): string; }
|
||||
>1 : number
|
||||
>2 : number
|
||||
|
||||
// Works for constructors too
|
||||
class X {
|
||||
>X : X
|
||||
|
||||
constructor(a,) { }
|
||||
>a : any
|
||||
}
|
||||
new X(1,);
|
||||
>new X(1,) : X
|
||||
>X : typeof X
|
||||
>1 : number
|
||||
|
||||
|
|
|
@ -5,3 +5,16 @@ f1(1,);
|
|||
function f2(...args,) {}
|
||||
|
||||
f2(...[],);
|
||||
|
||||
// Not confused by overloads
|
||||
declare function f3(x, ): number;
|
||||
declare function f3(x, y,): string;
|
||||
|
||||
<number>f3(1,);
|
||||
<string>f3(1, 2,);
|
||||
|
||||
// Works for constructors too
|
||||
class X {
|
||||
constructor(a,) { }
|
||||
}
|
||||
new X(1,);
|
||||
|
|
Loading…
Reference in a new issue