Skip to content

Commit 45cf20c

Browse files
authored
Merge pull request microsoft#37800 from jtbandes/diagnose-accidental-accessor-call
Better error message for accidental calls to get-accessors
2 parents 3340142 + 0b53172 commit 45cf20c

9 files changed

+120
-19
lines changed

src/compiler/checker.ts

+15-7
Original file line numberDiff line numberDiff line change
@@ -26383,7 +26383,7 @@ namespace ts {
2638326383
return true;
2638426384
}
2638526385

26386-
function invocationErrorDetails(apparentType: Type, kind: SignatureKind): { messageChain: DiagnosticMessageChain, relatedMessage: DiagnosticMessage | undefined } {
26386+
function invocationErrorDetails(errorTarget: Node, apparentType: Type, kind: SignatureKind): { messageChain: DiagnosticMessageChain, relatedMessage: DiagnosticMessage | undefined } {
2638726387
let errorInfo: DiagnosticMessageChain | undefined;
2638826388
const isCall = kind === SignatureKind.Call;
2638926389
const awaitedType = getAwaitedType(apparentType);
@@ -26452,16 +26452,24 @@ namespace ts {
2645226452
typeToString(apparentType)
2645326453
);
2645426454
}
26455+
26456+
let headMessage = isCall ? Diagnostics.This_expression_is_not_callable : Diagnostics.This_expression_is_not_constructable;
26457+
26458+
// Diagnose get accessors incorrectly called as functions
26459+
if (isCallExpression(errorTarget.parent) && errorTarget.parent.arguments.length === 0) {
26460+
const { resolvedSymbol } = getNodeLinks(errorTarget);
26461+
if (resolvedSymbol && resolvedSymbol.flags & SymbolFlags.GetAccessor) {
26462+
headMessage = Diagnostics.This_expression_is_not_callable_because_it_is_a_get_accessor_Did_you_mean_to_use_it_without;
26463+
}
26464+
}
26465+
2645526466
return {
26456-
messageChain: chainDiagnosticMessages(
26457-
errorInfo,
26458-
isCall ? Diagnostics.This_expression_is_not_callable : Diagnostics.This_expression_is_not_constructable
26459-
),
26467+
messageChain: chainDiagnosticMessages(errorInfo, headMessage),
2646026468
relatedMessage: maybeMissingAwait ? Diagnostics.Did_you_forget_to_use_await : undefined,
2646126469
};
2646226470
}
2646326471
function invocationError(errorTarget: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) {
26464-
const { messageChain, relatedMessage: relatedInfo } = invocationErrorDetails(apparentType, kind);
26472+
const { messageChain, relatedMessage: relatedInfo } = invocationErrorDetails(errorTarget, apparentType, kind);
2646526473
const diagnostic = createDiagnosticForNodeFromMessageChain(errorTarget, messageChain);
2646626474
if (relatedInfo) {
2646726475
addRelatedInfo(diagnostic, createDiagnosticForNode(errorTarget, relatedInfo));
@@ -26565,7 +26573,7 @@ namespace ts {
2656526573

2656626574
const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node);
2656726575
if (!callSignatures.length) {
26568-
const errorDetails = invocationErrorDetails(apparentType, SignatureKind.Call);
26576+
const errorDetails = invocationErrorDetails(node.expression, apparentType, SignatureKind.Call);
2656926577
const messageChain = chainDiagnosticMessages(errorDetails.messageChain, headMessage);
2657026578
const diag = createDiagnosticForNodeFromMessageChain(node.expression, messageChain);
2657126579
if (errorDetails.relatedMessage) {

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -4416,6 +4416,10 @@
44164416
"category": "Error",
44174417
"code": 6233
44184418
},
4419+
"This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'?": {
4420+
"category": "Error",
4421+
"code": 6234
4422+
},
44194423

44204424
"Projects to reference": {
44214425
"category": "Message",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
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 '()'?
2+
Type 'Number' has no call signatures.
3+
4+
5+
==== tests/cases/compiler/accessorAccidentalCallDiagnostic.ts (1 errors) ====
6+
// https://github.com/microsoft/TypeScript/issues/24554
7+
class Test24554 {
8+
get property(): number { return 1; }
9+
}
10+
function test24554(x: Test24554) {
11+
return x.property();
12+
~~~~~~~~
13+
!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'?
14+
!!! error TS6234: Type 'Number' has no call signatures.
15+
}
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [accessorAccidentalCallDiagnostic.ts]
2+
// https://github.com/microsoft/TypeScript/issues/24554
3+
class Test24554 {
4+
get property(): number { return 1; }
5+
}
6+
function test24554(x: Test24554) {
7+
return x.property();
8+
}
9+
10+
11+
//// [accessorAccidentalCallDiagnostic.js]
12+
// https://github.com/microsoft/TypeScript/issues/24554
13+
var Test24554 = /** @class */ (function () {
14+
function Test24554() {
15+
}
16+
Object.defineProperty(Test24554.prototype, "property", {
17+
get: function () { return 1; },
18+
enumerable: false,
19+
configurable: true
20+
});
21+
return Test24554;
22+
}());
23+
function test24554(x) {
24+
return x.property();
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/compiler/accessorAccidentalCallDiagnostic.ts ===
2+
// https://github.com/microsoft/TypeScript/issues/24554
3+
class Test24554 {
4+
>Test24554 : Symbol(Test24554, Decl(accessorAccidentalCallDiagnostic.ts, 0, 0))
5+
6+
get property(): number { return 1; }
7+
>property : Symbol(Test24554.property, Decl(accessorAccidentalCallDiagnostic.ts, 1, 17))
8+
}
9+
function test24554(x: Test24554) {
10+
>test24554 : Symbol(test24554, Decl(accessorAccidentalCallDiagnostic.ts, 3, 1))
11+
>x : Symbol(x, Decl(accessorAccidentalCallDiagnostic.ts, 4, 19))
12+
>Test24554 : Symbol(Test24554, Decl(accessorAccidentalCallDiagnostic.ts, 0, 0))
13+
14+
return x.property();
15+
>x.property : Symbol(Test24554.property, Decl(accessorAccidentalCallDiagnostic.ts, 1, 17))
16+
>x : Symbol(x, Decl(accessorAccidentalCallDiagnostic.ts, 4, 19))
17+
>property : Symbol(Test24554.property, Decl(accessorAccidentalCallDiagnostic.ts, 1, 17))
18+
}
19+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
=== tests/cases/compiler/accessorAccidentalCallDiagnostic.ts ===
2+
// https://github.com/microsoft/TypeScript/issues/24554
3+
class Test24554 {
4+
>Test24554 : Test24554
5+
6+
get property(): number { return 1; }
7+
>property : number
8+
>1 : 1
9+
}
10+
function test24554(x: Test24554) {
11+
>test24554 : (x: Test24554) => any
12+
>x : Test24554
13+
14+
return x.property();
15+
>x.property() : any
16+
>x.property : number
17+
>x : Test24554
18+
>property : number
19+
}
20+

tests/baselines/reference/instancePropertiesInheritedIntoClassType.errors.txt

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
22
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
3-
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(19,16): error TS2349: This expression is not callable.
3+
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 '()'?
44
Type 'Number' has no call signatures.
55
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(26,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
66
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(29,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
7-
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(41,16): error TS2349: This expression is not callable.
7+
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 '()'?
88
Type 'String' has no call signatures.
99

1010

@@ -33,8 +33,8 @@ tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIn
3333
r.y = 4;
3434
var r6 = d.y(); // error
3535
~
36-
!!! error TS2349: This expression is not callable.
37-
!!! error TS2349: Type 'Number' has no call signatures.
36+
!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'?
37+
!!! error TS6234: Type 'Number' has no call signatures.
3838

3939
}
4040

@@ -62,6 +62,6 @@ tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIn
6262
r.y = '';
6363
var r6 = d.y(); // error
6464
~
65-
!!! error TS2349: This expression is not callable.
66-
!!! error TS2349: Type 'String' has no call signatures.
65+
!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'?
66+
!!! error TS6234: Type 'String' has no call signatures.
6767
}

tests/baselines/reference/instancePropertyInClassType.errors.txt

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
22
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
3-
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(17,16): error TS2349: This expression is not callable.
3+
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 '()'?
44
Type 'Number' has no call signatures.
55
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(24,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
66
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(27,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
7-
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(37,16): error TS2349: This expression is not callable.
7+
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 '()'?
88
Type 'String' has no call signatures.
99

1010

@@ -31,8 +31,8 @@ tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.t
3131
r.y = 4;
3232
var r6 = c.y(); // error
3333
~
34-
!!! error TS2349: This expression is not callable.
35-
!!! error TS2349: Type 'Number' has no call signatures.
34+
!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'?
35+
!!! error TS6234: Type 'Number' has no call signatures.
3636

3737
}
3838

@@ -58,6 +58,6 @@ tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.t
5858
r.y = '';
5959
var r6 = c.y(); // error
6060
~
61-
!!! error TS2349: This expression is not callable.
62-
!!! error TS2349: Type 'String' has no call signatures.
61+
!!! error TS6234: This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'?
62+
!!! error TS6234: Type 'String' has no call signatures.
6363
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @target: es5
2+
3+
// https://github.com/microsoft/TypeScript/issues/24554
4+
class Test24554 {
5+
get property(): number { return 1; }
6+
}
7+
function test24554(x: Test24554) {
8+
return x.property();
9+
}

0 commit comments

Comments
 (0)