From 166fbf68913f7b2d1e8769f9fb8fb67a493f79a9 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Sun, 17 Jan 2016 23:21:27 -0800 Subject: [PATCH 1/3] Allow attributes on the generated module. If no doc attribute is present, sets a default doc comment for the module. --- tarpc/src/lib.rs | 2 +- tarpc/src/macros.rs | 227 ++++++++++++++++++++++++++++++++------------ 2 files changed, 169 insertions(+), 60 deletions(-) diff --git a/tarpc/src/lib.rs b/tarpc/src/lib.rs index 3de785b..6f866e9 100644 --- a/tarpc/src/lib.rs +++ b/tarpc/src/lib.rs @@ -42,7 +42,7 @@ //! ``` #![deny(missing_docs)] -#![feature(custom_derive, plugin)] +#![feature(custom_derive, plugin, trace_macros)] #![plugin(serde_macros)] extern crate serde; diff --git a/tarpc/src/macros.rs b/tarpc/src/macros.rs index db57768..d3017e8 100644 --- a/tarpc/src/macros.rs +++ b/tarpc/src/macros.rs @@ -1,7 +1,73 @@ +trace_macros!(true); + #[doc(hidden)] #[macro_export] macro_rules! as_item { ($i:item) => {$i} } +// Inserts a placeholder doc comment for the module if it's missing +#[doc(hidden)] +#[macro_export] +macro_rules! add_mod_doc { + // If nothing left, return + ( + @rec + { $(#[$done:meta])* } + { } + $i:item + ) => { + $(#[$done])* + #[doc="A module containing an rpc service and client stub."] + $i + }; + + // If we find a doc attribute, return + ( + @rec + { $(#[$done:meta])* } + { + #[doc=$doc:expr] + $(#[$rest:meta])* + } + $i:item + ) => { + $(#[$done])* + #[doc=$doc] + $(#[$rest])* + $i + }; + + // If we don't find a doc attribute, keep going + ( + @rec + { $(#[$($done:tt)*])* } + { + #[$($attr:tt)*] + $($rest:tt)* + } + $i:item + ) => { + add_mod_doc! { + @rec + { $(#[$($done)*])* #[$($attr)*] } + { $($rest)* } + $i + } + }; + + // Entry + ( + { $(#[$($attr:tt)*])* } + $i:item + ) => { + add_mod_doc! { + @rec + {} + { $(#[$($attr)*])* } + $i + } + }; +} + // Required because if-let can't be used with irrefutable patterns, so it needs // to be special cased. #[doc(hidden)] @@ -62,6 +128,7 @@ macro_rules! request_variant { #[macro_export] macro_rules! rpc { ( + $(#[$($service_attr:tt)*])* mod $server:ident { service { @@ -73,6 +140,7 @@ macro_rules! rpc { } ) => { rpc! { + $(#[$($service_attr)*])* mod $server { items { } @@ -89,6 +157,7 @@ macro_rules! rpc { ( // Names the service + $(#[$($service_attr:tt)*])* mod $server:ident { // Include any desired or required items. Conflicts can arise with the following names: @@ -108,77 +177,80 @@ macro_rules! rpc { } } ) => { - #[doc="A module containing an rpc service and client stub."] - pub mod $server { - $($i)* + add_mod_doc! { + { $(#[$($service_attr)*])* } + pub mod $server { - #[doc="The provided RPC service."] - pub trait Service: Send + Sync { - $( - $(#[$attr])* - fn $fn_name(&self, $($arg:$in_),*) -> $out; - )* - } + $($i)* - define_request!($($fn_name($($in_),*))*); - - #[allow(non_camel_case_types)] - #[derive(Debug, Serialize, Deserialize)] - enum __Reply { - $( - $fn_name($out), - )* - } - - #[doc="The client stub that makes RPC calls to the server."] - pub struct Client($crate::protocol::Client<__Request, __Reply>); - - impl Client { - #[doc="Create a new client that connects to the given address."] - pub fn new(addr: A, timeout: ::std::option::Option<::std::time::Duration>) - -> $crate::Result - where A: ::std::net::ToSocketAddrs, - { - let inner = try!($crate::protocol::Client::new(addr, timeout)); - Ok(Client(inner)) + #[doc="The provided RPC service."] + pub trait Service: Send + Sync { + $( + $(#[$attr])* + fn $fn_name(&self, $($arg:$in_),*) -> $out; + )* } - client_methods!( + define_request!($($fn_name($($in_),*))*); + + #[allow(non_camel_case_types)] + #[derive(Debug, Serialize, Deserialize)] + enum __Reply { $( - { $(#[$attr])* } - $fn_name($($arg: $in_),*) -> $out + $fn_name($out), )* - ); - } + } - struct __Server(S); + #[doc="The client stub that makes RPC calls to the server."] + pub struct Client($crate::protocol::Client<__Request, __Reply>); - impl $crate::protocol::Serve for __Server - where S: 'static + Service - { - type Request = __Request; - type Reply = __Reply; - fn serve(&self, request: __Request) -> __Reply { - match request { + impl Client { + #[doc="Create a new client that connects to the given address."] + pub fn new(addr: A, timeout: ::std::option::Option<::std::time::Duration>) + -> $crate::Result + where A: ::std::net::ToSocketAddrs, + { + let inner = try!($crate::protocol::Client::new(addr, timeout)); + Ok(Client(inner)) + } + + client_methods!( $( - request_variant!($fn_name $($arg),*) => - __Reply::$fn_name((self.0).$fn_name($($arg),*)), - )* + { $(#[$attr])* } + $fn_name($($arg: $in_),*) -> $out + )* + ); + } + + struct __Server(S); + + impl $crate::protocol::Serve for __Server + where S: 'static + Service + { + type Request = __Request; + type Reply = __Reply; + fn serve(&self, request: __Request) -> __Reply { + match request { + $( + request_variant!($fn_name $($arg),*) => + __Reply::$fn_name((self.0).$fn_name($($arg),*)), + )* + } } } - } - #[doc="Start a running service."] - pub fn serve(addr: A, - service: S, - read_timeout: ::std::option::Option<::std::time::Duration>) - -> $crate::Result<$crate::protocol::ServeHandle> - where A: ::std::net::ToSocketAddrs, - S: 'static + Service - { - let server = ::std::sync::Arc::new(__Server(service)); - Ok(try!($crate::protocol::serve_async(addr, server, read_timeout))) + #[doc="Start a running service."] + pub fn serve(addr: A, + service: S, + read_timeout: ::std::option::Option<::std::time::Duration>) + -> $crate::Result<$crate::protocol::ServeHandle> + where A: ::std::net::ToSocketAddrs, + S: 'static + Service + { + let server = ::std::sync::Arc::new(__Server(service)); + Ok(try!($crate::protocol::serve_async(addr, server, read_timeout))) + } } } } @@ -194,6 +266,8 @@ mod test { } rpc! { + #[deny(missing_docs)] + #[doc="Hello"] mod my_server { items { #[derive(PartialEq, Debug, Serialize, Deserialize)] @@ -237,7 +311,7 @@ mod test { // Tests a service definition with a fn that takes no args rpc! { - mod foo { + mod qux { service { rpc hello() -> String; } @@ -246,6 +320,22 @@ mod test { // Tests a service definition with an import rpc! { + mod foo { + items { + use std::collections::HashMap; + } + + service { + #[doc="Hello bob"] + #[inline(always)] + rpc baz(s: String) -> HashMap; + } + } + } + + // Tests a service definition with an attribute but no doc comment + rpc! { + #[deny(missing_docs)] mod bar { items { use std::collections::HashMap; @@ -253,6 +343,25 @@ mod test { service { #[doc="Hello bob"] + #[inline(always)] + rpc baz(s: String) -> HashMap; + } + } + } + + // Tests a service definition with an attribute and a doc comment + rpc! { + #[deny(missing_docs)] + #[doc="Hello bob"] + #[allow(unused)] + mod baz { + items { + use std::collections::HashMap; + } + + service { + #[doc="Hello bob"] + #[inline(always)] rpc baz(s: String) -> HashMap; } } From ce12f4a981baa150910ea4b2860c9fcf6263d129 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Sun, 17 Jan 2016 23:22:47 -0800 Subject: [PATCH 2/3] rm trace macros again --- tarpc/src/lib.rs | 2 +- tarpc/src/macros.rs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tarpc/src/lib.rs b/tarpc/src/lib.rs index 6f866e9..3de785b 100644 --- a/tarpc/src/lib.rs +++ b/tarpc/src/lib.rs @@ -42,7 +42,7 @@ //! ``` #![deny(missing_docs)] -#![feature(custom_derive, plugin, trace_macros)] +#![feature(custom_derive, plugin)] #![plugin(serde_macros)] extern crate serde; diff --git a/tarpc/src/macros.rs b/tarpc/src/macros.rs index d3017e8..4670030 100644 --- a/tarpc/src/macros.rs +++ b/tarpc/src/macros.rs @@ -1,5 +1,3 @@ -trace_macros!(true); - #[doc(hidden)] #[macro_export] macro_rules! as_item { ($i:item) => {$i} } From 57e39c77f7560fb3ae7e565c5253f01f5bcd8a79 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Sun, 24 Jan 2016 16:57:56 -0800 Subject: [PATCH 3/3] Expand macro invocation test for attributes on items in the items { } block --- tarpc/src/macros.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tarpc/src/macros.rs b/tarpc/src/macros.rs index 4670030..53fbde0 100644 --- a/tarpc/src/macros.rs +++ b/tarpc/src/macros.rs @@ -355,6 +355,9 @@ mod test { mod baz { items { use std::collections::HashMap; + + #[derive(Debug)] + pub struct Debuggable; } service { @@ -364,4 +367,9 @@ mod test { } } } + + #[test] + fn debug() { + println!("{:?}", baz::Debuggable); + } }