Rocket

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 7926ffd6f0a107e54ae57b40a59527a9bdbfd98f
parent 8e779610c499b645edcd0448c062b2654dce29a3
Author: Sergio Benitez <sb@sergio.bz>
Date:   Sun, 16 Sep 2018 00:44:47 -0700

Tidy 'routes!' and 'catchers!' proc-macros.

Diffstat:
Mcore/codegen/src/lib.rs | 1-
Mcore/codegen_next/Cargo.toml | 1-
Acore/codegen_next/src/bang/mod.rs | 48++++++++++++++++++++++++++++++++++++++++++++++++
Mcore/codegen_next/src/lib.rs | 24+++++++++---------------
Dcore/codegen_next/src/prefixing_vec.rs | 44--------------------------------------------
Mcore/codegen_next/src/syn_ext.rs | 1-
Dcore/codegen_next/tests/compile-fail/catchers.rs | 8--------
Dcore/codegen_next/tests/route.rs | 11-----------
Acore/codegen_next/tests/ui-fail/catchers.rs | 10++++++++++
Acore/codegen_next/tests/ui-fail/catchers.stderr | 20++++++++++++++++++++
Mcore/codegen_next/tests/ui-fail/routes.rs | 8+++++---
Mcore/codegen_next/tests/ui-fail/routes.stderr | 18+++++++++++++++---
Mcore/lib/src/lib.rs | 10----------
13 files changed, 107 insertions(+), 97 deletions(-)

