diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 436fb04ef2bcf..56be205a9b52a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -7094,11 +7094,17 @@ namespace Parser { case SyntaxKind.ProtectedKeyword: case SyntaxKind.PublicKeyword: case SyntaxKind.ReadonlyKeyword: + const previousToken = token(); nextToken(); // ASI takes effect for this modifier. if (scanner.hasPrecedingLineBreak()) { return false; } + if (previousToken === SyntaxKind.DeclareKeyword && token() === SyntaxKind.TypeKeyword) { + // If we see 'declare type', then commit to parsing a type alias. parseTypeAliasDeclaration will + // report Line_break_not_permitted_here if needed. + return true; + } continue; case SyntaxKind.GlobalKeyword: @@ -8092,6 +8098,9 @@ namespace Parser { function parseTypeAliasDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): TypeAliasDeclaration { parseExpected(SyntaxKind.TypeKeyword); + if (scanner.hasPrecedingLineBreak()) { + parseErrorAtCurrentToken(Diagnostics.Line_break_not_permitted_here); + } const name = parseIdentifier(); const typeParameters = parseTypeParameters(); parseExpected(SyntaxKind.EqualsToken); diff --git a/tests/baselines/reference/typeAliasDeclareKeywordNewlines.errors.txt b/tests/baselines/reference/typeAliasDeclareKeywordNewlines.errors.txt new file mode 100644 index 0000000000000..afbea95e16117 --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclareKeywordNewlines.errors.txt @@ -0,0 +1,26 @@ +typeAliasDeclareKeywordNewlines.ts(5,1): error TS1142: Line break not permitted here. + + +==== typeAliasDeclareKeywordNewlines.ts (1 errors) ==== + var declare: string, type: number; + + // The following is invalid but should declare a type alias named 'T1': + declare type /*unexpected newline*/ + T1 = null; + ~~ +!!! error TS1142: Line break not permitted here. + const t1: T1 = null; // Assert that T1 is the null type. + + let T: null; + // The following should use a variable named 'declare', use a variable named + // 'type', and assign to a variable named 'T'. + declare /*ASI*/ + type /*ASI*/ + T = null; + + // The following should use a variable named 'declare' and declare a type alias + // named 'T2': + declare /*ASI*/ + type T2 = null; + const t2: T2 = null; // Assert that T2 is the null type. + \ No newline at end of file diff --git a/tests/baselines/reference/typeAliasDeclareKeywordNewlines.js b/tests/baselines/reference/typeAliasDeclareKeywordNewlines.js new file mode 100644 index 0000000000000..dda27f355c915 --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclareKeywordNewlines.js @@ -0,0 +1,37 @@ +//// [tests/cases/compiler/typeAliasDeclareKeywordNewlines.ts] //// + +//// [typeAliasDeclareKeywordNewlines.ts] +var declare: string, type: number; + +// The following is invalid but should declare a type alias named 'T1': +declare type /*unexpected newline*/ +T1 = null; +const t1: T1 = null; // Assert that T1 is the null type. + +let T: null; +// The following should use a variable named 'declare', use a variable named +// 'type', and assign to a variable named 'T'. +declare /*ASI*/ +type /*ASI*/ +T = null; + +// The following should use a variable named 'declare' and declare a type alias +// named 'T2': +declare /*ASI*/ +type T2 = null; +const t2: T2 = null; // Assert that T2 is the null type. + + +//// [typeAliasDeclareKeywordNewlines.js] +var declare, type; +var t1 = null; // Assert that T1 is the null type. +var T; +// The following should use a variable named 'declare', use a variable named +// 'type', and assign to a variable named 'T'. +declare; /*ASI*/ +type; /*ASI*/ +T = null; +// The following should use a variable named 'declare' and declare a type alias +// named 'T2': +declare; /*ASI*/ +var t2 = null; // Assert that T2 is the null type. diff --git a/tests/baselines/reference/typeAliasDeclareKeywordNewlines.symbols b/tests/baselines/reference/typeAliasDeclareKeywordNewlines.symbols new file mode 100644 index 0000000000000..95ce65218ec83 --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclareKeywordNewlines.symbols @@ -0,0 +1,42 @@ +//// [tests/cases/compiler/typeAliasDeclareKeywordNewlines.ts] //// + +=== typeAliasDeclareKeywordNewlines.ts === +var declare: string, type: number; +>declare : Symbol(declare, Decl(typeAliasDeclareKeywordNewlines.ts, 0, 3)) +>type : Symbol(type, Decl(typeAliasDeclareKeywordNewlines.ts, 0, 20)) + +// The following is invalid but should declare a type alias named 'T1': +declare type /*unexpected newline*/ +T1 = null; +>T1 : Symbol(T1, Decl(typeAliasDeclareKeywordNewlines.ts, 0, 34)) + +const t1: T1 = null; // Assert that T1 is the null type. +>t1 : Symbol(t1, Decl(typeAliasDeclareKeywordNewlines.ts, 5, 5)) +>T1 : Symbol(T1, Decl(typeAliasDeclareKeywordNewlines.ts, 0, 34)) + +let T: null; +>T : Symbol(T, Decl(typeAliasDeclareKeywordNewlines.ts, 7, 3)) + +// The following should use a variable named 'declare', use a variable named +// 'type', and assign to a variable named 'T'. +declare /*ASI*/ +>declare : Symbol(declare, Decl(typeAliasDeclareKeywordNewlines.ts, 0, 3)) + +type /*ASI*/ +>type : Symbol(type, Decl(typeAliasDeclareKeywordNewlines.ts, 0, 20)) + +T = null; +>T : Symbol(T, Decl(typeAliasDeclareKeywordNewlines.ts, 7, 3)) + +// The following should use a variable named 'declare' and declare a type alias +// named 'T2': +declare /*ASI*/ +>declare : Symbol(declare, Decl(typeAliasDeclareKeywordNewlines.ts, 0, 3)) + +type T2 = null; +>T2 : Symbol(T2, Decl(typeAliasDeclareKeywordNewlines.ts, 16, 7)) + +const t2: T2 = null; // Assert that T2 is the null type. +>t2 : Symbol(t2, Decl(typeAliasDeclareKeywordNewlines.ts, 18, 5)) +>T2 : Symbol(T2, Decl(typeAliasDeclareKeywordNewlines.ts, 16, 7)) + diff --git a/tests/baselines/reference/typeAliasDeclareKeywordNewlines.types b/tests/baselines/reference/typeAliasDeclareKeywordNewlines.types new file mode 100644 index 0000000000000..43d7280052658 --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclareKeywordNewlines.types @@ -0,0 +1,41 @@ +//// [tests/cases/compiler/typeAliasDeclareKeywordNewlines.ts] //// + +=== typeAliasDeclareKeywordNewlines.ts === +var declare: string, type: number; +>declare : string +>type : number + +// The following is invalid but should declare a type alias named 'T1': +declare type /*unexpected newline*/ +T1 = null; +>T1 : null + +const t1: T1 = null; // Assert that T1 is the null type. +>t1 : null + +let T: null; +>T : null + +// The following should use a variable named 'declare', use a variable named +// 'type', and assign to a variable named 'T'. +declare /*ASI*/ +>declare : string + +type /*ASI*/ +>type : number + +T = null; +>T = null : null +>T : null + +// The following should use a variable named 'declare' and declare a type alias +// named 'T2': +declare /*ASI*/ +>declare : string + +type T2 = null; +>T2 : null + +const t2: T2 = null; // Assert that T2 is the null type. +>t2 : null + diff --git a/tests/cases/compiler/typeAliasDeclareKeywordNewlines.ts b/tests/cases/compiler/typeAliasDeclareKeywordNewlines.ts new file mode 100644 index 0000000000000..f8fd5867dd985 --- /dev/null +++ b/tests/cases/compiler/typeAliasDeclareKeywordNewlines.ts @@ -0,0 +1,19 @@ +var declare: string, type: number; + +// The following is invalid but should declare a type alias named 'T1': +declare type /*unexpected newline*/ +T1 = null; +const t1: T1 = null; // Assert that T1 is the null type. + +let T: null; +// The following should use a variable named 'declare', use a variable named +// 'type', and assign to a variable named 'T'. +declare /*ASI*/ +type /*ASI*/ +T = null; + +// The following should use a variable named 'declare' and declare a type alias +// named 'T2': +declare /*ASI*/ +type T2 = null; +const t2: T2 = null; // Assert that T2 is the null type.