mirror of
https://github.com/rwf2/Rocket.git
synced 2025-01-29 12:52:05 +00:00
Tidy 'routes!' and 'catchers!' proc-macros.
This commit is contained in:
parent
8e779610c4
commit
7926ffd6f0
@ -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_";
|
||||
|
||||
|
@ -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"
|
||||
|
48
core/codegen_next/src/bang/mod.rs
Normal file
48
core/codegen_next/src/bang/mod.rs
Normal file
@ -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))
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn catch(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
attribute::catch::catch_attribute(args, input)
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn routes(input: TokenStream) -> TokenStream {
|
||||
bang::routes_macro(input)
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn catchers(input: TokenStream) -> TokenStream {
|
||||
bang::catchers_macro(input)
|
||||
}
|
||||
|
@ -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()
|
||||
})
|
||||
}
|
@ -29,4 +29,3 @@ impl ReturnTypeExt for syn::ReturnType {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
10
core/codegen_next/tests/ui-fail/catchers.rs
Normal file
10
core/codegen_next/tests/ui-fail/catchers.rs
Normal file
@ -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
|
||||
}
|
20
core/codegen_next/tests/ui-fail/catchers.stderr
Normal file
20
core/codegen_next/tests/ui-fail/catchers.stderr
Normal file
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user