diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e333b031c6d..32965372e83 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26383,7 +26383,7 @@ namespace ts { return true; } - function invocationErrorDetails(apparentType: Type, kind: SignatureKind): { messageChain: DiagnosticMessageChain, relatedMessage: DiagnosticMessage | undefined } { + function invocationErrorDetails(errorTarget: Node, apparentType: Type, kind: SignatureKind): { messageChain: DiagnosticMessageChain, relatedMessage: DiagnosticMessage | undefined } { let errorInfo: DiagnosticMessageChain | undefined; const isCall = kind === SignatureKind.Call; const awaitedType = getAwaitedType(apparentType); @@ -26452,16 +26452,24 @@ namespace ts { typeToString(apparentType) ); } + + let headMessage = isCall ? Diagnostics.This_expression_is_not_callable : Diagnostics.This_expression_is_not_constructable; + + // Diagnose get accessors incorrectly called as functions + if (isCallExpression(errorTarget.parent) && errorTarget.parent.arguments.length === 0) { + const { resolvedSymbol } = getNodeLinks(errorTarget); + if (resolvedSymbol && resolvedSymbol.flags & SymbolFlags.GetAccessor) { + headMessage = Diagnostics.This_expression_is_not_callable_because_it_is_a_get_accessor_Did_you_mean_to_use_it_without; + } + } + return { - messageChain: chainDiagnosticMessages( - errorInfo, - isCall ? Diagnostics.This_expression_is_not_callable : Diagnostics.This_expression_is_not_constructable - ), + messageChain: chainDiagnosticMessages(errorInfo, headMessage), relatedMessage: maybeMissingAwait ? Diagnostics.Did_you_forget_to_use_await : undefined, }; } function invocationError(errorTarget: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) { - const { messageChain, relatedMessage: relatedInfo } = invocationErrorDetails(apparentType, kind); + const { messageChain, relatedMessage: relatedInfo } = invocationErrorDetails(errorTarget, apparentType, kind); const diagnostic = createDiagnosticForNodeFromMessageChain(errorTarget, messageChain); if (relatedInfo) { addRelatedInfo(diagnostic, createDiagnosticForNode(errorTarget, relatedInfo)); @@ -26565,7 +26573,7 @@ namespace ts { const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { - const errorDetails = invocationErrorDetails(apparentType, SignatureKind.Call); + const errorDetails = invocationErrorDetails(node.expression, apparentType, SignatureKind.Call); const messageChain = chainDiagnosticMessages(errorDetails.messageChain, headMessage); const diag = createDiagnosticForNodeFromMessageChain(node.expression, messageChain); if (errorDetails.relatedMessage) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index df3192652ac..ef46447faac 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4416,6 +4416,10 @@ "category": "Error", "code": 6233 }, + "This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'?": { + "category": "Error", + "code": 6234 + }, "Projects to reference": { "category": "Message", diff --git a/tests/baselines/reference/accessorAccidentalCallDiagnostic.errors.txt b/tests/baselines/reference/accessorAccidentalCallDiagnostic.errors.txt new file mode 100644 index 00000000000..ee57be17427 --- /dev/null +++ b/tests/baselines/reference/accessorAccidentalCallDiagnostic.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/accessorAccidentalCallDiagnostic.ts(6,14): error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? + Type 'Number' has no call signatures. + + +==== tests/cases/compiler/accessorAccidentalCallDiagnostic.ts (1 errors) ==== + // https://github.com/microsoft/TypeScript/issues/24554 + class Test24554 { + get property(): number { return 1; } + } + function test24554(x: Test24554) { + return x.property(); + ~~~~~~~~ +!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? +!!! error TS6234: Type 'Number' has no call signatures. + } + \ No newline at end of file diff --git a/tests/baselines/reference/accessorAccidentalCallDiagnostic.js b/tests/baselines/reference/accessorAccidentalCallDiagnostic.js new file mode 100644 index 00000000000..6d5ae04ad52 --- /dev/null +++ b/tests/baselines/reference/accessorAccidentalCallDiagnostic.js @@ -0,0 +1,25 @@ +//// [accessorAccidentalCallDiagnostic.ts] +// https://github.com/microsoft/TypeScript/issues/24554 +class Test24554 { + get property(): number { return 1; } +} +function test24554(x: Test24554) { + return x.property(); +} + + +//// [accessorAccidentalCallDiagnostic.js] +// https://github.com/microsoft/TypeScript/issues/24554 +var Test24554 = /** @class */ (function () { + function Test24554() { + } + Object.defineProperty(Test24554.prototype, "property", { + get: function () { return 1; }, + enumerable: false, + configurable: true + }); + return Test24554; +}()); +function test24554(x) { + return x.property(); +} diff --git a/tests/baselines/reference/accessorAccidentalCallDiagnostic.symbols b/tests/baselines/reference/accessorAccidentalCallDiagnostic.symbols new file mode 100644 index 00000000000..d60d466e4cd --- /dev/null +++ b/tests/baselines/reference/accessorAccidentalCallDiagnostic.symbols @@ -0,0 +1,19 @@ +=== tests/cases/compiler/accessorAccidentalCallDiagnostic.ts === +// https://github.com/microsoft/TypeScript/issues/24554 +class Test24554 { +>Test24554 : Symbol(Test24554, Decl(accessorAccidentalCallDiagnostic.ts, 0, 0)) + + get property(): number { return 1; } +>property : Symbol(Test24554.property, Decl(accessorAccidentalCallDiagnostic.ts, 1, 17)) +} +function test24554(x: Test24554) { +>test24554 : Symbol(test24554, Decl(accessorAccidentalCallDiagnostic.ts, 3, 1)) +>x : Symbol(x, Decl(accessorAccidentalCallDiagnostic.ts, 4, 19)) +>Test24554 : Symbol(Test24554, Decl(accessorAccidentalCallDiagnostic.ts, 0, 0)) + + return x.property(); +>x.property : Symbol(Test24554.property, Decl(accessorAccidentalCallDiagnostic.ts, 1, 17)) +>x : Symbol(x, Decl(accessorAccidentalCallDiagnostic.ts, 4, 19)) +>property : Symbol(Test24554.property, Decl(accessorAccidentalCallDiagnostic.ts, 1, 17)) +} + diff --git a/tests/baselines/reference/accessorAccidentalCallDiagnostic.types b/tests/baselines/reference/accessorAccidentalCallDiagnostic.types new file mode 100644 index 00000000000..17a59da43c8 --- /dev/null +++ b/tests/baselines/reference/accessorAccidentalCallDiagnostic.types @@ -0,0 +1,20 @@ +=== tests/cases/compiler/accessorAccidentalCallDiagnostic.ts === +// https://github.com/microsoft/TypeScript/issues/24554 +class Test24554 { +>Test24554 : Test24554 + + get property(): number { return 1; } +>property : number +>1 : 1 +} +function test24554(x: Test24554) { +>test24554 : (x: Test24554) => any +>x : Test24554 + + return x.property(); +>x.property() : any +>x.property : number +>x : Test24554 +>property : number +} + diff --git a/tests/baselines/reference/instancePropertiesInheritedIntoClassType.errors.txt b/tests/baselines/reference/instancePropertiesInheritedIntoClassType.errors.txt index 3b39bdc8e78..e7584c3d831 100644 --- a/tests/baselines/reference/instancePropertiesInheritedIntoClassType.errors.txt +++ b/tests/baselines/reference/instancePropertiesInheritedIntoClassType.errors.txt @@ -1,10 +1,10 @@ tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(19,16): error TS2349: This expression is not callable. +tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(19,16): error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? Type 'Number' has no call signatures. tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(26,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(29,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(41,16): error TS2349: This expression is not callable. +tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(41,16): error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? Type 'String' has no call signatures. @@ -33,8 +33,8 @@ tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIn r.y = 4; var r6 = d.y(); // error ~ -!!! error TS2349: This expression is not callable. -!!! error TS2349: Type 'Number' has no call signatures. +!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? +!!! error TS6234: Type 'Number' has no call signatures. } @@ -62,6 +62,6 @@ tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIn r.y = ''; var r6 = d.y(); // error ~ -!!! error TS2349: This expression is not callable. -!!! error TS2349: Type 'String' has no call signatures. +!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? +!!! error TS6234: Type 'String' has no call signatures. } \ No newline at end of file diff --git a/tests/baselines/reference/instancePropertyInClassType.errors.txt b/tests/baselines/reference/instancePropertyInClassType.errors.txt index aa5f4eaa8d6..224290a4c00 100644 --- a/tests/baselines/reference/instancePropertyInClassType.errors.txt +++ b/tests/baselines/reference/instancePropertyInClassType.errors.txt @@ -1,10 +1,10 @@ tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(17,16): error TS2349: This expression is not callable. +tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(17,16): error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? Type 'Number' has no call signatures. tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(24,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(27,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(37,16): error TS2349: This expression is not callable. +tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(37,16): error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? Type 'String' has no call signatures. @@ -31,8 +31,8 @@ tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.t r.y = 4; var r6 = c.y(); // error ~ -!!! error TS2349: This expression is not callable. -!!! error TS2349: Type 'Number' has no call signatures. +!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? +!!! error TS6234: Type 'Number' has no call signatures. } @@ -58,6 +58,6 @@ tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.t r.y = ''; var r6 = c.y(); // error ~ -!!! error TS2349: This expression is not callable. -!!! error TS2349: Type 'String' has no call signatures. +!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'? +!!! error TS6234: Type 'String' has no call signatures. } \ No newline at end of file diff --git a/tests/cases/compiler/accessorAccidentalCallDiagnostic.ts b/tests/cases/compiler/accessorAccidentalCallDiagnostic.ts new file mode 100644 index 00000000000..a616fabe8ab --- /dev/null +++ b/tests/cases/compiler/accessorAccidentalCallDiagnostic.ts @@ -0,0 +1,9 @@ +// @target: es5 + +// https://github.com/microsoft/TypeScript/issues/24554 +class Test24554 { + get property(): number { return 1; } +} +function test24554(x: Test24554) { + return x.property(); +}