Skip to content

Commit ee86510

Browse files
committed
feat: support break and continue in for loops
1 parent 3650fc8 commit ee86510

5 files changed

Lines changed: 52 additions & 27 deletions

File tree

packages/yew-macro/src/html_tree/html_for.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,9 @@ impl ToTokens for HtmlFor {
130130

131131
tokens.extend(quote!({
132132
let mut #acc = ::std::vec::Vec::<::yew::virtual_dom::VNode>::new();
133-
::std::iter::Iterator::for_each(
134-
::std::iter::IntoIterator::into_iter(#iter),
135-
|#pat| { #(#let_stmts)* #alloc_opt; #(#body);* }
136-
);
133+
for #pat in #iter {
134+
#(#let_stmts)* #alloc_opt; #(#body);*
135+
}
137136
#vlist_gen
138137
}))
139138
}

packages/yew-macro/src/html_tree/mod.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ pub enum HtmlType {
5252
If,
5353
For,
5454
Match,
55+
Break,
56+
Continue,
5557
Empty,
5658
}
5759

@@ -64,6 +66,8 @@ pub enum HtmlTree {
6466
For(Box<HtmlFor>),
6567
Match(Box<HtmlMatch>),
6668
Node(Box<HtmlNode>),
69+
Break(Token![break]),
70+
Continue(Token![continue]),
6771
Empty,
6872
}
6973

@@ -80,6 +84,8 @@ impl Parse for HtmlTree {
8084
HtmlType::If => Self::If(Box::new(input.parse()?)),
8185
HtmlType::For => Self::For(Box::new(input.parse()?)),
8286
HtmlType::Match => Self::Match(Box::new(input.parse()?)),
87+
HtmlType::Break => Self::Break(input.parse()?),
88+
HtmlType::Continue => Self::Continue(input.parse()?),
8389
})
8490
}
8591
}
@@ -113,6 +119,14 @@ impl HtmlTree {
113119
Some(HtmlType::For)
114120
} else if HtmlMatch::peek(cursor).is_some() {
115121
Some(HtmlType::Match)
122+
} else if cursor.ident().map(|(i, _)| i == "break").unwrap_or(false) {
123+
Some(HtmlType::Break)
124+
} else if cursor
125+
.ident()
126+
.map(|(i, _)| i == "continue")
127+
.unwrap_or(false)
128+
{
129+
Some(HtmlType::Continue)
116130
} else if input.peek(Token![<]) {
117131
let _lt: Token![<] = input.parse().ok()?;
118132

@@ -163,6 +177,8 @@ impl ToTokens for HtmlTree {
163177
Self::For(block) => block.to_tokens(tokens),
164178
Self::Match(block) => block.to_tokens(tokens),
165179
Self::Node(node) => node.to_tokens(tokens),
180+
Self::Break(token) => token.to_tokens(tokens),
181+
Self::Continue(token) => token.to_tokens(tokens),
166182
}
167183
}
168184
}
@@ -428,7 +444,12 @@ impl HtmlChildrenTree {
428444
HtmlNode::Expression(_) => None,
429445
};
430446
}
431-
HtmlTree::If(_) | HtmlTree::For(_) | HtmlTree::Match(_) | HtmlTree::Empty => {
447+
HtmlTree::If(_)
448+
| HtmlTree::For(_)
449+
| HtmlTree::Match(_)
450+
| HtmlTree::Break(_)
451+
| HtmlTree::Continue(_)
452+
| HtmlTree::Empty => {
432453
return Some(false);
433454
}
434455
}

packages/yew-macro/tests/html_macro/for-fail.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ fn main() {
1010
<span>{x}</span>
1111
}};
1212

13-
_ = ::yew::html!{for _ in 0 .. 10 {
14-
<span>{break}</span>
15-
}};
16-
1713
_ = ::yew::html!{for _ in 0 .. 10 {
1814
<div key="duplicate" />
1915
}};

packages/yew-macro/tests/html_macro/for-fail.stderr

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,42 +24,31 @@ error: unexpected end of input, expected curly braces
2424

2525
error: duplicate key for a node in a `for`-loop
2626
this will create elements with duplicate keys if the loop iterates more than once
27-
--> tests/html_macro/for-fail.rs:18:18
27+
--> tests/html_macro/for-fail.rs:14:18
2828
|
29-
18 | <div key="duplicate" />
29+
14 | <div key="duplicate" />
3030
| ^^^^^^^^^^^
3131

3232
error: duplicate key for a node in a `for`-loop
3333
this will create elements with duplicate keys if the loop iterates more than once
34-
--> tests/html_macro/for-fail.rs:22:19
34+
--> tests/html_macro/for-fail.rs:18:19
3535
|
36-
22 | <div key={smth::KEY} />
36+
18 | <div key={smth::KEY} />
3737
| ^^^^
3838

3939
error: unnecessary `<>...</>`. Children can be placed directly in the body
40-
--> tests/html_macro/for-fail.rs:27:9
40+
--> tests/html_macro/for-fail.rs:23:9
4141
|
42-
27 | <><span>{"a"}</span><span>{"b"}</span></>
42+
23 | <><span>{"a"}</span><span>{"b"}</span></>
4343
| ^^
4444

45-
error[E0267]: `break` inside of a closure
46-
--> tests/html_macro/for-fail.rs:14:16
47-
|
48-
13 | _ = ::yew::html!{for _ in 0 .. 10 {
49-
| _________-
50-
14 | | <span>{break}</span>
51-
| | ^^^^^ cannot `break` inside of a closure
52-
15 | | }};
53-
| |______- enclosing closure
54-
5545
error[E0308]: mismatched types
5646
--> tests/html_macro/for-fail.rs:9:26
5747
|
5848
9 | _ = ::yew::html!{for (x, y) in 0 .. 10 {
59-
| ^^^^^^
49+
| ^^^^^^ ------- this is an iterator with items of type `{integer}`
6050
| |
6151
| expected integer, found `(_, _)`
62-
| expected due to this
6352
|
6453
= note: expected type `{integer}`
6554
found tuple `(_, _)`

packages/yew-macro/tests/html_macro/for-pass.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,24 @@ fn main() {
118118
<hr/>
119119
}
120120
};
121+
122+
// break in for loop
123+
_ = ::yew::html!{
124+
for i in 0..10 {
125+
if i > 5 {
126+
break
127+
}
128+
<span>{i}</span>
129+
}
130+
};
131+
132+
// continue in for loop
133+
_ = ::yew::html!{
134+
for i in 0..10 {
135+
if i % 2 == 0 {
136+
continue
137+
}
138+
<span>{i}</span>
139+
}
140+
};
121141
}

0 commit comments

Comments
 (0)