Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2763,7 +2763,7 @@ namespace Parser {
return canFollowModifier();
}

function nextTokenCanFollowModifier() {
function nextTokenCanFollowModifier(permitLineBreak?: boolean) {
switch (token()) {
case SyntaxKind.ConstKeyword:
// 'const' is only a modifier if followed by 'enum'.
Expand All @@ -2787,10 +2787,15 @@ namespace Parser {
nextToken();
return canFollowGetOrSetKeyword();
default:
return nextTokenIsOnSameLineAndCanFollowModifier();
return permitLineBreak ? nextTokenCanFollowModifierWorker() : nextTokenIsOnSameLineAndCanFollowModifier();
}
}

function nextTokenCanFollowModifierWorker() {
nextToken();
return canFollowModifier();
}

function canFollowExportModifier(): boolean {
return token() === SyntaxKind.AtToken
|| token() !== SyntaxKind.AsteriskToken
Expand All @@ -2804,8 +2809,8 @@ namespace Parser {
return canFollowExportModifier();
}

function parseAnyContextualModifier(): boolean {
return isModifierKind(token()) && tryParse(nextTokenCanFollowModifier);
function parseAnyContextualModifier(permitLineBreak?: boolean): boolean {
return isModifierKind(token()) && tryParse(() => nextTokenCanFollowModifier(permitLineBreak));
}

function canFollowModifier(): boolean {
Expand Down Expand Up @@ -4042,8 +4047,8 @@ namespace Parser {

// Decorators are parsed in the outer [Await] context, the rest of the parameter is parsed in the function's [Await] context.
const modifiers = inOuterAwaitContext ?
doInAwaitContext(() => parseModifiers(/*allowDecorators*/ true)) :
doOutsideOfAwaitContext(() => parseModifiers(/*allowDecorators*/ true));
doInAwaitContext(() => parseModifiers(/*allowDecorators*/ true, /*permitConstAsModifier*/ false, /*stopOnStartOfClassStaticBlock*/ false, /*permitLineBreak*/ true)) :
doOutsideOfAwaitContext(() => parseModifiers(/*allowDecorators*/ true, /*permitConstAsModifier*/ false, /*stopOnStartOfClassStaticBlock*/ false, /*permitLineBreak*/ true));

if (token() === SyntaxKind.ThisKeyword) {
const node = factory.createParameterDeclaration(
Expand Down Expand Up @@ -7977,7 +7982,7 @@ namespace Parser {
return finishNode(factory.createDecorator(expression), pos);
}

function tryParseModifier(hasSeenStaticModifier: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): Modifier | undefined {
function tryParseModifier(hasSeenStaticModifier: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean, permitLineBreak?: boolean): Modifier | undefined {
const pos = getNodePos();
const kind = token();

Expand All @@ -7995,7 +8000,7 @@ namespace Parser {
return undefined;
}
else {
if (!parseAnyContextualModifier()) {
if (!parseAnyContextualModifier(permitLineBreak)) {
return undefined;
}
}
Expand All @@ -8010,9 +8015,9 @@ namespace Parser {
*
* In such situations, 'permitConstAsModifier' should be set to true.
*/
function parseModifiers(allowDecorators: false, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray<Modifier> | undefined;
function parseModifiers(allowDecorators: true, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray<ModifierLike> | undefined;
function parseModifiers(allowDecorators: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray<ModifierLike> | undefined {
function parseModifiers(allowDecorators: false, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean, permitLineBreak?: boolean): NodeArray<Modifier> | undefined;
function parseModifiers(allowDecorators: true, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean, permitLineBreak?: boolean): NodeArray<ModifierLike> | undefined;
function parseModifiers(allowDecorators: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean, permitLineBreak?: boolean): NodeArray<ModifierLike> | undefined {
Comment on lines +8018 to +8020
const pos = getNodePos();
let list: ModifierLike[] | undefined;
let decorator, modifier, hasSeenStaticModifier = false, hasLeadingModifier = false, hasTrailingDecorator = false;
Expand All @@ -8029,7 +8034,7 @@ namespace Parser {
}

// parse leading modifiers
while (modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock)) {
while (modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock, permitLineBreak)) {
if (modifier.kind === SyntaxKind.StaticKeyword) hasSeenStaticModifier = true;
list = append(list, modifier);
hasLeadingModifier = true;
Expand All @@ -8045,7 +8050,7 @@ namespace Parser {

// parse trailing modifiers, but only if we parsed any trailing decorators
if (hasTrailingDecorator) {
while (modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock)) {
while (modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock, permitLineBreak)) {
if (modifier.kind === SyntaxKind.StaticKeyword) hasSeenStaticModifier = true;
list = append(list, modifier);
}
Expand Down
46 changes: 46 additions & 0 deletions tests/baselines/reference/parameterPropertyWithNewline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//// [tests/cases/compiler/parameterPropertyWithNewline.ts] ////

//// [parameterPropertyWithNewline.ts]
class Foo1 {
constructor(public
foo: string) {}
}

class Foo2 {
constructor(private
bar: number) {}
}

class Foo3 {
constructor(protected
baz: boolean) {}
}

class Foo4 {
constructor(readonly
qux: string) {}
}


//// [parameterPropertyWithNewline.js]
"use strict";
class Foo1 {
constructor(foo) {
this.foo = foo;
}
}
class Foo2 {
constructor(bar) {
this.bar = bar;
}
}
class Foo3 {
constructor(baz) {
this.baz = baz;
}
}
class Foo4 {
constructor(qux) {
this.qux = qux;
}
}
35 changes: 35 additions & 0 deletions tests/baselines/reference/parameterPropertyWithNewline.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//// [tests/cases/compiler/parameterPropertyWithNewline.ts] ////

=== parameterPropertyWithNewline.ts ===
class Foo1 {
>Foo1 : Symbol(Foo1, Decl(parameterPropertyWithNewline.ts, 0, 0))

constructor(public
foo: string) {}
>foo : Symbol(Foo1.foo, Decl(parameterPropertyWithNewline.ts, 1, 14))
}

class Foo2 {
>Foo2 : Symbol(Foo2, Decl(parameterPropertyWithNewline.ts, 3, 1))

constructor(private
bar: number) {}
>bar : Symbol(Foo2.bar, Decl(parameterPropertyWithNewline.ts, 6, 14))
}

class Foo3 {
>Foo3 : Symbol(Foo3, Decl(parameterPropertyWithNewline.ts, 8, 1))

constructor(protected
baz: boolean) {}
>baz : Symbol(Foo3.baz, Decl(parameterPropertyWithNewline.ts, 11, 14))
}

class Foo4 {
>Foo4 : Symbol(Foo4, Decl(parameterPropertyWithNewline.ts, 13, 1))

constructor(readonly
qux: string) {}
>qux : Symbol(Foo4.qux, Decl(parameterPropertyWithNewline.ts, 16, 14))
}

43 changes: 43 additions & 0 deletions tests/baselines/reference/parameterPropertyWithNewline.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//// [tests/cases/compiler/parameterPropertyWithNewline.ts] ////

=== parameterPropertyWithNewline.ts ===
class Foo1 {
>Foo1 : Foo1
> : ^^^^

constructor(public
foo: string) {}
>foo : string
> : ^^^^^^
}

class Foo2 {
>Foo2 : Foo2
> : ^^^^

constructor(private
bar: number) {}
>bar : number
> : ^^^^^^
}

class Foo3 {
>Foo3 : Foo3
> : ^^^^

constructor(protected
baz: boolean) {}
>baz : boolean
> : ^^^^^^^
}

class Foo4 {
>Foo4 : Foo4
> : ^^^^

constructor(readonly
qux: string) {}
>qux : string
> : ^^^^^^
}

20 changes: 20 additions & 0 deletions tests/cases/compiler/parameterPropertyWithNewline.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// @target: es2015
class Foo1 {
constructor(public
foo: string) {}
}

class Foo2 {
constructor(private
bar: number) {}
}

class Foo3 {
constructor(protected
baz: boolean) {}
}

class Foo4 {
constructor(readonly
qux: string) {}
}
Comment on lines +12 to +20