diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index f67ec39b0a4..f88950f531a 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1544,8 +1544,8 @@ namespace ts { export function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement) { const node = 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 = 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 = 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 = 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 = 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 = 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(statement: T): T | EmptyStatement; + function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined; + function asEmbeddedStatement(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. diff --git a/tests/baselines/reference/constEnum4.js b/tests/baselines/reference/constEnum4.js index dc7c4b0e593..3c70df17dd3 100644 --- a/tests/baselines/reference/constEnum4.js +++ b/tests/baselines/reference/constEnum4.js @@ -9,5 +9,8 @@ else //// [constEnum4.js] if (1) + ; else if (2) + ; else + ; diff --git a/tests/baselines/reference/elidedEmbeddedStatementsReplacedWithSemicolon.js b/tests/baselines/reference/elidedEmbeddedStatementsReplacedWithSemicolon.js new file mode 100644 index 00000000000..00ed2e49aa8 --- /dev/null +++ b/tests/baselines/reference/elidedEmbeddedStatementsReplacedWithSemicolon.js @@ -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) + ; diff --git a/tests/baselines/reference/elidedEmbeddedStatementsReplacedWithSemicolon.symbols b/tests/baselines/reference/elidedEmbeddedStatementsReplacedWithSemicolon.symbols new file mode 100644 index 00000000000..e32425754f8 --- /dev/null +++ b/tests/baselines/reference/elidedEmbeddedStatementsReplacedWithSemicolon.symbols @@ -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 {} diff --git a/tests/baselines/reference/elidedEmbeddedStatementsReplacedWithSemicolon.types b/tests/baselines/reference/elidedEmbeddedStatementsReplacedWithSemicolon.types new file mode 100644 index 00000000000..2c4dc4daeb7 --- /dev/null +++ b/tests/baselines/reference/elidedEmbeddedStatementsReplacedWithSemicolon.types @@ -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 + diff --git a/tests/baselines/reference/labeledStatementWithLabel.js b/tests/baselines/reference/labeledStatementWithLabel.js index 4d5dc499e25..ada819c9908 100644 --- a/tests/baselines/reference/labeledStatementWithLabel.js +++ b/tests/baselines/reference/labeledStatementWithLabel.js @@ -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: diff --git a/tests/baselines/reference/labeledStatementWithLabel_es2015.js b/tests/baselines/reference/labeledStatementWithLabel_es2015.js index e2eea4c53be..34ceb7bc17a 100644 --- a/tests/baselines/reference/labeledStatementWithLabel_es2015.js +++ b/tests/baselines/reference/labeledStatementWithLabel_es2015.js @@ -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: diff --git a/tests/baselines/reference/labeledStatementWithLabel_strict.js b/tests/baselines/reference/labeledStatementWithLabel_strict.js index c4ac2caed06..bcf211fdbfd 100644 --- a/tests/baselines/reference/labeledStatementWithLabel_strict.js +++ b/tests/baselines/reference/labeledStatementWithLabel_strict.js @@ -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: diff --git a/tests/cases/compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts b/tests/cases/compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts new file mode 100644 index 00000000000..dd9f6cc09f3 --- /dev/null +++ b/tests/cases/compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts @@ -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 {} \ No newline at end of file