Skip to content
Merged
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
3 changes: 3 additions & 0 deletions tsc/internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -4343,6 +4343,9 @@ func (c *Checker) checkClassDeclaration(node *ast.Node) {
if node.Name() == nil && !ast.HasSyntacticModifier(node, ast.ModifierFlagsDefault) {
c.grammarErrorOnFirstToken(node, diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name)
}
if !c.containerAllowsBlockScopedVariable(node.Parent) {
c.grammarErrorOnNode(node, diagnostics.X_0_declarations_can_only_be_declared_inside_a_block, "class")
}
c.checkClassLikeDeclaration(node)
c.checkSourceElements(node.Members())
c.checkConstructorDeclaredProperties(node)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
a.ts(3,17): error TS1156: 'class' declarations can only be declared inside a block.
a.ts(4,25): error TS1156: 'class' declarations can only be declared inside a block.
a.ts(5,20): error TS1156: 'class' declarations can only be declared inside a block.
a.ts(6,10): error TS1156: 'class' declarations can only be declared inside a block.
a.ts(7,16): error TS1156: 'class' declarations can only be declared inside a block.
a.ts(8,27): error TS1156: 'class' declarations can only be declared inside a block.
a.ts(9,27): error TS1156: 'class' declarations can only be declared inside a block.
a.ts(10,11): error TS1344: A label is not allowed here.
a.ts(10,24): error TS1156: 'class' declarations can only be declared inside a block.
b.js(1,26): error TS1156: 'class' declarations can only be declared inside a block.


==== a.ts (9 errors) ====
declare const cond: boolean;

if (cond) class C1 {}
~~
!!! error TS1156: 'class' declarations can only be declared inside a block.
if (cond) {} else class C2 {}
~~
!!! error TS1156: 'class' declarations can only be declared inside a block.
while (cond) class C3 {}
~~
!!! error TS1156: 'class' declarations can only be declared inside a block.
do class C4 {} while (cond);
~~
!!! error TS1156: 'class' declarations can only be declared inside a block.
for (;;) class C5 {}
~~
!!! error TS1156: 'class' declarations can only be declared inside a block.
for (const k in {}) class C6 {}
~~
!!! error TS1156: 'class' declarations can only be declared inside a block.
for (const v of []) class C7 {}
~~
!!! error TS1156: 'class' declarations can only be declared inside a block.
if (cond) label: class C8 {}
~~~~~
!!! error TS1344: A label is not allowed here.
~~
!!! error TS1156: 'class' declarations can only be declared inside a block.

// OK
if (cond) {
class C10 {}
}
class C11 {}
switch (0) {
case 0:
class C12 {}
}
namespace N {
class C13 {}
}
function f() {
class C14 {}
return class C15 {};
}
let x;
if (cond) x = class C16 {};

==== b.js (1 errors) ====
if (Math.random()) class C17 {}
~~~
!!! error TS1156: 'class' declarations can only be declared inside a block.

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//// [tests/cases/compiler/classDeclarationInStatementPosition.ts] ////

//// [a.ts]
declare const cond: boolean;

if (cond) class C1 {}
if (cond) {} else class C2 {}
while (cond) class C3 {}
do class C4 {} while (cond);
for (;;) class C5 {}
for (const k in {}) class C6 {}
for (const v of []) class C7 {}
if (cond) label: class C8 {}

// OK
if (cond) {
class C10 {}
}
class C11 {}
switch (0) {
case 0:
class C12 {}
}
namespace N {
class C13 {}
}
function f() {
class C14 {}
return class C15 {};
}
let x;
if (cond) x = class C16 {};

//// [b.js]
if (Math.random()) class C17 {}


//// [a.js]
"use strict";
if (cond)
class C1 {
}
if (cond) { }
else
class C2 {
}
while (cond)
class C3 {
}
do
class C4 {
}
while (cond);
for (;;)
class C5 {
}
for (const k in {})
class C6 {
}
for (const v of [])
class C7 {
}
if (cond)
label: class C8 {
}
// OK
if (cond) {
class C10 {
}
}
class C11 {
}
switch (0) {
case 0:
class C12 {
}
}
var N;
(function (N) {
class C13 {
}
})(N || (N = {}));
function f() {
class C14 {
}
return class C15 {
};
}
let x;
if (cond)
x = class C16 {
};
//// [b.js]
"use strict";
if (Math.random())
class C17 {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//// [tests/cases/compiler/classDeclarationInStatementPosition.ts] ////

=== a.ts ===
declare const cond: boolean;
>cond : Symbol(cond, Decl(a.ts, 0, 13))

if (cond) class C1 {}
>cond : Symbol(cond, Decl(a.ts, 0, 13))
>C1 : Symbol(C1, Decl(a.ts, 2, 9))

if (cond) {} else class C2 {}
>cond : Symbol(cond, Decl(a.ts, 0, 13))
>C2 : Symbol(C2, Decl(a.ts, 3, 17))

while (cond) class C3 {}
>cond : Symbol(cond, Decl(a.ts, 0, 13))
>C3 : Symbol(C3, Decl(a.ts, 4, 12))

do class C4 {} while (cond);
>C4 : Symbol(C4, Decl(a.ts, 5, 2))
>cond : Symbol(cond, Decl(a.ts, 0, 13))

for (;;) class C5 {}
>C5 : Symbol(C5, Decl(a.ts, 6, 8))

for (const k in {}) class C6 {}
>k : Symbol(k, Decl(a.ts, 7, 10))
>C6 : Symbol(C6, Decl(a.ts, 7, 19))

for (const v of []) class C7 {}
>v : Symbol(v, Decl(a.ts, 8, 10))
>C7 : Symbol(C7, Decl(a.ts, 8, 19))

if (cond) label: class C8 {}
>cond : Symbol(cond, Decl(a.ts, 0, 13))
>C8 : Symbol(C8, Decl(a.ts, 9, 16))

// OK
if (cond) {
>cond : Symbol(cond, Decl(a.ts, 0, 13))

class C10 {}
>C10 : Symbol(C10, Decl(a.ts, 12, 11))
}
class C11 {}
>C11 : Symbol(C11, Decl(a.ts, 14, 1))

switch (0) {
case 0:
class C12 {}
>C12 : Symbol(C12, Decl(a.ts, 17, 11))
}
namespace N {
>N : Symbol(N, Decl(a.ts, 19, 1))

class C13 {}
>C13 : Symbol(C13, Decl(a.ts, 20, 13))
}
function f() {
>f : Symbol(f, Decl(a.ts, 22, 1))

class C14 {}
>C14 : Symbol(C14, Decl(a.ts, 23, 14))

return class C15 {};
>C15 : Symbol(C15, Decl(a.ts, 25, 10))
}
let x;
>x : Symbol(x, Decl(a.ts, 27, 3))

if (cond) x = class C16 {};
>cond : Symbol(cond, Decl(a.ts, 0, 13))
>x : Symbol(x, Decl(a.ts, 27, 3))
>C16 : Symbol(C16, Decl(a.ts, 28, 13))

=== b.js ===
if (Math.random()) class C17 {}
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>C17 : Symbol(C17, Decl(b.js, 0, 18))

Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//// [tests/cases/compiler/classDeclarationInStatementPosition.ts] ////

=== a.ts ===
declare const cond: boolean;
>cond : boolean

if (cond) class C1 {}
>cond : boolean
>C1 : C1

if (cond) {} else class C2 {}
>cond : boolean
>C2 : C2

while (cond) class C3 {}
>cond : boolean
>C3 : C3

do class C4 {} while (cond);
>C4 : C4
>cond : false

for (;;) class C5 {}
>C5 : C5

for (const k in {}) class C6 {}
>k : string
>{} : {}
>C6 : C6

for (const v of []) class C7 {}
>v : never
>[] : never[]
>C7 : C7

if (cond) label: class C8 {}
>cond : boolean
>label : any
>C8 : C8

// OK
if (cond) {
>cond : boolean

class C10 {}
>C10 : C10
}
class C11 {}
>C11 : C11

switch (0) {
>0 : 0

case 0:
>0 : 0

class C12 {}
>C12 : C12
}
namespace N {
>N : typeof N

class C13 {}
>C13 : C13
}
function f() {
>f : () => typeof C15

class C14 {}
>C14 : C14

return class C15 {};
>class C15 {} : typeof C15
>C15 : typeof C15
}
let x;
>x : any

if (cond) x = class C16 {};
>cond : boolean
>x = class C16 {} : typeof C16
>x : any
>class C16 {} : typeof C16
>C16 : typeof C16

=== b.js ===
if (Math.random()) class C17 {}
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>C17 : C17

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @target: es2015
// @allowJs: true
// @outDir: out

// https://github.com/microsoft/TypeScript/issues/22682

// @filename: a.ts
declare const cond: boolean;

if (cond) class C1 {}
if (cond) {} else class C2 {}
while (cond) class C3 {}
do class C4 {} while (cond);
for (;;) class C5 {}
for (const k in {}) class C6 {}
for (const v of []) class C7 {}
if (cond) label: class C8 {}

// OK
if (cond) {
class C10 {}
}
class C11 {}
switch (0) {
case 0:
class C12 {}
}
namespace N {
class C13 {}
}
function f() {
class C14 {}
return class C15 {};
}
let x;
if (cond) x = class C16 {};

// @filename: b.js
if (Math.random()) class C17 {}
Loading