diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 421162a07f8d5..ef22e9dfd73e6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35405,7 +35405,7 @@ namespace ts { superCallStatement = statement; break; } - if (!isPrologueDirective(statement) && nodeImmediatelyReferencesSuperOrThis(statement)) { + if (nodeImmediatelyReferencesSuperOrThis(statement)) { break; } } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 994601a426563..bcb92d9594a8a 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1938,14 +1938,14 @@ namespace ts { resumeLexicalEnvironment(); - const indexAfterLastPrologueStatement = factory.copyPrologue(body.statements, statements, /*ensureUseStrict*/ false, visitor); - const superStatementIndex = findSuperStatementIndex(body.statements, indexAfterLastPrologueStatement); + const prologueStatementCount = factory.copyPrologue(body.statements, statements, /*ensureUseStrict*/ false, visitor); + const superStatementIndex = findSuperStatementIndex(body.statements, prologueStatementCount); // If there was a super call, visit existing statements up to and including it if (superStatementIndex >= 0) { addRange( statements, - visitNodes(body.statements, visitor, isStatement, indexAfterLastPrologueStatement, superStatementIndex + 1 - indexAfterLastPrologueStatement), + visitNodes(body.statements, visitor, isStatement, prologueStatementCount, superStatementIndex + 1 - prologueStatementCount), ); } @@ -1967,13 +1967,17 @@ namespace ts { if (superStatementIndex >= 0) { addRange(statements, parameterPropertyAssignments); } - // Since there was no super() call, parameter properties are the first statements in the constructor + // Since there was no super() call, parameter properties are the first statements in the constructor after any prologue statements else { - statements = addRange(parameterPropertyAssignments, statements); + statements = [ + ...statements.slice(0, prologueStatementCount), + ...parameterPropertyAssignments, + ...statements.slice(prologueStatementCount), + ]; } - // Add remaining statements from the body, skipping the super() call if it was found - addRange(statements, visitNodes(body.statements, visitor, isStatement, superStatementIndex + 1)); + // Add remaining statements from the body, skipping the super() call if it was found and any (already added) prologue statements + addRange(statements, visitNodes(body.statements, visitor, isStatement, superStatementIndex + 1 + prologueStatementCount)); // End the lexical environment. statements = factory.mergeLexicalEnvironment(statements, endLexicalEnvironment()); diff --git a/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.js b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.js new file mode 100644 index 0000000000000..d952cf8ba177c --- /dev/null +++ b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.js @@ -0,0 +1,104 @@ +//// [parameterPropertyInConstructorWithPrologues.ts] +// https://github.com/microsoft/TypeScript/issues/48671 + +class Foo1 { + constructor(private A: string) { + "ngInject1"; + } +} + +class Foo2 { + constructor(private A: string, private B: string) { + "ngInject1"; + "ngInject2"; + } +} + +class Foo3 { + constructor(private A: string, private B: string, private C: string) { + "ngInject1"; + "ngInject2"; + } +} + +class Foo4 { + constructor(private A: string) { + "ngInject1"; + console.log("hi"); + } +} + +class Foo5 { + constructor(private A: string, private B: string) { + "ngInject1"; + "ngInject2"; + console.log("hi"); + } +} + +class Foo6 { + constructor(private A: string, private B: string, private C: string) { + "ngInject1"; + "ngInject2"; + console.log("hi"); + } +} + + +//// [parameterPropertyInConstructorWithPrologues.js] +// https://github.com/microsoft/TypeScript/issues/48671 +var Foo1 = /** @class */ (function () { + function Foo1(A) { + "ngInject1"; + this.A = A; + } + return Foo1; +}()); +var Foo2 = /** @class */ (function () { + function Foo2(A, B) { + "ngInject1"; + "ngInject2"; + this.A = A; + this.B = B; + } + return Foo2; +}()); +var Foo3 = /** @class */ (function () { + function Foo3(A, B, C) { + "ngInject1"; + "ngInject2"; + this.A = A; + this.B = B; + this.C = C; + } + return Foo3; +}()); +var Foo4 = /** @class */ (function () { + function Foo4(A) { + "ngInject1"; + this.A = A; + console.log("hi"); + } + return Foo4; +}()); +var Foo5 = /** @class */ (function () { + function Foo5(A, B) { + "ngInject1"; + "ngInject2"; + this.A = A; + this.B = B; + console.log("hi"); + } + return Foo5; +}()); +var Foo6 = /** @class */ (function () { + function Foo6(A, B, C) { + "ngInject1"; + "ngInject2"; + this.A = A; + this.B = B; + this.C = C; + console.log("hi"); + } + return Foo6; +}()); diff --git a/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.symbols b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.symbols new file mode 100644 index 0000000000000..582bfd762d229 --- /dev/null +++ b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.symbols @@ -0,0 +1,85 @@ +=== tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts === +// https://github.com/microsoft/TypeScript/issues/48671 + +class Foo1 { +>Foo1 : Symbol(Foo1, Decl(parameterPropertyInConstructorWithPrologues.ts, 0, 0)) + + constructor(private A: string) { +>A : Symbol(Foo1.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 3, 14)) + + "ngInject1"; + } +} + +class Foo2 { +>Foo2 : Symbol(Foo2, Decl(parameterPropertyInConstructorWithPrologues.ts, 6, 1)) + + constructor(private A: string, private B: string) { +>A : Symbol(Foo2.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 9, 14)) +>B : Symbol(Foo2.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 9, 32)) + + "ngInject1"; + "ngInject2"; + } +} + +class Foo3 { +>Foo3 : Symbol(Foo3, Decl(parameterPropertyInConstructorWithPrologues.ts, 13, 1)) + + constructor(private A: string, private B: string, private C: string) { +>A : Symbol(Foo3.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 16, 14)) +>B : Symbol(Foo3.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 16, 32)) +>C : Symbol(Foo3.C, Decl(parameterPropertyInConstructorWithPrologues.ts, 16, 51)) + + "ngInject1"; + "ngInject2"; + } +} + +class Foo4 { +>Foo4 : Symbol(Foo4, Decl(parameterPropertyInConstructorWithPrologues.ts, 20, 1)) + + constructor(private A: string) { +>A : Symbol(Foo4.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 23, 14)) + + "ngInject1"; + console.log("hi"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } +} + +class Foo5 { +>Foo5 : Symbol(Foo5, Decl(parameterPropertyInConstructorWithPrologues.ts, 27, 1)) + + constructor(private A: string, private B: string) { +>A : Symbol(Foo5.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 30, 14)) +>B : Symbol(Foo5.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 30, 32)) + + "ngInject1"; + "ngInject2"; + console.log("hi"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } +} + +class Foo6 { +>Foo6 : Symbol(Foo6, Decl(parameterPropertyInConstructorWithPrologues.ts, 35, 1)) + + constructor(private A: string, private B: string, private C: string) { +>A : Symbol(Foo6.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 38, 14)) +>B : Symbol(Foo6.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 38, 32)) +>C : Symbol(Foo6.C, Decl(parameterPropertyInConstructorWithPrologues.ts, 38, 51)) + + "ngInject1"; + "ngInject2"; + console.log("hi"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } +} + diff --git a/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.types b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.types new file mode 100644 index 0000000000000..2f676ee39ee50 --- /dev/null +++ b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.types @@ -0,0 +1,108 @@ +=== tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts === +// https://github.com/microsoft/TypeScript/issues/48671 + +class Foo1 { +>Foo1 : Foo1 + + constructor(private A: string) { +>A : string + + "ngInject1"; +>"ngInject1" : "ngInject1" + } +} + +class Foo2 { +>Foo2 : Foo2 + + constructor(private A: string, private B: string) { +>A : string +>B : string + + "ngInject1"; +>"ngInject1" : "ngInject1" + + "ngInject2"; +>"ngInject2" : "ngInject2" + } +} + +class Foo3 { +>Foo3 : Foo3 + + constructor(private A: string, private B: string, private C: string) { +>A : string +>B : string +>C : string + + "ngInject1"; +>"ngInject1" : "ngInject1" + + "ngInject2"; +>"ngInject2" : "ngInject2" + } +} + +class Foo4 { +>Foo4 : Foo4 + + constructor(private A: string) { +>A : string + + "ngInject1"; +>"ngInject1" : "ngInject1" + + console.log("hi"); +>console.log("hi") : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>"hi" : "hi" + } +} + +class Foo5 { +>Foo5 : Foo5 + + constructor(private A: string, private B: string) { +>A : string +>B : string + + "ngInject1"; +>"ngInject1" : "ngInject1" + + "ngInject2"; +>"ngInject2" : "ngInject2" + + console.log("hi"); +>console.log("hi") : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>"hi" : "hi" + } +} + +class Foo6 { +>Foo6 : Foo6 + + constructor(private A: string, private B: string, private C: string) { +>A : string +>B : string +>C : string + + "ngInject1"; +>"ngInject1" : "ngInject1" + + "ngInject2"; +>"ngInject2" : "ngInject2" + + console.log("hi"); +>console.log("hi") : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>"hi" : "hi" + } +} + diff --git a/tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts b/tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts new file mode 100644 index 0000000000000..aa6acde1ae90c --- /dev/null +++ b/tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts @@ -0,0 +1,44 @@ +// https://github.com/microsoft/TypeScript/issues/48671 + +class Foo1 { + constructor(private A: string) { + "ngInject1"; + } +} + +class Foo2 { + constructor(private A: string, private B: string) { + "ngInject1"; + "ngInject2"; + } +} + +class Foo3 { + constructor(private A: string, private B: string, private C: string) { + "ngInject1"; + "ngInject2"; + } +} + +class Foo4 { + constructor(private A: string) { + "ngInject1"; + console.log("hi"); + } +} + +class Foo5 { + constructor(private A: string, private B: string) { + "ngInject1"; + "ngInject2"; + console.log("hi"); + } +} + +class Foo6 { + constructor(private A: string, private B: string, private C: string) { + "ngInject1"; + "ngInject2"; + console.log("hi"); + } +}