diff --git a/tonic-build/src/client.rs b/tonic-build/src/client.rs index a104eb7..15cf1da 100644 --- a/tonic-build/src/client.rs +++ b/tonic-build/src/client.rs @@ -1,4 +1,4 @@ -use crate::generate_doc_comments; +use crate::{generate_doc_comment, generate_doc_comments}; use proc_macro2::TokenStream; use prost_build::{Method, Service}; use quote::{format_ident, quote}; @@ -30,6 +30,7 @@ pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream { Self { inner } } + /// Check if the service is ready. pub async fn ready(&mut self) -> Result<(), tonic::Status> { self.inner.ready().await.map_err(|e| { tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into())) @@ -51,8 +52,19 @@ pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream { #[cfg(feature = "transport")] fn generate_connect(service_ident: &syn::Ident) -> TokenStream { + let doc_example = format!( + "let client = {}::connect(\"http://[::1]:50051\")?;", + service_ident + ); + let doc_example = generate_doc_comment(&doc_example); + quote! { impl #service_ident { + /// Attempt to create a new client by connecting to a given endpoint. + /// + /// ```rust,no_run + #doc_example + /// ``` pub fn connect(dst: D) -> Result where D: std::convert::TryInto, diff --git a/tonic-build/src/lib.rs b/tonic-build/src/lib.rs index f684892..9038379 100644 --- a/tonic-build/src/lib.rs +++ b/tonic-build/src/lib.rs @@ -171,6 +171,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator { let clients = &self.clients; let client_service = quote::quote! { + /// Generated client implementations. pub mod client { #![allow(unused_variables, dead_code, missing_docs)] use tonic::codegen::*; @@ -187,6 +188,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator { let servers = &self.servers; let server_service = quote::quote! { + /// Generated server implementations. pub mod server { #![allow(unused_variables, dead_code, missing_docs)] use tonic::codegen::*; @@ -202,7 +204,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator { } // Generate a singular line of a doc comment -fn generate_doc_comment(comment: &str, stream: &mut TokenStream) { +fn generate_doc_comment(comment: &str) -> TokenStream { let mut doc_stream = TokenStream::new(); doc_stream.append(Ident::new("doc", Span::call_site())); @@ -211,8 +213,10 @@ fn generate_doc_comment(comment: &str, stream: &mut TokenStream) { let group = Group::new(Delimiter::Bracket, doc_stream); + let mut stream = TokenStream::new(); stream.append(Punct::new('#', Spacing::Alone)); stream.append(group); + stream } // Generate a larger doc comment composed of many lines of doc comments @@ -220,7 +224,7 @@ fn generate_doc_comments>(comments: &[T]) -> TokenStream { let mut stream = TokenStream::new(); for comment in comments { - generate_doc_comment(comment.as_ref(), &mut stream); + stream.extend(generate_doc_comment(comment.as_ref())); } stream diff --git a/tonic-build/src/service.rs b/tonic-build/src/service.rs index 4099fc2..2b0e5b4 100644 --- a/tonic-build/src/service.rs +++ b/tonic-build/src/service.rs @@ -1,4 +1,4 @@ -use crate::generate_doc_comments; +use crate::{generate_doc_comment, generate_doc_comments}; use proc_macro2::{Span, TokenStream}; use prost_build::{Method, Service}; use quote::quote; @@ -12,6 +12,10 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream { let server_trait = quote::format_ident!("{}", service.name); let generated_trait = generate_trait(service, proto_path, server_trait.clone()); let service_doc = generate_doc_comments(&service.comments.leading); + let server_new_doc = generate_doc_comment(&format!( + "Create a new {} from a type that implements {}.", + server_make_service, server_trait + )); quote! { #generated_trait @@ -29,6 +33,7 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream { } impl #server_make_service { + #server_new_doc pub fn new(inner: T) -> Self { let inner = Arc::new(inner); Self::from_shared(inner) @@ -84,8 +89,13 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream { fn generate_trait(service: &Service, proto_path: &str, server_trait: Ident) -> TokenStream { let methods = generate_trait_methods(service, proto_path); + let trait_doc = generate_doc_comment(&format!( + "Generated trait containing gRPC methods that should be implemented for use with {}Server.", + service.name + )); quote! { + #trait_doc #[async_trait] pub trait #server_trait : Send + Sync + 'static { #methods @@ -103,35 +113,51 @@ fn generate_trait_methods(service: &Service, proto_path: &str) -> TokenStream { let res_message: Path = syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap(); + let method_doc = generate_doc_comments(&method.comments.leading); + let method = match (method.client_streaming, method.server_streaming) { (false, false) => { quote! { + #method_doc async fn #name(&self, request: tonic::Request<#req_message>) -> Result, tonic::Status>; } } (true, false) => { quote! { + #method_doc async fn #name(&self, request: tonic::Request>) -> Result, tonic::Status>; } } (false, true) => { let stream = quote::format_ident!("{}Stream", method.proto_name); + let stream_doc = generate_doc_comment(&format!( + "Server streaming response type for the {} method.", + method.proto_name + )); quote! { + #stream_doc type #stream: Stream> + Send + 'static; + #method_doc async fn #name(&self, request: tonic::Request<#req_message>) -> Result, tonic::Status>; } } (true, true) => { let stream = quote::format_ident!("{}Stream", method.proto_name); + let stream_doc = generate_doc_comment(&format!( + "Server streaming response type for the {} method.", + method.proto_name + )); quote! { + #stream_doc type #stream: Stream> + Send + 'static; + #method_doc async fn #name(&self, request: tonic::Request>) -> Result, tonic::Status>; }