Refactor toggleable attributes

This commit is contained in:
Chris Wong 2015-02-09 15:05:50 +13:00
parent 7e6528550d
commit fa9404872e
2 changed files with 28 additions and 19 deletions
maud_macros/src

View file

@ -1,4 +1,4 @@
use syntax::ast::{Expr, Lit, Stmt, TokenTree, TtDelimited, TtToken};
use syntax::ast::{Expr, ExprParen, Lit, Stmt, TokenTree, TtDelimited, TtToken};
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::parse;
@ -207,7 +207,14 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
// Toggle the attribute based on a boolean expression
self.shift(1);
let cond = self.splice(tt.get_span());
self.render.attribute_empty_if(name.as_str(), cond);
// Silence "unnecessary parentheses" warnings
let cond = strip_outer_parens(cond);
let body = {
let mut r = self.render.fork();
r.attribute_empty(name.as_str());
r.into_stmts()
};
self.render.emit_if(cond, body, None);
} else {
// Write the attribute unconditionally
self.render.attribute_empty(name.as_str());
@ -249,3 +256,11 @@ fn lit_to_string(cx: &ExtCtxt, lit: Lit, minus: bool) -> Option<String> {
};
Some(result)
}
/// If the expression is wrapped in parentheses, strip them off.
fn strip_outer_parens(expr: P<Expr>) -> P<Expr> {
expr.and_then(|expr| match expr {
Expr { node: ExprParen(inner), .. } => inner,
expr => P(expr),
})
}

View file

@ -1,5 +1,5 @@
use std::borrow::IntoCow;
use syntax::ast::{Expr, ExprParen, Ident, Stmt};
use syntax::ast::{Expr, Ident, Stmt};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
@ -112,22 +112,6 @@ impl<'cx, 's> Renderer<'cx, 's> {
self.write(name);
}
pub fn attribute_empty_if(&mut self, name: &str, cond: P<Expr>) {
// Silence "unnecessary parentheses" warnings
let cond = match cond.node {
ExprParen(ref inner) => inner.clone(),
_ => cond.clone(),
};
let body = {
let mut r = self.fork();
r.write(" ");
r.write(name);
r.into_stmts()
};
let stmt = quote_stmt!(self.cx, if $cond { $body });
self.stmts.push(stmt);
}
pub fn attribute_end(&mut self) {
self.write("\"");
}
@ -141,4 +125,14 @@ impl<'cx, 's> Renderer<'cx, 's> {
self.write(name);
self.write(">");
}
pub fn emit_if(&mut self, cond: P<Expr>, if_body: Vec<P<Stmt>>,
else_body: Option<Vec<P<Stmt>>>) {
let stmt = match else_body {
None => quote_stmt!(self.cx, if $cond { $if_body }),
Some(else_body) =>
quote_stmt!(self.cx, if $cond { $if_body } else { $else_body }),
};
self.stmts.push(stmt);
}
}