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:
committed by
Lucio Franco
parent
d2355ed83c
commit
8becd257bc
@@ -1,4 +1,4 @@
|
|||||||
use crate::generate_doc_comments;
|
use crate::{generate_doc_comment, generate_doc_comments};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use prost_build::{Method, Service};
|
use prost_build::{Method, Service};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
@@ -30,6 +30,7 @@ pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream {
|
|||||||
Self { inner }
|
Self { inner }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the service is ready.
|
||||||
pub async fn ready(&mut self) -> Result<(), tonic::Status> {
|
pub async fn ready(&mut self) -> Result<(), tonic::Status> {
|
||||||
self.inner.ready().await.map_err(|e| {
|
self.inner.ready().await.map_err(|e| {
|
||||||
tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into()))
|
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")]
|
#[cfg(feature = "transport")]
|
||||||
fn generate_connect(service_ident: &syn::Ident) -> TokenStream {
|
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! {
|
quote! {
|
||||||
impl #service_ident<tonic::transport::Channel> {
|
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>
|
pub fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
|
||||||
where
|
where
|
||||||
D: std::convert::TryInto<tonic::transport::Endpoint>,
|
D: std::convert::TryInto<tonic::transport::Endpoint>,
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
|
|||||||
let clients = &self.clients;
|
let clients = &self.clients;
|
||||||
|
|
||||||
let client_service = quote::quote! {
|
let client_service = quote::quote! {
|
||||||
|
/// Generated client implementations.
|
||||||
pub mod client {
|
pub mod client {
|
||||||
#![allow(unused_variables, dead_code, missing_docs)]
|
#![allow(unused_variables, dead_code, missing_docs)]
|
||||||
use tonic::codegen::*;
|
use tonic::codegen::*;
|
||||||
@@ -187,6 +188,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
|
|||||||
let servers = &self.servers;
|
let servers = &self.servers;
|
||||||
|
|
||||||
let server_service = quote::quote! {
|
let server_service = quote::quote! {
|
||||||
|
/// Generated server implementations.
|
||||||
pub mod server {
|
pub mod server {
|
||||||
#![allow(unused_variables, dead_code, missing_docs)]
|
#![allow(unused_variables, dead_code, missing_docs)]
|
||||||
use tonic::codegen::*;
|
use tonic::codegen::*;
|
||||||
@@ -202,7 +204,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate a singular line of a doc comment
|
// 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();
|
let mut doc_stream = TokenStream::new();
|
||||||
|
|
||||||
doc_stream.append(Ident::new("doc", Span::call_site()));
|
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 group = Group::new(Delimiter::Bracket, doc_stream);
|
||||||
|
|
||||||
|
let mut stream = TokenStream::new();
|
||||||
stream.append(Punct::new('#', Spacing::Alone));
|
stream.append(Punct::new('#', Spacing::Alone));
|
||||||
stream.append(group);
|
stream.append(group);
|
||||||
|
stream
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a larger doc comment composed of many lines of doc comments
|
// 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();
|
let mut stream = TokenStream::new();
|
||||||
|
|
||||||
for comment in comments {
|
for comment in comments {
|
||||||
generate_doc_comment(comment.as_ref(), &mut stream);
|
stream.extend(generate_doc_comment(comment.as_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
stream
|
stream
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::generate_doc_comments;
|
use crate::{generate_doc_comment, generate_doc_comments};
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use prost_build::{Method, Service};
|
use prost_build::{Method, Service};
|
||||||
use quote::quote;
|
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 server_trait = quote::format_ident!("{}", service.name);
|
||||||
let generated_trait = generate_trait(service, proto_path, server_trait.clone());
|
let generated_trait = generate_trait(service, proto_path, server_trait.clone());
|
||||||
let service_doc = generate_doc_comments(&service.comments.leading);
|
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! {
|
quote! {
|
||||||
#generated_trait
|
#generated_trait
|
||||||
@@ -29,6 +33,7 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: #server_trait> #server_make_service<T> {
|
impl<T: #server_trait> #server_make_service<T> {
|
||||||
|
#server_new_doc
|
||||||
pub fn new(inner: T) -> Self {
|
pub fn new(inner: T) -> Self {
|
||||||
let inner = Arc::new(inner);
|
let inner = Arc::new(inner);
|
||||||
Self::from_shared(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 {
|
fn generate_trait(service: &Service, proto_path: &str, server_trait: Ident) -> TokenStream {
|
||||||
let methods = generate_trait_methods(service, proto_path);
|
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! {
|
quote! {
|
||||||
|
#trait_doc
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait #server_trait : Send + Sync + 'static {
|
pub trait #server_trait : Send + Sync + 'static {
|
||||||
#methods
|
#methods
|
||||||
@@ -103,35 +113,51 @@ fn generate_trait_methods(service: &Service, proto_path: &str) -> TokenStream {
|
|||||||
let res_message: Path =
|
let res_message: Path =
|
||||||
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
|
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) {
|
let method = match (method.client_streaming, method.server_streaming) {
|
||||||
(false, false) => {
|
(false, false) => {
|
||||||
quote! {
|
quote! {
|
||||||
|
#method_doc
|
||||||
async fn #name(&self, request: tonic::Request<#req_message>)
|
async fn #name(&self, request: tonic::Request<#req_message>)
|
||||||
-> Result<tonic::Response<#res_message>, tonic::Status>;
|
-> Result<tonic::Response<#res_message>, tonic::Status>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
quote! {
|
quote! {
|
||||||
|
#method_doc
|
||||||
async fn #name(&self, request: tonic::Request<tonic::Streaming<#req_message>>)
|
async fn #name(&self, request: tonic::Request<tonic::Streaming<#req_message>>)
|
||||||
-> Result<tonic::Response<#res_message>, tonic::Status>;
|
-> Result<tonic::Response<#res_message>, tonic::Status>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(false, true) => {
|
(false, true) => {
|
||||||
let stream = quote::format_ident!("{}Stream", method.proto_name);
|
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! {
|
quote! {
|
||||||
|
#stream_doc
|
||||||
type #stream: Stream<Item = Result<#res_message, tonic::Status>> + Send + 'static;
|
type #stream: Stream<Item = Result<#res_message, tonic::Status>> + Send + 'static;
|
||||||
|
|
||||||
|
#method_doc
|
||||||
async fn #name(&self, request: tonic::Request<#req_message>)
|
async fn #name(&self, request: tonic::Request<#req_message>)
|
||||||
-> Result<tonic::Response<Self::#stream>, tonic::Status>;
|
-> Result<tonic::Response<Self::#stream>, tonic::Status>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(true, true) => {
|
(true, true) => {
|
||||||
let stream = quote::format_ident!("{}Stream", method.proto_name);
|
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! {
|
quote! {
|
||||||
|
#stream_doc
|
||||||
type #stream: Stream<Item = Result<#res_message, tonic::Status>> + Send + 'static;
|
type #stream: Stream<Item = Result<#res_message, tonic::Status>> + Send + 'static;
|
||||||
|
|
||||||
|
#method_doc
|
||||||
async fn #name(&self, request: tonic::Request<tonic::Streaming<#req_message>>)
|
async fn #name(&self, request: tonic::Request<tonic::Streaming<#req_message>>)
|
||||||
-> Result<tonic::Response<Self::#stream>, tonic::Status>;
|
-> Result<tonic::Response<Self::#stream>, tonic::Status>;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user