@@ -21298,8 +21298,34 @@ namespace ts {
21298
21298
return Debug.fail();
21299
21299
}
21300
21300
}
21301
+ function getDiagnosticSpanForCallNode(node: CallExpression, doNotIncludeArguments?: boolean) {
21302
+ let start: number;
21303
+ let length: number;
21304
+ const sourceFile = getSourceFileOfNode(node);
21301
21305
21302
- function getArgumentArityError(node: Node, signatures: ReadonlyArray<Signature>, args: ReadonlyArray<Expression>) {
21306
+ if (isPropertyAccessExpression(node.expression)) {
21307
+ const nameSpan = getErrorSpanForNode(sourceFile, node.expression.name);
21308
+ start = nameSpan.start;
21309
+ length = doNotIncludeArguments ? nameSpan.length : node.end - start;
21310
+ }
21311
+ else {
21312
+ const expressionSpan = getErrorSpanForNode(sourceFile, node.expression);
21313
+ start = expressionSpan.start;
21314
+ length = doNotIncludeArguments ? expressionSpan.length : node.end - start;
21315
+ }
21316
+ return { start, length, sourceFile };
21317
+ }
21318
+ function getDiagnosticForCallNode(node: CallLikeExpression, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): DiagnosticWithLocation {
21319
+ if (isCallExpression(node)) {
21320
+ const { sourceFile, start, length } = getDiagnosticSpanForCallNode(node);
21321
+ return createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2, arg3);
21322
+ }
21323
+ else {
21324
+ return createDiagnosticForNode(node, message, arg0, arg1, arg2, arg3);
21325
+ }
21326
+ }
21327
+
21328
+ function getArgumentArityError(node: CallLikeExpression, signatures: ReadonlyArray<Signature>, args: ReadonlyArray<Expression>) {
21303
21329
let min = Number.POSITIVE_INFINITY;
21304
21330
let max = Number.NEGATIVE_INFINITY;
21305
21331
let belowArgCount = Number.NEGATIVE_INFINITY;
@@ -21346,11 +21372,11 @@ namespace ts {
21346
21372
}
21347
21373
}
21348
21374
if (min < argCount && argCount < max) {
21349
- return createDiagnosticForNode (node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, argCount, belowArgCount, aboveArgCount);
21375
+ return getDiagnosticForCallNode (node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, argCount, belowArgCount, aboveArgCount);
21350
21376
}
21351
21377
21352
21378
if (!hasSpreadArgument && argCount < min) {
21353
- const diagnostic = createDiagnosticForNode (node, error, paramRange, argCount);
21379
+ const diagnostic = getDiagnosticForCallNode (node, error, paramRange, argCount);
21354
21380
return related ? addRelatedInfo(diagnostic, related) : diagnostic;
21355
21381
}
21356
21382
@@ -21425,8 +21451,7 @@ namespace ts {
21425
21451
reorderCandidates(signatures, candidates);
21426
21452
if (!candidates.length) {
21427
21453
if (reportErrors) {
21428
- const errorNode = getCallErrorNode(node);
21429
- diagnostics.add(createDiagnosticForNode(errorNode, Diagnostics.Call_target_does_not_contain_any_signatures));
21454
+ diagnostics.add(getDiagnosticForCallNode(node, Diagnostics.Call_target_does_not_contain_any_signatures));
21430
21455
}
21431
21456
return resolveErrorCall(node);
21432
21457
}
@@ -21504,45 +21529,32 @@ namespace ts {
21504
21529
// If candidate is undefined, it means that no candidates had a suitable arity. In that case,
21505
21530
// skip the checkApplicableSignature check.
21506
21531
if (reportErrors) {
21507
- const errorNode = getCallErrorNode(node);
21508
21532
21509
21533
if (candidateForArgumentError) {
21510
21534
checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, CheckMode.Normal, /*reportErrors*/ true);
21511
21535
}
21512
21536
else if (candidateForArgumentArityError) {
21513
- diagnostics.add(getArgumentArityError(errorNode , [candidateForArgumentArityError], args));
21537
+ diagnostics.add(getArgumentArityError(node , [candidateForArgumentArityError], args));
21514
21538
}
21515
21539
else if (candidateForTypeArgumentError) {
21516
21540
checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression | JsxOpeningLikeElement).typeArguments!, /*reportErrors*/ true, fallbackError);
21517
21541
}
21518
21542
else {
21519
21543
const signaturesWithCorrectTypeArgumentArity = filter(signatures, s => hasCorrectTypeArgumentArity(s, typeArguments));
21520
21544
if (signaturesWithCorrectTypeArgumentArity.length === 0) {
21521
- diagnostics.add(getTypeArgumentArityError(errorNode , signatures, typeArguments!));
21545
+ diagnostics.add(getTypeArgumentArityError(node , signatures, typeArguments!));
21522
21546
}
21523
21547
else if (!isDecorator) {
21524
- diagnostics.add(getArgumentArityError(errorNode , signaturesWithCorrectTypeArgumentArity, args));
21548
+ diagnostics.add(getArgumentArityError(node , signaturesWithCorrectTypeArgumentArity, args));
21525
21549
}
21526
21550
else if (fallbackError) {
21527
- diagnostics.add(createDiagnosticForNode(errorNode , fallbackError));
21551
+ diagnostics.add(getDiagnosticForCallNode(node , fallbackError));
21528
21552
}
21529
21553
}
21530
21554
}
21531
21555
21532
21556
return produceDiagnostics || !args ? resolveErrorCall(node) : getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
21533
21557
21534
- function getCallErrorNode(node: CallLikeExpression): Node {
21535
- if (isCallExpression(node)) {
21536
- if (isPropertyAccessExpression(node.expression)) {
21537
- return node.expression.name;
21538
- }
21539
- else {
21540
- return node.expression;
21541
- }
21542
- }
21543
- return node;
21544
- }
21545
-
21546
21558
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
21547
21559
candidateForArgumentError = undefined;
21548
21560
candidateForArgumentArityError = undefined;
@@ -21825,7 +21837,7 @@ namespace ts {
21825
21837
relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.It_is_highly_likely_that_you_are_missing_a_semicolon);
21826
21838
}
21827
21839
}
21828
- invocationError(node, apparentType, SignatureKind.Call, relatedInformation);
21840
+ invocationError(node.expression , apparentType, SignatureKind.Call, relatedInformation);
21829
21841
}
21830
21842
return resolveErrorCall(node);
21831
21843
}
@@ -21942,7 +21954,7 @@ namespace ts {
21942
21954
return signature;
21943
21955
}
21944
21956
21945
- invocationError(node, expressionType, SignatureKind.Construct);
21957
+ invocationError(node.expression , expressionType, SignatureKind.Construct);
21946
21958
return resolveErrorCall(node);
21947
21959
}
21948
21960
@@ -22015,11 +22027,88 @@ namespace ts {
22015
22027
return true;
22016
22028
}
22017
22029
22018
- function invocationError(node: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) {
22019
- const diagnostic = error(node, (kind === SignatureKind.Call ?
22020
- Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures :
22021
- Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature
22022
- ), typeToString(apparentType));
22030
+ function invocationErrorDetails(apparentType: Type, kind: SignatureKind): DiagnosticMessageChain {
22031
+ let errorInfo: DiagnosticMessageChain | undefined;
22032
+ const isCall = kind === SignatureKind.Call;
22033
+ if (apparentType.flags & TypeFlags.Union) {
22034
+ const types = (apparentType as UnionType).types;
22035
+ let hasSignatures = false;
22036
+ for (const constituent of types) {
22037
+ const signatures = getSignaturesOfType(constituent, kind);
22038
+ if (signatures.length !== 0) {
22039
+ hasSignatures = true;
22040
+ if (errorInfo) {
22041
+ // Bail early if we already have an error, no chance of "No constituent of type is callable"
22042
+ break;
22043
+ }
22044
+ }
22045
+ else {
22046
+ // Error on the first non callable constituent only
22047
+ if (!errorInfo) {
22048
+ errorInfo = chainDiagnosticMessages(
22049
+ errorInfo,
22050
+ isCall ?
22051
+ Diagnostics.Type_0_has_no_call_signatures :
22052
+ Diagnostics.Type_0_has_no_construct_signatures,
22053
+ typeToString(constituent)
22054
+ );
22055
+ errorInfo = chainDiagnosticMessages(
22056
+ errorInfo,
22057
+ isCall ?
22058
+ Diagnostics.Not_all_constituents_of_type_0_are_callable :
22059
+ Diagnostics.Not_all_constituents_of_type_0_are_constructable,
22060
+ typeToString(apparentType)
22061
+ );
22062
+ }
22063
+ if (hasSignatures) {
22064
+ // Bail early if we already found a siganture, no chance of "No constituent of type is callable"
22065
+ break;
22066
+ }
22067
+ }
22068
+ }
22069
+ if (!hasSignatures) {
22070
+ errorInfo = chainDiagnosticMessages(
22071
+ /* detials */ undefined,
22072
+ isCall ?
22073
+ Diagnostics.No_constituent_of_type_0_is_callable :
22074
+ Diagnostics.No_constituent_of_type_0_is_constructable,
22075
+ typeToString(apparentType)
22076
+ );
22077
+ }
22078
+ if (!errorInfo) {
22079
+ errorInfo = chainDiagnosticMessages(
22080
+ errorInfo,
22081
+ isCall ?
22082
+ Diagnostics.Each_member_of_the_union_type_0_has_signatures_but_none_of_those_signatures_are_compatible_with_each_other :
22083
+ Diagnostics.Each_member_of_the_union_type_0_has_construct_signatures_but_none_of_those_signatures_are_compatible_with_each_other,
22084
+ typeToString(apparentType)
22085
+ );
22086
+ }
22087
+ }
22088
+ else {
22089
+ errorInfo = chainDiagnosticMessages(
22090
+ errorInfo,
22091
+ isCall ?
22092
+ Diagnostics.Type_0_has_no_call_signatures :
22093
+ Diagnostics.Type_0_has_no_construct_signatures,
22094
+ typeToString(apparentType)
22095
+ );
22096
+ }
22097
+ return chainDiagnosticMessages(
22098
+ errorInfo,
22099
+ isCall ?
22100
+ Diagnostics.This_expression_is_not_callable :
22101
+ Diagnostics.This_expression_is_not_constructable
22102
+ );
22103
+ }
22104
+ function invocationError(errorTarget: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) {
22105
+ const diagnostic = createDiagnosticForNodeFromMessageChain(errorTarget, invocationErrorDetails(apparentType, kind));
22106
+ if (isCallExpression(errorTarget.parent)) {
22107
+ const { start, length } = getDiagnosticSpanForCallNode(errorTarget.parent, /* doNotIncludeArguments */ true);
22108
+ diagnostic.start = start;
22109
+ diagnostic.length = length;
22110
+ }
22111
+ diagnostics.add(diagnostic);
22023
22112
invocationErrorRecovery(apparentType, kind, relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic);
22024
22113
}
22025
22114
@@ -22057,7 +22146,7 @@ namespace ts {
22057
22146
}
22058
22147
22059
22148
if (!callSignatures.length) {
22060
- invocationError(node, apparentType, SignatureKind.Call);
22149
+ invocationError(node.tag , apparentType, SignatureKind.Call);
22061
22150
return resolveErrorCall(node);
22062
22151
}
22063
22152
@@ -22113,9 +22202,9 @@ namespace ts {
22113
22202
22114
22203
const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node);
22115
22204
if (!callSignatures.length) {
22116
- 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) );
22205
+ let errorInfo = invocationErrorDetails(apparentType, SignatureKind.Call );
22117
22206
errorInfo = chainDiagnosticMessages(errorInfo, headMessage);
22118
- const diag = createDiagnosticForNodeFromMessageChain(node, errorInfo);
22207
+ const diag = createDiagnosticForNodeFromMessageChain(node.expression , errorInfo);
22119
22208
diagnostics.add(diag);
22120
22209
invocationErrorRecovery(apparentType, SignatureKind.Call, diag);
22121
22210
return resolveErrorCall(node);
0 commit comments