diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ee05ca893c7e6..3dba3c505a85d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1801,6 +1801,10 @@ "category": "Error", "code": 1537 }, + "A non-null assertion must be preceded by an identifier.": { + "category": "Error", + "code": 1538 + }, "The types of '{0}' are incompatible between these types.": { "category": "Error", diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 23267f21866e7..968d06261b554 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6451,8 +6451,12 @@ namespace Parser { if (!questionDotToken) { if (token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { + const start = scanner.getTokenFullStart(); nextToken(); expression = finishNode(factory.createNonNullExpression(expression), pos); + if (expression.end - start !== 1) { + parseErrorAt(start, expression.end, Diagnostics.A_non_null_assertion_must_be_preceded_by_an_identifier); + } continue; } const typeArguments = tryParse(parseTypeArgumentsInExpression); diff --git a/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.errors.txt b/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.errors.txt new file mode 100644 index 0000000000000..b83bb2a7d33ce --- /dev/null +++ b/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.errors.txt @@ -0,0 +1,42 @@ +parseNoWhitespaceBeforeExclamation.ts(3,6): error TS1538: A non-null assertion must be preceded by an identifier. +parseNoWhitespaceBeforeExclamation.ts(4,6): error TS1538: A non-null assertion must be preceded by an identifier. +parseNoWhitespaceBeforeExclamation.ts(5,6): error TS1538: A non-null assertion must be preceded by an identifier. +parseNoWhitespaceBeforeExclamation.ts(6,6): error TS1538: A non-null assertion must be preceded by an identifier. +parseNoWhitespaceBeforeExclamation.ts(7,6): error TS1538: A non-null assertion must be preceded by an identifier. +parseNoWhitespaceBeforeExclamation.ts(8,6): error TS1538: A non-null assertion must be preceded by an identifier. +parseNoWhitespaceBeforeExclamation.ts(9,6): error TS1538: A non-null assertion must be preceded by an identifier. +parseNoWhitespaceBeforeExclamation.ts(10,6): error TS1538: A non-null assertion must be preceded by an identifier. +parseNoWhitespaceBeforeExclamation.ts(11,6): error TS1538: A non-null assertion must be preceded by an identifier. + + +==== parseNoWhitespaceBeforeExclamation.ts (9 errors) ==== + declare var value: any; + + value !; + ~~ +!!! error TS1538: A non-null assertion must be preceded by an identifier. + value !instanceof String; + ~~ +!!! error TS1538: A non-null assertion must be preceded by an identifier. + value ! instanceof String + ~~ +!!! error TS1538: A non-null assertion must be preceded by an identifier. + value/* this is a comment */!instanceof String; + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1538: A non-null assertion must be preceded by an identifier. + value/* this is a comment */! instanceof String; + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1538: A non-null assertion must be preceded by an identifier. + value !in String; + ~~ +!!! error TS1538: A non-null assertion must be preceded by an identifier. + value ! in String + ~~ +!!! error TS1538: A non-null assertion must be preceded by an identifier. + value/* this is a comment */!in String; + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1538: A non-null assertion must be preceded by an identifier. + value/* this is a comment */! in String; + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1538: A non-null assertion must be preceded by an identifier. + \ No newline at end of file diff --git a/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.js b/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.js new file mode 100644 index 0000000000000..38a32cdc7a17d --- /dev/null +++ b/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.js @@ -0,0 +1,26 @@ +//// [tests/cases/compiler/parseNoWhitespaceBeforeExclamation.ts] //// + +//// [parseNoWhitespaceBeforeExclamation.ts] +declare var value: any; + +value !; +value !instanceof String; +value ! instanceof String +value/* this is a comment */!instanceof String; +value/* this is a comment */! instanceof String; +value !in String; +value ! in String +value/* this is a comment */!in String; +value/* this is a comment */! in String; + + +//// [parseNoWhitespaceBeforeExclamation.js] +value; +value instanceof String; +value instanceof String; +value /* this is a comment */ instanceof String; +value /* this is a comment */ instanceof String; +value in String; +value in String; +value /* this is a comment */ in String; +value /* this is a comment */ in String; diff --git a/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.symbols b/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.symbols new file mode 100644 index 0000000000000..4094ce3f5cba9 --- /dev/null +++ b/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.symbols @@ -0,0 +1,41 @@ +//// [tests/cases/compiler/parseNoWhitespaceBeforeExclamation.ts] //// + +=== parseNoWhitespaceBeforeExclamation.ts === +declare var value: any; +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) + +value !; +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) + +value !instanceof String; +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) +>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +value ! instanceof String +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) +>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +value/* this is a comment */!instanceof String; +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) +>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +value/* this is a comment */! instanceof String; +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) +>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +value !in String; +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) +>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +value ! in String +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) +>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +value/* this is a comment */!in String; +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) +>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +value/* this is a comment */! in String; +>value : Symbol(value, Decl(parseNoWhitespaceBeforeExclamation.ts, 0, 11)) +>String : Symbol(String, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.types b/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.types new file mode 100644 index 0000000000000..660abb5dc82ca --- /dev/null +++ b/tests/baselines/reference/parseNoWhitespaceBeforeExclamation.types @@ -0,0 +1,93 @@ +//// [tests/cases/compiler/parseNoWhitespaceBeforeExclamation.ts] //// + +=== parseNoWhitespaceBeforeExclamation.ts === +declare var value: any; +>value : any +> : ^^^ + +value !; +>value ! : any +> : ^^^ +>value : any +> : ^^^ + +value !instanceof String; +>value !instanceof String : boolean +> : ^^^^^^^ +>value ! : any +> : ^^^ +>value : any +> : ^^^ +>String : StringConstructor +> : ^^^^^^^^^^^^^^^^^ + +value ! instanceof String +>value ! instanceof String : boolean +> : ^^^^^^^ +>value ! : any +> : ^^^ +>value : any +> : ^^^ +>String : StringConstructor +> : ^^^^^^^^^^^^^^^^^ + +value/* this is a comment */!instanceof String; +>value/* this is a comment */!instanceof String : boolean +> : ^^^^^^^ +>value/* this is a comment */! : any +> : ^^^ +>value : any +> : ^^^ +>String : StringConstructor +> : ^^^^^^^^^^^^^^^^^ + +value/* this is a comment */! instanceof String; +>value/* this is a comment */! instanceof String : boolean +> : ^^^^^^^ +>value/* this is a comment */! : any +> : ^^^ +>value : any +> : ^^^ +>String : StringConstructor +> : ^^^^^^^^^^^^^^^^^ + +value !in String; +>value !in String : boolean +> : ^^^^^^^ +>value ! : any +> : ^^^ +>value : any +> : ^^^ +>String : StringConstructor +> : ^^^^^^^^^^^^^^^^^ + +value ! in String +>value ! in String : boolean +> : ^^^^^^^ +>value ! : any +> : ^^^ +>value : any +> : ^^^ +>String : StringConstructor +> : ^^^^^^^^^^^^^^^^^ + +value/* this is a comment */!in String; +>value/* this is a comment */!in String : boolean +> : ^^^^^^^ +>value/* this is a comment */! : any +> : ^^^ +>value : any +> : ^^^ +>String : StringConstructor +> : ^^^^^^^^^^^^^^^^^ + +value/* this is a comment */! in String; +>value/* this is a comment */! in String : boolean +> : ^^^^^^^ +>value/* this is a comment */! : any +> : ^^^ +>value : any +> : ^^^ +>String : StringConstructor +> : ^^^^^^^^^^^^^^^^^ + diff --git a/tests/cases/compiler/parseNoWhitespaceBeforeExclamation.ts b/tests/cases/compiler/parseNoWhitespaceBeforeExclamation.ts new file mode 100644 index 0000000000000..f5c7d75984d67 --- /dev/null +++ b/tests/cases/compiler/parseNoWhitespaceBeforeExclamation.ts @@ -0,0 +1,11 @@ +declare var value: any; + +value !; +value !instanceof String; +value ! instanceof String +value/* this is a comment */!instanceof String; +value/* this is a comment */! instanceof String; +value !in String; +value ! in String +value/* this is a comment */!in String; +value/* this is a comment */! in String; diff --git a/tests/cases/fourslash/formattingNonNullAssertionOperator.ts b/tests/cases/fourslash/formattingNonNullAssertionOperator.ts index 2d8b96daaff4d..057b8383f4d97 100644 --- a/tests/cases/fourslash/formattingNonNullAssertionOperator.ts +++ b/tests/cases/fourslash/formattingNonNullAssertionOperator.ts @@ -8,12 +8,12 @@ format.document(); goTo.marker("1"); -verify.currentLineContentIs("'bar'!;"); +verify.currentLineContentIs("'bar' !;"); goTo.marker("2"); -verify.currentLineContentIs("('bar')!;"); +verify.currentLineContentIs("('bar') !;"); goTo.marker("3"); -verify.currentLineContentIs("'bar'[1]!;"); +verify.currentLineContentIs("'bar'[1] !;"); goTo.marker("4"); -verify.currentLineContentIs("var bar = 'bar'.foo!;"); +verify.currentLineContentIs("var bar = 'bar'.foo !;"); goTo.marker("5"); -verify.currentLineContentIs("var foo = bar!;"); \ No newline at end of file +verify.currentLineContentIs("var foo = bar !;");