diff options
Diffstat (limited to '')
-rw-r--r-- | askama_shared/src/generator.rs | 89 | ||||
-rw-r--r-- | askama_shared/src/input.rs | 86 | ||||
-rw-r--r-- | askama_shared/src/lib.rs | 2 |
3 files changed, 70 insertions, 107 deletions
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs index a1b090d..e4eb9ec 100644 --- a/askama_shared/src/generator.rs +++ b/askama_shared/src/generator.rs @@ -81,9 +81,12 @@ fn trait_name_for_path(base: &Option<&Expr>, path: &Path) -> String { res } -fn get_parent_type(ast: &syn::DeriveInput) -> Option<&syn::Ty> { - match ast.body { - syn::Body::Struct(ref data) => data.fields().iter().filter_map(|f| { +fn get_parent_type<'a>(ast: &'a syn::DeriveInput) -> Option<&'a syn::Type> { + match ast.data { + syn::Data::Struct(syn::DataStruct { + fields: syn::Fields::Named(ref fields), + .. + }) => fields.named.iter().filter_map(|f| { f.ident.as_ref().and_then(|name| { if name.as_ref() == "_parent" { Some(&f.ty) @@ -180,11 +183,11 @@ impl<'a> Generator<'a> { } // Implement `Deref<Parent>` for an inheriting context struct. - fn deref_to_parent(&mut self, state: &'a State, parent_type: &syn::Ty) { + fn deref_to_parent(&mut self, state: &'a State, parent_type: &syn::Type) { self.write_header(state, "::std::ops::Deref", &[]); let mut tokens = Tokens::new(); parent_type.to_tokens(&mut tokens); - self.writeln(&format!("type Target = {};", tokens.as_str())); + self.writeln(&format!("type Target = {};", tokens)); self.writeln("fn deref(&self) -> &Self::Target {"); self.writeln("&self._parent"); self.writeln("}"); @@ -254,7 +257,7 @@ impl<'a> Generator<'a> { // Implement Rocket's `Responder`. fn impl_responder(&mut self, state: &'a State) { - self.write_header(state, "::askama::rocket::Responder<'r>", &["'r"]); + self.write_header(state, "::askama::rocket::Responder<'r>", &[quote!('r)]); self.writeln("fn respond_to(self, _: &::askama::rocket::Request) \ -> ::askama::rocket::Result<'r> {"); @@ -270,64 +273,22 @@ impl<'a> Generator<'a> { // Writes header for the `impl` for `TraitFromPathName` or `Template` // for the given context struct. - fn write_header(&mut self, state: &'a State, target: &str, extra_anno: &[&str]) { - let mut full_anno = Tokens::new(); - let mut orig_anno = Tokens::new(); - let need_anno = !state.input.ast.generics.lifetimes.is_empty() || - !state.input.ast.generics.ty_params.is_empty() || - !extra_anno.is_empty(); - if need_anno { - full_anno.append("<"); - orig_anno.append("<"); - } - - let (mut full_sep, mut orig_sep) = (false, false); - for lt in &state.input.ast.generics.lifetimes { - if full_sep { - full_anno.append(","); - } - if orig_sep { - orig_anno.append(","); - } - lt.to_tokens(&mut full_anno); - lt.to_tokens(&mut orig_anno); - full_sep = true; - orig_sep = true; - } - - for anno in extra_anno { - if full_sep { - full_anno.append(","); - } - full_anno.append(anno); - full_sep = true; - } - - for param in &state.input.ast.generics.ty_params { - if full_sep { - full_anno.append(","); - } - if orig_sep { - orig_anno.append(","); - } - let mut impl_param = param.clone(); - impl_param.default = None; - impl_param.to_tokens(&mut full_anno); - param.ident.to_tokens(&mut orig_anno); - full_sep = true; - orig_sep = true; - } - - if need_anno { - full_anno.append(">"); - orig_anno.append(">"); - } - - let mut where_clause = Tokens::new(); - state.input.ast.generics.where_clause.to_tokens(&mut where_clause); - self.writeln(&format!("impl{} {} for {}{}{} {{", - full_anno.as_str(), target, state.input.ast.ident.as_ref(), - orig_anno.as_str(), where_clause.as_str())); + fn write_header(&mut self, state: &'a State, target: &str, vars: &[Tokens]) { + let mut generics = state.input.ast.generics.clone(); + for v in vars.iter() { + generics.params.push_value(parse_quote!(#v)); + } + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let ident = state.input.ast.ident.as_ref(); + self.writeln( + format!( + "{} {} for {}{} {{", + quote!(impl#impl_generics), + target, + ident, + quote!(#ty_generics #where_clause), + ).as_ref(), + ); } /* Helper methods for handling node types */ diff --git a/askama_shared/src/input.rs b/askama_shared/src/input.rs index 25382cb..e3b64da 100644 --- a/askama_shared/src/input.rs +++ b/askama_shared/src/input.rs @@ -1,6 +1,5 @@ use path; -use std::borrow::Cow; use std::path::{Path, PathBuf}; use syn; @@ -8,26 +7,26 @@ use syn; pub struct TemplateInput<'a> { pub ast: &'a syn::DeriveInput, - pub meta: TemplateMeta<'a>, + pub meta: TemplateMeta, pub path: PathBuf, - pub source: Cow<'a, str>, + pub source: String, } impl<'a> TemplateInput<'a> { pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> { let meta = TemplateMeta::new(ast); let (path, source) = match meta.source { - Source::Source(s) => { + Source::Source(ref s) => { let path = match meta.ext { - Some(v) => PathBuf::from(format!("_.{}", v)), + Some(ref v) => PathBuf::from(format!("_.{}", v)), None => PathBuf::new(), }; - (path, Cow::Borrowed(s)) + (path, s.clone()) }, - Source::Path(s) => { - let path = path::find_template_from_path(s, None); + Source::Path(ref s) => { + let path = path::find_template_from_path(&s, None); let src = path::get_template_source(&path); - (path, Cow::Owned(src)) + (path, src) }, }; TemplateInput { ast, meta, path, source } @@ -35,16 +34,18 @@ impl<'a> TemplateInput<'a> { } // Holds metadata for the template, based on the `template()` attribute. -pub struct TemplateMeta<'a> { - source: Source<'a>, +pub struct TemplateMeta { + source: Source, pub print: Print, pub escaping: EscapeMode, - pub ext: Option<&'a str>, + pub ext: Option<String>, } -impl<'a> TemplateMeta<'a> { - fn new(ast: &'a syn::DeriveInput) -> TemplateMeta<'a> { - let attr = ast.attrs.iter().find(|a| a.name() == "template"); +impl TemplateMeta { + fn new(ast: &syn::DeriveInput) -> TemplateMeta { + let attr = ast.attrs + .iter() + .find(|a| a.interpret_meta().unwrap().name() == "template"); if attr.is_none() { let msg = format!("'template' attribute not found on struct '{}'", ast.ident.as_ref()); @@ -56,39 +57,39 @@ impl<'a> TemplateMeta<'a> { let mut print = Print::None; let mut escaping = None; let mut ext = None; - if let syn::MetaItem::List(_, ref inner) = attr.value { - for nm_item in inner { - if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item { - if let syn::MetaItem::NameValue(ref key, ref val) = *item { - match key.as_ref() { - "path" => if let syn::Lit::Str(ref s, _) = *val { + if let syn::Meta::List(ref inner) = attr.interpret_meta().unwrap() { + for nm_item in inner.nested.iter() { + if let syn::NestedMeta::Meta(ref item) = *nm_item { + if let syn::Meta::NameValue(ref pair) = *item { + match pair.ident.as_ref() { + "path" => if let syn::Lit::Str(ref s) = pair.lit { if source.is_some() { panic!("must specify 'source' or 'path', not both"); } - source = Some(Source::Path(s.as_ref())); + source = Some(Source::Path(s.value())); } else { panic!("template path must be string literal"); }, - "source" => if let syn::Lit::Str(ref s, _) = *val { + "source" => if let syn::Lit::Str(ref s) = pair.lit { if source.is_some() { panic!("must specify 'source' or 'path', not both"); } - source = Some(Source::Source(s.as_ref())); + source = Some(Source::Source(s.value())); } else { panic!("template source must be string literal"); }, - "print" => if let syn::Lit::Str(ref s, _) = *val { - print = (s.as_ref() as &str).into(); + "print" => if let syn::Lit::Str(ref s) = pair.lit { + print = s.value().into(); } else { panic!("print value must be string literal"); }, - "escape" => if let syn::Lit::Str(ref s, _) = *val { - escaping = Some((s.as_ref() as &str).into()); + "escape" => if let syn::Lit::Str(ref s) = pair.lit { + escaping = Some(s.value().into()); } else { panic!("escape value must be string literal"); }, - "ext" => if let syn::Lit::Str(ref s, _) = *val { - ext = Some((s.as_ref() as &str).into()); + "ext" => if let syn::Lit::Str(ref s) = pair.lit { + ext = Some(s.value()); } else { panic!("ext value must be string literal"); }, @@ -113,10 +114,9 @@ impl<'a> TemplateMeta<'a> { Some(m) => m, None => { let ext = match source { - Source::Path(p) => { - Path::new(p).extension().map(|s| s.to_str().unwrap()).unwrap_or("") - }, - Source::Source(_) => ext.unwrap(), // Already panicked if None + Source::Path(ref p) => + Path::new(p).extension().map(|s| s.to_str().unwrap()).unwrap_or(""), + Source::Source(_) => ext.as_ref().unwrap(), // Already panicked if None }; if HTML_EXTENSIONS.contains(&ext) { EscapeMode::Html @@ -129,9 +129,9 @@ impl<'a> TemplateMeta<'a> { } } -enum Source<'a> { - Path(&'a str), - Source(&'a str), +enum Source { + Path(String), + Source(String), } #[derive(PartialEq)] @@ -140,10 +140,10 @@ pub enum EscapeMode { None, } -impl<'a> From<&'a str> for EscapeMode { - fn from(s: &'a str) -> EscapeMode { +impl From<String> for EscapeMode { + fn from(s: String) -> EscapeMode { use self::EscapeMode::*; - match s { + match s.as_ref() { "html" => Html, "none" => None, v => panic!("invalid value for escape option: {}", v), @@ -159,10 +159,10 @@ pub enum Print { None, } -impl<'a> From<&'a str> for Print { - fn from(s: &'a str) -> Print { +impl From<String> for Print { + fn from(s: String) -> Print { use self::Print::*; - match s { + match s.as_ref() { "all" => All, "ast" => Ast, "code" => Code, diff --git a/askama_shared/src/lib.rs b/askama_shared/src/lib.rs index 0f46b91..ed2357d 100644 --- a/askama_shared/src/lib.rs +++ b/askama_shared/src/lib.rs @@ -2,7 +2,9 @@ extern crate error_chain; #[macro_use] extern crate nom; +#[macro_use] extern crate quote; +#[macro_use(parse_quote)] extern crate syn; #[cfg(feature = "serde-json")] |