@@ -21405,8 +21405,34 @@ namespace ts {
21405
21405
return Debug.fail();
21406
21406
}
21407
21407
}
21408
+ function getDiagnosticSpanForCallNode(node: CallExpression, doNotIncludeArguments?: boolean) {
21409
+ let start: number;
21410
+ let length: number;
21411
+ const sourceFile = getSourceFileOfNode(node);
21408
21412
21409
- function getArgumentArityError(node: Node, signatures: ReadonlyArray<Signature>, args: ReadonlyArray<Expression>) {
21413
+ if (isPropertyAccessExpression(node.expression)) {
21414
+ const nameSpan = getErrorSpanForNode(sourceFile, node.expression.name);
21415
+ start = nameSpan.start;
21416
+ length = doNotIncludeArguments ? nameSpan.length : node.end - start;
21417
+ }
21418
+ else {
21419
+ const expressionSpan = getErrorSpanForNode(sourceFile, node.expression);
21420
+ start = expressionSpan.start;
21421
+ length = doNotIncludeArguments ? expressionSpan.length : node.end - start;
21422
+ }
21423
+ return { start, length, sourceFile };
21424
+ }
21425
+ function getDiagnosticForCallNode(node: CallLikeExpression, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): DiagnosticWithLocation {
21426
+ if (isCallExpression(node)) {
21427
+ const { sourceFile, start, length } = getDiagnosticSpanForCallNode(node);
21428
+ return createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2, arg3);
21429
+ }
21430
+ else {
21431
+ return createDiagnosticForNode(node, message, arg0, arg1, arg2, arg3);
21432
+ }
21433
+ }
21434
+
21435
+ function getArgumentArityError(node: CallLikeExpression, signatures: ReadonlyArray<Signature>, args: ReadonlyArray<Expression>) {
21410
21436
let min = Number.POSITIVE_INFINITY;
21411
21437
let max = Number.NEGATIVE_INFINITY;
21412
21438
let belowArgCount = Number.NEGATIVE_INFINITY;
@@ -21453,11 +21479,11 @@ namespace ts {
21453
21479
}
21454
21480
}
21455
21481
if (min < argCount && argCount < max) {
21456
- return createDiagnosticForNode (node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, argCount, belowArgCount, aboveArgCount);
21482
+ return getDiagnosticForCallNode (node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, argCount, belowArgCount, aboveArgCount);
21457
21483
}
21458
21484
21459
21485
if (!hasSpreadArgument && argCount < min) {
21460
- const diagnostic = createDiagnosticForNode (node, error, paramRange, argCount);
21486
+ const diagnostic = getDiagnosticForCallNode (node, error, paramRange, argCount);
21461
21487
return related ? addRelatedInfo(diagnostic, related) : diagnostic;
21462
21488
}
21463
21489
@@ -21532,8 +21558,7 @@ namespace ts {
21532
21558
reorderCandidates(signatures, candidates);
21533
21559
if (!candidates.length) {
21534
21560
if (reportErrors) {
21535
- const errorNode = getCallErrorNode(node);
21536
- diagnostics.add(createDiagnosticForNode(errorNode, Diagnostics.Call_target_does_not_contain_any_signatures));
21561
+ diagnostics.add(getDiagnosticForCallNode(node, Diagnostics.Call_target_does_not_contain_any_signatures));
21537
21562
}
21538
21563
return resolveErrorCall(node);
21539
21564
}
@@ -21611,7 +21636,6 @@ namespace ts {
21611
21636
// If candidate is undefined, it means that no candidates had a suitable arity. In that case,
21612
21637
// skip the checkApplicableSignature check.
21613
21638
if (reportErrors) {
21614
- const errorNode = getCallErrorNode(node);
21615
21639
if (candidatesForArgumentError) {
21616
21640
if (candidatesForArgumentError.length === 1 || candidatesForArgumentError.length > 3) {
21617
21641
const last = candidatesForArgumentError[candidatesForArgumentError.length - 1];
@@ -21663,39 +21687,27 @@ namespace ts {
21663
21687
}
21664
21688
}
21665
21689
else if (candidateForArgumentArityError) {
21666
- diagnostics.add(getArgumentArityError(errorNode , [candidateForArgumentArityError], args));
21690
+ diagnostics.add(getArgumentArityError(node , [candidateForArgumentArityError], args));
21667
21691
}
21668
21692
else if (candidateForTypeArgumentError) {
21669
21693
checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression | JsxOpeningLikeElement).typeArguments!, /*reportErrors*/ true, fallbackError);
21670
21694
}
21671
21695
else {
21672
21696
const signaturesWithCorrectTypeArgumentArity = filter(signatures, s => hasCorrectTypeArgumentArity(s, typeArguments));
21673
21697
if (signaturesWithCorrectTypeArgumentArity.length === 0) {
21674
- diagnostics.add(getTypeArgumentArityError(errorNode , signatures, typeArguments!));
21698
+ diagnostics.add(getTypeArgumentArityError(node , signatures, typeArguments!));
21675
21699
}
21676
21700
else if (!isDecorator) {
21677
- diagnostics.add(getArgumentArityError(errorNode , signaturesWithCorrectTypeArgumentArity, args));
21701
+ diagnostics.add(getArgumentArityError(node , signaturesWithCorrectTypeArgumentArity, args));
21678
21702
}
21679
21703
else if (fallbackError) {
21680
- diagnostics.add(createDiagnosticForNode(errorNode , fallbackError));
21704
+ diagnostics.add(getDiagnosticForCallNode(node , fallbackError));
21681
21705
}
21682
21706
}
21683
21707
}
21684
21708
21685
21709
return produceDiagnostics || !args ? resolveErrorCall(node) : getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
21686
21710
21687
- function getCallErrorNode(node: CallLikeExpression): Node {
21688
- if (isCallExpression(node)) {
21689
- if (isPropertyAccessExpression(node.expression)) {
21690
- return node.expression.name;
21691
- }
21692
- else {
21693
- return node.expression;
21694
- }
21695
- }
21696
- return node;
21697
- }
21698
-
21699
21711
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
21700
21712
candidatesForArgumentError = undefined;
21701
21713
candidateForArgumentArityError = undefined;
@@ -21974,7 +21986,7 @@ namespace ts {
21974
21986
relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.It_is_highly_likely_that_you_are_missing_a_semicolon);
21975
21987
}
21976
21988
}
21977
- invocationError(node, apparentType, SignatureKind.Call, relatedInformation);
21989
+ invocationError(node.expression , apparentType, SignatureKind.Call, relatedInformation);
21978
21990
}
21979
21991
return resolveErrorCall(node);
21980
21992
}
@@ -22091,7 +22103,7 @@ namespace ts {
22091
22103
return signature;
22092
22104
}
22093
22105
22094
- invocationError(node, expressionType, SignatureKind.Construct);
22106
+ invocationError(node.expression , expressionType, SignatureKind.Construct);
22095
22107
return resolveErrorCall(node);
22096
22108
}
22097
22109
@@ -22164,11 +22176,88 @@ namespace ts {
22164
22176
return true;
22165
22177
}
22166
22178
22167
- function invocationError(node: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) {
22168
- const diagnostic = error(node, (kind === SignatureKind.Call ?
22169
- Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures :
22170
- Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature
22171
- ), typeToString(apparentType));
22179
+ function invocationErrorDetails(apparentType: Type, kind: SignatureKind): DiagnosticMessageChain {
22180
+ let errorInfo: DiagnosticMessageChain | undefined;
22181
+ const isCall = kind === SignatureKind.Call;
22182
+ if (apparentType.flags & TypeFlags.Union) {
22183
+ const types = (apparentType as UnionType).types;
22184
+ let hasSignatures = false;
22185
+ for (const constituent of types) {
22186
+ const signatures = getSignaturesOfType(constituent, kind);
22187
+ if (signatures.length !== 0) {
22188
+ hasSignatures = true;
22189
+ if (errorInfo) {
22190
+ // Bail early if we already have an error, no chance of "No constituent of type is callable"
22191
+ break;
22192
+ }
22193
+ }
22194
+ else {
22195
+ // Error on the first non callable constituent only
22196
+ if (!errorInfo) {
22197
+ errorInfo = chainDiagnosticMessages(
22198
+ errorInfo,
22199
+ isCall ?
22200
+ Diagnostics.Type_0_has_no_call_signatures :
22201
+ Diagnostics.Type_0_has_no_construct_signatures,
22202
+ typeToString(constituent)
22203
+ );
22204
+ errorInfo = chainDiagnosticMessages(
22205
+ errorInfo,
22206
+ isCall ?
22207
+ Diagnostics.Not_all_constituents_of_type_0_are_callable :
22208
+ Diagnostics.Not_all_constituents_of_type_0_are_constructable,
22209
+ typeToString(apparentType)
22210
+ );
22211
+ }
22212
+ if (hasSignatures) {
22213
+ // Bail early if we already found a siganture, no chance of "No constituent of type is callable"
22214
+ break;
22215
+ }
22216
+ }
22217
+ }
22218
+ if (!hasSignatures) {
22219
+ errorInfo = chainDiagnosticMessages(
22220
+ /* detials */ undefined,
22221
+ isCall ?
22222
+ Diagnostics.No_constituent_of_type_0_is_callable :
22223
+ Diagnostics.No_constituent_of_type_0_is_constructable,
22224
+ typeToString(apparentType)
22225
+ );
22226
+ }
22227
+ if (!errorInfo) {
22228
+ errorInfo = chainDiagnosticMessages(
22229
+ errorInfo,
22230
+ isCall ?
22231
+ Diagnostics.Each_member_of_the_union_type_0_has_signatures_but_none_of_those_signatures_are_compatible_with_each_other :
22232
+ Diagnostics.Each_member_of_the_union_type_0_has_construct_signatures_but_none_of_those_signatures_are_compatible_with_each_other,
22233
+ typeToString(apparentType)
22234
+ );
22235
+ }
22236
+ }
22237
+ else {
22238
+ errorInfo = chainDiagnosticMessages(
22239
+ errorInfo,
22240
+ isCall ?
22241
+ Diagnostics.Type_0_has_no_call_signatures :
22242
+ Diagnostics.Type_0_has_no_construct_signatures,
22243
+ typeToString(apparentType)
22244
+ );
22245
+ }
22246
+ return chainDiagnosticMessages(
22247
+ errorInfo,
22248
+ isCall ?
22249
+ Diagnostics.This_expression_is_not_callable :
22250
+ Diagnostics.This_expression_is_not_constructable
22251
+ );
22252
+ }
22253
+ function invocationError(errorTarget: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) {
22254
+ const diagnostic = createDiagnosticForNodeFromMessageChain(errorTarget, invocationErrorDetails(apparentType, kind));
22255
+ if (isCallExpression(errorTarget.parent)) {
22256
+ const { start, length } = getDiagnosticSpanForCallNode(errorTarget.parent, /* doNotIncludeArguments */ true);
22257
+ diagnostic.start = start;
22258
+ diagnostic.length = length;
22259
+ }
22260
+ diagnostics.add(diagnostic);
22172
22261
invocationErrorRecovery(apparentType, kind, relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic);
22173
22262
}
22174
22263
@@ -22206,7 +22295,7 @@ namespace ts {
22206
22295
}
22207
22296
22208
22297
if (!callSignatures.length) {
22209
- invocationError(node, apparentType, SignatureKind.Call);
22298
+ invocationError(node.tag , apparentType, SignatureKind.Call);
22210
22299
return resolveErrorCall(node);
22211
22300
}
22212
22301
@@ -22262,9 +22351,9 @@ namespace ts {
22262
22351
22263
22352
const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node);
22264
22353
if (!callSignatures.length) {
22265
- let errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType) );
22354
+ let errorInfo = invocationErrorDetails(apparentType, SignatureKind.Call );
22266
22355
errorInfo = chainDiagnosticMessages(errorInfo, headMessage);
22267
- const diag = createDiagnosticForNodeFromMessageChain(node, errorInfo);
22356
+ const diag = createDiagnosticForNodeFromMessageChain(node.expression , errorInfo);
22268
22357
diagnostics.add(diag);
22269
22358
invocationErrorRecovery(apparentType, SignatureKind.Call, diag);
22270
22359
return resolveErrorCall(node);
0 commit comments