mirror of https://github.com/rwf2/Rocket.git
Remove 'proc_macro' features.
This commit is contained in:
parent
7bcf82a199
commit
3f2b8f6006
|
@ -20,7 +20,7 @@ proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "e58b3ac9a" }
|
devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "57d6eb80" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
yansi = "0.5"
|
yansi = "0.5"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use devise::{Spanned, Result};
|
use devise::{Spanned, Result, ext::SpanDiagnosticExt};
|
||||||
|
|
||||||
use crate::syn::{DataStruct, Fields, Data, Type, LitStr, DeriveInput, Ident, Visibility};
|
use crate::syn::{DataStruct, Fields, Data, Type, LitStr, DeriveInput, Ident, Visibility};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![feature(proc_macro_diagnostic)]
|
|
||||||
#![recursion_limit="256"]
|
#![recursion_limit="256"]
|
||||||
|
|
||||||
#![warn(rust_2018_idioms)]
|
#![warn(rust_2018_idioms)]
|
||||||
|
@ -42,8 +41,6 @@ use proc_macro::TokenStream;
|
||||||
#[cfg(feature = "database_attribute")]
|
#[cfg(feature = "database_attribute")]
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn database(attr: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn database(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
crate::database::database_attr(attr, input).unwrap_or_else(|diag| {
|
crate::database::database_attr(attr, input)
|
||||||
diag.emit();
|
.unwrap_or_else(|diag| diag.emit_as_tokens().into())
|
||||||
TokenStream::new()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ proc-macro = true
|
||||||
indexmap = "1.0"
|
indexmap = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
rocket_http = { version = "0.5.0-dev", path = "../http/" }
|
rocket_http = { version = "0.5.0-dev", path = "../http/" }
|
||||||
devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "e58b3ac9a" }
|
devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "17f647e" }
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
use proc_macro::{TokenStream, Span};
|
use devise::{syn, Diagnostic, Spanned, Result};
|
||||||
use devise::{syn, Spanned, Result};
|
use devise::ext::SpanDiagnosticExt;
|
||||||
|
use devise::proc_macro2::{TokenStream, Span};
|
||||||
use crate::proc_macro2::TokenStream as TokenStream2;
|
|
||||||
use crate::syn_ext::syn_to_diag;
|
|
||||||
|
|
||||||
trait EntryAttr {
|
trait EntryAttr {
|
||||||
/// Whether the attribute requires the attributed function to be `async`.
|
/// Whether the attribute requires the attributed function to be `async`.
|
||||||
const REQUIRES_ASYNC: bool;
|
const REQUIRES_ASYNC: bool;
|
||||||
|
|
||||||
/// Return a new or rewritten function, using block as the main execution.
|
/// Return a new or rewritten function, using block as the main execution.
|
||||||
fn function(f: &syn::ItemFn, body: &syn::Block) -> Result<TokenStream2>;
|
fn function(f: &syn::ItemFn, body: &syn::Block) -> Result<TokenStream>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Main;
|
struct Main;
|
||||||
|
@ -17,13 +15,12 @@ struct Main;
|
||||||
impl EntryAttr for Main {
|
impl EntryAttr for Main {
|
||||||
const REQUIRES_ASYNC: bool = true;
|
const REQUIRES_ASYNC: bool = true;
|
||||||
|
|
||||||
fn function(f: &syn::ItemFn, block: &syn::Block) -> Result<TokenStream2> {
|
fn function(f: &syn::ItemFn, block: &syn::Block) -> Result<TokenStream> {
|
||||||
let (attrs, vis, mut sig) = (&f.attrs, &f.vis, f.sig.clone());
|
let (attrs, vis, mut sig) = (&f.attrs, &f.vis, f.sig.clone());
|
||||||
if sig.ident != "main" {
|
if sig.ident != "main" {
|
||||||
Span::call_site()
|
return Err(Span::call_site()
|
||||||
.warning("attribute is typically applied to `main` function")
|
.warning("attribute is typically applied to `main` function")
|
||||||
.span_note(sig.span(), "this function is not `main`")
|
.span_note(sig.span(), "this function is not `main`"));
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sig.asyncness = None;
|
sig.asyncness = None;
|
||||||
|
@ -38,7 +35,7 @@ struct Test;
|
||||||
impl EntryAttr for Test {
|
impl EntryAttr for Test {
|
||||||
const REQUIRES_ASYNC: bool = true;
|
const REQUIRES_ASYNC: bool = true;
|
||||||
|
|
||||||
fn function(f: &syn::ItemFn, block: &syn::Block) -> Result<TokenStream2> {
|
fn function(f: &syn::ItemFn, block: &syn::Block) -> Result<TokenStream> {
|
||||||
let (attrs, vis, mut sig) = (&f.attrs, &f.vis, f.sig.clone());
|
let (attrs, vis, mut sig) = (&f.attrs, &f.vis, f.sig.clone());
|
||||||
sig.asyncness = None;
|
sig.asyncness = None;
|
||||||
Ok(quote_spanned!(block.span().into() => #(#attrs)* #[test] #vis #sig {
|
Ok(quote_spanned!(block.span().into() => #(#attrs)* #[test] #vis #sig {
|
||||||
|
@ -52,7 +49,7 @@ struct Launch;
|
||||||
impl EntryAttr for Launch {
|
impl EntryAttr for Launch {
|
||||||
const REQUIRES_ASYNC: bool = false;
|
const REQUIRES_ASYNC: bool = false;
|
||||||
|
|
||||||
fn function(f: &syn::ItemFn, block: &syn::Block) -> Result<TokenStream2> {
|
fn function(f: &syn::ItemFn, block: &syn::Block) -> Result<TokenStream> {
|
||||||
if f.sig.ident == "main" {
|
if f.sig.ident == "main" {
|
||||||
return Err(Span::call_site()
|
return Err(Span::call_site()
|
||||||
.error("attribute cannot be applied to `main` function")
|
.error("attribute cannot be applied to `main` function")
|
||||||
|
@ -89,9 +86,9 @@ impl EntryAttr for Launch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_input<A: EntryAttr>(input: TokenStream) -> Result<syn::ItemFn> {
|
fn parse_input<A: EntryAttr>(input: proc_macro::TokenStream) -> Result<syn::ItemFn> {
|
||||||
let function: syn::ItemFn = syn::parse(input)
|
let function: syn::ItemFn = syn::parse(input)
|
||||||
.map_err(syn_to_diag)
|
.map_err(Diagnostic::from)
|
||||||
.map_err(|d| d.help("attribute can only be applied to functions"))?;
|
.map_err(|d| d.help("attribute can only be applied to functions"))?;
|
||||||
|
|
||||||
if A::REQUIRES_ASYNC && function.sig.asyncness.is_none() {
|
if A::REQUIRES_ASYNC && function.sig.asyncness.is_none() {
|
||||||
|
@ -109,19 +106,26 @@ fn parse_input<A: EntryAttr>(input: TokenStream) -> Result<syn::ItemFn> {
|
||||||
Ok(function)
|
Ok(function)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _async_entry<A: EntryAttr>(_args: TokenStream, input: TokenStream) -> Result<TokenStream> {
|
fn _async_entry<A: EntryAttr>(
|
||||||
|
_args: proc_macro::TokenStream,
|
||||||
|
input: proc_macro::TokenStream
|
||||||
|
) -> Result<TokenStream> {
|
||||||
let function = parse_input::<A>(input)?;
|
let function = parse_input::<A>(input)?;
|
||||||
A::function(&function, &function.block).map(|t| t.into())
|
A::function(&function, &function.block).map(|t| t.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn async_test_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
|
macro_rules! async_entry {
|
||||||
_async_entry::<Test>(args, input).unwrap_or_else(|d| { d.emit(); TokenStream::new() })
|
($name:ident, $kind:ty, $default:expr) => (
|
||||||
|
pub fn $name(a: proc_macro::TokenStream, i: proc_macro::TokenStream) -> TokenStream {
|
||||||
|
_async_entry::<$kind>(a, i).unwrap_or_else(|d| {
|
||||||
|
let d = d.emit_as_tokens();
|
||||||
|
let default = $default;
|
||||||
|
quote!(#d #default)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
|
async_entry!(async_test_attribute, Test, quote!());
|
||||||
_async_entry::<Main>(args, input).unwrap_or_else(|d| { d.emit(); quote!(fn main() {}).into() })
|
async_entry!(main_attribute, Main, quote!(fn main() {}));
|
||||||
}
|
async_entry!(launch_attribute, Launch, quote!(fn main() {}));
|
||||||
|
|
||||||
pub fn launch_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
||||||
_async_entry::<Launch>(args, input).unwrap_or_else(|d| { d.emit(); quote!(fn main() {}).into() })
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use proc_macro::{TokenStream, Span};
|
use devise::{syn, Spanned, Result, FromMeta, Diagnostic};
|
||||||
use devise::{syn, Spanned, Result, FromMeta};
|
use devise::ext::SpanDiagnosticExt;
|
||||||
use crate::proc_macro2::TokenStream as TokenStream2;
|
|
||||||
|
|
||||||
|
use crate::proc_macro2::{TokenStream, Span};
|
||||||
use crate::http_codegen::Status;
|
use crate::http_codegen::Status;
|
||||||
use crate::syn_ext::{syn_to_diag, IdentExt, ReturnTypeExt, TokenStreamExt};
|
use crate::syn_ext::{IdentExt, ReturnTypeExt, TokenStreamExt};
|
||||||
use self::syn::{Attribute, parse::Parser};
|
use self::syn::{Attribute, parse::Parser};
|
||||||
use crate::{CATCH_FN_PREFIX, CATCH_STRUCT_PREFIX};
|
use crate::{CATCH_FN_PREFIX, CATCH_STRUCT_PREFIX};
|
||||||
|
|
||||||
|
@ -22,12 +22,16 @@ struct CatchParams {
|
||||||
function: syn::ItemFn,
|
function: syn::ItemFn,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_params(args: TokenStream2, input: TokenStream) -> Result<CatchParams> {
|
fn parse_params(
|
||||||
let function: syn::ItemFn = syn::parse(input).map_err(syn_to_diag)
|
args: TokenStream,
|
||||||
|
input: proc_macro::TokenStream
|
||||||
|
) -> Result<CatchParams> {
|
||||||
|
let function: syn::ItemFn = syn::parse(input)
|
||||||
|
.map_err(Diagnostic::from)
|
||||||
.map_err(|diag| diag.help("`#[catch]` can only be used on functions"))?;
|
.map_err(|diag| diag.help("`#[catch]` can only be used on functions"))?;
|
||||||
|
|
||||||
let full_attr = quote!(#[catch(#args)]);
|
let full_attr = quote!(#[catch(#args)]);
|
||||||
let attrs = Attribute::parse_outer.parse2(full_attr).map_err(syn_to_diag)?;
|
let attrs = Attribute::parse_outer.parse2(full_attr)?;
|
||||||
let attribute = match CatchAttribute::from_attrs("catch", &attrs) {
|
let attribute = match CatchAttribute::from_attrs("catch", &attrs) {
|
||||||
Some(result) => result.map_err(|d| {
|
Some(result) => result.map_err(|d| {
|
||||||
d.help("`#[catch]` expects a single status integer, e.g.: #[catch(404)]")
|
d.help("`#[catch]` expects a single status integer, e.g.: #[catch(404)]")
|
||||||
|
@ -38,9 +42,12 @@ fn parse_params(args: TokenStream2, input: TokenStream) -> Result<CatchParams> {
|
||||||
Ok(CatchParams { status: attribute.status, function })
|
Ok(CatchParams { status: attribute.status, function })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _catch(args: TokenStream, input: TokenStream) -> Result<TokenStream> {
|
pub fn _catch(
|
||||||
|
args: proc_macro::TokenStream,
|
||||||
|
input: proc_macro::TokenStream
|
||||||
|
) -> Result<TokenStream> {
|
||||||
// Parse and validate all of the user's input.
|
// Parse and validate all of the user's input.
|
||||||
let catch = parse_params(TokenStream2::from(args), input)?;
|
let catch = parse_params(args.into(), input)?;
|
||||||
|
|
||||||
// Gather everything we'll need to generate the catcher.
|
// Gather everything we'll need to generate the catcher.
|
||||||
let user_catcher_fn = &catch.function;
|
let user_catcher_fn = &catch.function;
|
||||||
|
@ -124,9 +131,12 @@ pub fn _catch(args: TokenStream, input: TokenStream) -> Result<TokenStream> {
|
||||||
code: #status_code,
|
code: #status_code,
|
||||||
handler: #generated_fn_name,
|
handler: #generated_fn_name,
|
||||||
};
|
};
|
||||||
}.into())
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn catch_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn catch_attribute(
|
||||||
_catch(args, input).unwrap_or_else(|d| { d.emit(); TokenStream::new() })
|
args: proc_macro::TokenStream,
|
||||||
|
input: proc_macro::TokenStream
|
||||||
|
) -> TokenStream {
|
||||||
|
_catch(args, input).unwrap_or_else(|d| d.emit_as_tokens())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,17 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
use proc_macro::{TokenStream, Span};
|
use devise::{syn, Spanned, SpanWrapped, Result, FromMeta, Diagnostic};
|
||||||
use crate::proc_macro2::TokenStream as TokenStream2;
|
use devise::ext::{SpanDiagnosticExt, TypeExt};
|
||||||
use devise::{syn, Spanned, SpanWrapped, Result, FromMeta, ext::TypeExt};
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
use crate::proc_macro_ext::{Diagnostics, StringLit};
|
use crate::proc_macro_ext::{Diagnostics, StringLit};
|
||||||
use crate::syn_ext::{syn_to_diag, IdentExt};
|
use crate::syn_ext::IdentExt;
|
||||||
use self::syn::{Attribute, parse::Parser};
|
use crate::proc_macro2::{TokenStream, Span};
|
||||||
|
|
||||||
use crate::http_codegen::{Method, MediaType, RoutePath, DataSegment, Optional};
|
use crate::http_codegen::{Method, MediaType, RoutePath, DataSegment, Optional};
|
||||||
use crate::attribute::segments::{Source, Kind, Segment};
|
use crate::attribute::segments::{Source, Kind, Segment};
|
||||||
|
use crate::syn::{Attribute, parse::Parser};
|
||||||
|
|
||||||
use crate::{ROUTE_FN_PREFIX, ROUTE_STRUCT_PREFIX, URI_MACRO_PREFIX, ROCKET_PARAM_PREFIX};
|
use crate::{ROUTE_FN_PREFIX, ROUTE_STRUCT_PREFIX, URI_MACRO_PREFIX, ROCKET_PARAM_PREFIX};
|
||||||
|
|
||||||
/// The raw, parsed `#[route]` attribute.
|
/// The raw, parsed `#[route]` attribute.
|
||||||
|
@ -59,9 +59,10 @@ fn parse_route(attr: RouteAttribute, function: syn::ItemFn) -> Result<Route> {
|
||||||
if let Some(ref data) = attr.data {
|
if let Some(ref data) = attr.data {
|
||||||
if !attr.method.0.supports_payload() {
|
if !attr.method.0.supports_payload() {
|
||||||
let msg = format!("'{}' does not typically support payloads", attr.method.0);
|
let msg = format!("'{}' does not typically support payloads", attr.method.0);
|
||||||
|
// FIXME(diag: warning)
|
||||||
data.full_span.warning("`data` used with non-payload-supporting method")
|
data.full_span.warning("`data` used with non-payload-supporting method")
|
||||||
.span_note(attr.method.span, msg)
|
.span_note(attr.method.span, msg)
|
||||||
.emit()
|
.emit_as_tokens();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,10 +128,10 @@ fn parse_route(attr: RouteAttribute, function: syn::ItemFn) -> Result<Route> {
|
||||||
diags.head_err_or(Route { attribute: attr, function, inputs, segments })
|
diags.head_err_or(Route { attribute: attr, function, inputs, segments })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn param_expr(seg: &Segment, ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 {
|
fn param_expr(seg: &Segment, ident: &syn::Ident, ty: &syn::Type) -> TokenStream {
|
||||||
define_vars_and_mods!(req, data, error, log, request, _None, _Some, _Ok, _Err, Outcome);
|
define_vars_and_mods!(req, data, error, log, request, _None, _Some, _Ok, _Err, Outcome);
|
||||||
let i = seg.index.expect("dynamic parameters must be indexed");
|
let i = seg.index.expect("dynamic parameters must be indexed");
|
||||||
let span = ident.span().unstable().join(ty.span()).unwrap().into();
|
let span = ident.span().join(ty.span()).unwrap_or_else(|| ty.span());
|
||||||
let name = ident.to_string();
|
let name = ident.to_string();
|
||||||
|
|
||||||
// All dynamic parameter should be found if this function is being called;
|
// All dynamic parameter should be found if this function is being called;
|
||||||
|
@ -175,9 +176,9 @@ fn param_expr(seg: &Segment, ident: &syn::Ident, ty: &syn::Type) -> TokenStream2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 {
|
fn data_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream {
|
||||||
define_vars_and_mods!(req, data, FromTransformedData, Outcome, Transform);
|
define_vars_and_mods!(req, data, FromTransformedData, Outcome, Transform);
|
||||||
let span = ident.span().unstable().join(ty.span()).unwrap().into();
|
let span = ident.span().join(ty.span()).unwrap_or_else(|| ty.span());
|
||||||
quote_spanned! { span =>
|
quote_spanned! { span =>
|
||||||
let __transform = <#ty as #FromTransformedData>::transform(#req, #data).await;
|
let __transform = <#ty as #FromTransformedData>::transform(#req, #data).await;
|
||||||
|
|
||||||
|
@ -204,7 +205,7 @@ fn data_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query_exprs(route: &Route) -> Option<TokenStream2> {
|
fn query_exprs(route: &Route) -> Option<TokenStream> {
|
||||||
define_vars_and_mods!(_None, _Some, _Ok, _Err, _Option);
|
define_vars_and_mods!(_None, _Some, _Ok, _Err, _Option);
|
||||||
define_vars_and_mods!(data, trail, log, request, req, Outcome, SmallVec, Query);
|
define_vars_and_mods!(data, trail, log, request, req, Outcome, SmallVec, Query);
|
||||||
let query_segments = route.attribute.path.query.as_ref()?;
|
let query_segments = route.attribute.path.query.as_ref()?;
|
||||||
|
@ -217,7 +218,7 @@ fn query_exprs(route: &Route) -> Option<TokenStream2> {
|
||||||
.map(|(_, rocket_ident, ty)| (rocket_ident, ty))
|
.map(|(_, rocket_ident, ty)| (rocket_ident, ty))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let span = ident.span().unstable().join(ty.span()).unwrap();
|
let span = ident.span().join(ty.span()).unwrap_or_else(|| ty.span());
|
||||||
(Some(ident), Some(ty), span.into())
|
(Some(ident), Some(ty), span.into())
|
||||||
} else {
|
} else {
|
||||||
(None, None, segment.span.into())
|
(None, None, segment.span.into())
|
||||||
|
@ -309,9 +310,9 @@ fn query_exprs(route: &Route) -> Option<TokenStream2> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_guard_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 {
|
fn request_guard_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream {
|
||||||
define_vars_and_mods!(req, data, request, Outcome);
|
define_vars_and_mods!(req, data, request, Outcome);
|
||||||
let span = ident.span().unstable().join(ty.span()).unwrap().into();
|
let span = ident.span().join(ty.span()).unwrap_or_else(|| ty.span());
|
||||||
quote_spanned! { span =>
|
quote_spanned! { span =>
|
||||||
#[allow(non_snake_case, unreachable_patterns, unreachable_code)]
|
#[allow(non_snake_case, unreachable_patterns, unreachable_code)]
|
||||||
let #ident: #ty = match <#ty as #request::FromRequest>::from_request(#req).await {
|
let #ident: #ty = match <#ty as #request::FromRequest>::from_request(#req).await {
|
||||||
|
@ -322,7 +323,7 @@ fn request_guard_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_internal_uri_macro(route: &Route) -> TokenStream2 {
|
fn generate_internal_uri_macro(route: &Route) -> TokenStream {
|
||||||
// Keep a global counter (+ thread ID later) to generate unique ids.
|
// Keep a global counter (+ thread ID later) to generate unique ids.
|
||||||
static COUNTER: AtomicUsize = AtomicUsize::new(0);
|
static COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
@ -344,7 +345,7 @@ fn generate_internal_uri_macro(route: &Route) -> TokenStream2 {
|
||||||
let inner_generated_macro_name = generated_macro_name.append(&hasher.finish().to_string());
|
let inner_generated_macro_name = generated_macro_name.append(&hasher.finish().to_string());
|
||||||
let route_uri = route.attribute.path.origin.0.to_string();
|
let route_uri = route.attribute.path.origin.0.to_string();
|
||||||
|
|
||||||
quote! {
|
quote_spanned! { Span::call_site() =>
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! #inner_generated_macro_name {
|
macro_rules! #inner_generated_macro_name {
|
||||||
|
@ -360,7 +361,7 @@ fn generate_internal_uri_macro(route: &Route) -> TokenStream2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_respond_expr(route: &Route) -> TokenStream2 {
|
fn generate_respond_expr(route: &Route) -> TokenStream {
|
||||||
let ret_span = match route.function.sig.output {
|
let ret_span = match route.function.sig.output {
|
||||||
syn::ReturnType::Default => route.function.sig.ident.span(),
|
syn::ReturnType::Default => route.function.sig.ident.span(),
|
||||||
syn::ReturnType::Type(_, ref ty) => ty.span().into()
|
syn::ReturnType::Type(_, ref ty) => ty.span().into()
|
||||||
|
@ -460,12 +461,13 @@ fn codegen_route(route: Route) -> Result<TokenStream> {
|
||||||
}.into())
|
}.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_route(args: TokenStream2, input: TokenStream) -> Result<TokenStream> {
|
fn complete_route(args: TokenStream, input: TokenStream) -> Result<TokenStream> {
|
||||||
let function: syn::ItemFn = syn::parse(input).map_err(syn_to_diag)
|
let function: syn::ItemFn = syn::parse2(input)
|
||||||
|
.map_err(|e| Diagnostic::from(e))
|
||||||
.map_err(|diag| diag.help("`#[route]` can only be used on functions"))?;
|
.map_err(|diag| diag.help("`#[route]` can only be used on functions"))?;
|
||||||
|
|
||||||
let full_attr = quote!(#[route(#args)]);
|
let full_attr = quote!(#[route(#args)]);
|
||||||
let attrs = Attribute::parse_outer.parse2(full_attr).map_err(syn_to_diag)?;
|
let attrs = Attribute::parse_outer.parse2(full_attr)?;
|
||||||
let attribute = match RouteAttribute::from_attrs("route", &attrs) {
|
let attribute = match RouteAttribute::from_attrs("route", &attrs) {
|
||||||
Some(result) => result?,
|
Some(result) => result?,
|
||||||
None => return Err(Span::call_site().error("internal error: bad attribute"))
|
None => return Err(Span::call_site().error("internal error: bad attribute"))
|
||||||
|
@ -476,7 +478,7 @@ fn complete_route(args: TokenStream2, input: TokenStream) -> Result<TokenStream>
|
||||||
|
|
||||||
fn incomplete_route(
|
fn incomplete_route(
|
||||||
method: crate::http::Method,
|
method: crate::http::Method,
|
||||||
args: TokenStream2,
|
args: TokenStream,
|
||||||
input: TokenStream
|
input: TokenStream
|
||||||
) -> Result<TokenStream> {
|
) -> Result<TokenStream> {
|
||||||
let method_str = method.to_string().to_lowercase();
|
let method_str = method.to_string().to_lowercase();
|
||||||
|
@ -486,11 +488,12 @@ fn incomplete_route(
|
||||||
|
|
||||||
let method_ident = syn::Ident::new(&method_str, method_span.into());
|
let method_ident = syn::Ident::new(&method_str, method_span.into());
|
||||||
|
|
||||||
let function: syn::ItemFn = syn::parse(input).map_err(syn_to_diag)
|
let function: syn::ItemFn = syn::parse2(input)
|
||||||
|
.map_err(|e| Diagnostic::from(e))
|
||||||
.map_err(|d| d.help(format!("#[{}] can only be used on functions", method_str)))?;
|
.map_err(|d| d.help(format!("#[{}] can only be used on functions", method_str)))?;
|
||||||
|
|
||||||
let full_attr = quote!(#[#method_ident(#args)]);
|
let full_attr = quote!(#[#method_ident(#args)]);
|
||||||
let attrs = Attribute::parse_outer.parse2(full_attr).map_err(syn_to_diag)?;
|
let attrs = Attribute::parse_outer.parse2(full_attr)?;
|
||||||
let method_attribute = match MethodRouteAttribute::from_attrs(&method_str, &attrs) {
|
let method_attribute = match MethodRouteAttribute::from_attrs(&method_str, &attrs) {
|
||||||
Some(result) => result?,
|
Some(result) => result?,
|
||||||
None => return Err(Span::call_site().error("internal error: bad attribute"))
|
None => return Err(Span::call_site().error("internal error: bad attribute"))
|
||||||
|
@ -511,13 +514,13 @@ fn incomplete_route(
|
||||||
|
|
||||||
pub fn route_attribute<M: Into<Option<crate::http::Method>>>(
|
pub fn route_attribute<M: Into<Option<crate::http::Method>>>(
|
||||||
method: M,
|
method: M,
|
||||||
args: TokenStream,
|
args: proc_macro::TokenStream,
|
||||||
input: TokenStream
|
input: proc_macro::TokenStream
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let result = match method.into() {
|
let result = match method.into() {
|
||||||
Some(method) => incomplete_route(method, args.into(), input),
|
Some(method) => incomplete_route(method, args.into(), input.into()),
|
||||||
None => complete_route(args.into(), input)
|
None => complete_route(args.into(), input.into())
|
||||||
};
|
};
|
||||||
|
|
||||||
result.unwrap_or_else(|diag| { diag.emit(); TokenStream::new() })
|
result.unwrap_or_else(|diag| diag.emit_as_tokens())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
use devise::syn;
|
use devise::{syn, Diagnostic, ext::SpanDiagnosticExt};
|
||||||
use proc_macro::{Span, Diagnostic};
|
use crate::proc_macro2::Span;
|
||||||
|
|
||||||
use crate::http::uri::{UriPart, Path};
|
use crate::http::uri::{UriPart, Path};
|
||||||
use crate::http::route::RouteSegment;
|
use crate::http::route::RouteSegment;
|
||||||
|
@ -36,7 +36,7 @@ impl From<&syn::Ident> for Segment {
|
||||||
Segment {
|
Segment {
|
||||||
kind: Kind::Static,
|
kind: Kind::Static,
|
||||||
source: Source::Unknown,
|
source: Source::Unknown,
|
||||||
span: ident.span().unstable(),
|
span: ident.span(),
|
||||||
name: ident.to_string(),
|
name: ident.to_string(),
|
||||||
index: None,
|
index: None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use proc_macro::TokenStream;
|
use devise::Result;
|
||||||
use crate::proc_macro2::TokenStream as TokenStream2;
|
|
||||||
|
|
||||||
use devise::{syn, Spanned, Result};
|
use crate::syn_ext::IdentExt;
|
||||||
use self::syn::{Path, punctuated::Punctuated, parse::Parser, token::Comma};
|
use crate::syn::{Path, punctuated::Punctuated, parse::Parser, Token};
|
||||||
use crate::syn_ext::{IdentExt, syn_to_diag};
|
use crate::syn::spanned::Spanned;
|
||||||
|
use crate::proc_macro2::TokenStream;
|
||||||
use crate::{ROUTE_STRUCT_PREFIX, CATCH_STRUCT_PREFIX};
|
use crate::{ROUTE_STRUCT_PREFIX, CATCH_STRUCT_PREFIX};
|
||||||
|
|
||||||
mod uri;
|
mod uri;
|
||||||
|
@ -17,13 +17,11 @@ pub fn prefix_last_segment(path: &mut Path, prefix: &str) {
|
||||||
|
|
||||||
fn _prefixed_vec(
|
fn _prefixed_vec(
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
input: TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
ty: &TokenStream2
|
ty: &TokenStream
|
||||||
) -> Result<TokenStream2> {
|
) -> Result<TokenStream> {
|
||||||
// Parse a comma-separated list of paths.
|
// Parse a comma-separated list of paths.
|
||||||
let mut paths = <Punctuated<Path, Comma>>::parse_terminated
|
let mut paths = <Punctuated<Path, Token![,]>>::parse_terminated.parse(input)?;
|
||||||
.parse(input)
|
|
||||||
.map_err(syn_to_diag)?;
|
|
||||||
|
|
||||||
// Prefix the last segment in each path with `prefix`.
|
// Prefix the last segment in each path with `prefix`.
|
||||||
paths.iter_mut().for_each(|p| prefix_last_segment(p, prefix));
|
paths.iter_mut().for_each(|p| prefix_last_segment(p, prefix));
|
||||||
|
@ -35,39 +33,46 @@ fn _prefixed_vec(
|
||||||
Ok(quote!(vec![#(#prefixed_mapped_paths),*]))
|
Ok(quote!(vec![#(#prefixed_mapped_paths),*]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prefixed_vec(prefix: &str, input: TokenStream, ty: TokenStream2) -> TokenStream {
|
fn prefixed_vec(
|
||||||
let vec = _prefixed_vec(prefix, input, &ty)
|
prefix: &str,
|
||||||
.map_err(|diag| diag.emit())
|
input: proc_macro::TokenStream,
|
||||||
.unwrap_or_else(|_| quote!(vec![]));
|
ty: TokenStream
|
||||||
|
) -> TokenStream {
|
||||||
quote!({
|
define_vars_and_mods!(_Vec);
|
||||||
let __vector: Vec<#ty> = #vec;
|
_prefixed_vec(prefix, input, &ty)
|
||||||
__vector
|
.map(|vec| quote!({
|
||||||
}).into()
|
let __vector: #_Vec<#ty> = #vec;
|
||||||
|
__vector
|
||||||
|
}))
|
||||||
|
.unwrap_or_else(|diag| {
|
||||||
|
let diag_tokens = diag.emit_as_tokens();
|
||||||
|
quote!({
|
||||||
|
#diag_tokens
|
||||||
|
let __vec: #_Vec<#ty> = vec![];
|
||||||
|
__vec
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn routes_macro(input: TokenStream) -> TokenStream {
|
pub fn routes_macro(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
prefixed_vec(ROUTE_STRUCT_PREFIX, input, quote!(::rocket::Route))
|
prefixed_vec(ROUTE_STRUCT_PREFIX, input, quote!(::rocket::Route))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn catchers_macro(input: TokenStream) -> TokenStream {
|
pub fn catchers_macro(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
prefixed_vec(CATCH_STRUCT_PREFIX, input, quote!(::rocket::Catcher))
|
prefixed_vec(CATCH_STRUCT_PREFIX, input, quote!(::rocket::Catcher))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uri_macro(input: TokenStream) -> TokenStream {
|
pub fn uri_macro(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
uri::_uri_macro(input)
|
uri::_uri_macro(input.into())
|
||||||
.map_err(|diag| diag.emit())
|
.unwrap_or_else(|diag| diag.emit_as_tokens())
|
||||||
.unwrap_or_else(|_| quote!(()).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uri_internal_macro(input: TokenStream) -> TokenStream {
|
pub fn uri_internal_macro(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
uri::_uri_internal_macro(input)
|
uri::_uri_internal_macro(input.into())
|
||||||
.map_err(|diag| diag.emit())
|
.unwrap_or_else(|diag| diag.emit_as_tokens())
|
||||||
.unwrap_or_else(|_| quote!(()).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn guide_tests_internal(input: TokenStream) -> TokenStream {
|
pub fn guide_tests_internal(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
test_guide::_macro(input)
|
test_guide::_macro(input)
|
||||||
.map_err(|diag| diag.emit())
|
.unwrap_or_else(|diag| diag.emit_as_tokens())
|
||||||
.unwrap_or_else(|_| quote!(()).into())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use devise::ext::SpanDiagnosticExt;
|
||||||
use devise::{syn::{self, Ident, LitStr}, Result};
|
use devise::syn::{self, Ident, LitStr};
|
||||||
|
use devise::proc_macro2::TokenStream;
|
||||||
|
|
||||||
use crate::syn_ext::syn_to_diag;
|
pub fn _macro(input: proc_macro::TokenStream) -> devise::Result<TokenStream> {
|
||||||
use crate::proc_macro2::TokenStream as TokenStream2;
|
let root_glob = syn::parse::<LitStr>(input.into())?;
|
||||||
|
|
||||||
pub fn _macro(input: TokenStream) -> Result<TokenStream> {
|
|
||||||
let root_glob = syn::parse::<LitStr>(input.into()).map_err(syn_to_diag)?;
|
|
||||||
let modules = entry_to_modules(&root_glob)
|
let modules = entry_to_modules(&root_glob)
|
||||||
.map_err(|e| root_glob.span().unstable().error(format!("failed to read: {}", e)))?;
|
.map_err(|e| root_glob.span().error(format!("failed to read: {}", e)))?;
|
||||||
|
|
||||||
Ok(quote_spanned!(root_glob.span() =>
|
Ok(quote_spanned!(root_glob.span() =>
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -19,7 +17,7 @@ pub fn _macro(input: TokenStream) -> Result<TokenStream> {
|
||||||
).into())
|
).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn entry_to_modules(root_glob: &LitStr) -> std::result::Result<Vec<TokenStream2>, Box<dyn Error>> {
|
fn entry_to_modules(root_glob: &LitStr) -> Result<Vec<TokenStream>, Box<dyn Error>> {
|
||||||
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("MANIFEST_DIR");
|
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("MANIFEST_DIR");
|
||||||
let full_glob = Path::new(&manifest_dir).join(&root_glob.value()).display().to_string();
|
let full_glob = Path::new(&manifest_dir).join(&root_glob.value()).display().to_string();
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use proc_macro::TokenStream;
|
|
||||||
use crate::proc_macro2::TokenStream as TokenStream2;
|
|
||||||
|
|
||||||
use devise::{syn, Result};
|
use devise::{syn, Result, ext::SpanDiagnosticExt};
|
||||||
use devise::syn::{Expr, Ident, Type, spanned::Spanned};
|
|
||||||
use crate::http::{uri::{Origin, Path, Query}, ext::IntoOwned};
|
use crate::http::{uri::{Origin, Path, Query}, ext::IntoOwned};
|
||||||
use crate::http::route::{RouteSegment, Kind, Source};
|
use crate::http::route::{RouteSegment, Kind, Source};
|
||||||
|
|
||||||
|
use crate::syn::{Expr, Ident, Type, spanned::Spanned};
|
||||||
use crate::http_codegen::Optional;
|
use crate::http_codegen::Optional;
|
||||||
use crate::syn_ext::{IdentExt, syn_to_diag};
|
use crate::syn_ext::IdentExt;
|
||||||
use crate::bang::{prefix_last_segment, uri_parsing::*};
|
use crate::bang::{prefix_last_segment, uri_parsing::*};
|
||||||
|
use crate::proc_macro2::TokenStream;
|
||||||
|
|
||||||
use crate::URI_MACRO_PREFIX;
|
use crate::URI_MACRO_PREFIX;
|
||||||
|
|
||||||
|
@ -24,12 +24,12 @@ macro_rules! p {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _uri_macro(input: TokenStream) -> Result<TokenStream> {
|
pub fn _uri_macro(input: TokenStream) -> Result<TokenStream> {
|
||||||
let input2: TokenStream2 = input.clone().into();
|
let input2: TokenStream = input.clone().into();
|
||||||
let mut params = syn::parse::<UriParams>(input).map_err(syn_to_diag)?;
|
let mut params = syn::parse2::<UriParams>(input)?;
|
||||||
prefix_last_segment(&mut params.route_path, URI_MACRO_PREFIX);
|
prefix_last_segment(&mut params.route_path, URI_MACRO_PREFIX);
|
||||||
|
|
||||||
let path = ¶ms.route_path;
|
let path = ¶ms.route_path;
|
||||||
Ok(quote!(#path!(#input2)).into())
|
Ok(quote!(#path!(#input2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_exprs<'a>(internal: &'a InternalUriParams) -> Result<(
|
fn extract_exprs<'a>(internal: &'a InternalUriParams) -> Result<(
|
||||||
|
@ -43,8 +43,7 @@ fn extract_exprs<'a>(internal: &'a InternalUriParams) -> Result<(
|
||||||
let path_param_count = internal.route_uri.path().matches('<').count();
|
let path_param_count = internal.route_uri.path().matches('<').count();
|
||||||
for expr in exprs.iter().take(path_param_count) {
|
for expr in exprs.iter().take(path_param_count) {
|
||||||
if !expr.as_expr().is_some() {
|
if !expr.as_expr().is_some() {
|
||||||
return Err(expr.span().unstable()
|
return Err(expr.span().error("path parameters cannot be ignored"));
|
||||||
.error("path parameters cannot be ignored"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,13 +90,13 @@ fn extract_exprs<'a>(internal: &'a InternalUriParams) -> Result<(
|
||||||
|
|
||||||
if !extra.is_empty() {
|
if !extra.is_empty() {
|
||||||
let (ps, msg) = join(extra.iter());
|
let (ps, msg) = join(extra.iter());
|
||||||
let spans: Vec<_> = extra.iter().map(|ident| ident.span().unstable()).collect();
|
let spans: Vec<_> = extra.iter().map(|ident| ident.span()).collect();
|
||||||
diag = diag.span_help(spans, format!("unknown {}: {}", ps, msg));
|
diag = diag.span_help(spans, format!("unknown {}: {}", ps, msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dup.is_empty() {
|
if !dup.is_empty() {
|
||||||
let (ps, msg) = join(dup.iter());
|
let (ps, msg) = join(dup.iter());
|
||||||
let spans: Vec<_> = dup.iter().map(|ident| ident.span().unstable()).collect();
|
let spans: Vec<_> = dup.iter().map(|ident| ident.span()).collect();
|
||||||
diag = diag.span_help(spans, format!("duplicate {}: {}", ps, msg));
|
diag = diag.span_help(spans, format!("duplicate {}: {}", ps, msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +105,7 @@ fn extract_exprs<'a>(internal: &'a InternalUriParams) -> Result<(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_binding(to: &mut Vec<TokenStream2>, ident: &Ident, ty: &Type, expr: &Expr, source: Source) {
|
fn add_binding(to: &mut Vec<TokenStream>, ident: &Ident, ty: &Type, expr: &Expr, source: Source) {
|
||||||
let uri_mod = quote!(rocket::http::uri);
|
let uri_mod = quote!(rocket::http::uri);
|
||||||
let (span, ident_tmp) = (expr.span(), ident.prepend("__tmp_"));
|
let (span, ident_tmp) = (expr.span(), ident.prepend("__tmp_"));
|
||||||
let from_uri_param = if source == Source::Query {
|
let from_uri_param = if source == Source::Query {
|
||||||
|
@ -124,9 +123,9 @@ fn add_binding(to: &mut Vec<TokenStream2>, ident: &Ident, ty: &Type, expr: &Expr
|
||||||
|
|
||||||
fn explode_path<'a, I: Iterator<Item = (&'a Ident, &'a Type, &'a Expr)>>(
|
fn explode_path<'a, I: Iterator<Item = (&'a Ident, &'a Type, &'a Expr)>>(
|
||||||
uri: &Origin<'_>,
|
uri: &Origin<'_>,
|
||||||
bindings: &mut Vec<TokenStream2>,
|
bindings: &mut Vec<TokenStream>,
|
||||||
mut items: I
|
mut items: I
|
||||||
) -> TokenStream2 {
|
) -> TokenStream {
|
||||||
let (uri_mod, path) = (quote!(rocket::http::uri), uri.path());
|
let (uri_mod, path) = (quote!(rocket::http::uri), uri.path());
|
||||||
if !path.contains('<') {
|
if !path.contains('<') {
|
||||||
return quote!(#uri_mod::UriArgumentsKind::Static(#path));
|
return quote!(#uri_mod::UriArgumentsKind::Static(#path));
|
||||||
|
@ -153,9 +152,9 @@ fn explode_path<'a, I: Iterator<Item = (&'a Ident, &'a Type, &'a Expr)>>(
|
||||||
|
|
||||||
fn explode_query<'a, I: Iterator<Item = (&'a Ident, &'a Type, &'a ArgExpr)>>(
|
fn explode_query<'a, I: Iterator<Item = (&'a Ident, &'a Type, &'a ArgExpr)>>(
|
||||||
uri: &Origin<'_>,
|
uri: &Origin<'_>,
|
||||||
bindings: &mut Vec<TokenStream2>,
|
bindings: &mut Vec<TokenStream>,
|
||||||
mut items: I
|
mut items: I
|
||||||
) -> Option<TokenStream2> {
|
) -> Option<TokenStream> {
|
||||||
let (uri_mod, query) = (quote!(rocket::http::uri), uri.query()?);
|
let (uri_mod, query) = (quote!(rocket::http::uri), uri.query()?);
|
||||||
if !query.contains('<') {
|
if !query.contains('<') {
|
||||||
return Some(quote!(#uri_mod::UriArgumentsKind::Static(#query)));
|
return Some(quote!(#uri_mod::UriArgumentsKind::Static(#query)));
|
||||||
|
@ -215,7 +214,7 @@ fn build_origin(internal: &InternalUriParams) -> Origin<'static> {
|
||||||
|
|
||||||
pub fn _uri_internal_macro(input: TokenStream) -> Result<TokenStream> {
|
pub fn _uri_internal_macro(input: TokenStream) -> Result<TokenStream> {
|
||||||
// Parse the internal invocation and the user's URI param expressions.
|
// Parse the internal invocation and the user's URI param expressions.
|
||||||
let internal = syn::parse::<InternalUriParams>(input).map_err(syn_to_diag)?;
|
let internal = syn::parse2::<InternalUriParams>(input)?;
|
||||||
let (path_params, query_params) = extract_exprs(&internal)?;
|
let (path_params, query_params) = extract_exprs(&internal)?;
|
||||||
|
|
||||||
let mut bindings = vec![];
|
let mut bindings = vec![];
|
||||||
|
@ -227,5 +226,5 @@ pub fn _uri_internal_macro(input: TokenStream) -> Result<TokenStream> {
|
||||||
Ok(quote!({
|
Ok(quote!({
|
||||||
#(#bindings)*
|
#(#bindings)*
|
||||||
#uri_mod::UriArguments { path: #path, query: #query, }.into_origin()
|
#uri_mod::UriArguments { path: #path, query: #query, }.into_origin()
|
||||||
}).into())
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
use proc_macro::Span;
|
use indexmap::IndexMap;
|
||||||
|
use devise::{Spanned, ext::TypeExt};
|
||||||
use devise::{syn, Spanned};
|
|
||||||
use devise::proc_macro2::TokenStream as TokenStream2;
|
|
||||||
use devise::ext::TypeExt;
|
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
|
|
||||||
use self::syn::{Expr, Ident, LitStr, Path, Token, Type};
|
use crate::syn::{self, Expr, Ident, LitStr, Path, Token, Type};
|
||||||
use self::syn::parse::{self, Parse, ParseStream};
|
use crate::syn::parse::{self, Parse, ParseStream};
|
||||||
use self::syn::punctuated::Punctuated;
|
use crate::syn::punctuated::Punctuated;
|
||||||
|
|
||||||
use crate::http::{uri::Origin, ext::IntoOwned};
|
use crate::http::{uri::Origin, ext::IntoOwned};
|
||||||
use indexmap::IndexMap;
|
use crate::proc_macro2::{TokenStream, Span};
|
||||||
|
|
||||||
|
// TODO(diag): Use 'Diagnostic' in place of syn::Error.
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ArgExpr {
|
pub enum ArgExpr {
|
||||||
|
@ -124,7 +123,7 @@ impl Parse for UriParams {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if !input.peek(Token![,]) && input.cursor().eof() {
|
if !input.peek(Token![,]) && input.cursor().eof() {
|
||||||
return err(string.span().unstable(), "unexpected end of input: \
|
return err(string.span(), "unexpected end of input: \
|
||||||
expected ',' followed by route path");
|
expected ',' followed by route path");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +326,7 @@ impl ArgExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for ArgExpr {
|
impl ToTokens for ArgExpr {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
match self {
|
match self {
|
||||||
ArgExpr::Expr(e) => e.to_tokens(tokens),
|
ArgExpr::Expr(e) => e.to_tokens(tokens),
|
||||||
ArgExpr::Ignored(e) => e.to_tokens(tokens)
|
ArgExpr::Ignored(e) => e.to_tokens(tokens)
|
||||||
|
@ -336,7 +335,7 @@ impl ToTokens for ArgExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for Arg {
|
impl ToTokens for Arg {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
match self {
|
match self {
|
||||||
Arg::Unnamed(e) => e.to_tokens(tokens),
|
Arg::Unnamed(e) => e.to_tokens(tokens),
|
||||||
Arg::Named(ident, eq, expr) => tokens.extend(quote!(#ident #eq #expr)),
|
Arg::Named(ident, eq, expr) => tokens.extend(quote!(#ident #eq #expr)),
|
||||||
|
@ -345,7 +344,7 @@ impl ToTokens for Arg {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for Args {
|
impl ToTokens for Args {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
match self {
|
match self {
|
||||||
Args::Unnamed(e) | Args::Named(e) => e.to_tokens(tokens)
|
Args::Unnamed(e) | Args::Named(e) => e.to_tokens(tokens)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use proc_macro::{Span, TokenStream};
|
use devise::{*, ext::{TypeExt, Split3, SpanDiagnosticExt}};
|
||||||
use devise::{*, ext::{TypeExt, Split3}};
|
|
||||||
|
use crate::proc_macro2::{Span, TokenStream};
|
||||||
|
|
||||||
#[derive(FromMeta)]
|
#[derive(FromMeta)]
|
||||||
pub struct Form {
|
pub struct Form {
|
||||||
|
@ -57,7 +58,7 @@ fn validate_struct(gen: &DeriveGenerator, data: Struct<'_>) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn derive_from_form(input: TokenStream) -> TokenStream {
|
pub fn derive_from_form(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
let form_error = quote!(::rocket::request::FormParseError);
|
let form_error = quote!(::rocket::request::FormParseError);
|
||||||
DeriveGenerator::build_for(input, quote!(impl<'__f> ::rocket::request::FromForm<'__f>))
|
DeriveGenerator::build_for(input, quote!(impl<'__f> ::rocket::request::FromForm<'__f>))
|
||||||
.generic_support(GenericSupport::Lifetime | GenericSupport::Type)
|
.generic_support(GenericSupport::Lifetime | GenericSupport::Type)
|
||||||
|
@ -126,5 +127,5 @@ pub fn derive_from_form(input: TokenStream) -> TokenStream {
|
||||||
#_Ok(Self { #(#builders)* })
|
#_Ok(Self { #(#builders)* })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.to_tokens()
|
.to_tokens2()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
use devise::*;
|
use devise::{*, ext::SpanDiagnosticExt};
|
||||||
use proc_macro::TokenStream;
|
|
||||||
|
use crate::proc_macro2::TokenStream;
|
||||||
|
|
||||||
#[derive(FromMeta)]
|
#[derive(FromMeta)]
|
||||||
struct Form {
|
struct Form {
|
||||||
value: String,
|
value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn derive_from_form_value(input: TokenStream) -> TokenStream {
|
pub fn derive_from_form_value(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
define_vars_and_mods!(_Ok, _Err, _Result);
|
define_vars_and_mods!(_Ok, _Err, _Result);
|
||||||
DeriveGenerator::build_for(input, quote!(impl<'__v> ::rocket::request::FromFormValue<'__v>))
|
DeriveGenerator::build_for(input, quote!(impl<'__v> ::rocket::request::FromFormValue<'__v>))
|
||||||
.generic_support(GenericSupport::None)
|
.generic_support(GenericSupport::None)
|
||||||
|
@ -21,7 +22,8 @@ pub fn derive_from_form_value(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
// Emit a warning if the enum is empty.
|
// Emit a warning if the enum is empty.
|
||||||
if data.variants.is_empty() {
|
if data.variants.is_empty() {
|
||||||
generator.input.span().warning("deriving for empty enum").emit();
|
return Err(generator.input.span()
|
||||||
|
.error("enum must have at least one field"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -51,5 +53,5 @@ pub fn derive_from_form_value(input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.to_tokens()
|
.to_tokens2()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use quote::ToTokens;
|
|
||||||
use proc_macro::TokenStream;
|
|
||||||
use devise::{*, ext::TypeExt};
|
|
||||||
use devise::proc_macro2::TokenStream as TokenStream2;
|
|
||||||
|
|
||||||
|
use quote::ToTokens;
|
||||||
|
use devise::{*, ext::{TypeExt, SpanDiagnosticExt}};
|
||||||
|
|
||||||
|
use crate::proc_macro2::TokenStream;
|
||||||
use crate::http_codegen::{ContentType, Status};
|
use crate::http_codegen::{ContentType, Status};
|
||||||
|
|
||||||
#[derive(Default, FromMeta)]
|
#[derive(Default, FromMeta)]
|
||||||
|
@ -16,15 +16,11 @@ struct FieldAttr {
|
||||||
ignore: bool,
|
ignore: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn derive_responder(input: TokenStream) -> TokenStream {
|
pub fn derive_responder(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
// NOTE: Due to a bug in devise, we can't do the more correct:
|
DeriveGenerator::build_for(input, quote!(impl<'__r, '__o: '__r> ::rocket::response::Responder<'__r, '__o>))
|
||||||
// quote!(impl<'__r, '__o: '__r> ::rocket::response::Responder<'__r, '__o>))
|
|
||||||
// replace_generic(1, 0)
|
|
||||||
// A bugfix (on devise master) fixes this so the above works. Hack.
|
|
||||||
DeriveGenerator::build_for(input, quote!(impl<'__r> ::rocket::response::Responder<'__r, '__r>))
|
|
||||||
.generic_support(GenericSupport::Lifetime)
|
.generic_support(GenericSupport::Lifetime)
|
||||||
.data_support(DataSupport::Struct | DataSupport::Enum)
|
.data_support(DataSupport::Struct | DataSupport::Enum)
|
||||||
.replace_generic(0, 0)
|
.replace_generic(1, 0)
|
||||||
.validate_generics(|_, generics| match generics.lifetimes().count() > 1 {
|
.validate_generics(|_, generics| match generics.lifetimes().count() > 1 {
|
||||||
true => Err(generics.span().error("only one lifetime is supported")),
|
true => Err(generics.span().error("only one lifetime is supported")),
|
||||||
false => Ok(())
|
false => Ok(())
|
||||||
|
@ -37,13 +33,13 @@ pub fn derive_responder(input: TokenStream) -> TokenStream {
|
||||||
fn respond_to(
|
fn respond_to(
|
||||||
self,
|
self,
|
||||||
__req: &'__r ::rocket::request::Request
|
__req: &'__r ::rocket::request::Request
|
||||||
) -> ::rocket::response::Result<'__r> {
|
) -> ::rocket::response::Result<'__o> {
|
||||||
#inner
|
#inner
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.try_map_fields(|_, fields| {
|
.try_map_fields(|_, fields| {
|
||||||
define_vars_and_mods!(_Ok);
|
define_vars_and_mods!(_Ok);
|
||||||
fn set_header_tokens<T: ToTokens + Spanned>(item: T) -> TokenStream2 {
|
fn set_header_tokens<T: ToTokens + Spanned>(item: T) -> TokenStream {
|
||||||
quote_spanned!(item.span().into() => __res.set_header(#item);)
|
quote_spanned!(item.span().into() => __res.set_header(#item);)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,5 +78,5 @@ pub fn derive_responder(input: TokenStream) -> TokenStream {
|
||||||
#_Ok(__res)
|
#_Ok(__res)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.to_tokens()
|
.to_tokens2()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use proc_macro::{Span, TokenStream};
|
|
||||||
use devise::*;
|
use devise::{*, ext::SpanDiagnosticExt};
|
||||||
|
|
||||||
use crate::derive::from_form::Form;
|
use crate::derive::from_form::Form;
|
||||||
use crate::proc_macro2::TokenStream as TokenStream2;
|
use crate::proc_macro2::{TokenStream, Span};
|
||||||
|
|
||||||
const NO_EMPTY_FIELDS: &str = "fieldless structs or variants are not supported";
|
const NO_EMPTY_FIELDS: &str = "fieldless structs or variants are not supported";
|
||||||
const NO_NULLARY: &str = "nullary items are not supported";
|
const NO_NULLARY: &str = "nullary items are not supported";
|
||||||
|
@ -39,7 +39,7 @@ fn validate_enum(gen: &DeriveGenerator, data: Enum<'_>) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn derive_uri_display_query(input: TokenStream) -> TokenStream {
|
pub fn derive_uri_display_query(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
let Query = quote!(::rocket::http::uri::Query);
|
let Query = quote!(::rocket::http::uri::Query);
|
||||||
let UriDisplay = quote!(::rocket::http::uri::UriDisplay<#Query>);
|
let UriDisplay = quote!(::rocket::http::uri::UriDisplay<#Query>);
|
||||||
let Formatter = quote!(::rocket::http::uri::Formatter<#Query>);
|
let Formatter = quote!(::rocket::http::uri::Formatter<#Query>);
|
||||||
|
@ -116,15 +116,15 @@ pub fn derive_uri_display_query(input: TokenStream) -> TokenStream {
|
||||||
})
|
})
|
||||||
.to_tokens();
|
.to_tokens();
|
||||||
|
|
||||||
let mut ts = TokenStream2::from(uri_display);
|
let mut ts = TokenStream::from(uri_display);
|
||||||
ts.extend(TokenStream2::from(from_self));
|
ts.extend(TokenStream::from(from_self));
|
||||||
ts.extend(TokenStream2::from(from_ref));
|
ts.extend(TokenStream::from(from_ref));
|
||||||
ts.extend(TokenStream2::from(from_mut));
|
ts.extend(TokenStream::from(from_mut));
|
||||||
ts.into()
|
ts.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn derive_uri_display_path(input: TokenStream) -> TokenStream {
|
pub fn derive_uri_display_path(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
let Path = quote!(::rocket::http::uri::Path);
|
let Path = quote!(::rocket::http::uri::Path);
|
||||||
let UriDisplay = quote!(::rocket::http::uri::UriDisplay<#Path>);
|
let UriDisplay = quote!(::rocket::http::uri::UriDisplay<#Path>);
|
||||||
let Formatter = quote!(::rocket::http::uri::Formatter<#Path>);
|
let Formatter = quote!(::rocket::http::uri::Formatter<#Path>);
|
||||||
|
@ -179,8 +179,8 @@ pub fn derive_uri_display_path(input: TokenStream) -> TokenStream {
|
||||||
})
|
})
|
||||||
.to_tokens();
|
.to_tokens();
|
||||||
|
|
||||||
let mut ts = TokenStream2::from(uri_display);
|
let mut ts = TokenStream::from(uri_display);
|
||||||
ts.extend(TokenStream2::from(from_self));
|
ts.extend(TokenStream::from(from_self));
|
||||||
ts.extend(TokenStream2::from(from_ref));
|
ts.extend(TokenStream::from(from_ref));
|
||||||
ts.into()
|
ts.into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use crate::proc_macro2::TokenStream as TokenStream2;
|
use devise::{FromMeta, MetaItem, Result, ext::{Split2, PathExt, SpanDiagnosticExt}};
|
||||||
use devise::{FromMeta, MetaItem, Result, ext::{Split2, PathExt}};
|
|
||||||
|
use crate::proc_macro2::TokenStream;
|
||||||
use crate::http::{self, ext::IntoOwned};
|
use crate::http::{self, ext::IntoOwned};
|
||||||
use crate::http::uri::{Path, Query};
|
use crate::http::uri::{Path, Query};
|
||||||
use crate::attribute::segments::{parse_segments, parse_data_segment, Segment, Kind};
|
use crate::attribute::segments::{parse_segments, parse_data_segment, Segment, Kind};
|
||||||
|
@ -53,7 +54,7 @@ impl FromMeta for Status {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for Status {
|
impl ToTokens for Status {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
let (code, reason) = (self.0.code, self.0.reason);
|
let (code, reason) = (self.0.code, self.0.reason);
|
||||||
tokens.extend(quote!(rocket::http::Status { code: #code, reason: #reason }));
|
tokens.extend(quote!(rocket::http::Status { code: #code, reason: #reason }));
|
||||||
}
|
}
|
||||||
|
@ -68,7 +69,7 @@ impl FromMeta for ContentType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for ContentType {
|
impl ToTokens for ContentType {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
// Yeah, yeah. (((((i))).kn0w()))
|
// Yeah, yeah. (((((i))).kn0w()))
|
||||||
let media_type = MediaType((self.0).clone().0);
|
let media_type = MediaType((self.0).clone().0);
|
||||||
tokens.extend(quote!(::rocket::http::ContentType(#media_type)));
|
tokens.extend(quote!(::rocket::http::ContentType(#media_type)));
|
||||||
|
@ -81,9 +82,10 @@ impl FromMeta for MediaType {
|
||||||
.ok_or(meta.value_span().error("invalid or unknown media type"))?;
|
.ok_or(meta.value_span().error("invalid or unknown media type"))?;
|
||||||
|
|
||||||
if !mt.is_known() {
|
if !mt.is_known() {
|
||||||
|
// FIXME(diag: warning)
|
||||||
meta.value_span()
|
meta.value_span()
|
||||||
.warning(format!("'{}' is not a known media type", mt))
|
.warning(format!("'{}' is not a known media type", mt))
|
||||||
.emit();
|
.emit_as_tokens();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(MediaType(mt))
|
Ok(MediaType(mt))
|
||||||
|
@ -91,7 +93,7 @@ impl FromMeta for MediaType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for MediaType {
|
impl ToTokens for MediaType {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
let (top, sub) = (self.0.top().as_str(), self.0.sub().as_str());
|
let (top, sub) = (self.0.top().as_str(), self.0.sub().as_str());
|
||||||
let (keys, values) = self.0.params().split2();
|
let (keys, values) = self.0.params().split2();
|
||||||
|
@ -150,7 +152,7 @@ impl FromMeta for Method {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for Method {
|
impl ToTokens for Method {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
let method_tokens = match self.0 {
|
let method_tokens = match self.0 {
|
||||||
http::Method::Get => quote!(::rocket::http::Method::Get),
|
http::Method::Get => quote!(::rocket::http::Method::Get),
|
||||||
http::Method::Put => quote!(::rocket::http::Method::Put),
|
http::Method::Put => quote!(::rocket::http::Method::Put),
|
||||||
|
@ -234,7 +236,7 @@ impl FromMeta for RoutePath {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ToTokens> ToTokens for Optional<T> {
|
impl<T: ToTokens> ToTokens for Optional<T> {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
define_vars_and_mods!(_Some, _None);
|
define_vars_and_mods!(_Some, _None);
|
||||||
let opt_tokens = match self.0 {
|
let opt_tokens = match self.0 {
|
||||||
Some(ref val) => quote!(#_Some(#val)),
|
Some(ref val) => quote!(#_Some(#val)),
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![feature(proc_macro_diagnostic, proc_macro_span)]
|
|
||||||
#![recursion_limit="128"]
|
#![recursion_limit="128"]
|
||||||
|
|
||||||
#![doc(html_root_url = "https://api.rocket.rs/v0.5")]
|
#![doc(html_root_url = "https://api.rocket.rs/v0.5")]
|
||||||
|
@ -101,6 +100,7 @@ vars_and_mods! {
|
||||||
_Ok => ::std::result::Result::Ok,
|
_Ok => ::std::result::Result::Ok,
|
||||||
_Err => ::std::result::Result::Err,
|
_Err => ::std::result::Result::Err,
|
||||||
_Box => ::std::boxed::Box,
|
_Box => ::std::boxed::Box,
|
||||||
|
_Vec => ::std::vec::Vec,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! define_vars_and_mods {
|
macro_rules! define_vars_and_mods {
|
||||||
|
@ -118,7 +118,7 @@ mod syn_ext;
|
||||||
|
|
||||||
use crate::http::Method;
|
use crate::http::Method;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use devise::proc_macro2;
|
use devise::{proc_macro2, syn};
|
||||||
|
|
||||||
static ROUTE_STRUCT_PREFIX: &str = "static_rocket_route_info_for_";
|
static ROUTE_STRUCT_PREFIX: &str = "static_rocket_route_info_for_";
|
||||||
static CATCH_STRUCT_PREFIX: &str = "static_rocket_catch_info_for_";
|
static CATCH_STRUCT_PREFIX: &str = "static_rocket_catch_info_for_";
|
||||||
|
@ -129,15 +129,19 @@ static ROCKET_PARAM_PREFIX: &str = "__rocket_param_";
|
||||||
|
|
||||||
macro_rules! emit {
|
macro_rules! emit {
|
||||||
($tokens:expr) => ({
|
($tokens:expr) => ({
|
||||||
let tokens = $tokens;
|
use devise::ext::SpanDiagnosticExt;
|
||||||
|
|
||||||
|
let mut tokens = $tokens;
|
||||||
if std::env::var_os("ROCKET_CODEGEN_DEBUG").is_some() {
|
if std::env::var_os("ROCKET_CODEGEN_DEBUG").is_some() {
|
||||||
proc_macro::Span::call_site()
|
let debug_tokens = proc_macro2::Span::call_site()
|
||||||
.note("emitting Rocket code generation debug output")
|
.note("emitting Rocket code generation debug output")
|
||||||
.note(tokens.to_string())
|
.note(tokens.to_string())
|
||||||
.emit()
|
.emit_as_tokens();
|
||||||
|
|
||||||
|
tokens.extend(debug_tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens
|
tokens.into()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use std::ops::RangeBounds;
|
use std::ops::RangeBounds;
|
||||||
|
|
||||||
use proc_macro::{Span, Diagnostic, Literal};
|
use devise::Diagnostic;
|
||||||
|
|
||||||
|
use crate::proc_macro2::{Span, Literal};
|
||||||
|
|
||||||
pub type PResult<T> = std::result::Result<T, Diagnostic>;
|
pub type PResult<T> = std::result::Result<T, Diagnostic>;
|
||||||
|
|
||||||
|
@ -27,7 +29,8 @@ impl Diagnostics {
|
||||||
let mut iter = self.0.into_iter();
|
let mut iter = self.0.into_iter();
|
||||||
let mut last = iter.next().expect("Diagnostic::emit_head empty");
|
let mut last = iter.next().expect("Diagnostic::emit_head empty");
|
||||||
for diag in iter {
|
for diag in iter {
|
||||||
last.emit();
|
// FIXME(diag: emit, can there be errors here?)
|
||||||
|
last.emit_as_tokens();
|
||||||
last = diag;
|
last = diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +89,8 @@ impl StringLit {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to obtain a subspan, or, failing that, produce the full span.
|
/// Attempt to obtain a subspan, or, failing that, produce the full span.
|
||||||
/// This will create suboptimal diagnostics, but better than failing to build entirely.
|
/// This will create suboptimal diagnostics, but better than failing to
|
||||||
|
/// build entirely.
|
||||||
pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Span {
|
pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Span {
|
||||||
self.1.subspan(range).unwrap_or_else(|| self.span())
|
self.1.subspan(range).unwrap_or_else(|| self.span())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
//! Extensions to `syn` types.
|
//! Extensions to `syn` types.
|
||||||
|
|
||||||
use devise::syn;
|
use devise::syn;
|
||||||
use proc_macro::Diagnostic;
|
|
||||||
|
|
||||||
pub fn syn_to_diag(error: syn::parse::Error) -> Diagnostic {
|
|
||||||
error.span().unstable().error(error.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait IdentExt {
|
pub trait IdentExt {
|
||||||
fn prepend(&self, string: &str) -> syn::Ident;
|
fn prepend(&self, string: &str) -> syn::Ident;
|
||||||
|
|
|
@ -22,7 +22,7 @@ enum Foo4 {
|
||||||
|
|
||||||
#[derive(FromFormValue)]
|
#[derive(FromFormValue)]
|
||||||
enum Foo5 { }
|
enum Foo5 { }
|
||||||
//~^ WARNING empty enum
|
//~^ ERROR at least one field
|
||||||
|
|
||||||
#[derive(FromFormValue)]
|
#[derive(FromFormValue)]
|
||||||
enum Foo6<T> {
|
enum Foo6<T> {
|
||||||
|
|
|
@ -53,11 +53,18 @@ note: error occurred while deriving `FromFormValue`
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
warning: deriving for empty enum
|
error: enum must have at least one field
|
||||||
--> $DIR/from_form_value.rs:24:1
|
--> $DIR/from_form_value.rs:24:1
|
||||||
|
|
|
|
||||||
24 | enum Foo5 { }
|
24 | enum Foo5 { }
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: error occurred while deriving `FromFormValue`
|
||||||
|
--> $DIR/from_form_value.rs:23:10
|
||||||
|
|
|
||||||
|
23 | #[derive(FromFormValue)]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: type generics are not supported
|
error: type generics are not supported
|
||||||
--> $DIR/from_form_value.rs:28:11
|
--> $DIR/from_form_value.rs:28:11
|
||||||
|
@ -98,5 +105,5 @@ note: error occurred while deriving `FromFormValue`
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 7 previous errors; 1 warning emitted
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
|
|
@ -51,10 +51,10 @@ note: error occurred while deriving `UriDisplay`
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: tuple structs or variants must have exactly one field
|
error: tuple structs or variants must have exactly one field
|
||||||
--> $DIR/uri_display.rs:39:12
|
--> $DIR/uri_display.rs:39:13
|
||||||
|
|
|
|
||||||
39 | struct Foo5(String, String);
|
39 | struct Foo5(String, String);
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: error occurred while deriving `UriDisplay`
|
note: error occurred while deriving `UriDisplay`
|
||||||
--> $DIR/uri_display.rs:35:10
|
--> $DIR/uri_display.rs:35:10
|
||||||
|
@ -77,10 +77,10 @@ note: error occurred while deriving `UriDisplay`
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: struct must have exactly one field
|
error: struct must have exactly one field
|
||||||
--> $DIR/uri_display.rs:55:12
|
--> $DIR/uri_display.rs:55:13
|
||||||
|
|
|
|
||||||
55 | struct Foo7(String, usize);
|
55 | struct Foo7(String, usize);
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: error occurred while deriving `UriDisplay`
|
note: error occurred while deriving `UriDisplay`
|
||||||
--> $DIR/uri_display.rs:52:10
|
--> $DIR/uri_display.rs:52:10
|
||||||
|
|
|
@ -8,7 +8,6 @@ publish = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { path = "../../core/lib" }
|
rocket = { path = "../../core/lib" }
|
||||||
lazy_static = "1.0"
|
lazy_static = "1.0"
|
||||||
uuid = "0.8"
|
|
||||||
|
|
||||||
[dependencies.rocket_contrib]
|
[dependencies.rocket_contrib]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
#[macro_use] extern crate lazy_static;
|
#[macro_use] extern crate lazy_static;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use rocket_contrib::uuid::Uuid;
|
use rocket_contrib::uuid::Uuid;
|
||||||
|
use rocket_contrib::uuid::uuid_crate as uuid;
|
||||||
|
|
||||||
#[cfg(test)] mod tests;
|
#[cfg(test)] mod tests;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue