Skip to content

Commit 71379a9

Browse files
authored
feat(build): allow to specify trait attributes (#2348)
1 parent 88994ea commit 71379a9

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

tonic-build/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ pub struct Attributes {
8888
module: Vec<(String, String)>,
8989
/// `struct` attributes.
9090
structure: Vec<(String, String)>,
91+
/// `trait` attributes.
92+
trait_attributes: Vec<(String, String)>,
9193
}
9294

9395
impl Attributes {
@@ -99,6 +101,10 @@ impl Attributes {
99101
generate_attributes(name, &self.structure)
100102
}
101103

104+
fn for_trait(&self, name: &str) -> Vec<syn::Attribute> {
105+
generate_attributes(name, &self.trait_attributes)
106+
}
107+
102108
/// Add an attribute that will be added to `mod` items matching the given pattern.
103109
///
104110
/// # Examples
@@ -124,6 +130,19 @@ impl Attributes {
124130
pub fn push_struct(&mut self, pattern: impl Into<String>, attr: impl Into<String>) {
125131
self.structure.push((pattern.into(), attr.into()));
126132
}
133+
134+
/// Add an attribute that will be added to `trait` items matching the given pattern.
135+
///
136+
/// # Examples
137+
///
138+
/// ```
139+
/// # use tonic_build::*;
140+
/// let mut attributes = Attributes::default();
141+
/// attributes.push_trait("Server", "#[mockall::automock]");
142+
/// ```
143+
pub fn push_trait(&mut self, pattern: impl Into<String>, attr: impl Into<String>) {
144+
self.trait_attributes.push((pattern.into(), attr.into()));
145+
}
127146
}
128147

129148
fn format_service_name<T: Service>(service: &T, emit_package: bool) -> String {

tonic-build/src/server.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub(crate) fn generate_internal<T: Service>(
3232
let server_service = quote::format_ident!("{}Server", service.name());
3333
let server_trait = quote::format_ident!("{}", service.name());
3434
let server_mod = quote::format_ident!("{}_server", naive_snake_case(service.name()));
35+
let trait_attributes = attributes.for_trait(service.name());
3536
let generated_trait = generate_trait(
3637
service,
3738
emit_package,
@@ -41,6 +42,7 @@ pub(crate) fn generate_internal<T: Service>(
4142
disable_comments,
4243
use_arc_self,
4344
generate_default_stubs,
45+
trait_attributes,
4446
);
4547
let package = if emit_package { service.package() } else { "" };
4648
// Transport based implementations
@@ -203,6 +205,7 @@ fn generate_trait<T: Service>(
203205
disable_comments: &HashSet<String>,
204206
use_arc_self: bool,
205207
generate_default_stubs: bool,
208+
trait_attributes: Vec<syn::Attribute>,
206209
) -> TokenStream {
207210
let methods = generate_trait_methods(
208211
service,
@@ -220,6 +223,7 @@ fn generate_trait<T: Service>(
220223

221224
quote! {
222225
#trait_doc
226+
#(#trait_attributes)*
223227
#[async_trait]
224228
pub trait #server_trait : std::marker::Send + std::marker::Sync + 'static {
225229
#methods

tonic-prost-build/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,14 @@ impl Builder {
545545
self
546546
}
547547

548+
/// Add additional attribute to matched traits. Passed directly to
549+
/// `prost_build::Config.message_attribute`
550+
pub fn trait_attribute<P: AsRef<str>, A: AsRef<str>>(mut self, path: P, attribute: A) -> Self {
551+
self.server_attributes
552+
.push_trait(path.as_ref(), attribute.as_ref());
553+
self
554+
}
555+
548556
/// Add additional attribute to matched client `mod`s. Passed directly to
549557
/// `prost_build::Config.message_attribute`
550558
pub fn client_mod_attribute<P: AsRef<str>, A: AsRef<str>>(

0 commit comments

Comments
 (0)