diff --git a/core/codegen/src/lib.rs b/core/codegen/src/lib.rs @@ -410,7 +410,6 @@ const DEBUG_ENV_VAR: &str = "ROCKET_CODEGEN_DEBUG"; const PARAM_PREFIX: &str = "rocket_param_"; const ROUTE_STRUCT_PREFIX: &str = "static_rocket_route_info_for_"; -const CATCH_STRUCT_PREFIX: &str = "static_rocket_catch_info_for_"; const ROUTE_FN_PREFIX: &str = "rocket_route_fn_"; const URI_INFO_MACRO_PREFIX: &str = "rocket_uri_for_"; diff --git a/core/codegen_next/Cargo.toml b/core/codegen_next/Cargo.toml @@ -26,5 +26,4 @@ rev = "87ad56ba" [dev-dependencies] rocket = { version = "0.4.0-dev", path = "../lib" } -rocket_codegen = { version = "0.4.0-dev", path = "../codegen" } compiletest_rs = "0.3.14" diff --git a/core/codegen_next/src/bang/mod.rs b/core/codegen_next/src/bang/mod.rs @@ -0,0 +1,48 @@ +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; + +use derive_utils::{syn, Spanned, Result}; +use self::syn::{Path, punctuated::Punctuated, parse::Parser, token::Comma}; +use syn_ext::{IdentExt, syn_to_diag}; + +fn _prefixed_vec(prefix: &str, input: TokenStream, ty: &TokenStream2) -> Result<TokenStream2> { + // Parse a comma-separated list of paths. + let mut paths = <Punctuated<Path, Comma>>::parse_terminated + .parse(input) + .map_err(syn_to_diag)?; + + // Prefix the last segment in each path with `prefix`. + for path in paths.iter_mut() { + let mut last_seg = path.segments.last_mut().expect("last path segment"); + last_seg.value_mut().ident = last_seg.value().ident.prepend(prefix); + } + + // Return a `vec!` of the prefixed, mapped paths. + let prefixed_mapped_paths = paths.iter() + .map(|path| quote_spanned!(path.span().into() => #ty::from(&#path))); + + Ok(quote!(vec![#(#prefixed_mapped_paths),*])) +} + +fn prefixed_vec(prefix: &str, input: TokenStream, ty: TokenStream2) -> TokenStream { + let vec = _prefixed_vec(prefix, input, &ty) + .map_err(|diag| diag.emit()) + .unwrap_or_else(|_| quote!(vec![])); + + quote!({ + let __vector: Vec<#ty> = #vec; + __vector + }).into() +} + +pub static ROUTE_STRUCT_PREFIX: &str = "static_rocket_route_info_for_"; + +pub fn routes_macro(input: TokenStream) -> TokenStream { + prefixed_vec(ROUTE_STRUCT_PREFIX, input, quote!(::rocket::Route)) +} + +pub static CATCH_STRUCT_PREFIX: &str = "static_rocket_catch_info_for_"; + +pub fn catchers_macro(input: TokenStream) -> TokenStream { + prefixed_vec(CATCH_STRUCT_PREFIX, input, quote!(::rocket::Catcher)) +} diff --git a/core/codegen_next/src/lib.rs b/core/codegen_next/src/lib.rs @@ -9,9 +9,9 @@ extern crate rocket_http; mod derive; mod attribute; +mod bang; mod http_codegen; mod syn_ext; -mod prefixing_vec; crate use derive_utils::proc_macro2; @@ -32,23 +32,17 @@ pub fn derive_responder(input: TokenStream) -> TokenStream { derive::responder::derive_responder(input) } -const ROUTE_STRUCT_PREFIX: &'static str = "static_rocket_route_info_for_"; -#[proc_macro] -pub fn rocket_routes_internal(input: TokenStream) -> TokenStream { - prefixing_vec::prefixing_vec_macro(ROUTE_STRUCT_PREFIX, |path| { - quote!(::rocket::Route::from(&#path)) - }, input) +#[proc_macro_attribute] +pub fn catch(args: TokenStream, input: TokenStream) -> TokenStream { + attribute::catch::catch_attribute(args, input) } -const CATCH_STRUCT_PREFIX: &'static str = "static_rocket_catch_info_for_"; #[proc_macro] -pub fn rocket_catchers_internal(input: TokenStream) -> TokenStream { - prefixing_vec::prefixing_vec_macro(CATCH_STRUCT_PREFIX, |path| { - quote!(::rocket::Catcher::from(&#path)) - }, input) +pub fn routes(input: TokenStream) -> TokenStream { + bang::routes_macro(input) } -#[proc_macro_attribute] -pub fn catch(args: TokenStream, input: TokenStream) -> TokenStream { - attribute::catch::catch_attribute(args, input) +#[proc_macro] +pub fn catchers(input: TokenStream) -> TokenStream { + bang::catchers_macro(input) } diff --git a/core/codegen_next/src/prefixing_vec.rs b/core/codegen_next/src/prefixing_vec.rs @@ -1,44 +0,0 @@ -use proc_macro::TokenStream; -use proc_macro2::TokenStream as TokenStream2; - -use syn::{Ident, Path}; - -use derive_utils::parser::{Parser, Seperator, Result as PResult}; - -#[inline] -fn prefix_path(prefix: &str, path: &mut Path) { - let mut last_seg = path.segments.last_mut().expect("last path segment"); - let last_value = last_seg.value_mut(); - last_value.ident = Ident::new(&format!("{}{}", prefix, last_value.ident), last_value.ident.span()); -} - -pub fn prefixing_vec_macro_internal<F>(prefix: &str, to_expr: F, args: TokenStream) -> PResult<TokenStream> - where F: FnMut(Path) -> TokenStream2 -{ - let mut parser = Parser::new(args); - let mut paths = parser.parse_sep(Seperator::Comma, |p| { - p.parse::<Path>() - })?; - parser.eof().map_err(|_| { - parser.current_span() - .error("expected `,` or `::` or end of macro invocation") - })?; - - for ref mut p in &mut paths { - prefix_path(prefix, p); - } - let path_exprs: Vec<_> = paths.into_iter().map(to_expr).collect(); - - let tokens = quote! { vec![#(#path_exprs),*] }; - Ok(tokens.into()) -} - -pub fn prefixing_vec_macro<F>(prefix: &str, to_expr: F, args: TokenStream) -> TokenStream - where F: FnMut(Path) -> TokenStream2 -{ - prefixing_vec_macro_internal(prefix, to_expr, args) - .unwrap_or_else(|diag| { - diag.emit(); - (quote! { vec![] }).into() - }) -} diff --git a/core/codegen_next/src/syn_ext.rs b/core/codegen_next/src/syn_ext.rs @@ -29,4 +29,3 @@ impl ReturnTypeExt for syn::ReturnType { } } } - diff --git a/core/codegen_next/tests/compile-fail/catchers.rs b/core/codegen_next/tests/compile-fail/catchers.rs @@ -1,8 +0,0 @@ -#![feature(plugin, decl_macro, proc_macro_non_items)] - -#[macro_use] extern crate rocket; - -fn main() { - let _ = catchers![a b]; //~ ERROR expected -} - diff --git a/core/codegen_next/tests/route.rs b/core/codegen_next/tests/route.rs @@ -1,11 +0,0 @@ -#![feature(plugin, decl_macro, proc_macro_non_items)] -#![plugin(rocket_codegen)] - -#[macro_use] extern crate rocket; - -#[get("/")] -fn get() {} - -fn main() { - rocket::ignite().mount("/", routes![get]); -} diff --git a/core/codegen_next/tests/ui-fail/catchers.rs b/core/codegen_next/tests/ui-fail/catchers.rs @@ -0,0 +1,10 @@ +#![feature(proc_macro_non_items)] + +#[macro_use] extern crate rocket; + +fn main() { + let _ = catchers![a b]; //~ ERROR expected + let _ = catchers![]; + let _ = catchers![a::, ]; //~ ERROR expected identifier + let _ = catchers![a::]; //~ ERROR expected identifier +} diff --git a/core/codegen_next/tests/ui-fail/catchers.stderr b/core/codegen_next/tests/ui-fail/catchers.stderr @@ -0,0 +1,20 @@ +error: expected `,` + --> $DIR/catchers.rs:6:25 + | +6 | let _ = catchers![a b]; //~ ERROR expected + | ^ + +error: expected identifier + --> $DIR/catchers.rs:8:26 + | +8 | let _ = catchers![a::, ]; //~ ERROR expected identifier + | ^ + +error: unexpected end of input, expected identifier + --> $DIR/catchers.rs:9:13 + | +9 | let _ = catchers![a::]; //~ ERROR expected identifier + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/core/codegen_next/tests/ui-fail/routes.rs b/core/codegen_next/tests/ui-fail/routes.rs @@ -1,8 +1,10 @@ -#![feature(plugin, decl_macro, proc_macro_non_items)] +#![feature(proc_macro_non_items)] #[macro_use] extern crate rocket; fn main() { - let _ = routes![a b]; - //~^ ERROR expected + let _ = routes![a b]; //~ ERROR expected `,` + let _ = routes![]; + let _ = routes![a::, ]; //~ ERROR expected identifier + let _ = routes![a::]; //~ ERROR expected identifier } diff --git a/core/codegen_next/tests/ui-fail/routes.stderr b/core/codegen_next/tests/ui-fail/routes.stderr @@ -1,8 +1,20 @@ -error: expected `,` or `::` or end of macro invocation +error: expected `,` --> $DIR/routes.rs:6:23 | -6 | let _ = routes![a b]; +6 | let _ = routes![a b]; //~ ERROR expected `,` | ^ -error: aborting due to previous error +error: expected identifier + --> $DIR/routes.rs:8:24 + | +8 | let _ = routes![a::, ]; //~ ERROR expected identifier + | ^ + +error: unexpected end of input, expected identifier + --> $DIR/routes.rs:9:13 + | +9 | let _ = routes![a::]; //~ ERROR expected identifier + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/core/lib/src/lib.rs b/core/lib/src/lib.rs @@ -102,16 +102,6 @@ #[allow(unused_imports)] #[macro_use] extern crate rocket_codegen_next; #[doc(hidden)] pub use rocket_codegen_next::*; -#[macro_export] -macro_rules! routes { - ($($input:tt)*) => { $crate::rocket_routes_internal![$($input)*] }; -} - -#[macro_export] -macro_rules! catchers { - ($($input:tt)*) => { $crate::rocket_catchers_internal![$($input)*] }; -} - extern crate rocket_http; #[macro_use] extern crate log; #[macro_use] extern crate pear;