Skip to content

Commit cafebdc

Browse files
Copilotjakebailey
andcommitted
Disallow [await] using statements under case/default clauses (#2742)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
1 parent d7e8346 commit cafebdc

6 files changed

Lines changed: 89 additions & 172 deletions

File tree

internal/checker/grammarchecks.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,9 @@ func (c *Checker) checkGrammarVariableDeclarationList(declarationList *ast.Varia
16761676
if declarationList.Flags&ast.NodeFlagsAmbient != 0 {
16771677
return c.grammarErrorOnNode(declarationList.AsNode(), core.IfElse(blockScopeFlags == ast.NodeFlagsUsing, diagnostics.X_using_declarations_are_not_allowed_in_ambient_contexts, diagnostics.X_await_using_declarations_are_not_allowed_in_ambient_contexts))
16781678
}
1679+
if ast.IsVariableStatement(declarationList.Parent) && (ast.IsCaseClause(declarationList.Parent.Parent) || ast.IsDefaultClause(declarationList.Parent.Parent)) {
1680+
return c.grammarErrorOnNode(declarationList.AsNode(), core.IfElse(blockScopeFlags == ast.NodeFlagsUsing, diagnostics.X_using_declarations_are_not_allowed_in_case_or_default_clauses_unless_contained_within_a_block, diagnostics.X_await_using_declarations_are_not_allowed_in_case_or_default_clauses_unless_contained_within_a_block))
1681+
}
16791682
}
16801683

16811684
if blockScopeFlags == ast.NodeFlagsAwaitUsing {

internal/transformers/estransforms/using.go

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ func (tx *usingDeclarationTransformer) visit(node *ast.Node) *ast.Node {
4646
node = tx.visitForStatement(node.AsForStatement())
4747
case ast.KindForOfStatement:
4848
node = tx.visitForOfStatement(node.AsForInOrOfStatement())
49-
case ast.KindSwitchStatement:
50-
node = tx.visitSwitchStatement(node.AsSwitchStatement())
5149
default:
5250
node = tx.Visitor().VisitEachChild(node)
5351
}
@@ -298,68 +296,6 @@ func (tx *usingDeclarationTransformer) visitForOfStatement(node *ast.ForInOrOfSt
298296
return tx.Visitor().VisitEachChild(node.AsNode())
299297
}
300298

301-
func (tx *usingDeclarationTransformer) visitCaseOrDefaultClause(node *ast.CaseOrDefaultClause, envBinding *ast.IdentifierNode) *ast.Node {
302-
if getUsingKindOfStatements(node.Statements.Nodes) != usingKindNone {
303-
return tx.Factory().UpdateCaseOrDefaultClause(
304-
node,
305-
tx.Visitor().VisitNode(node.Expression),
306-
tx.Factory().NewNodeList(tx.transformUsingDeclarations(node.Statements.Nodes, envBinding, nil /*topLevelStatements*/)),
307-
)
308-
}
309-
return tx.Visitor().VisitEachChild(node.AsNode())
310-
}
311-
312-
func (tx *usingDeclarationTransformer) visitSwitchStatement(node *ast.SwitchStatement) *ast.Node {
313-
// given:
314-
//
315-
// switch (expr) {
316-
// case expr:
317-
// using res = expr;
318-
// }
319-
//
320-
// produces:
321-
//
322-
// const env_1 = { stack: [], error: void 0, hasError: false };
323-
// try {
324-
// switch(expr) {
325-
// case expr:
326-
// const res = __addDisposableResource(env_1, expr, false);
327-
// }
328-
// }
329-
// catch (e_1) {
330-
// env_1.error = e_1;
331-
// env_1.hasError = true;
332-
// }
333-
// finally {
334-
// __disposeResources(env_1);
335-
// }
336-
//
337-
usingKind := getUsingKindOfCaseOrDefaultClauses(node.CaseBlock.AsCaseBlock().Clauses.Nodes)
338-
if usingKind != usingKindNone {
339-
envBinding := tx.createEnvBinding()
340-
return transformers.SingleOrMany(tx.createDownlevelUsingStatements(
341-
[]*ast.Statement{
342-
tx.Factory().UpdateSwitchStatement(
343-
node,
344-
tx.Visitor().VisitNode(node.Expression),
345-
tx.Factory().UpdateCaseBlock(
346-
node.CaseBlock.AsCaseBlock(),
347-
tx.Factory().NewNodeList(
348-
core.Map(node.CaseBlock.AsCaseBlock().Clauses.Nodes, func(clause *ast.CaseOrDefaultClauseNode) *ast.CaseOrDefaultClauseNode {
349-
return tx.visitCaseOrDefaultClause(clause.AsCaseOrDefaultClause(), envBinding)
350-
}),
351-
),
352-
),
353-
),
354-
},
355-
envBinding,
356-
usingKind == usingKindAsync,
357-
), tx.Factory())
358-
}
359-
360-
return tx.Visitor().VisitEachChild(node.AsNode())
361-
}
362-
363299
func (tx *usingDeclarationTransformer) transformUsingDeclarations(statementsIn []*ast.Statement, envBinding *ast.IdentifierNode, topLevelStatements *[]*ast.Statement) []*ast.Node {
364300
var statements []*ast.Statement
365301

@@ -851,17 +787,3 @@ func getUsingKindOfStatements(statements []*ast.Node) usingKind {
851787
}
852788
return result
853789
}
854-
855-
func getUsingKindOfCaseOrDefaultClauses(clauses []*ast.CaseOrDefaultClauseNode) usingKind {
856-
result := usingKindNone
857-
for _, clause := range clauses {
858-
usingKind := getUsingKindOfStatements(clause.Statements())
859-
if usingKind == usingKindAsync {
860-
return usingKindAsync
861-
}
862-
if usingKind > result {
863-
result = usingKind
864-
}
865-
}
866-
return result
867-
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
awaitUsingDeclarations.17.ts(3,9): error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
2+
awaitUsingDeclarations.17.ts(7,9): error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
3+
awaitUsingDeclarations.17.ts(11,9): error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
4+
awaitUsingDeclarations.17.ts(17,13): error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
5+
awaitUsingDeclarations.17.ts(21,13): error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
6+
7+
8+
==== awaitUsingDeclarations.17.ts (5 errors) ====
9+
switch (Math.random()) {
10+
case 0:
11+
await using d20 = { async [Symbol.asyncDispose]() {} };
12+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13+
!!! error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
14+
break;
15+
16+
case 1:
17+
await using d21 = { async [Symbol.asyncDispose]() {} };
18+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19+
!!! error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
20+
break;
21+
22+
default:
23+
await using d22 = { async [Symbol.asyncDispose]() {} };
24+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25+
!!! error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
26+
}
27+
28+
if (true)
29+
switch (0) {
30+
case 0:
31+
await using d23 = { async [Symbol.asyncDispose]() {} };
32+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33+
!!! error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
34+
break;
35+
36+
default:
37+
await using d24 = { async [Symbol.asyncDispose]() {} };
38+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39+
!!! error TS1548: 'await using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
40+
}
41+
42+
export {};
43+

testdata/baselines/reference/submodule/conformance/awaitUsingDeclarations.17.errors.txt.diff

Lines changed: 0 additions & 47 deletions
This file was deleted.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
usingDeclarations.17.ts(3,9): error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
2+
usingDeclarations.17.ts(7,9): error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
3+
usingDeclarations.17.ts(11,9): error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
4+
usingDeclarations.17.ts(17,13): error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
5+
usingDeclarations.17.ts(21,13): error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
6+
7+
8+
==== usingDeclarations.17.ts (5 errors) ====
9+
switch (Math.random()) {
10+
case 0:
11+
using d20 = { [Symbol.dispose]() {} };
12+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13+
!!! error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
14+
break;
15+
16+
case 1:
17+
using d21 = { [Symbol.dispose]() {} };
18+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19+
!!! error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
20+
break;
21+
22+
default:
23+
using d22 = { [Symbol.dispose]() {} };
24+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25+
!!! error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
26+
}
27+
28+
if (true)
29+
switch (0) {
30+
case 0:
31+
using d23 = { [Symbol.dispose]() {} };
32+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33+
!!! error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
34+
break;
35+
36+
default:
37+
using d24 = { [Symbol.dispose]() {} };
38+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39+
!!! error TS1547: 'using' declarations are not allowed in 'case' or 'default' clauses unless contained within a block.
40+
}
41+
42+
export {};
43+

testdata/baselines/reference/submodule/conformance/usingDeclarations.17.errors.txt.diff

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)