From 6911e1d86caa9fa87457f99b76eb456cb6fd394c Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 5 Sep 2017 19:54:15 +0200 Subject: Move tightly coupled code from derive to shared crate --- askama_derive/src/lib.rs | 112 +--------------------------------------------- askama_shared/src/lib.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 113 deletions(-) diff --git a/askama_derive/src/lib.rs b/askama_derive/src/lib.rs index 0333c06..012ad65 100644 --- a/askama_derive/src/lib.rs +++ b/askama_derive/src/lib.rs @@ -4,9 +4,6 @@ extern crate syn; use proc_macro::TokenStream; -use std::borrow::Cow; -use std::path::PathBuf; - #[proc_macro_derive(Template, attributes(template))] pub fn derive_template(input: TokenStream) -> TokenStream { let ast = syn::parse_derive_input(&input.to_string()).unwrap(); @@ -14,112 +11,5 @@ pub fn derive_template(input: TokenStream) -> TokenStream { syn::Body::Struct(ref data) => data, _ => panic!("#[derive(Template)] can only be used with structs"), }; - build_template(&ast).parse().unwrap() -} - -/// Takes a `syn::DeriveInput` and generates source code for it -/// -/// Reads the metadata from the `template()` attribute to get the template -/// metadata, then fetches the source from the filesystem. The source is -/// parsed, and the parse tree is fed to the code generator. Will print -/// the parse tree and/or generated source according to the `print` key's -/// value as passed to the `template()` attribute. -fn build_template(ast: &syn::DeriveInput) -> String { - let meta = get_template_meta(ast); - let (path, src) = match meta.source { - Source::Source(s) => (PathBuf::new(), Cow::Borrowed(s)), - Source::Path(s) => { - let path = shared::path::find_template_from_path(&s, None); - let src = shared::path::get_template_source(&path); - (path, Cow::Owned(src)) - }, - }; - let nodes = shared::parse(src.as_ref()); - if meta.print == Print::Ast || meta.print == Print::All { - println!("{:?}", nodes); - } - let code = shared::generate(ast, &path, nodes); - if meta.print == Print::Code || meta.print == Print::All { - println!("{}", code); - } - code -} - -// Returns a `TemplateMeta` based on the `template()` attribute data found -// in the parsed struct or enum. Will panic if it does not find the required -// template path, or if the `print` key has an unexpected value. -fn get_template_meta<'a>(ast: &'a syn::DeriveInput) -> TemplateMeta<'a> { - let attr = ast.attrs.iter().find(|a| a.name() == "template"); - if attr.is_none() { - let msg = format!("'template' attribute not found on struct '{}'", - ast.ident.as_ref()); - panic!(msg); - } - - let attr = attr.unwrap(); - let mut source = None; - let mut print = Print::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 { - source = Some(Source::Path(s.as_ref())); - } else { - panic!("template path must be string literal"); - }, - "source" => if let syn::Lit::Str(ref s, _) = *val { - source = Some(Source::Source(s.as_ref())); - } else { - panic!("template source must be string literal"); - }, - "print" => if let syn::Lit::Str(ref s, _) = *val { - print = s.into(); - } else { - panic!("print value must be string literal"); - }, - _ => { panic!("unsupported annotation key found") } - } - } - } - } - } - - match source { - Some(s) => TemplateMeta { source: s, print }, - None => panic!("template path or source not found in struct attributes"), - } -} - -// Holds metadata for the template, based on the `template()` attribute. -struct TemplateMeta<'a> { - source: Source<'a>, - print: Print, -} - -enum Source<'a> { - Path(&'a str), - Source(&'a str), -} - -#[derive(PartialEq)] -enum Print { - All, - Ast, - Code, - None, -} - -impl<'a> From<&'a String> for Print { - fn from(s: &'a String) -> Print { - use Print::*; - match s.as_ref() { - "all" => All, - "ast" => Ast, - "code" => Code, - "none" => None, - v => panic!("invalid value for print option: {}", v), - } - } + shared::build_template(&ast).parse().unwrap() } diff --git a/askama_shared/src/lib.rs b/askama_shared/src/lib.rs index b5bc9af..60a263f 100644 --- a/askama_shared/src/lib.rs +++ b/askama_shared/src/lib.rs @@ -14,13 +14,90 @@ pub use escaping::MarkupDisplay; pub use errors::{Error, Result}; pub mod filters; pub mod path; -pub use parser::parse; -pub use generator::generate; mod escaping; mod generator; mod parser; +use std::borrow::Cow; +use std::path::PathBuf; + + +/// Takes a `syn::DeriveInput` and generates source code for it +/// +/// Reads the metadata from the `template()` attribute to get the template +/// metadata, then fetches the source from the filesystem. The source is +/// parsed, and the parse tree is fed to the code generator. Will print +/// the parse tree and/or generated source according to the `print` key's +/// value as passed to the `template()` attribute. +pub fn build_template(ast: &syn::DeriveInput) -> String { + let meta = get_template_meta(ast); + let (path, src) = match meta.source { + Source::Source(s) => (PathBuf::new(), Cow::Borrowed(s)), + Source::Path(s) => { + let path = path::find_template_from_path(&s, None); + let src = path::get_template_source(&path); + (path, Cow::Owned(src)) + }, + }; + let nodes = parser::parse(src.as_ref()); + if meta.print == Print::Ast || meta.print == Print::All { + println!("{:?}", nodes); + } + let code = generator::generate(ast, &path, nodes); + if meta.print == Print::Code || meta.print == Print::All { + println!("{}", code); + } + code +} + +// Returns a `TemplateMeta` based on the `template()` attribute data found +// in the parsed struct or enum. Will panic if it does not find the required +// template path, or if the `print` key has an unexpected value. +fn get_template_meta<'a>(ast: &'a syn::DeriveInput) -> TemplateMeta<'a> { + let attr = ast.attrs.iter().find(|a| a.name() == "template"); + if attr.is_none() { + let msg = format!("'template' attribute not found on struct '{}'", + ast.ident.as_ref()); + panic!(msg); + } + + let attr = attr.unwrap(); + let mut source = None; + let mut print = Print::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 { + source = Some(Source::Path(s.as_ref())); + } else { + panic!("template path must be string literal"); + }, + "source" => if let syn::Lit::Str(ref s, _) = *val { + source = Some(Source::Source(s.as_ref())); + } else { + panic!("template source must be string literal"); + }, + "print" => if let syn::Lit::Str(ref s, _) = *val { + print = s.into(); + } else { + panic!("print value must be string literal"); + }, + _ => { panic!("unsupported annotation key found") } + } + } + } + } + } + + match source { + Some(s) => TemplateMeta { source: s, print }, + None => panic!("template path or source not found in struct attributes"), + } +} + mod errors { error_chain! { foreign_links { @@ -29,3 +106,35 @@ mod errors { } } } + +// Holds metadata for the template, based on the `template()` attribute. +struct TemplateMeta<'a> { + source: Source<'a>, + print: Print, +} + +enum Source<'a> { + Path(&'a str), + Source(&'a str), +} + +#[derive(PartialEq)] +enum Print { + All, + Ast, + Code, + None, +} + +impl<'a> From<&'a String> for Print { + fn from(s: &'a String) -> Print { + use Print::*; + match s.as_ref() { + "all" => All, + "ast" => Ast, + "code" => Code, + "none" => None, + v => panic!("invalid value for print option: {}", v), + } + } +} -- cgit