Skip to content

Commit 0ad3adc

Browse files
JeanMechethePunderWoman
authored andcommitted
fix(compiler): Support empty cases
Before this commit empty @Cases ended up being interpreted as consecutive cases.
1 parent bb0dc8c commit 0ad3adc

6 files changed

Lines changed: 74 additions & 8 deletions

File tree

packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_control_flow/GOLDEN_PARTIAL.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2342,6 +2342,7 @@ export class MyApp {
23422342
<div>
23432343
{{message}}
23442344
@switch (value()) {
2345+
@case (-1) {}
23452346
@case (0) @case(1) {
23462347
case 01
23472348
}
@@ -2362,6 +2363,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE
23622363
<div>
23632364
{{message}}
23642365
@switch (value()) {
2366+
@case (-1) {}
23652367
@case (0) @case(1) {
23662368
case 01
23672369
}

packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_control_flow/switch_multiple_cases.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import {Component} from '@angular/core';
1+
import { Component } from '@angular/core';
22

33
@Component({
44
template: `
55
<div>
66
{{message}}
77
@switch (value()) {
8+
@case (-1) {}
89
@case (0) @case(1) {
910
case 01
1011
}
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
function MyApp_Case_2_Template(rf, ctx) {
1+
function MyApp_Case_2_Template(rf, ctx) {}
2+
3+
function MyApp_Case_3_Template(rf, ctx) {
24
if (rf & 1) {
35
$r3$.ɵɵtext(0, " case 01 ");
46
}
57
}
68

7-
function MyApp_Case_3_Template(rf, ctx) {
9+
function MyApp_Case_4_Template(rf, ctx) {
810
if (rf & 1) {
911
$r3$.ɵɵtext(0, " case 2 ");
1012
}
1113
}
1214

13-
function MyApp_Case_4_Template(rf, ctx) {
15+
function MyApp_Case_5_Template(rf, ctx) {
1416
if (rf & 1) {
1517
$r3$.ɵɵtext(0, " default ");
1618
}
@@ -20,14 +22,14 @@ function MyApp_Template(rf, ctx) {
2022
if (rf & 1) {
2123
$r3$.ɵɵelementStart(0, "div");
2224
$r3$.ɵɵtext(1);
23-
$r3$.ɵɵconditionalCreate(2, MyApp_Case_2_Template, 1, 0)(3, MyApp_Case_3_Template, 1, 0)(4, MyApp_Case_4_Template, 1, 0);
25+
$r3$.ɵɵconditionalCreate(2, MyApp_Case_2_Template, 0, 0)(3, MyApp_Case_3_Template, 1, 0)(4, MyApp_Case_4_Template, 1, 0)(5, MyApp_Case_5_Template, 1, 0);
2426
$r3$.ɵɵelementEnd();
2527
}
2628
if (rf & 2) {
2729
let $MyApp_contFlowTmp$;
2830
$r3$.ɵɵadvance();
2931
$r3$.ɵɵtextInterpolate1(" ", ctx.message, " ");
3032
$r3$.ɵɵadvance();
31-
$r3$.ɵɵconditional(($MyApp_contFlowTmp$ = ctx.value()) === 0 ? 2 : $MyApp_contFlowTmp$ === 1 ? 2 : $MyApp_contFlowTmp$ === 2 ? 3 : 4);
33+
$r3$.ɵɵconditional((tmp_1_0 = ctx.value()) === -1 ? 2 : tmp_1_0 === 0 ? 3 : tmp_1_0 === 1 ? 3 : tmp_1_0 === 2 ? 4 : 5);
3234
}
3335
}

packages/compiler/src/render3/r3_control_flow.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,12 @@ export function createSwitchBlock(
260260
);
261261
collectedCases.push(switchCase);
262262

263-
const caseWithoutBody = node.children.length === 0;
263+
// We need to take into account that some cases might have an empty body. ({})
264+
const caseWithoutBody =
265+
node.children.length === 0 &&
266+
node.endSourceSpan !== null &&
267+
node.endSourceSpan.start.offset === node.endSourceSpan.end.offset;
268+
264269
if (caseWithoutBody) {
265270
if (firstCaseStart === null) {
266271
firstCaseStart = node.sourceSpan;

packages/compiler/test/ml_parser/html_parser_spec.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
import * as html from '../../src/ml_parser/ast';
1010
import {HtmlParser} from '../../src/ml_parser/html_parser';
11-
import {ParseTreeResult, TreeError} from '../../src/ml_parser/parser';
1211
import {TokenizeOptions} from '../../src/ml_parser/lexer';
12+
import {ParseTreeResult, TreeError} from '../../src/ml_parser/parser';
1313
import {ParseError} from '../../src/parse_util';
1414

1515
import {
@@ -1093,6 +1093,30 @@ describe('HtmlParser', () => {
10931093
]);
10941094
});
10951095

1096+
it('should parse empty cases in a switch block', () => {
1097+
expect(
1098+
humanizeDom(
1099+
parser.parse(
1100+
`@switch (expr) {@case ('foo') {} @case ('bar') {bar} @case('baz') { baz }}`,
1101+
`TestComp`,
1102+
),
1103+
),
1104+
).toEqual([
1105+
[html.Block, 'switch', 0],
1106+
[html.BlockParameter, 'expr'],
1107+
[html.Block, 'case', 1],
1108+
[html.BlockParameter, `'foo'`],
1109+
[html.Text, ' ', 1, [' ']],
1110+
[html.Block, 'case', 1],
1111+
[html.BlockParameter, `'bar'`],
1112+
[html.Text, 'bar', 2, ['bar']],
1113+
[html.Text, ' ', 1, [' ']],
1114+
[html.Block, 'case', 1],
1115+
[html.BlockParameter, `'baz'`],
1116+
[html.Text, ' baz ', 2, [' baz ']],
1117+
]);
1118+
});
1119+
10961120
it('should close void elements used right before a block', () => {
10971121
expect(humanizeDom(parser.parse('<img>@defer {hello}', 'TestComp'))).toEqual([
10981122
[html.Element, 'img', 0],

packages/core/test/acceptance/control_flow_switch_spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,4 +322,36 @@ describe('control flow - switch', () => {
322322
fixture.detectChanges();
323323
expect(fixture.nativeElement.textContent).toBe(' default or case 1 ');
324324
});
325+
326+
it('should support an empty case block', () => {
327+
@Component({
328+
template: `
329+
@switch (case) {
330+
@case (0) {}
331+
@case (1) {
332+
case 1
333+
}
334+
@default {
335+
default
336+
}
337+
}
338+
`,
339+
})
340+
class TestComponent {
341+
case = 0;
342+
}
343+
344+
const fixture = TestBed.createComponent(TestComponent);
345+
fixture.detectChanges();
346+
347+
expect(fixture.nativeElement.textContent).toBe('');
348+
349+
fixture.componentInstance.case = 1;
350+
fixture.detectChanges();
351+
expect(fixture.nativeElement.textContent).toBe(' case 1 ');
352+
353+
fixture.componentInstance.case = 5;
354+
fixture.detectChanges();
355+
expect(fixture.nativeElement.textContent).toBe(' default ');
356+
});
325357
});

0 commit comments

Comments
 (0)