fix(codegen): Fix Empty protobuf type and add unimplemented (#26)
* Add license attribute to tonic-build * fix(codegen): Fix Empty protobuf type and add unimplemented * Remove syn full feature
This commit is contained in:
@@ -3,6 +3,7 @@ name = "tonic-build"
|
||||
version = "0.1.0-alpha.1"
|
||||
authors = ["Lucio Franco <luciofranco14@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
documentation = "https://docs.rs/tonic/0.1.0-alpha.1/tonic/"
|
||||
repository = "https://github.com/hyperium/tonic"
|
||||
homepage = "https://github.com/hyperium/tonic"
|
||||
|
||||
@@ -2,7 +2,6 @@ use crate::generate_doc_comments;
|
||||
use proc_macro2::TokenStream;
|
||||
use prost_build::{Method, Service};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::Path;
|
||||
|
||||
pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream {
|
||||
let service_ident = quote::format_ident!("{}Client", service.name);
|
||||
@@ -97,8 +96,8 @@ fn generate_methods(service: &Service, proto: &str) -> TokenStream {
|
||||
|
||||
fn generate_unary(method: &Method, proto: &str, path: String) -> TokenStream {
|
||||
let ident = format_ident!("{}", method.name);
|
||||
let request: Path = syn::parse_str(&format!("{}::{}", proto, method.input_type)).unwrap();
|
||||
let response: Path = syn::parse_str(&format!("{}::{}", proto, method.output_type)).unwrap();
|
||||
let request = crate::replace_wellknown(proto, &method.input_type);
|
||||
let response = crate::replace_wellknown(proto, &method.output_type);
|
||||
|
||||
quote! {
|
||||
pub async fn #ident(&mut self, request: tonic::Request<#request>)
|
||||
@@ -113,8 +112,9 @@ fn generate_unary(method: &Method, proto: &str, path: String) -> TokenStream {
|
||||
|
||||
fn generate_server_streaming(method: &Method, proto: &str, path: String) -> TokenStream {
|
||||
let ident = format_ident!("{}", method.name);
|
||||
let request: Path = syn::parse_str(&format!("{}::{}", proto, method.input_type)).unwrap();
|
||||
let response: Path = syn::parse_str(&format!("{}::{}", proto, method.output_type)).unwrap();
|
||||
|
||||
let request = crate::replace_wellknown(proto, &method.input_type);
|
||||
let response = crate::replace_wellknown(proto, &method.output_type);
|
||||
|
||||
quote! {
|
||||
pub async fn #ident(&mut self, request: tonic::Request<#request>)
|
||||
@@ -129,8 +129,9 @@ fn generate_server_streaming(method: &Method, proto: &str, path: String) -> Toke
|
||||
|
||||
fn generate_client_streaming(method: &Method, proto: &str, path: String) -> TokenStream {
|
||||
let ident = format_ident!("{}", method.name);
|
||||
let request: Path = syn::parse_str(&format!("{}::{}", proto, method.input_type)).unwrap();
|
||||
let response: Path = syn::parse_str(&format!("{}::{}", proto, method.output_type)).unwrap();
|
||||
|
||||
let request = crate::replace_wellknown(proto, &method.input_type);
|
||||
let response = crate::replace_wellknown(proto, &method.output_type);
|
||||
|
||||
quote! {
|
||||
pub async fn #ident<S>(&mut self, request: tonic::Request<S>)
|
||||
@@ -147,8 +148,9 @@ fn generate_client_streaming(method: &Method, proto: &str, path: String) -> Toke
|
||||
|
||||
fn generate_streaming(method: &Method, proto: &str, path: String) -> TokenStream {
|
||||
let ident = format_ident!("{}", method.name);
|
||||
let request: Path = syn::parse_str(&format!("{}::{}", proto, method.input_type)).unwrap();
|
||||
let response: Path = syn::parse_str(&format!("{}::{}", proto, method.output_type)).unwrap();
|
||||
|
||||
let request = crate::replace_wellknown(proto, &method.input_type);
|
||||
let response = crate::replace_wellknown(proto, &method.output_type);
|
||||
|
||||
quote! {
|
||||
pub async fn #ident<S>(&mut self, request: tonic::Request<S>)
|
||||
|
||||
+31
-2
@@ -59,7 +59,7 @@
|
||||
|
||||
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream};
|
||||
use prost_build::Config;
|
||||
use quote::TokenStreamExt;
|
||||
use quote::{ToTokens, TokenStreamExt};
|
||||
|
||||
#[cfg(feature = "rustfmt")]
|
||||
use std::process::Command;
|
||||
@@ -77,6 +77,8 @@ pub struct Builder {
|
||||
build_client: bool,
|
||||
build_server: bool,
|
||||
out_dir: Option<PathBuf>,
|
||||
#[cfg(feature = "rustfmt")]
|
||||
format: bool,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
@@ -92,6 +94,13 @@ impl Builder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable the output to be formated by rustfmt.
|
||||
#[cfg(feature = "rustfmt")]
|
||||
pub fn format(mut self, run: bool) -> Self {
|
||||
self.format = run;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the output directory to generate code to.
|
||||
///
|
||||
/// Defaults to the `OUT_DIR` environment variable.
|
||||
@@ -104,6 +113,9 @@ impl Builder {
|
||||
pub fn compile<P: AsRef<Path>>(self, protos: &[P], includes: &[P]) -> io::Result<()> {
|
||||
let mut config = Config::new();
|
||||
|
||||
#[cfg(feature = "rustfmt")]
|
||||
let format = self.format;
|
||||
|
||||
let out_dir = self
|
||||
.out_dir
|
||||
.clone()
|
||||
@@ -114,7 +126,11 @@ impl Builder {
|
||||
config.compile_protos(protos, includes)?;
|
||||
|
||||
#[cfg(feature = "rustfmt")]
|
||||
fmt(out_dir.to_str().expect("Expected utf8 out_dir"));
|
||||
{
|
||||
if format {
|
||||
fmt(out_dir.to_str().expect("Expected utf8 out_dir"));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -128,6 +144,8 @@ pub fn configure() -> Builder {
|
||||
build_client: true,
|
||||
build_server: true,
|
||||
out_dir: None,
|
||||
#[cfg(feature = "rustfmt")]
|
||||
format: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,3 +280,14 @@ fn generate_doc_comments<T: AsRef<str>>(comments: &[T]) -> TokenStream {
|
||||
|
||||
stream
|
||||
}
|
||||
|
||||
fn replace_wellknown(proto_path: &str, output: &str) -> TokenStream {
|
||||
// TODO: detect more wellknown protobuf types
|
||||
// https://github.com/danburkert/prost/blob/master/prost-types/src/protobuf.rs
|
||||
match output {
|
||||
"()" => quote::quote! { () },
|
||||
_ => syn::parse_str::<syn::Path>(&format!("{}::{}", proto_path, output))
|
||||
.unwrap()
|
||||
.to_token_stream(),
|
||||
}
|
||||
}
|
||||
|
||||
+19
-19
@@ -2,7 +2,7 @@ use crate::{generate_doc_comment, generate_doc_comments};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use prost_build::{Method, Service};
|
||||
use quote::quote;
|
||||
use syn::{Ident, Lit, LitStr, Path};
|
||||
use syn::{Ident, Lit, LitStr};
|
||||
|
||||
pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream {
|
||||
let methods = generate_methods(&service, proto_path);
|
||||
@@ -79,8 +79,13 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream {
|
||||
match req.uri().path() {
|
||||
#methods
|
||||
|
||||
// TODO: implement grpc unimplemented for server
|
||||
_ => unimplemented!(),
|
||||
_ => Box::pin(async move {
|
||||
Ok(http::Response::builder()
|
||||
.status(200)
|
||||
.header("grpc-status", "12")
|
||||
.body(tonic::body::BoxBody::empty())
|
||||
.unwrap())
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,10 +113,9 @@ fn generate_trait_methods(service: &Service, proto_path: &str) -> TokenStream {
|
||||
|
||||
for method in &service.methods {
|
||||
let name = quote::format_ident!("{}", method.name);
|
||||
let req_message: Path =
|
||||
syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
|
||||
let res_message: Path =
|
||||
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
|
||||
|
||||
let req_message = crate::replace_wellknown(proto_path, &method.input_type);
|
||||
let res_message = crate::replace_wellknown(proto_path, &method.output_type);
|
||||
|
||||
let method_doc = generate_doc_comments(&method.comments.leading);
|
||||
|
||||
@@ -214,9 +218,8 @@ fn generate_unary(
|
||||
) -> TokenStream {
|
||||
let service_ident = Ident::new(&method.proto_name, Span::call_site());
|
||||
|
||||
let request: Path = syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
|
||||
let response: Path =
|
||||
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
|
||||
let request = crate::replace_wellknown(proto_path, &method.input_type);
|
||||
let response = crate::replace_wellknown(proto_path, &method.output_type);
|
||||
|
||||
quote! {
|
||||
struct #service_ident<T: #server_trait >(pub Arc<T>);
|
||||
@@ -255,9 +258,8 @@ fn generate_server_streaming(
|
||||
) -> TokenStream {
|
||||
let service_ident = Ident::new(&method.proto_name, Span::call_site());
|
||||
|
||||
let request: Path = syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
|
||||
let response: Path =
|
||||
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
|
||||
let request = crate::replace_wellknown(proto_path, &method.input_type);
|
||||
let response = crate::replace_wellknown(proto_path, &method.output_type);
|
||||
|
||||
let response_stream = quote::format_ident!("{}Stream", method.proto_name);
|
||||
|
||||
@@ -300,9 +302,8 @@ fn generate_client_streaming(
|
||||
) -> TokenStream {
|
||||
let service_ident = Ident::new(&method.proto_name, Span::call_site());
|
||||
|
||||
let request: Path = syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
|
||||
let response: Path =
|
||||
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
|
||||
let request = crate::replace_wellknown(proto_path, &method.input_type);
|
||||
let response = crate::replace_wellknown(proto_path, &method.output_type);
|
||||
|
||||
quote! {
|
||||
struct #service_ident<T: #server_trait >(pub Arc<T>);
|
||||
@@ -343,9 +344,8 @@ fn generate_streaming(
|
||||
) -> TokenStream {
|
||||
let service_ident = Ident::new(&method.proto_name, Span::call_site());
|
||||
|
||||
let request: Path = syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
|
||||
let response: Path =
|
||||
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
|
||||
let request = crate::replace_wellknown(proto_path, &method.input_type);
|
||||
let response = crate::replace_wellknown(proto_path, &method.output_type);
|
||||
|
||||
let response_stream = quote::format_ident!("{}Stream", method.proto_name);
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#[test]
|
||||
fn empty() {
|
||||
let tmp = std::env::temp_dir();
|
||||
tonic_build::configure()
|
||||
.out_dir(tmp)
|
||||
.format(false)
|
||||
.compile(&["tests/protos/empty.proto"], &["tests/protos"])
|
||||
.unwrap();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
syntax = "proto3";
|
||||
package empty;
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
service Admin {
|
||||
rpc EmptyCall(google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
}
|
||||
Reference in New Issue
Block a user