More documentation generation (#12)

* generate rustdoc comments from .proto file comments

* move imports to top of file

* more docs gen

* trait docs

* more docs

* use singular doc gen fn here

* remove pesky space
This commit is contained in:
John Doneth
2019-09-26 19:41:51 -04:00
committed by Lucio Franco
parent d2355ed83c
commit 8becd257bc
3 changed files with 46 additions and 4 deletions
+13 -1
View File
@@ -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<tonic::transport::Channel> {
/// Attempt to create a new client by connecting to a given endpoint.
///
/// ```rust,no_run
#doc_example
/// ```
pub fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
where
D: std::convert::TryInto<tonic::transport::Endpoint>,
+6 -2
View File
@@ -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<T: AsRef<str>>(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
+27 -1
View File
@@ -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<T: #server_trait> #server_make_service<T> {
#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::Response<#res_message>, tonic::Status>;
}
}
(true, false) => {
quote! {
#method_doc
async fn #name(&self, request: tonic::Request<tonic::Streaming<#req_message>>)
-> Result<tonic::Response<#res_message>, 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<Item = Result<#res_message, tonic::Status>> + Send + 'static;
#method_doc
async fn #name(&self, request: tonic::Request<#req_message>)
-> Result<tonic::Response<Self::#stream>, 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<Item = Result<#res_message, tonic::Status>> + Send + 'static;
#method_doc
async fn #name(&self, request: tonic::Request<tonic::Streaming<#req_message>>)
-> Result<tonic::Response<Self::#stream>, tonic::Status>;
}