mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Add elaboration when call fails all overloads but succeeds against the implementation signature
This commit is contained in:
@@ -274,7 +274,7 @@ namespace ts {
|
||||
result.relatedInformation = relatedInformation ?
|
||||
relatedInformation.length ?
|
||||
relatedInformation.map(r => convertToDiagnosticRelatedInformation(r, newProgram, toPath)) :
|
||||
emptyArray :
|
||||
[] :
|
||||
undefined;
|
||||
return result;
|
||||
});
|
||||
@@ -824,7 +824,7 @@ namespace ts {
|
||||
result.relatedInformation = relatedInformation ?
|
||||
relatedInformation.length ?
|
||||
relatedInformation.map(r => convertToReusableDiagnosticRelatedInformation(r, relativeToBuildInfo)) :
|
||||
emptyArray :
|
||||
[] :
|
||||
undefined;
|
||||
return result;
|
||||
});
|
||||
|
||||
@@ -27227,10 +27227,10 @@ 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, signatureHelpTrailingComma);
|
||||
result = chooseOverload(candidates, subtypeRelation, isSingleNonGenericCandidate, signatureHelpTrailingComma);
|
||||
}
|
||||
if (!result) {
|
||||
result = chooseOverload(candidates, assignableRelation, signatureHelpTrailingComma);
|
||||
result = chooseOverload(candidates, assignableRelation, isSingleNonGenericCandidate, signatureHelpTrailingComma);
|
||||
}
|
||||
if (result) {
|
||||
return result;
|
||||
@@ -27255,6 +27255,7 @@ namespace ts {
|
||||
if (last.declaration && candidatesForArgumentError.length > 3) {
|
||||
addRelatedInfo(d, createDiagnosticForNode(last.declaration, Diagnostics.The_last_overload_is_declared_here));
|
||||
}
|
||||
addImplementationSuccessElaboration(last, d);
|
||||
diagnostics.add(d);
|
||||
}
|
||||
}
|
||||
@@ -27290,14 +27291,19 @@ namespace ts {
|
||||
const chain = chainDiagnosticMessages(
|
||||
map(diags, d => typeof d.messageText === "string" ? (d as DiagnosticMessageChain) : d.messageText),
|
||||
Diagnostics.No_overload_matches_this_call);
|
||||
const related = flatMap(diags, d => (d as Diagnostic).relatedInformation) as DiagnosticRelatedInformation[];
|
||||
// The below is a spread to guarantee we get a new (mutable) array - our `flatMap` helper tries to do "smart" optimizations where it reuses input
|
||||
// arrays and the emptyArray singleton where possible, which is decidedly not what we want while we're still constructing this diagnostic
|
||||
const related = [...flatMap(diags, d => (d as Diagnostic).relatedInformation) as DiagnosticRelatedInformation[]];
|
||||
let diag: Diagnostic;
|
||||
if (every(diags, d => d.start === diags[0].start && d.length === diags[0].length && d.file === diags[0].file)) {
|
||||
const { file, start, length } = diags[0];
|
||||
diagnostics.add({ file, start, length, code: chain.code, category: chain.category, messageText: chain, relatedInformation: related });
|
||||
diag = { file, start, length, code: chain.code, category: chain.category, messageText: chain, relatedInformation: related };
|
||||
}
|
||||
else {
|
||||
diagnostics.add(createDiagnosticForNodeFromMessageChain(node, chain, related));
|
||||
diag = createDiagnosticForNodeFromMessageChain(node, chain, related);
|
||||
}
|
||||
addImplementationSuccessElaboration(candidatesForArgumentError[0], diag);
|
||||
diagnostics.add(diag);
|
||||
}
|
||||
}
|
||||
else if (candidateForArgumentArityError) {
|
||||
@@ -27322,7 +27328,30 @@ namespace ts {
|
||||
|
||||
return getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
|
||||
|
||||
function chooseOverload(candidates: Signature[], relation: ESMap<string, RelationComparisonResult>, signatureHelpTrailingComma = false) {
|
||||
function addImplementationSuccessElaboration(failed: Signature, d: Diagnostic) {
|
||||
const oldCandidatesForArgumentError = candidatesForArgumentError;
|
||||
const oldCandidateForArgumentArityError = candidateForArgumentArityError;
|
||||
const oldCandidateForTypeArgumentError = candidateForTypeArgumentError;
|
||||
|
||||
const declCount = length(failed.declaration?.symbol.declarations);
|
||||
const isOverload = declCount > 1;
|
||||
const implDecl = isOverload ? failed.declaration?.symbol.declarations[declCount - 1] : undefined;
|
||||
|
||||
|
||||
if (isOverload && implDecl && nodeIsPresent((implDecl as FunctionLikeDeclaration).body)) {
|
||||
const candidate = getSignatureFromDeclaration(implDecl as FunctionLikeDeclaration);
|
||||
const isSingleNonGenericCandidate = !candidate.typeParameters;
|
||||
if (!!chooseOverload([candidate], assignableRelation, isSingleNonGenericCandidate)) {
|
||||
addRelatedInfo(d, createDiagnosticForNode(implDecl, Diagnostics.The_call_would_have_succeeded_against_this_implementation_but_implementation_signatures_of_overloads_are_not_externally_visible));
|
||||
}
|
||||
}
|
||||
|
||||
candidatesForArgumentError = oldCandidatesForArgumentError;
|
||||
candidateForArgumentArityError = oldCandidateForArgumentArityError;
|
||||
candidateForTypeArgumentError = oldCandidateForTypeArgumentError;
|
||||
}
|
||||
|
||||
function chooseOverload(candidates: Signature[], relation: ESMap<string, RelationComparisonResult>, isSingleNonGenericCandidate: boolean, signatureHelpTrailingComma = false) {
|
||||
candidatesForArgumentError = undefined;
|
||||
candidateForArgumentArityError = undefined;
|
||||
candidateForTypeArgumentError = undefined;
|
||||
|
||||
@@ -3043,7 +3043,10 @@
|
||||
"category": "Error",
|
||||
"code": 2792
|
||||
},
|
||||
|
||||
"The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.": {
|
||||
"category": "Error",
|
||||
"code": 2793
|
||||
},
|
||||
"Expected {0} arguments, but got {1}. Did you forget to include 'void' in your type argument to 'Promise'?": {
|
||||
"category": "Error",
|
||||
"code": 2794
|
||||
|
||||
@@ -6653,6 +6653,7 @@ namespace ts {
|
||||
if (!diagnostic.relatedInformation) {
|
||||
diagnostic.relatedInformation = [];
|
||||
}
|
||||
Debug.assert(diagnostic.relatedInformation !== emptyArray, "Diagnostic had empty array singleton for related info, but is still being constructed!");
|
||||
diagnostic.relatedInformation.push(...relatedInformation);
|
||||
return diagnostic;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user