Skip to content

Commit 2670b34

Browse files
authored
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
1 parent 2734d3a commit 2670b34

6 files changed

Lines changed: 78 additions & 30 deletions

File tree

tonic-build/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name = "tonic-build"
33
version = "0.1.0-alpha.1"
44
authors = ["Lucio Franco <luciofranco14@gmail.com>"]
55
edition = "2018"
6+
license = "MIT"
67
documentation = "https://docs.rs/tonic/0.1.0-alpha.1/tonic/"
78
repository = "https://github.com/hyperium/tonic"
89
homepage = "https://github.com/hyperium/tonic"

tonic-build/src/client.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use crate::generate_doc_comments;
22
use proc_macro2::TokenStream;
33
use prost_build::{Method, Service};
44
use quote::{format_ident, quote};
5-
use syn::Path;
65

76
pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream {
87
let service_ident = quote::format_ident!("{}Client", service.name);
@@ -97,8 +96,8 @@ fn generate_methods(service: &Service, proto: &str) -> TokenStream {
9796

9897
fn generate_unary(method: &Method, proto: &str, path: String) -> TokenStream {
9998
let ident = format_ident!("{}", method.name);
100-
let request: Path = syn::parse_str(&format!("{}::{}", proto, method.input_type)).unwrap();
101-
let response: Path = syn::parse_str(&format!("{}::{}", proto, method.output_type)).unwrap();
99+
let request = crate::replace_wellknown(proto, &method.input_type);
100+
let response = crate::replace_wellknown(proto, &method.output_type);
102101

103102
quote! {
104103
pub async fn #ident(&mut self, request: tonic::Request<#request>)
@@ -113,8 +112,9 @@ fn generate_unary(method: &Method, proto: &str, path: String) -> TokenStream {
113112

114113
fn generate_server_streaming(method: &Method, proto: &str, path: String) -> TokenStream {
115114
let ident = format_ident!("{}", method.name);
116-
let request: Path = syn::parse_str(&format!("{}::{}", proto, method.input_type)).unwrap();
117-
let response: Path = syn::parse_str(&format!("{}::{}", proto, method.output_type)).unwrap();
115+
116+
let request = crate::replace_wellknown(proto, &method.input_type);
117+
let response = crate::replace_wellknown(proto, &method.output_type);
118118

119119
quote! {
120120
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
129129

130130
fn generate_client_streaming(method: &Method, proto: &str, path: String) -> TokenStream {
131131
let ident = format_ident!("{}", method.name);
132-
let request: Path = syn::parse_str(&format!("{}::{}", proto, method.input_type)).unwrap();
133-
let response: Path = syn::parse_str(&format!("{}::{}", proto, method.output_type)).unwrap();
132+
133+
let request = crate::replace_wellknown(proto, &method.input_type);
134+
let response = crate::replace_wellknown(proto, &method.output_type);
134135

135136
quote! {
136137
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
147148

148149
fn generate_streaming(method: &Method, proto: &str, path: String) -> TokenStream {
149150
let ident = format_ident!("{}", method.name);
150-
let request: Path = syn::parse_str(&format!("{}::{}", proto, method.input_type)).unwrap();
151-
let response: Path = syn::parse_str(&format!("{}::{}", proto, method.output_type)).unwrap();
151+
152+
let request = crate::replace_wellknown(proto, &method.input_type);
153+
let response = crate::replace_wellknown(proto, &method.output_type);
152154

153155
quote! {
154156
pub async fn #ident<S>(&mut self, request: tonic::Request<S>)

tonic-build/src/lib.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959

6060
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream};
6161
use prost_build::Config;
62-
use quote::TokenStreamExt;
62+
use quote::{ToTokens, TokenStreamExt};
6363

6464
#[cfg(feature = "rustfmt")]
6565
use std::process::Command;
@@ -77,6 +77,8 @@ pub struct Builder {
7777
build_client: bool,
7878
build_server: bool,
7979
out_dir: Option<PathBuf>,
80+
#[cfg(feature = "rustfmt")]
81+
format: bool,
8082
}
8183

8284
impl Builder {
@@ -92,6 +94,13 @@ impl Builder {
9294
self
9395
}
9496

97+
/// Enable the output to be formated by rustfmt.
98+
#[cfg(feature = "rustfmt")]
99+
pub fn format(mut self, run: bool) -> Self {
100+
self.format = run;
101+
self
102+
}
103+
95104
/// Set the output directory to generate code to.
96105
///
97106
/// Defaults to the `OUT_DIR` environment variable.
@@ -104,6 +113,9 @@ impl Builder {
104113
pub fn compile<P: AsRef<Path>>(self, protos: &[P], includes: &[P]) -> io::Result<()> {
105114
let mut config = Config::new();
106115

116+
#[cfg(feature = "rustfmt")]
117+
let format = self.format;
118+
107119
let out_dir = self
108120
.out_dir
109121
.clone()
@@ -114,7 +126,11 @@ impl Builder {
114126
config.compile_protos(protos, includes)?;
115127

116128
#[cfg(feature = "rustfmt")]
117-
fmt(out_dir.to_str().expect("Expected utf8 out_dir"));
129+
{
130+
if format {
131+
fmt(out_dir.to_str().expect("Expected utf8 out_dir"));
132+
}
133+
}
118134

119135
Ok(())
120136
}
@@ -128,6 +144,8 @@ pub fn configure() -> Builder {
128144
build_client: true,
129145
build_server: true,
130146
out_dir: None,
147+
#[cfg(feature = "rustfmt")]
148+
format: true,
131149
}
132150
}
133151

@@ -262,3 +280,14 @@ fn generate_doc_comments<T: AsRef<str>>(comments: &[T]) -> TokenStream {
262280

263281
stream
264282
}
283+
284+
fn replace_wellknown(proto_path: &str, output: &str) -> TokenStream {
285+
// TODO: detect more wellknown protobuf types
286+
// https://github.com/danburkert/prost/blob/master/prost-types/src/protobuf.rs
287+
match output {
288+
"()" => quote::quote! { () },
289+
_ => syn::parse_str::<syn::Path>(&format!("{}::{}", proto_path, output))
290+
.unwrap()
291+
.to_token_stream(),
292+
}
293+
}

tonic-build/src/service.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{generate_doc_comment, generate_doc_comments};
22
use proc_macro2::{Span, TokenStream};
33
use prost_build::{Method, Service};
44
use quote::quote;
5-
use syn::{Ident, Lit, LitStr, Path};
5+
use syn::{Ident, Lit, LitStr};
66

77
pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream {
88
let methods = generate_methods(&service, proto_path);
@@ -79,8 +79,13 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream {
7979
match req.uri().path() {
8080
#methods
8181

82-
// TODO: implement grpc unimplemented for server
83-
_ => unimplemented!(),
82+
_ => Box::pin(async move {
83+
Ok(http::Response::builder()
84+
.status(200)
85+
.header("grpc-status", "12")
86+
.body(tonic::body::BoxBody::empty())
87+
.unwrap())
88+
}),
8489
}
8590
}
8691
}
@@ -108,10 +113,9 @@ fn generate_trait_methods(service: &Service, proto_path: &str) -> TokenStream {
108113

109114
for method in &service.methods {
110115
let name = quote::format_ident!("{}", method.name);
111-
let req_message: Path =
112-
syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
113-
let res_message: Path =
114-
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
116+
117+
let req_message = crate::replace_wellknown(proto_path, &method.input_type);
118+
let res_message = crate::replace_wellknown(proto_path, &method.output_type);
115119

116120
let method_doc = generate_doc_comments(&method.comments.leading);
117121

@@ -214,9 +218,8 @@ fn generate_unary(
214218
) -> TokenStream {
215219
let service_ident = Ident::new(&method.proto_name, Span::call_site());
216220

217-
let request: Path = syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
218-
let response: Path =
219-
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
221+
let request = crate::replace_wellknown(proto_path, &method.input_type);
222+
let response = crate::replace_wellknown(proto_path, &method.output_type);
220223

221224
quote! {
222225
struct #service_ident<T: #server_trait >(pub Arc<T>);
@@ -255,9 +258,8 @@ fn generate_server_streaming(
255258
) -> TokenStream {
256259
let service_ident = Ident::new(&method.proto_name, Span::call_site());
257260

258-
let request: Path = syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
259-
let response: Path =
260-
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
261+
let request = crate::replace_wellknown(proto_path, &method.input_type);
262+
let response = crate::replace_wellknown(proto_path, &method.output_type);
261263

262264
let response_stream = quote::format_ident!("{}Stream", method.proto_name);
263265

@@ -300,9 +302,8 @@ fn generate_client_streaming(
300302
) -> TokenStream {
301303
let service_ident = Ident::new(&method.proto_name, Span::call_site());
302304

303-
let request: Path = syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
304-
let response: Path =
305-
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
305+
let request = crate::replace_wellknown(proto_path, &method.input_type);
306+
let response = crate::replace_wellknown(proto_path, &method.output_type);
306307

307308
quote! {
308309
struct #service_ident<T: #server_trait >(pub Arc<T>);
@@ -343,9 +344,8 @@ fn generate_streaming(
343344
) -> TokenStream {
344345
let service_ident = Ident::new(&method.proto_name, Span::call_site());
345346

346-
let request: Path = syn::parse_str(&format!("{}::{}", proto_path, method.input_type)).unwrap();
347-
let response: Path =
348-
syn::parse_str(&format!("{}::{}", proto_path, method.output_type)).unwrap();
347+
let request = crate::replace_wellknown(proto_path, &method.input_type);
348+
let response = crate::replace_wellknown(proto_path, &method.output_type);
349349

350350
let response_stream = quote::format_ident!("{}Stream", method.proto_name);
351351

tonic-build/tests/empty.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#[test]
2+
fn empty() {
3+
let tmp = std::env::temp_dir();
4+
tonic_build::configure()
5+
.out_dir(tmp)
6+
.format(false)
7+
.compile(&["tests/protos/empty.proto"], &["tests/protos"])
8+
.unwrap();
9+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
syntax = "proto3";
2+
package empty;
3+
import "google/protobuf/empty.proto";
4+
5+
service Admin {
6+
rpc EmptyCall(google.protobuf.Empty) returns (google.protobuf.Empty);
7+
}

0 commit comments

Comments
 (0)