Merge pull request #27020 from Kingwl/improve_accidentally_calling_type-assertion_expressions

improve Diagnostics for accidentally calling type-assertion expressions
This commit is contained in:
Daniel Rosenwasser 2018-09-11 14:00:31 -07:00 committed by GitHub
commit aa9230f313
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 179 additions and 6 deletions

View File

@ -19672,7 +19672,14 @@ namespace ts {
error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
}
else {
invocationError(node, apparentType, SignatureKind.Call);
let relatedInformation: DiagnosticRelatedInformation | undefined;
if (node.arguments.length === 1 && isTypeAssertion(first(node.arguments))) {
const text = getSourceFileOfNode(node).text;
if (isLineBreak(text.charCodeAt(skipTrivia(text, node.expression.end, /* stopAfterLineBreak */ true) - 1))) {
relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.It_is_highly_likely_that_you_are_missing_a_semicolon);
}
}
invocationError(node, apparentType, SignatureKind.Call, relatedInformation);
}
return resolveErrorCall(node);
}
@ -19842,11 +19849,12 @@ namespace ts {
return true;
}
function invocationError(node: Node, apparentType: Type, kind: SignatureKind) {
invocationErrorRecovery(apparentType, kind, error(node, kind === SignatureKind.Call
? Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures
: Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature
, typeToString(apparentType)));
function invocationError(node: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) {
const diagnostic = error(node, (kind === SignatureKind.Call ?
Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures :
Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature
), typeToString(apparentType));
invocationErrorRecovery(apparentType, kind, relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic);
}
function invocationErrorRecovery(apparentType: Type, kind: SignatureKind, diagnostic: Diagnostic) {

View File

@ -2457,6 +2457,10 @@
"category": "Error",
"code": 2733
},
"It is highly likely that you are missing a semicolon.": {
"category": "Error",
"code": 2734
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",

View File

@ -0,0 +1,39 @@
tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(3,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(5,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(7,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(10,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(13,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
==== tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts (5 errors) ====
declare function foo(): string;
foo()(1 as number).toString();
~~~~~~~~~~~~~~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
foo() (1 as number).toString();
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
foo()
~~~~~
(1 as number).toString();
~~~~~~~~~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:7:1: It is highly likely that you are missing a semicolon.
foo()
~~~~~~~~
(1 as number).toString();
~~~~~~~~~~~~~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:10:1: It is highly likely that you are missing a semicolon.
foo()
~~~~~~~~
(<number>1).toString();
~~~~~~~~~~~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:13:1: It is highly likely that you are missing a semicolon.

View File

@ -0,0 +1,23 @@
//// [betterErrorForAccidentallyCallingTypeAssertionExpressions.ts]
declare function foo(): string;
foo()(1 as number).toString();
foo() (1 as number).toString();
foo()
(1 as number).toString();
foo()
(1 as number).toString();
foo()
(<number>1).toString();
//// [betterErrorForAccidentallyCallingTypeAssertionExpressions.js]
foo()(1).toString();
foo()(1).toString();
foo()(1).toString();
foo()(1).toString();
foo()(1).toString();

View File

@ -0,0 +1,25 @@
=== tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts ===
declare function foo(): string;
>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0))
foo()(1 as number).toString();
>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0))
foo() (1 as number).toString();
>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0))
foo()
>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0))
(1 as number).toString();
foo()
>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0))
(1 as number).toString();
foo()
>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0))
(<number>1).toString();

View File

@ -0,0 +1,60 @@
=== tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts ===
declare function foo(): string;
>foo : () => string
foo()(1 as number).toString();
>foo()(1 as number).toString() : any
>foo()(1 as number).toString : any
>foo()(1 as number) : any
>foo() : string
>foo : () => string
>1 as number : number
>1 : 1
>toString : any
foo() (1 as number).toString();
>foo() (1 as number).toString() : any
>foo() (1 as number).toString : any
>foo() (1 as number) : any
>foo() : string
>foo : () => string
>1 as number : number
>1 : 1
>toString : any
foo()
>foo()(1 as number).toString() : any
>foo()(1 as number).toString : any
>foo()(1 as number) : any
>foo() : string
>foo : () => string
(1 as number).toString();
>1 as number : number
>1 : 1
>toString : any
foo()
>foo() (1 as number).toString() : any
>foo() (1 as number).toString : any
>foo() (1 as number) : any
>foo() : string
>foo : () => string
(1 as number).toString();
>1 as number : number
>1 : 1
>toString : any
foo()
>foo() (<number>1).toString() : any
>foo() (<number>1).toString : any
>foo() (<number>1) : any
>foo() : string
>foo : () => string
(<number>1).toString();
><number>1 : number
>1 : 1
>toString : any

View File

@ -0,0 +1,14 @@
declare function foo(): string;
foo()(1 as number).toString();
foo() (1 as number).toString();
foo()
(1 as number).toString();
foo()
(1 as number).toString();
foo()
(<number>1).toString();