From 6ead20d324a6578466df2483240aa8fcc3bd7e80 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 7 Feb 2023 22:11:13 -0800 Subject: [PATCH 01/10] Add failing test --- tests/cases/compiler/typeAssertionExpressionInJsNoCrash.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/cases/compiler/typeAssertionExpressionInJsNoCrash.ts diff --git a/tests/cases/compiler/typeAssertionExpressionInJsNoCrash.ts b/tests/cases/compiler/typeAssertionExpressionInJsNoCrash.ts new file mode 100644 index 0000000000000..fff525e70bb75 --- /dev/null +++ b/tests/cases/compiler/typeAssertionExpressionInJsNoCrash.ts @@ -0,0 +1,7 @@ +// @allowJs: true +// @noEmit: true +// @checkJs: true +// @filename: index.js + +const x = "oops"; +const y = delete x; From c51439f9aa9e7396f748a1f3a328cb0ca0d8ea54 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 7 Feb 2023 22:13:17 -0800 Subject: [PATCH 02/10] Don't Debug.fail on TypeAssertionExpression in JS --- src/compiler/program.ts | 3 +-- .../typeAssertionExpressionInJsNoCrash.errors.txt | 15 +++++++++++++++ .../typeAssertionExpressionInJsNoCrash.symbols | 8 ++++++++ .../typeAssertionExpressionInJsNoCrash.types | 11 +++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt create mode 100644 tests/baselines/reference/typeAssertionExpressionInJsNoCrash.symbols create mode 100644 tests/baselines/reference/typeAssertionExpressionInJsNoCrash.types diff --git a/src/compiler/program.ts b/src/compiler/program.ts index b1428a56bfa8c..2ebd6eabbbbf2 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2930,13 +2930,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg diagnostics.push(createDiagnosticForNode(node, Diagnostics.Non_null_assertions_can_only_be_used_in_TypeScript_files)); return "skip"; case SyntaxKind.AsExpression: + case SyntaxKind.TypeAssertionExpression: diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; case SyntaxKind.SatisfiesExpression: diagnostics.push(createDiagnosticForNode((node as SatisfiesExpression).type, Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; - case SyntaxKind.TypeAssertionExpression: - Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX. } } diff --git a/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt new file mode 100644 index 0000000000000..0a0151755bdd4 --- /dev/null +++ b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/index.js(2,18): error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. +tests/cases/compiler/index.js(2,18): error TS2703: The operand of a 'delete' operator must be a property reference. +tests/cases/compiler/index.js(2,19): error TS8016: Type assertion expressions can only be used in TypeScript files. + + +==== tests/cases/compiler/index.js (3 errors) ==== + const x = "oops"; + const y = delete x; + ~~~~~~~~~~ +!!! error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. + ~~~~~~~~~~ +!!! error TS2703: The operand of a 'delete' operator must be a property reference. + ~~~~~~ +!!! error TS8016: Type assertion expressions can only be used in TypeScript files. + \ No newline at end of file diff --git a/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.symbols b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.symbols new file mode 100644 index 0000000000000..a4507f4db54ac --- /dev/null +++ b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/index.js === +const x = "oops"; +>x : Symbol(x, Decl(index.js, 0, 5)) + +const y = delete x; +>y : Symbol(y, Decl(index.js, 1, 5)) +>x : Symbol(x, Decl(index.js, 0, 5)) + diff --git a/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.types b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.types new file mode 100644 index 0000000000000..360744ac0e4bc --- /dev/null +++ b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/index.js === +const x = "oops"; +>x : "oops" +>"oops" : "oops" + +const y = delete x; +>y : boolean +>delete x : boolean +> x : number +>x : "oops" + From a3e53436cf83a6d5e64e78eded654e988553a0e4 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 7 Feb 2023 22:14:33 -0800 Subject: [PATCH 03/10] Use correct type --- src/compiler/program.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 2ebd6eabbbbf2..f4c817ca55d64 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -6,8 +6,8 @@ import { append, arrayFrom, arrayIsEqualTo, - AsExpression, AssertClause, + AssertionExpression, BuilderProgram, CancellationToken, canHaveDecorators, @@ -2931,7 +2931,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return "skip"; case SyntaxKind.AsExpression: case SyntaxKind.TypeAssertionExpression: - diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); + diagnostics.push(createDiagnosticForNode((node as AssertionExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; case SyntaxKind.SatisfiesExpression: diagnostics.push(createDiagnosticForNode((node as SatisfiesExpression).type, Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files)); From 4fed642408ef13c4bab0c0d3adb3fab35fe0e1b2 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 7 Feb 2023 22:15:31 -0800 Subject: [PATCH 04/10] Revert "Use correct type" This reverts commit a3e53436cf83a6d5e64e78eded654e988553a0e4. --- src/compiler/program.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f4c817ca55d64..2ebd6eabbbbf2 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -6,8 +6,8 @@ import { append, arrayFrom, arrayIsEqualTo, + AsExpression, AssertClause, - AssertionExpression, BuilderProgram, CancellationToken, canHaveDecorators, @@ -2931,7 +2931,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg return "skip"; case SyntaxKind.AsExpression: case SyntaxKind.TypeAssertionExpression: - diagnostics.push(createDiagnosticForNode((node as AssertionExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); + diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; case SyntaxKind.SatisfiesExpression: diagnostics.push(createDiagnosticForNode((node as SatisfiesExpression).type, Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files)); From cd4f6448be130435db7445cf27681152abe6b8c7 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 7 Feb 2023 22:17:12 -0800 Subject: [PATCH 05/10] Put error in right place --- src/compiler/program.ts | 4 +++- .../reference/typeAssertionExpressionInJsNoCrash.errors.txt | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 2ebd6eabbbbf2..fecf416d09a88 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2930,12 +2930,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg diagnostics.push(createDiagnosticForNode(node, Diagnostics.Non_null_assertions_can_only_be_used_in_TypeScript_files)); return "skip"; case SyntaxKind.AsExpression: - case SyntaxKind.TypeAssertionExpression: diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; case SyntaxKind.SatisfiesExpression: diagnostics.push(createDiagnosticForNode((node as SatisfiesExpression).type, Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; + case SyntaxKind.TypeAssertionExpression: + diagnostics.push(createDiagnosticForNode(node, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); + return "skip"; } } diff --git a/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt index 0a0151755bdd4..ea5175de01033 100644 --- a/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt +++ b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/index.js(2,18): error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. tests/cases/compiler/index.js(2,18): error TS2703: The operand of a 'delete' operator must be a property reference. -tests/cases/compiler/index.js(2,19): error TS8016: Type assertion expressions can only be used in TypeScript files. +tests/cases/compiler/index.js(2,18): error TS8016: Type assertion expressions can only be used in TypeScript files. ==== tests/cases/compiler/index.js (3 errors) ==== @@ -10,6 +10,6 @@ tests/cases/compiler/index.js(2,19): error TS8016: Type assertion expressions ca !!! error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. ~~~~~~~~~~ !!! error TS2703: The operand of a 'delete' operator must be a property reference. - ~~~~~~ + ~~~~~~~~~~ !!! error TS8016: Type assertion expressions can only be used in TypeScript files. \ No newline at end of file From f027812ffb348b1e90d9c7b19356ce4d93db9f63 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 8 Feb 2023 11:09:11 -0800 Subject: [PATCH 06/10] Fix it correctly this time --- src/compiler/parser.ts | 6 ++++++ src/compiler/program.ts | 3 +-- ...UnaryExpressionNoTypeAssertionInJsx.errors.txt | 15 +++++++++++++++ ...seUnaryExpressionNoTypeAssertionInJsx.symbols} | 3 +-- ...parseUnaryExpressionNoTypeAssertionInJsx.types | 13 +++++++++++++ .../typeAssertionExpressionInJsNoCrash.errors.txt | 15 --------------- .../typeAssertionExpressionInJsNoCrash.types | 11 ----------- ...> parseUnaryExpressionNoTypeAssertionInJsx.ts} | 2 +- 8 files changed, 37 insertions(+), 31 deletions(-) create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.errors.txt rename tests/baselines/reference/{typeAssertionExpressionInJsNoCrash.symbols => parseUnaryExpressionNoTypeAssertionInJsx.symbols} (64%) create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.types delete mode 100644 tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt delete mode 100644 tests/baselines/reference/typeAssertionExpressionInJsNoCrash.types rename tests/cases/compiler/{typeAssertionExpressionInJsNoCrash.ts => parseUnaryExpressionNoTypeAssertionInJsx.ts} (72%) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 0baf8b65bc412..7677197183071 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5648,6 +5648,11 @@ namespace Parser { case SyntaxKind.VoidKeyword: return parseVoidExpression(); case SyntaxKind.LessThanToken: + // Just like in parseUpdateExpression, we need to avoid parsing type assertions when + // in JSX and we see an expression like "+ bar". + if (languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); + } // This is modified UnaryExpression grammar in TypeScript // UnaryExpression (modified): // < type > UnaryExpression @@ -6163,6 +6168,7 @@ namespace Parser { } function parseTypeAssertion(): TypeAssertion { + Debug.assert(scriptKind === ScriptKind.TS || scriptKind === ScriptKind.TSX, "Type assertions should never be parsed outside of TS/TSX; they should either be comparisons or JSX."); const pos = getNodePos(); parseExpected(SyntaxKind.LessThanToken); const type = parseType(); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index fecf416d09a88..b1428a56bfa8c 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2936,8 +2936,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg diagnostics.push(createDiagnosticForNode((node as SatisfiesExpression).type, Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; case SyntaxKind.TypeAssertionExpression: - diagnostics.push(createDiagnosticForNode(node, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); - return "skip"; + Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX. } } diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.errors.txt b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.errors.txt new file mode 100644 index 0000000000000..6a77ea5512e67 --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/index.js(2,13): error TS17004: Cannot use JSX unless the '--jsx' flag is provided. +tests/cases/compiler/index.js(2,14): error TS17008: JSX element 'number' has no corresponding closing tag. +tests/cases/compiler/index.js(3,1): error TS1005: ' x; + ~~~~~~~~ +!!! error TS17004: Cannot use JSX unless the '--jsx' flag is provided. + ~~~~~~ +!!! error TS17008: JSX element 'number' has no corresponding closing tag. + + +!!! error TS1005: 'x : Symbol(x, Decl(index.js, 0, 5)) -const y = delete x; +const y = + x; >y : Symbol(y, Decl(index.js, 1, 5)) ->x : Symbol(x, Decl(index.js, 0, 5)) diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.types b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.types new file mode 100644 index 0000000000000..e2d8b7e2fec9d --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.types @@ -0,0 +1,13 @@ +=== tests/cases/compiler/index.js === +const x = "oops"; +>x : "oops" +>"oops" : "oops" + +const y = + x; +>y : number +>+ x; : number +> x; : any +>number : any + +> : any + diff --git a/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt deleted file mode 100644 index ea5175de01033..0000000000000 --- a/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.errors.txt +++ /dev/null @@ -1,15 +0,0 @@ -tests/cases/compiler/index.js(2,18): error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. -tests/cases/compiler/index.js(2,18): error TS2703: The operand of a 'delete' operator must be a property reference. -tests/cases/compiler/index.js(2,18): error TS8016: Type assertion expressions can only be used in TypeScript files. - - -==== tests/cases/compiler/index.js (3 errors) ==== - const x = "oops"; - const y = delete x; - ~~~~~~~~~~ -!!! error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. - ~~~~~~~~~~ -!!! error TS2703: The operand of a 'delete' operator must be a property reference. - ~~~~~~~~~~ -!!! error TS8016: Type assertion expressions can only be used in TypeScript files. - \ No newline at end of file diff --git a/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.types b/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.types deleted file mode 100644 index 360744ac0e4bc..0000000000000 --- a/tests/baselines/reference/typeAssertionExpressionInJsNoCrash.types +++ /dev/null @@ -1,11 +0,0 @@ -=== tests/cases/compiler/index.js === -const x = "oops"; ->x : "oops" ->"oops" : "oops" - -const y = delete x; ->y : boolean ->delete x : boolean -> x : number ->x : "oops" - diff --git a/tests/cases/compiler/typeAssertionExpressionInJsNoCrash.ts b/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx.ts similarity index 72% rename from tests/cases/compiler/typeAssertionExpressionInJsNoCrash.ts rename to tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx.ts index fff525e70bb75..1c9be1bd45a12 100644 --- a/tests/cases/compiler/typeAssertionExpressionInJsNoCrash.ts +++ b/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx.ts @@ -4,4 +4,4 @@ // @filename: index.js const x = "oops"; -const y = delete x; +const y = + x; From b64f3e20b3e760e41a90ad1fa3745ae0618c0a29 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 8 Feb 2023 11:11:39 -0800 Subject: [PATCH 07/10] Simplify --- src/compiler/parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 7677197183071..2c21f8eccac20 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5650,7 +5650,7 @@ namespace Parser { case SyntaxKind.LessThanToken: // Just like in parseUpdateExpression, we need to avoid parsing type assertions when // in JSX and we see an expression like "+ bar". - if (languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + if (languageVariant === LanguageVariant.JSX && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } // This is modified UnaryExpression grammar in TypeScript From 47d3f52e96abf8209cab11fd3718e3d90a08fe6e Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 8 Feb 2023 11:53:43 -0800 Subject: [PATCH 08/10] Fix a few more cases --- src/compiler/parser.ts | 2 +- ...aryExpressionNoTypeAssertionInJsx1.errors.txt} | 0 ...eUnaryExpressionNoTypeAssertionInJsx1.symbols} | 0 ...rseUnaryExpressionNoTypeAssertionInJsx1.types} | 0 ...naryExpressionNoTypeAssertionInJsx2.errors.txt | 15 +++++++++++++++ ...seUnaryExpressionNoTypeAssertionInJsx2.symbols | 7 +++++++ ...arseUnaryExpressionNoTypeAssertionInJsx2.types | 10 ++++++++++ ...naryExpressionNoTypeAssertionInJsx3.errors.txt | 15 +++++++++++++++ ...seUnaryExpressionNoTypeAssertionInJsx3.symbols | 8 ++++++++ ...arseUnaryExpressionNoTypeAssertionInJsx3.types | 14 ++++++++++++++ ... parseUnaryExpressionNoTypeAssertionInJsx1.ts} | 0 .../parseUnaryExpressionNoTypeAssertionInJsx2.ts | 7 +++++++ .../parseUnaryExpressionNoTypeAssertionInJsx3.ts | 7 +++++++ 13 files changed, 84 insertions(+), 1 deletion(-) rename tests/baselines/reference/{parseUnaryExpressionNoTypeAssertionInJsx.errors.txt => parseUnaryExpressionNoTypeAssertionInJsx1.errors.txt} (100%) rename tests/baselines/reference/{parseUnaryExpressionNoTypeAssertionInJsx.symbols => parseUnaryExpressionNoTypeAssertionInJsx1.symbols} (100%) rename tests/baselines/reference/{parseUnaryExpressionNoTypeAssertionInJsx.types => parseUnaryExpressionNoTypeAssertionInJsx1.types} (100%) create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx2.errors.txt create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx2.symbols create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx2.types create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.errors.txt create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.symbols create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.types rename tests/cases/compiler/{parseUnaryExpressionNoTypeAssertionInJsx.ts => parseUnaryExpressionNoTypeAssertionInJsx1.ts} (100%) create mode 100644 tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx2.ts create mode 100644 tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx3.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 2c21f8eccac20..ff083df06ece2 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5650,7 +5650,7 @@ namespace Parser { case SyntaxKind.LessThanToken: // Just like in parseUpdateExpression, we need to avoid parsing type assertions when // in JSX and we see an expression like "+ bar". - if (languageVariant === LanguageVariant.JSX && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + if (languageVariant === LanguageVariant.JSX) { return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } // This is modified UnaryExpression grammar in TypeScript diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.errors.txt b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx1.errors.txt similarity index 100% rename from tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.errors.txt rename to tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx1.errors.txt diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.symbols b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx1.symbols similarity index 100% rename from tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.symbols rename to tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx1.symbols diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.types b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx1.types similarity index 100% rename from tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx.types rename to tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx1.types diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx2.errors.txt b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx2.errors.txt new file mode 100644 index 0000000000000..b1acc4a477479 --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx2.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/index.js(2,12): error TS17014: JSX fragment has no corresponding closing tag. +tests/cases/compiler/index.js(2,13): error TS17004: Cannot use JSX unless the '--jsx' flag is provided. +tests/cases/compiler/index.js(3,1): error TS1005: ' x; + ~~~ +!!! error TS17014: JSX fragment has no corresponding closing tag. + ~~ +!!! error TS17004: Cannot use JSX unless the '--jsx' flag is provided. + + +!!! error TS1005: 'x : Symbol(x, Decl(index.js, 0, 5)) + +const y = + <> x; +>y : Symbol(y, Decl(index.js, 1, 5)) + diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx2.types b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx2.types new file mode 100644 index 0000000000000..b8a8ef32d643e --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx2.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/index.js === +const x = "oops"; +>x : "oops" +>"oops" : "oops" + +const y = + <> x; +>y : number +>+ <> x; : number +><> x; : any + diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.errors.txt b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.errors.txt new file mode 100644 index 0000000000000..132f825fe40a2 --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/index.js(2,13): error TS17004: Cannot use JSX unless the '--jsx' flag is provided. +tests/cases/compiler/index.js(2,14): error TS1003: Identifier expected. +tests/cases/compiler/index.js(2,14): error TS2365: Operator '>' cannot be applied to types 'number' and 'string'. + + +==== tests/cases/compiler/index.js (3 errors) ==== + const x = "oops"; + const y = + <1234> x; + ~ +!!! error TS17004: Cannot use JSX unless the '--jsx' flag is provided. + ~~~~ +!!! error TS1003: Identifier expected. + ~~~~~~~ +!!! error TS2365: Operator '>' cannot be applied to types 'number' and 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.symbols b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.symbols new file mode 100644 index 0000000000000..a8c0e88d94597 --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/index.js === +const x = "oops"; +>x : Symbol(x, Decl(index.js, 0, 5)) + +const y = + <1234> x; +>y : Symbol(y, Decl(index.js, 1, 5)) +>x : Symbol(x, Decl(index.js, 0, 5)) + diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.types b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.types new file mode 100644 index 0000000000000..9cdbabb588e9a --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx3.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/index.js === +const x = "oops"; +>x : "oops" +>"oops" : "oops" + +const y = + <1234> x; +>y : number +>+ < : number +>< : any +> : any +>1234> x : boolean +>1234 : 1234 +>x : "oops" + diff --git a/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx.ts b/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx1.ts similarity index 100% rename from tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx.ts rename to tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx1.ts diff --git a/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx2.ts b/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx2.ts new file mode 100644 index 0000000000000..1b6b86d830d0b --- /dev/null +++ b/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx2.ts @@ -0,0 +1,7 @@ +// @allowJs: true +// @noEmit: true +// @checkJs: true +// @filename: index.js + +const x = "oops"; +const y = + <> x; diff --git a/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx3.ts b/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx3.ts new file mode 100644 index 0000000000000..09407f0a85fd0 --- /dev/null +++ b/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx3.ts @@ -0,0 +1,7 @@ +// @allowJs: true +// @noEmit: true +// @checkJs: true +// @filename: index.js + +const x = "oops"; +const y = + <1234> x; From cb9ce02e954a216a4380b937aa1b30ee62ab7c59 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 9 Feb 2023 11:04:40 -0800 Subject: [PATCH 09/10] Also test tsx --- src/compiler/parser.ts | 2 +- ...ExpressionNoTypeAssertionInJsx4.errors.txt | 24 +++++++++++++++++++ ...rseUnaryExpressionNoTypeAssertionInJsx4.js | 14 +++++++++++ ...aryExpressionNoTypeAssertionInJsx4.symbols | 10 ++++++++ ...UnaryExpressionNoTypeAssertionInJsx4.types | 20 ++++++++++++++++ ...rseUnaryExpressionNoTypeAssertionInJsx4.ts | 8 +++++++ 6 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.errors.txt create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.js create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.symbols create mode 100644 tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.types create mode 100644 tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx4.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ff083df06ece2..69335c3f13248 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6168,7 +6168,7 @@ namespace Parser { } function parseTypeAssertion(): TypeAssertion { - Debug.assert(scriptKind === ScriptKind.TS || scriptKind === ScriptKind.TSX, "Type assertions should never be parsed outside of TS/TSX; they should either be comparisons or JSX."); + Debug.assert(scriptKind === ScriptKind.TS, "Type assertions should never be parsed outside of TS/TSX; they should either be comparisons or JSX."); const pos = getNodePos(); parseExpected(SyntaxKind.LessThanToken); const type = parseType(); diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.errors.txt b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.errors.txt new file mode 100644 index 0000000000000..24710242160d4 --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.errors.txt @@ -0,0 +1,24 @@ +tests/cases/compiler/index.tsx(3,14): error TS17008: JSX element 'number' has no corresponding closing tag. +tests/cases/compiler/index.tsx(4,13): error TS17014: JSX fragment has no corresponding closing tag. +tests/cases/compiler/index.tsx(5,14): error TS1003: Identifier expected. +tests/cases/compiler/index.tsx(5,18): error TS1382: Unexpected token. Did you mean `{'>'}` or `>`? +tests/cases/compiler/index.tsx(6,1): error TS1005: ' x; + ~~~~~~ +!!! error TS17008: JSX element 'number' has no corresponding closing tag. + const b = + <> x; + ~~ +!!! error TS17014: JSX fragment has no corresponding closing tag. + const c = + <1234> x; + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1382: Unexpected token. Did you mean `{'>'}` or `>`? + + +!!! error TS1005: ' x; +const b = + <> x; +const c = + <1234> x; + + +//// [index.jsx] +var x = "oops"; +var a = + x; +const b = + <> x; +const c = + < />1234> x; +; diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.symbols b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.symbols new file mode 100644 index 0000000000000..50a8c1e513c7c --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/index.tsx === +const x = "oops"; +>x : Symbol(x, Decl(index.tsx, 0, 5)) + +const a = + x; +>a : Symbol(a, Decl(index.tsx, 2, 5)) + +const b = + <> x; +const c = + <1234> x; + diff --git a/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.types b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.types new file mode 100644 index 0000000000000..e0e0c0d4d6461 --- /dev/null +++ b/tests/baselines/reference/parseUnaryExpressionNoTypeAssertionInJsx4.types @@ -0,0 +1,20 @@ +=== tests/cases/compiler/index.tsx === +const x = "oops"; +>x : "oops" +>"oops" : "oops" + +const a = + x; +>a : number +>+ x;const b = + <> x;const c = + <1234> x; : number +> x;const b = + <> x;const c = + <1234> x; : any +>number : any + +const b = + <> x; +><> x;const c = + <1234> x; : any + +const c = + <1234> x; +>< : any +> : any + +> : any + diff --git a/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx4.ts b/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx4.ts new file mode 100644 index 0000000000000..4f892516d10b4 --- /dev/null +++ b/tests/cases/compiler/parseUnaryExpressionNoTypeAssertionInJsx4.ts @@ -0,0 +1,8 @@ +// @filename: index.tsx +// @jsx: preserve + +const x = "oops"; + +const a = + x; +const b = + <> x; +const c = + <1234> x; From b96d39a128487cc8bc0d8c67dff65c1b6f70d49a Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 9 Feb 2023 11:06:20 -0800 Subject: [PATCH 10/10] Fix message --- src/compiler/parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 69335c3f13248..4763040626b76 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6168,7 +6168,7 @@ namespace Parser { } function parseTypeAssertion(): TypeAssertion { - Debug.assert(scriptKind === ScriptKind.TS, "Type assertions should never be parsed outside of TS/TSX; they should either be comparisons or JSX."); + Debug.assert(scriptKind === ScriptKind.TS, "Type assertions should never be parsed outside of TS; they should either be comparisons or JSX."); const pos = getNodePos(); parseExpected(SyntaxKind.LessThanToken); const type = parseType();