diff --git a/Cargo.lock b/Cargo.lock index 6bbdc17..f54473f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -409,9 +409,9 @@ dependencies = [ [[package]] name = "prost-validate-build" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab43b6e5205c68862d6de355f00ad8925e53040bbe8712e1a8baea13044d4fd" +checksum = "c7d6cd03a548e9d5667505b1aac8e482d3ac1ca6dacdf8abb087971e62b53ac4" dependencies = [ "heck", "prost-build", @@ -422,9 +422,9 @@ dependencies = [ [[package]] name = "prost-validate-derive-core" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98641bf15f3397b4605c3d090d1d14dc54bca51a0db4aafa25e8caed6c4535d" +checksum = "63172761d1942a0c98a12776c9c168eedd8e481b0e024a81eca5a1e2a6152ab2" dependencies = [ "anyhow", "darling", @@ -443,9 +443,9 @@ dependencies = [ [[package]] name = "prost-validate-types" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934047e83d036525d54c4d349066059da8b4a7b0b978f21d2bcad125b3e49eae" +checksum = "f8f172d4e1e2daee8e327e1d271d9e9ed6deb72c0664a1231d8cbac24cef3604" dependencies = [ "anyhow", "once_cell", @@ -506,6 +506,7 @@ dependencies = [ "prost-validate-derive-core", "prost-validate-types", "protoc-gen-prost", + "quote", "syn 2.0.75", ] diff --git a/protoc-gen-prost-validate/Cargo.toml b/protoc-gen-prost-validate/Cargo.toml index 481efb3..96d08cf 100644 --- a/protoc-gen-prost-validate/Cargo.toml +++ b/protoc-gen-prost-validate/Cargo.toml @@ -13,10 +13,13 @@ prost-build.workspace = true prost-types.workspace = true prost.workspace = true protoc-gen-prost = { version = "0.4.0", path = "../protoc-gen-prost" } -prost-validate-build = { version = "0.2.3" } -prost-validate-derive-core = { version = "0.2.3" } -prost-validate-types = { version = "0.2.3" } +prost-validate-build = { version = "0.2.4" } +prost-validate-derive-core = { version = "0.2.4" } +prost-validate-types = { version = "0.2.4" } syn = "2.0.75" proc-macro2 = "1.0.86" prost-reflect = "0.14.2" +quote = "1" prettyplease = "0.2.9" + +[dev-dependencies] diff --git a/protoc-gen-prost-validate/src/generator.rs b/protoc-gen-prost-validate/src/generator.rs index bef5ac5..d22bfc1 100644 --- a/protoc-gen-prost-validate/src/generator.rs +++ b/protoc-gen-prost-validate/src/generator.rs @@ -6,6 +6,7 @@ use prost_types::compiler::code_generator_response::File; use prost_validate_build::Builder; use protoc_gen_prost::{Error, Generator, ModuleRequest, ModuleRequestSet, Result}; use std::collections::HashMap; +use syn::__private::quote::quote; use syn::__private::ToTokens; pub struct ProstValidateGenerator { @@ -86,7 +87,8 @@ impl ProstValidateGenerator { .items .iter() .filter_map(filter_item) - .map(|stream| prost_validate_derive_core::derive(stream)) + .flatten() + .map(|item| prost_validate_derive_core::derive_with_module(item.stream, item.module)) .for_each(|stream| stream.to_tokens(&mut file_stream)); if file_stream.is_empty() { @@ -122,22 +124,54 @@ impl ProstValidateGenerator { } } -fn filter_item(item: &syn::Item) -> Option { +struct Item { + module: Option, + stream: TokenStream, +} + +fn filter_item(item: &syn::Item) -> Option> { + do_filter_item(item, None) +} + +fn do_filter_item(item: &syn::Item, module: Option) -> Option> { match item { syn::Item::Struct(s) => { if has_validator_derive(&s.attrs) { - Some(item.to_token_stream()) + Some(vec![Item { + stream: item.to_token_stream(), + module, + }]) } else { None } } syn::Item::Enum(e) => { if has_validator_derive(&e.attrs) { - Some(item.to_token_stream()) + Some(vec![Item { + stream: item.to_token_stream(), + module, + }]) } else { None } } + syn::Item::Mod(m) => { + // if the parent module is not None, we need to prefix the module path to the item identity + let module = match module { + Some(m2) => { + let ident = m.ident.to_token_stream(); + Some(quote! { #m2::#ident }) + } + None => Some(m.ident.to_token_stream()), + }; + let mut items = Vec::new(); + for item in m.content.as_ref()?.1.iter() { + if let Some(item) = do_filter_item(item, module.clone()) { + items.extend(item); + } + } + Some(items) + } _ => None, } }