mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-03-15 14:05:47 -05:00
Fix not emitted statement in then clauses producing syntactically invalid output (#32010)
* Fix not emitted statement in then clauses producing syntactically invalid output * Refactor to common code, apply to all embedded statements
This commit is contained in:
@@ -1544,8 +1544,8 @@ namespace ts {
|
||||
export function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement) {
|
||||
const node = <IfStatement>createSynthesizedNode(SyntaxKind.IfStatement);
|
||||
node.expression = expression;
|
||||
node.thenStatement = thenStatement;
|
||||
node.elseStatement = elseStatement;
|
||||
node.thenStatement = asEmbeddedStatement(thenStatement);
|
||||
node.elseStatement = asEmbeddedStatement(elseStatement);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1559,7 +1559,7 @@ namespace ts {
|
||||
|
||||
export function createDo(statement: Statement, expression: Expression) {
|
||||
const node = <DoStatement>createSynthesizedNode(SyntaxKind.DoStatement);
|
||||
node.statement = statement;
|
||||
node.statement = asEmbeddedStatement(statement);
|
||||
node.expression = expression;
|
||||
return node;
|
||||
}
|
||||
@@ -1574,7 +1574,7 @@ namespace ts {
|
||||
export function createWhile(expression: Expression, statement: Statement) {
|
||||
const node = <WhileStatement>createSynthesizedNode(SyntaxKind.WhileStatement);
|
||||
node.expression = expression;
|
||||
node.statement = statement;
|
||||
node.statement = asEmbeddedStatement(statement);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1590,7 +1590,7 @@ namespace ts {
|
||||
node.initializer = initializer;
|
||||
node.condition = condition;
|
||||
node.incrementor = incrementor;
|
||||
node.statement = statement;
|
||||
node.statement = asEmbeddedStatement(statement);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1607,7 +1607,7 @@ namespace ts {
|
||||
const node = <ForInStatement>createSynthesizedNode(SyntaxKind.ForInStatement);
|
||||
node.initializer = initializer;
|
||||
node.expression = expression;
|
||||
node.statement = statement;
|
||||
node.statement = asEmbeddedStatement(statement);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1624,7 +1624,7 @@ namespace ts {
|
||||
node.awaitModifier = awaitModifier;
|
||||
node.initializer = initializer;
|
||||
node.expression = expression;
|
||||
node.statement = statement;
|
||||
node.statement = asEmbeddedStatement(statement);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1676,7 +1676,7 @@ namespace ts {
|
||||
export function createWith(expression: Expression, statement: Statement) {
|
||||
const node = <WithStatement>createSynthesizedNode(SyntaxKind.WithStatement);
|
||||
node.expression = expression;
|
||||
node.statement = statement;
|
||||
node.statement = asEmbeddedStatement(statement);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1704,7 +1704,7 @@ namespace ts {
|
||||
export function createLabel(label: string | Identifier, statement: Statement) {
|
||||
const node = <LabeledStatement>createSynthesizedNode(SyntaxKind.LabeledStatement);
|
||||
node.label = asName(label);
|
||||
node.statement = statement;
|
||||
node.statement = asEmbeddedStatement(statement);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -3080,6 +3080,12 @@ namespace ts {
|
||||
return typeof value === "number" ? createToken(value) : value;
|
||||
}
|
||||
|
||||
function asEmbeddedStatement<T extends Node>(statement: T): T | EmptyStatement;
|
||||
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined;
|
||||
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined {
|
||||
return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any EmitNode entries from parse-tree nodes.
|
||||
* @param sourceFile A source file.
|
||||
|
||||
@@ -9,5 +9,8 @@ else
|
||||
|
||||
//// [constEnum4.js]
|
||||
if (1)
|
||||
;
|
||||
else if (2)
|
||||
;
|
||||
else
|
||||
;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
//// [elidedEmbeddedStatementsReplacedWithSemicolon.ts]
|
||||
if (1)
|
||||
const enum A {}
|
||||
else
|
||||
const enum B {}
|
||||
|
||||
do
|
||||
const enum C {}
|
||||
while (0);
|
||||
|
||||
while (0)
|
||||
const enum D {}
|
||||
|
||||
for (;0;)
|
||||
const enum E {}
|
||||
|
||||
for (let _ in [])
|
||||
const enum F {}
|
||||
|
||||
for (let _ of [])
|
||||
const enum G {}
|
||||
|
||||
// @ts-ignore suppress `with` statement error
|
||||
with (window)
|
||||
const enum H {}
|
||||
|
||||
//// [elidedEmbeddedStatementsReplacedWithSemicolon.js]
|
||||
if (1)
|
||||
;
|
||||
else
|
||||
;
|
||||
do
|
||||
;
|
||||
while (0);
|
||||
while (0)
|
||||
;
|
||||
for (; 0;)
|
||||
;
|
||||
for (var _ in [])
|
||||
;
|
||||
for (var _i = 0, _a = []; _i < _a.length; _i++) {
|
||||
var _ = _a[_i];
|
||||
;
|
||||
}
|
||||
// @ts-ignore suppress `with` statement error
|
||||
with (window)
|
||||
;
|
||||
@@ -0,0 +1,40 @@
|
||||
=== tests/cases/compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts ===
|
||||
if (1)
|
||||
const enum A {}
|
||||
>A : Symbol(A, Decl(elidedEmbeddedStatementsReplacedWithSemicolon.ts, 0, 6))
|
||||
|
||||
else
|
||||
const enum B {}
|
||||
>B : Symbol(B, Decl(elidedEmbeddedStatementsReplacedWithSemicolon.ts, 2, 4))
|
||||
|
||||
do
|
||||
const enum C {}
|
||||
>C : Symbol(C, Decl(elidedEmbeddedStatementsReplacedWithSemicolon.ts, 5, 2))
|
||||
|
||||
while (0);
|
||||
|
||||
while (0)
|
||||
const enum D {}
|
||||
>D : Symbol(D, Decl(elidedEmbeddedStatementsReplacedWithSemicolon.ts, 9, 9))
|
||||
|
||||
for (;0;)
|
||||
const enum E {}
|
||||
>E : Symbol(E, Decl(elidedEmbeddedStatementsReplacedWithSemicolon.ts, 12, 9))
|
||||
|
||||
for (let _ in [])
|
||||
>_ : Symbol(_, Decl(elidedEmbeddedStatementsReplacedWithSemicolon.ts, 15, 8))
|
||||
|
||||
const enum F {}
|
||||
>F : Symbol(F, Decl(elidedEmbeddedStatementsReplacedWithSemicolon.ts, 15, 17))
|
||||
|
||||
for (let _ of [])
|
||||
>_ : Symbol(_, Decl(elidedEmbeddedStatementsReplacedWithSemicolon.ts, 18, 8))
|
||||
|
||||
const enum G {}
|
||||
>G : Symbol(G, Decl(elidedEmbeddedStatementsReplacedWithSemicolon.ts, 18, 17))
|
||||
|
||||
// @ts-ignore suppress `with` statement error
|
||||
with (window)
|
||||
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
const enum H {}
|
||||
@@ -0,0 +1,51 @@
|
||||
=== tests/cases/compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts ===
|
||||
if (1)
|
||||
>1 : 1
|
||||
|
||||
const enum A {}
|
||||
>A : A
|
||||
|
||||
else
|
||||
const enum B {}
|
||||
>B : B
|
||||
|
||||
do
|
||||
const enum C {}
|
||||
>C : C
|
||||
|
||||
while (0);
|
||||
>0 : 0
|
||||
|
||||
while (0)
|
||||
>0 : 0
|
||||
|
||||
const enum D {}
|
||||
>D : D
|
||||
|
||||
for (;0;)
|
||||
>0 : 0
|
||||
|
||||
const enum E {}
|
||||
>E : E
|
||||
|
||||
for (let _ in [])
|
||||
>_ : string
|
||||
>[] : undefined[]
|
||||
|
||||
const enum F {}
|
||||
>F : F
|
||||
|
||||
for (let _ of [])
|
||||
>_ : any
|
||||
>[] : undefined[]
|
||||
|
||||
const enum G {}
|
||||
>G : G
|
||||
|
||||
// @ts-ignore suppress `with` statement error
|
||||
with (window)
|
||||
>window : Window
|
||||
|
||||
const enum H {}
|
||||
>H : error
|
||||
|
||||
@@ -64,7 +64,7 @@ label: {
|
||||
(function (E) {
|
||||
})(E || (E = {}));
|
||||
}
|
||||
label:
|
||||
label: ;
|
||||
label: {
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
@@ -75,6 +75,6 @@ label: {
|
||||
label: var a = 1;
|
||||
label: var b = 1;
|
||||
label: var c = 1;
|
||||
label:
|
||||
label:
|
||||
label: ;
|
||||
label: ;
|
||||
label:
|
||||
|
||||
@@ -33,12 +33,12 @@ label: {
|
||||
(function (E) {
|
||||
})(E || (E = {}));
|
||||
}
|
||||
label:
|
||||
label: ;
|
||||
label: class C {
|
||||
}
|
||||
label: var a = 1;
|
||||
label: let b = 1;
|
||||
label: const c = 1;
|
||||
label:
|
||||
label:
|
||||
label: ;
|
||||
label: ;
|
||||
label:
|
||||
|
||||
@@ -35,12 +35,12 @@ label: {
|
||||
(function (E) {
|
||||
})(E || (E = {}));
|
||||
}
|
||||
label:
|
||||
label: ;
|
||||
label: class C {
|
||||
}
|
||||
label: var a = 1;
|
||||
label: let b = 1;
|
||||
label: const c = 1;
|
||||
label:
|
||||
label:
|
||||
label: ;
|
||||
label: ;
|
||||
label:
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
if (1)
|
||||
const enum A {}
|
||||
else
|
||||
const enum B {}
|
||||
|
||||
do
|
||||
const enum C {}
|
||||
while (0);
|
||||
|
||||
while (0)
|
||||
const enum D {}
|
||||
|
||||
for (;0;)
|
||||
const enum E {}
|
||||
|
||||
for (let _ in [])
|
||||
const enum F {}
|
||||
|
||||
for (let _ of [])
|
||||
const enum G {}
|
||||
|
||||
// @ts-ignore suppress `with` statement error
|
||||
with (window)
|
||||
const enum H {}
|
||||
Reference in New Issue
Block a user