Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a new prost ServiceGenerator finalizer to fix duplicate client and server definitions #147

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"tonic-examples",
"tonic-interop",

"tests/complex_package_layout",
"tests/included_service",
"tests/same_name",
"tests/wellknown",
Expand Down
15 changes: 15 additions & 0 deletions tests/complex_package_layout/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "complex_package_layout"
version = "0.1.0"
authors = ["Jay Oster <[email protected]>"]
edition = "2018"
publish = false
license = "MIT"

[dependencies]
bytes = "0.4"
prost = "0.5"
tonic = { path = "../../tonic" }

[build-dependencies]
tonic-build = { path = "../../tonic-build" }
9 changes: 9 additions & 0 deletions tests/complex_package_layout/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn main() {
tonic_build::configure()
.compile(&["proto/hello.proto", "proto/goodbye.proto"], &["proto"])
.unwrap();

println!("cargo:rerun-if-changed=proto/hello.proto");
println!("cargo:rerun-if-changed=proto/goodbye.proto");
println!("cargo:rerun-if-changed=proto/types.proto");
}
9 changes: 9 additions & 0 deletions tests/complex_package_layout/proto/goodbye.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

import "types.proto";

package helloworld;

service Farewell {
rpc Goodbye (Message) returns (Response) {}
}
9 changes: 9 additions & 0 deletions tests/complex_package_layout/proto/hello.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

import "types.proto";

package helloworld;

service Greeting {
rpc Hello (Message) returns (Response) {}
}
11 changes: 11 additions & 0 deletions tests/complex_package_layout/proto/types.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
syntax = "proto3";

package helloworld;

message Message {
string say = 1;
}

message Response {
string say = 1;
}
8 changes: 8 additions & 0 deletions tests/complex_package_layout/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mod pb {
tonic::include_proto!("helloworld");
}

// Ensure that multiple services defined for a single package, spread across multiple `.proto`
// files, are all available in the generated Rust module.
type _Test1 = dyn pb::server::Greeting;
type _Test2 = dyn pb::server::Farewell;
2 changes: 1 addition & 1 deletion tonic-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ keywords = ["rpc", "grpc", "async", "codegen", "protobuf"]


[dependencies]
prost-build = "0.5"
prost-build = { git = "https://github.com/parasyte/prost.git", branch = "feature/defer-service-generator-finalize" }
syn = "1.0"
quote = "1.0"
proc-macro2 = "1.0"
Expand Down
37 changes: 24 additions & 13 deletions tonic-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenS
use prost_build::{Config, Method};
use quote::{ToTokens, TokenStreamExt};

use std::collections::HashMap;
#[cfg(feature = "rustfmt")]
use std::process::Command;
use std::{
Expand Down Expand Up @@ -217,16 +218,16 @@ fn fmt(out_dir: &str) {

struct ServiceGenerator {
builder: Builder,
clients: TokenStream,
servers: TokenStream,
clients: HashMap<String, TokenStream>,
servers: HashMap<String, TokenStream>,
}

impl ServiceGenerator {
fn new(builder: Builder) -> Self {
ServiceGenerator {
builder,
clients: TokenStream::default(),
servers: TokenStream::default(),
clients: HashMap::default(),
servers: HashMap::default(),
}
}
}
Expand All @@ -237,18 +238,25 @@ impl prost_build::ServiceGenerator for ServiceGenerator {

if self.builder.build_server {
let server = server::generate(&service, path);
self.servers.extend(server);
self.servers
.entry(service.package.clone())
.or_insert_with(TokenStream::default)
.extend(server);
}

if self.builder.build_client {
let client = client::generate(&service, path);
self.clients.extend(client);
self.clients
.entry(service.package)
.or_insert_with(TokenStream::default)
.extend(client);
}
}

fn finalize(&mut self, buf: &mut String) {
if self.builder.build_client && !self.clients.is_empty() {
let clients = &self.clients;
fn finalize_package(&mut self, package: &str, buf: &mut String) {
let clients = self.clients.get(package);
if self.builder.build_client && clients.is_some() {
let clients = clients.unwrap();

let client_service = quote::quote! {
/// Generated client implementations.
Expand All @@ -263,11 +271,13 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
let code = format!("{}", client_service);
buf.push_str(&code);

self.clients = TokenStream::default();
self.clients
.insert(package.to_string(), TokenStream::default());
}

if self.builder.build_server && !self.servers.is_empty() {
let servers = &self.servers;
let servers = self.servers.get(package);
if self.builder.build_server && servers.is_some() {
let servers = servers.unwrap();

let server_service = quote::quote! {
/// Generated server implementations.
Expand All @@ -282,7 +292,8 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
let code = format!("{}", server_service);
buf.push_str(&code);

self.servers = TokenStream::default();
self.servers
.insert(package.to_string(), TokenStream::default());
}
}
}
Expand Down