From 293159904f6bcdde6489552f64ec75f982a8bfdb Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Sun, 3 Apr 2016 04:25:37 -0700 Subject: [PATCH] Fixed codegen to work with new API. --- examples/optional_redirect/src/main.rs | 8 +++++++- lib/src/router/route.rs | 10 +++++++++- macros/src/route_decorator.rs | 17 ++++++++--------- macros/src/routes_macro.rs | 22 ++++++++++++++++------ macros/src/utils.rs | 15 +++++++++++++++ 5 files changed, 55 insertions(+), 17 deletions(-) diff --git a/examples/optional_redirect/src/main.rs b/examples/optional_redirect/src/main.rs index 1636a77a..dd219a44 100644 --- a/examples/optional_redirect/src/main.rs +++ b/examples/optional_redirect/src/main.rs @@ -5,6 +5,11 @@ extern crate rocket; use rocket::Rocket; use rocket::response::Redirect; +#[route(GET, path = "/")] +fn root() -> Redirect { + Redirect::to("/users/login") +} + #[route(GET, path = "/users/")] fn user(name: &str) -> Result<&'static str, Redirect> { match name { @@ -19,5 +24,6 @@ fn login() -> &'static str { } fn main() { - Rocket::new("localhost", 8000).mount_and_launch("/", routes![user, login]); + let rocket = Rocket::new("localhost", 8000); + rocket.mount_and_launch("/", routes![root, user, login]); } diff --git a/lib/src/router/route.rs b/lib/src/router/route.rs index 428d45d9..ee4a3bf2 100644 --- a/lib/src/router/route.rs +++ b/lib/src/router/route.rs @@ -1,9 +1,11 @@ use term_painter::ToStyle; use term_painter::Color::*; -use std::fmt; use method::Method; use super::{Collider, URI, URIBuf}; // :D use handler::Handler; +use codegen::StaticRouteInfo; +use std::fmt; +use std::convert::From; pub struct Route { pub method: Method, @@ -61,6 +63,12 @@ impl fmt::Display for Route { } } +impl<'a> From<&'a StaticRouteInfo> for Route { + fn from(info: &'a StaticRouteInfo) -> Route { + Route::new(info.method, info.path, info.handler) + } +} + impl Collider for Route { fn collides_with(&self, b: &Route) -> bool { if self.path.segment_count() != b.path.segment_count() diff --git a/macros/src/route_decorator.rs b/macros/src/route_decorator.rs index c975a903..0a81bd45 100644 --- a/macros/src/route_decorator.rs +++ b/macros/src/route_decorator.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use std::collections::HashSet; use syntax::ext::quote::rt::ToTokens; -use syntax::codemap::{Span, BytePos, DUMMY_SP, Spanned}; +use syntax::codemap::{Span, BytePos, /* DUMMY_SP, */ Spanned}; use syntax::ast::{Ident, TokenTree, PatKind, Stmt}; use syntax::ast::{Item, Expr, ItemKind, MetaItem, MetaItemKind, FnDecl, Ty}; use syntax::ext::base::{Annotatable, ExtCtxt}; @@ -215,6 +215,12 @@ impl SimpleArg { } } +impl ToTokens for SimpleArg { + fn to_tokens(&self, cx: &ExtCtxt) -> Vec { + str_to_ident(self.as_str()).to_tokens(cx) + } +} + fn get_fn_params<'a>(ecx: &ExtCtxt, dec_span: Span, path: &'a KVSpanned, fn_decl: &Spanned<&FnDecl>, mut external: HashSet<&'a str>) -> Vec { @@ -330,14 +336,7 @@ pub fn route_decorator(ecx: &mut ExtCtxt, sp: Span, meta_item: &MetaItem, // Create a comma seperated list (token tree) of the function parameters // We pass this in to the user's function that we're wrapping. - let mut fn_param_idents: Vec = vec![]; - for i in 0..fn_params.len() { - let tokens = str_to_ident(fn_params[i].as_str()).to_tokens(ecx); - fn_param_idents.extend(tokens); - if i < fn_params.len() - 1 { - fn_param_idents.push(TokenTree::Token(DUMMY_SP, token::Comma)); - } - } + let fn_param_idents = token_separate(ecx, &fn_params, token::Comma); // Generate the statements that will attempt to parse forms during run-time. // let form_span = route_params.form.map_or(DUMMY_SP, |f| f.span.clone()); diff --git a/macros/src/routes_macro.rs b/macros/src/routes_macro.rs index c16e0510..add5a5ad 100644 --- a/macros/src/routes_macro.rs +++ b/macros/src/routes_macro.rs @@ -1,13 +1,15 @@ use super::{STRUCT_PREFIX}; -use utils::prepend_ident; - +use utils::{prepend_ident, token_separate}; use syntax::codemap::Span; -use syntax::ast::{Path, TokenTree}; +use syntax::ast::{Path, TokenTree, Expr}; use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; use syntax::ext::build::AstBuilder; use syntax::parse::parser::{Parser, PathParsingMode}; use syntax::parse::PResult; use syntax::parse::token::Token; +use syntax::ptr::P; + +const DEBUG: bool = false; fn get_paths<'a>(parser: &mut Parser<'a>) -> PResult<'a, Vec> { if parser.eat(&Token::Eof) { @@ -26,7 +28,7 @@ fn get_paths<'a>(parser: &mut Parser<'a>) -> PResult<'a, Vec> { Ok(results) } -pub fn routes_macro(ecx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) +pub fn routes_macro(ecx: &mut ExtCtxt, _sp: Span, args: &[TokenTree]) -> Box { let mut parser = ecx.new_parser_from_tts(args); let mut paths = get_paths(&mut parser).unwrap_or_else(|mut e| { @@ -42,7 +44,15 @@ pub fn routes_macro(ecx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) last_seg.identifier = new_ident; } + debug!("Found paths: {:?}", paths); // Build up the P for each path. - let path_exprs = paths.iter().map(|p| { quote_expr!(ecx, &$p) }).collect(); - MacEager::expr(ecx.expr_vec_slice(sp, path_exprs)) + let path_exprs: Vec> = paths.iter().map(|p| { + quote_expr!(ecx, rocket::Route::from(&$p)) + }).collect(); + + debug!("Path Exprs: {:?}", path_exprs); + // Now put them all in one vector and return the thing. + let path_list = token_separate(ecx, &path_exprs, Token::Comma); + let output = quote_expr!(ecx, vec![$path_list]).unwrap(); + MacEager::expr(P(output)) } diff --git a/macros/src/utils.rs b/macros/src/utils.rs index 73785f5f..3aac043a 100644 --- a/macros/src/utils.rs +++ b/macros/src/utils.rs @@ -1,4 +1,5 @@ use syntax::parse::{token}; +use syntax::parse::token::Token; use syntax::ast::{Ident, MetaItem, MetaItemKind, LitKind, TokenTree}; use syntax::ext::base::{ExtCtxt}; use syntax::codemap::{Span, Spanned, BytePos, DUMMY_SP}; @@ -138,6 +139,20 @@ pub fn get_key_values<'b>(ecx: &mut ExtCtxt, sp: Span, required: &[&str], kv_pairs } + +pub fn token_separate(ecx: &ExtCtxt, things: &Vec, + token: Token) -> Vec { + let mut output: Vec = vec![]; + for (i, thing) in things.iter().enumerate() { + output.extend(thing.to_tokens(ecx)); + if i < things.len() - 1 { + output.push(TokenTree::Token(DUMMY_SP, token.clone())); + } + } + + output +} + // pub fn find_value_for(key: &str, kv_params: &[P]) -> Option { // for param in kv_params { // if let MetaItemKind::NameValue(ref name, ref value) = param.node {