Skip to content

Commit

Permalink
feat(build): Add CodeGenBuilder (#1154)
Browse files Browse the repository at this point in the history
This commit adds a new `CodeGenBuilder` that replaces the
client/server generate fn with a builder stlye that allows
adding config items in an non-breaking way. This also deprecates
both of the client/server generate fn in favor of the builder ones.
  • Loading branch information
LucioFranco authored Nov 28, 2022
1 parent 542c5b3 commit c4525ba
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 38 deletions.
2 changes: 1 addition & 1 deletion tonic-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ license = "MIT"
name = "tonic-build"
readme = "README.md"
repository = "https://github.com/hyperium/tonic"
version = "0.8.2"
version = "0.8.3"

[dependencies]
prettyplease = { version = "0.1" }
Expand Down
20 changes: 20 additions & 0 deletions tonic-build/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,33 @@ use quote::{format_ident, quote};
///
/// This takes some `Service` and will generate a `TokenStream` that contains
/// a public module with the generated client.
#[deprecated(since = "0.8.3", note = "Use the CodeGenBuilder::generate_client")]
pub fn generate<T: Service>(
service: &T,
emit_package: bool,
proto_path: &str,
compile_well_known_types: bool,
build_transport: bool,
attributes: &Attributes,
) -> TokenStream {
generate_internal(
service,
emit_package,
proto_path,
compile_well_known_types,
build_transport,
attributes,
&HashSet::default(),
)
}

pub(crate) fn generate_internal<T: Service>(
service: &T,
emit_package: bool,
proto_path: &str,
compile_well_known_types: bool,
build_transport: bool,
attributes: &Attributes,
disable_comments: &HashSet<String>,
) -> TokenStream {
let service_ident = quote::format_ident!("{}Client", service.name());
Expand Down
102 changes: 102 additions & 0 deletions tonic-build/src/code_gen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use std::collections::HashSet;

use proc_macro2::TokenStream;

use crate::{Attributes, Service};

/// Builder for the generic code generation of server and clients.
#[derive(Debug)]
pub struct CodeGen8uilder {
emit_package: bool,
compile_well_known_types: bool,
attributes: Attributes,
build_transport: bool,
disable_comments: HashSet<String>,
}

impl CodeGen8uilder {
/// Create a new code gen builder with default options.
pub fn new() -> Self {
Default::default()
}

/// Enable code generation to emit the package name.
pub fn emit_package(&mut self, enable: bool) -> &mut Self {
self.emit_package = enable;
self
}

/// Attributes that will be added to `mod` and `struct` items.
///
/// Reference [`Attributes`] for more information.
pub fn attributes(&mut self, attributes: Attributes) -> &mut Self {
self.attributes = attributes;
self
}

/// Enable transport code to be generated, this requires `tonic`'s `transport`
/// feature.
///
/// This allows codegen level control of generating the transport code and
/// is a work around when other crates in a workspace enable this feature.
pub fn build_transport(&mut self, build_transport: bool) -> &mut Self {
self.build_transport = build_transport;
self
}

/// Enable compiling well knonw types, this will force codegen to not
/// use the well known types from `prost-types`.
pub fn compile_well_known_types(&mut self, enable: bool) -> &mut Self {
self.compile_well_known_types = enable;
self
}

/// Disable comments based on a proto path.
pub fn disable_comments(&mut self, disable_comments: HashSet<String>) -> &mut Self {
self.disable_comments = disable_comments;
self
}

/// Generate client code based on `Service`.
///
/// This takes some `Service` and will generate a `TokenStream` that contains
/// a public module with the generated client.
pub fn generate_client(&self, service: &impl Service, proto_path: &str) -> TokenStream {
crate::client::generate_internal(
service,
self.emit_package,
proto_path,
self.compile_well_known_types,
self.build_transport,
&self.attributes,
&self.disable_comments,
)
}

/// Generate server code based on `Service`.
///
/// This takes some `Service` and will generate a `TokenStream` that contains
/// a public module with the generated client.
pub fn generate_server(&self, service: &impl Service, proto_path: &str) -> TokenStream {
crate::server::generate_internal(
service,
self.emit_package,
proto_path,
self.compile_well_known_types,
&self.attributes,
&self.disable_comments,
)
}
}

impl Default for CodeGen8uilder {
fn default() -> Self {
Self {
emit_package: true,
compile_well_known_types: false,
attributes: Attributes::default(),
build_transport: true,
disable_comments: HashSet::default(),
}
}
}
3 changes: 3 additions & 0 deletions tonic-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ pub mod client;
/// Service code generation for Server
pub mod server;

mod code_gen;
pub use code_gen::CodeGen8uilder;

/// Service generation trait.
///
/// This trait can be implemented and consumed
Expand Down
32 changes: 13 additions & 19 deletions tonic-build/src/manual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
//! }
//! ```

use super::{client, server, Attributes};
use crate::code_gen::CodeGen8uilder;

use proc_macro2::TokenStream;
use quote::ToTokens;
use std::{
collections::HashSet,
fs,
path::{Path, PathBuf},
};
Expand Down Expand Up @@ -352,27 +352,21 @@ struct ServiceGenerator {
impl ServiceGenerator {
fn generate(&mut self, service: &Service) {
if self.builder.build_server {
let server = server::generate(
service,
true, // emit_package,
"", // proto_path, -- not used
false, // compile_well_known_types -- not used
&Attributes::default(),
&HashSet::default(),
);
let server = CodeGen8uilder::new()
.emit_package(true)
.compile_well_known_types(false)
.generate_server(service, "");

self.servers.extend(server);
}

if self.builder.build_client {
let client = client::generate(
service,
true, // emit_package,
"", // proto_path, -- not used
false, // compile_well_known_types, -- not used
self.builder.build_transport,
&Attributes::default(),
&HashSet::default(),
);
let client = CodeGen8uilder::new()
.emit_package(true)
.compile_well_known_types(false)
.build_transport(self.builder.build_transport)
.generate_client(service, "");

self.clients.extend(client);
}
}
Expand Down
36 changes: 18 additions & 18 deletions tonic-build/src/prost.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use super::{client, server, Attributes};
use crate::code_gen::CodeGen8uilder;

use super::Attributes;
use proc_macro2::TokenStream;
use prost_build::{Config, Method, Service};
use quote::ToTokens;
Expand Down Expand Up @@ -159,27 +161,25 @@ impl ServiceGenerator {
impl prost_build::ServiceGenerator for ServiceGenerator {
fn generate(&mut self, service: prost_build::Service, _buf: &mut String) {
if self.builder.build_server {
let server = server::generate(
&service,
self.builder.emit_package,
&self.builder.proto_path,
self.builder.compile_well_known_types,
&self.builder.server_attributes,
&self.builder.disable_comments,
);
let server = CodeGen8uilder::new()
.emit_package(self.builder.emit_package)
.compile_well_known_types(self.builder.compile_well_known_types)
.attributes(self.builder.server_attributes.clone())
.disable_comments(self.builder.disable_comments.clone())
.generate_server(&service, &self.builder.proto_path);

self.servers.extend(server);
}

if self.builder.build_client {
let client = client::generate(
&service,
self.builder.emit_package,
&self.builder.proto_path,
self.builder.compile_well_known_types,
self.builder.build_transport,
&self.builder.client_attributes,
&self.builder.disable_comments,
);
let client = CodeGen8uilder::new()
.emit_package(self.builder.emit_package)
.compile_well_known_types(self.builder.compile_well_known_types)
.attributes(self.builder.client_attributes.clone())
.disable_comments(self.builder.disable_comments.clone())
.build_transport(self.builder.build_transport)
.generate_client(&service, &self.builder.proto_path);

self.clients.extend(client);
}
}
Expand Down
18 changes: 18 additions & 0 deletions tonic-build/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,30 @@ use syn::{Ident, Lit, LitStr};
///
/// This takes some `Service` and will generate a `TokenStream` that contains
/// a public module containing the server service and handler trait.
#[deprecated(since = "0.8.3", note = "Use CodeGenBuilder::generate_server")]
pub fn generate<T: Service>(
service: &T,
emit_package: bool,
proto_path: &str,
compile_well_known_types: bool,
attributes: &Attributes,
) -> TokenStream {
generate_internal(
service,
emit_package,
proto_path,
compile_well_known_types,
attributes,
&HashSet::default(),
)
}

pub(crate) fn generate_internal<T: Service>(
service: &T,
emit_package: bool,
proto_path: &str,
compile_well_known_types: bool,
attributes: &Attributes,
disable_comments: &HashSet<String>,
) -> TokenStream {
let methods = generate_methods(service, proto_path, compile_well_known_types);
Expand Down

0 comments on commit c4525ba

Please sign in to comment.