diff --git a/tonic-build/Cargo.toml b/tonic-build/Cargo.toml index f75c69540..4dd1c51f5 100644 --- a/tonic-build/Cargo.toml +++ b/tonic-build/Cargo.toml @@ -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" } diff --git a/tonic-build/src/client.rs b/tonic-build/src/client.rs index 0aff59d3d..81f75b879 100644 --- a/tonic-build/src/client.rs +++ b/tonic-build/src/client.rs @@ -9,6 +9,7 @@ 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( service: &T, emit_package: bool, @@ -16,6 +17,25 @@ pub fn generate( 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( + service: &T, + emit_package: bool, + proto_path: &str, + compile_well_known_types: bool, + build_transport: bool, + attributes: &Attributes, disable_comments: &HashSet, ) -> TokenStream { let service_ident = quote::format_ident!("{}Client", service.name()); diff --git a/tonic-build/src/code_gen.rs b/tonic-build/src/code_gen.rs new file mode 100644 index 000000000..a7169da12 --- /dev/null +++ b/tonic-build/src/code_gen.rs @@ -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, +} + +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) -> &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(), + } + } +} diff --git a/tonic-build/src/lib.rs b/tonic-build/src/lib.rs index 458e81ccf..81d4151c2 100644 --- a/tonic-build/src/lib.rs +++ b/tonic-build/src/lib.rs @@ -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 diff --git a/tonic-build/src/manual.rs b/tonic-build/src/manual.rs index 5368fab7c..c1cd28aec 100644 --- a/tonic-build/src/manual.rs +++ b/tonic-build/src/manual.rs @@ -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}, }; @@ -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); } } diff --git a/tonic-build/src/prost.rs b/tonic-build/src/prost.rs index 37eb37b91..54c98d181 100644 --- a/tonic-build/src/prost.rs +++ b/tonic-build/src/prost.rs @@ -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; @@ -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); } } diff --git a/tonic-build/src/server.rs b/tonic-build/src/server.rs index 080a00fd7..40bf62f8d 100644 --- a/tonic-build/src/server.rs +++ b/tonic-build/src/server.rs @@ -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( 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( + service: &T, + emit_package: bool, + proto_path: &str, + compile_well_known_types: bool, + attributes: &Attributes, disable_comments: &HashSet, ) -> TokenStream { let methods = generate_methods(service, proto_path, compile_well_known_types);