From 4fd5464e448925ac5a3ce52be15e961f397370f3 Mon Sep 17 00:00:00 2001 From: Dominic Date: Mon, 23 Nov 2020 01:22:03 +0100 Subject: [PATCH] get rid of mod's in error messages --- derive/src/method.rs | 161 ++++++++++++++------------- derive/src/resource.rs | 3 +- tests/ui/method_async_state.stderr | 16 --- tests/ui/method_no_resource.stderr | 4 +- tests/ui/method_self.stderr | 10 +- tests/ui/method_too_few_args.stderr | 8 -- tests/ui/method_too_many_args.stderr | 8 -- tests/ui/method_unsafe.stderr | 8 -- 8 files changed, 91 insertions(+), 127 deletions(-) diff --git a/derive/src/method.rs b/derive/src/method.rs index f892734..c9e5056 100644 --- a/derive/src/method.rs +++ b/derive/src/method.rs @@ -4,7 +4,7 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote}; use std::str::FromStr; use syn::{ - spanned::Spanned, Attribute, AttributeArgs, Error, FnArg, ItemFn, Lit, LitBool, Meta, NestedMeta, PatType, Result, + spanned::Spanned, Attribute, AttributeArgs, Error, FnArg, ItemFn, Lit, LitBool, Meta, NestedMeta, PatType, Path, Result, ReturnType, Type }; @@ -82,20 +82,12 @@ impl Method { format_ident!("{}", name) } - pub fn mod_ident(&self, resource: &str) -> Ident { - format_ident!( - "_gotham_restful_resource_{}_method_{}", - resource.to_snake_case(), - self.fn_ident() - ) - } - pub fn handler_struct_ident(&self, resource: &str) -> Ident { format_ident!("{}{}Handler", resource.to_camel_case(), self.trait_ident()) } pub fn setup_ident(&self, resource: &str) -> Ident { - format_ident!("{}_{}_setup_impl", resource.to_snake_case(), self.fn_ident()) + format_ident!("_gotham_restful_{}_{}_setup_impl", resource.to_snake_case(), self.fn_ident()) } } @@ -249,33 +241,16 @@ fn expand_wants_auth(attrs: &[NestedMeta], default: bool) -> TokenStream { } #[allow(clippy::comparison_chain)] -pub fn expand_method(method: Method, mut attrs: AttributeArgs, fun: ItemFn) -> Result { +fn setup_body( + method: &Method, + fun: &ItemFn, + attrs: &[NestedMeta], + resource_name: &str, + resource_path: &Path +) -> Result { let krate = super::krate(); - // parse attributes - if attrs.len() < 1 { - return Err(Error::new( - Span::call_site(), - "Missing Resource struct. Example: #[read_all(MyResource)]" - )); - } - let resource_path = match attrs.remove(0) { - NestedMeta::Meta(Meta::Path(path)) => path, - p => { - return Err(Error::new( - p.span(), - "Expected name of the Resource struct this method belongs to" - )) - }, - }; - let resource_name = resource_path - .segments - .last() - .map(|s| s.ident.to_string()) - .ok_or_else(|| Error::new(resource_path.span(), "Resource name must not be empty"))?; - let fun_ident = &fun.sig.ident; - let fun_vis = &fun.vis; let fun_is_async = fun.sig.asyncness.is_some(); if let Some(unsafety) = fun.sig.unsafety { @@ -284,9 +259,7 @@ pub fn expand_method(method: Method, mut attrs: AttributeArgs, fun: ItemFn) -> R let trait_ident = method.trait_ident(); let method_ident = method.fn_ident(); - let mod_ident = method.mod_ident(&resource_name); - let handler_ident = method.handler_struct_ident(&resource_name); - let setup_ident = method.setup_ident(&resource_name); + let handler_ident = method.handler_struct_ident(resource_name); let (ret, is_no_content) = match &fun.sig.output { ReturnType::Default => (quote!(#krate::NoContent), true), @@ -410,52 +383,84 @@ pub fn expand_method(method: Method, mut attrs: AttributeArgs, fun: ItemFn) -> R } // attribute generated code - let operation_id = expand_operation_id(&attrs); - let wants_auth = expand_wants_auth(&attrs, args.iter().any(|arg| (*arg).ty.is_auth_status())); + let operation_id = expand_operation_id(attrs); + let wants_auth = expand_wants_auth(attrs, args.iter().any(|arg| (*arg).ty.is_auth_status())); // put everything together + let mut dummy = format_ident!("_IMPL_RESOURCEMETHOD_FOR_{}", fun_ident); + dummy.set_span(Span::call_site()); + Ok(quote! { + struct #handler_ident; + + impl #krate::ResourceMethod for #handler_ident { + type Res = #ret; + + #operation_id + #wants_auth + } + + impl #krate::#trait_ident for #handler_ident + where #where_clause + { + #(#generics)* + + fn #method_ident(#(#args_def),*) -> std::pin::Pin + Send>> { + #[allow(unused_imports)] + use #krate::{export::FutureExt, FromState}; + + #state_block + + async move { + let #res_ident = { #block }; + (#state_ident, #res_ident) + }.boxed() + } + } + + route.#method_ident::<#handler_ident>(); + }) +} + +pub fn expand_method(method: Method, mut attrs: AttributeArgs, fun: ItemFn) -> Result { + let krate = super::krate(); + + // parse attributes + if attrs.len() < 1 { + return Err(Error::new( + Span::call_site(), + "Missing Resource struct. Example: #[read_all(MyResource)]" + )); + } + let resource_path = match attrs.remove(0) { + NestedMeta::Meta(Meta::Path(path)) => path, + p => { + return Err(Error::new( + p.span(), + "Expected name of the Resource struct this method belongs to" + )) + }, + }; + let resource_name = resource_path + .segments + .last() + .map(|s| s.ident.to_string()) + .ok_or_else(|| Error::new(resource_path.span(), "Resource name must not be empty"))?; + + let fun_vis = &fun.vis; + let setup_ident = method.setup_ident(&resource_name); + let setup_body = match setup_body(&method, &fun, &attrs, &resource_name, &resource_path) { + Ok(body) => body, + Err(err) => err.to_compile_error() + }; + Ok(quote! { #fun - #fun_vis mod #mod_ident - { - use super::*; - - struct #handler_ident; - - impl #krate::ResourceMethod for #handler_ident - { - type Res = #ret; - - #operation_id - #wants_auth - } - - impl #krate::#trait_ident for #handler_ident - where #where_clause - { - #(#generics)* - - fn #method_ident(#(#args_def),*) -> std::pin::Pin + Send>> - { - #[allow(unused_imports)] - use #krate::{export::FutureExt, FromState}; - - #state_block - - async move { - let #res_ident = { #block }; - (#state_ident, #res_ident) - }.boxed() - } - } - - #[deny(dead_code)] - pub fn #setup_ident(route : &mut D) - { - route.#method_ident::<#handler_ident>(); - } - + #[deny(dead_code)] + #[doc(hidden)] + /// `gotham_restful` implementation detail. + #fun_vis fn #setup_ident(route : &mut D) { + #setup_body } }) } diff --git a/derive/src/resource.rs b/derive/src/resource.rs index a81e6d9..60ae159 100644 --- a/derive/src/resource.rs +++ b/derive/src/resource.rs @@ -38,9 +38,8 @@ pub fn expand_resource(input: DeriveInput) -> Result { .flat_map(|list| match list { Ok(iter) => Box::new(iter.map(|method| { let method = Method::from_str(&method.to_string()).map_err(|err| Error::new(method.span(), err))?; - let mod_ident = method.mod_ident(&name); let ident = method.setup_ident(&name); - Ok(quote!(#mod_ident::#ident(&mut route);)) + Ok(quote!(#ident(&mut route);)) })) as Box>>, Err(err) => Box::new(iter::once(Err(err))) }) diff --git a/tests/ui/method_async_state.stderr b/tests/ui/method_async_state.stderr index f66a260..571c334 100644 --- a/tests/ui/method_async_state.stderr +++ b/tests/ui/method_async_state.stderr @@ -3,19 +3,3 @@ error: async fn must not take &State as an argument as State is not Sync, consid | 9 | async fn read_all(state : &State) | ^^^^^ - -error[E0433]: failed to resolve: use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` - --> $DIR/method_async_state.rs:4:10 - | -4 | #[derive(Resource)] - | ^^^^^^^^ use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` - | - = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) - -warning: unused import: `gotham_restful::State` - --> $DIR/method_async_state.rs:2:5 - | -2 | use gotham_restful::State; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/tests/ui/method_no_resource.stderr b/tests/ui/method_no_resource.stderr index d5c5521..1cddd9e 100644 --- a/tests/ui/method_no_resource.stderr +++ b/tests/ui/method_no_resource.stderr @@ -6,10 +6,10 @@ error: Missing Resource struct. Example: #[read_all(MyResource)] | = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` +error[E0425]: cannot find function `_gotham_restful_foo_resource_read_all_setup_impl` in this scope --> $DIR/method_no_resource.rs:3:10 | 3 | #[derive(Resource)] - | ^^^^^^^^ use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` + | ^^^^^^^^ not found in this scope | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/method_self.stderr b/tests/ui/method_self.stderr index 0e4b492..1ad62ca 100644 --- a/tests/ui/method_self.stderr +++ b/tests/ui/method_self.stderr @@ -4,10 +4,10 @@ error: Didn't expect self parameter 8 | fn read_all(self) | ^^^^ -error[E0433]: failed to resolve: use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` - --> $DIR/method_self.rs:3:10 +error: `self` parameter is only allowed in associated functions + --> $DIR/method_self.rs:8:13 | -3 | #[derive(Resource)] - | ^^^^^^^^ use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` +8 | fn read_all(self) + | ^^^^ not semantically valid as function parameter | - = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + = note: associated functions are those in `impl` or `trait` definitions diff --git a/tests/ui/method_too_few_args.stderr b/tests/ui/method_too_few_args.stderr index 0aed829..2036d86 100644 --- a/tests/ui/method_too_few_args.stderr +++ b/tests/ui/method_too_few_args.stderr @@ -3,11 +3,3 @@ error: Too few arguments | 8 | fn read() | ^^^^ - -error[E0433]: failed to resolve: use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read` - --> $DIR/method_too_few_args.rs:3:10 - | -3 | #[derive(Resource)] - | ^^^^^^^^ use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read` - | - = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/method_too_many_args.stderr b/tests/ui/method_too_many_args.stderr index ad8a37b..0c251e4 100644 --- a/tests/ui/method_too_many_args.stderr +++ b/tests/ui/method_too_many_args.stderr @@ -3,11 +3,3 @@ error: Too many arguments | 8 | fn read_all(_id : u64) | ^^^ - -error[E0433]: failed to resolve: use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` - --> $DIR/method_too_many_args.rs:3:10 - | -3 | #[derive(Resource)] - | ^^^^^^^^ use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` - | - = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/method_unsafe.stderr b/tests/ui/method_unsafe.stderr index ad42326..92308bf 100644 --- a/tests/ui/method_unsafe.stderr +++ b/tests/ui/method_unsafe.stderr @@ -3,11 +3,3 @@ error: Resource methods must not be unsafe | 8 | unsafe fn read_all() | ^^^^^^ - -error[E0433]: failed to resolve: use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` - --> $DIR/method_unsafe.rs:3:10 - | -3 | #[derive(Resource)] - | ^^^^^^^^ use of undeclared crate or module `_gotham_restful_resource_foo_resource_method_read_all` - | - = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)