Skip to content

Commit

Permalink
Add elifdef+else to ifdef block
Browse files Browse the repository at this point in the history
  • Loading branch information
Kijewski committed Jul 11, 2024
1 parent 1b14769 commit efdb597
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 18 deletions.
21 changes: 15 additions & 6 deletions rinja_derive/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,12 +725,21 @@ impl<'a> Generator<'a> {
ifdef: &'a WithSpan<'_, IfdefBlock<'_>>,
level: AstLevel,
) -> Result<usize, CompileError> {
self.handle_ws(ifdef.ws1);
let size_hint = match self.input.test_ifdef_cond(ctx, &ifdef.cond)? {
true => self.handle(ctx, &ifdef.nodes, buf, level)?,
false => 0,
};
self.prepare_ws(ifdef.ws2);
let mut size_hint = 0;
let mut found = false;
for branch in &ifdef.branches {
self.handle_ws(branch.ws);
if !found {
found = match &branch.cond {
Some(cond) => self.input.test_ifdef_cond(ctx, cond)?,
None => true,
};
if found {
size_hint = self.handle(ctx, &branch.nodes, buf, level)?
}
}
}
self.handle_ws(ifdef.last_ws);
Ok(size_hint)
}

Expand Down
4 changes: 3 additions & 1 deletion rinja_derive/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,9 @@ impl TemplateInput<'_> {
}
}
Node::Ifdef(i) => {
nested.push(&i.nodes);
for branch in &i.branches {
nested.push(&branch.nodes);
}
}
Node::Lit(_)
| Node::Comment(_)
Expand Down
84 changes: 73 additions & 11 deletions rinja_parser/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,10 +1046,15 @@ impl<'a> Comment<'a> {

#[derive(Debug, PartialEq)]
pub struct IfdefBlock<'a> {
pub ws1: Ws,
pub cond: WithSpan<'a, IfdefTest<'a>>,
pub branches: Vec<WithSpan<'a, IfdefBranch<'a>>>,
pub last_ws: Ws,
}

#[derive(Debug, PartialEq)]
pub struct IfdefBranch<'a> {
pub ws: Ws,
pub cond: Option<WithSpan<'a, IfdefTest<'a>>>,
pub nodes: Vec<Node<'a>>,
pub ws2: Ws,
}

#[derive(Debug, PartialEq)]
Expand All @@ -1062,28 +1067,85 @@ pub enum IfdefTest<'a> {

impl<'a> IfdefBlock<'a> {
fn parse(start: &'a str, s: &State<'_>) -> ParseResult<'a, WithSpan<'a, Self>> {
let (i, (pws1, _, (cond, nws1, _, nodes, _, pws2, _, nws2))) = tuple((
let end = map(
tuple((
opt(Whitespace::parse),
ws(keyword("endifdef")),
opt(Whitespace::parse),
)),
|(pws, _, nws)| Ws(pws, nws),
);

let (i, (fst, (mut branches, otherwise, last_ws))) = s.nest(
start,
pair(
|i| IfdefBranch::parse(i, s, "ifdef"),
cut(tuple((
many0(|i| IfdefBranch::parse(i, s, "elifdef")),
opt(|i| IfdefBranch::parse_else(i, s)),
end,
))),
),
)?;

branches.reserve_exact(1 + otherwise.is_some() as usize);
branches.insert(0, fst);
if let Some(otherwise) = otherwise {
branches.push(otherwise);
}

Ok((i, WithSpan::new(Self { branches, last_ws }, start)))
}
}

impl<'a> IfdefBranch<'a> {
fn parse(
start: &'a str,
s: &State<'_>,
kw: &'static str,
) -> ParseResult<'a, WithSpan<'a, Self>> {
let (i, (pws, _, (cond, nws, _, nodes, _))) = tuple((
opt(Whitespace::parse),
ws(keyword("ifdef")),
ws(keyword(kw)),
cut(tuple((
ws(|i| IfdefTest::parse(i, s)),
opt(Whitespace::parse),
|i| s.tag_block_end(i),
|i| Node::many(i, s),
|i| s.tag_block_start(i),
))),
))(start)?;
Ok((
i,
WithSpan::new(
IfdefBranch {
ws: Ws(pws, nws),
cond: Some(cond),
nodes,
},
start,
),
))
}

fn parse_else(start: &'a str, s: &State<'_>) -> ParseResult<'a, WithSpan<'a, Self>> {
let (i, (pws, _, (nws, _, nodes, _))) = tuple((
opt(Whitespace::parse),
ws(keyword("else")),
cut(tuple((
opt(Whitespace::parse),
ws(keyword("endifdef")),
opt(Whitespace::parse),
|i| s.tag_block_end(i),
|i| Node::many(i, s),
|i| s.tag_block_start(i),
))),
))(start)?;
Ok((
i,
WithSpan::new(
Self {
ws1: Ws(pws1, nws1),
cond,
IfdefBranch {
ws: Ws(pws, nws),
cond: None,
nodes,
ws2: Ws(pws2, nws2),
},
start,
),
Expand Down
76 changes: 76 additions & 0 deletions testing/tests/ifdef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,79 @@ fn test_b() {

assert_eq!(B { b: 2 }.to_string(), "b=2d=!");
}

#[test]
fn test_else_abcd() {
#[derive(Template)]
#[template(
source = "
{%- ifdef a -%} a={{a}}
{%- elifdef b -%} b={{b}}
{%- elifdef c -%} c={{c}}
{%- else -%} ?
{%- endifdef -%}
",
ext = "txt"
)]
#[allow(dead_code)]
struct Abcd {
a: u32,
b: u32,
c: u32,
d: u32,
}

assert_eq!(
Abcd {
a: 1,
b: 2,
c: 3,
d: 4,
}
.to_string(),
"a=1"
);
}

#[test]
fn test_else_cd() {
#[derive(Template)]
#[template(
source = "
{%- ifdef a -%} a={{a}}
{%- elifdef b -%} b={{b}}
{%- elifdef c -%} c={{c}}
{%- else -%} ?
{%- endifdef -%}
",
ext = "txt"
)]
#[allow(dead_code)]
struct Cd {
c: u32,
d: u32,
}

assert_eq!(Cd { c: 3, d: 4 }.to_string(), "c=3");
}

#[test]
fn test_else_d() {
#[derive(Template)]
#[template(
source = "
{%- ifdef a -%} a={{a}}
{%- elifdef b -%} b={{b}}
{%- elifdef c -%} c={{c}}
{%- else -%} ?
{%- endifdef -%}
",
ext = "txt"
)]
#[allow(dead_code)]
struct D {
d: u32,
}

assert_eq!(D { d: 4 }.to_string(), "?");
}

0 comments on commit efdb597

Please sign in to comment.