diff --git a/prost-build/src/code_generator.rs b/prost-build/src/code_generator.rs index 4f348baaf..ecd21852a 100644 --- a/prost-build/src/code_generator.rs +++ b/prost-build/src/code_generator.rs @@ -122,18 +122,7 @@ impl<'a> CodeGenerator<'a> { debug!(" message: {:?}", message.name()); let message_name = message.name().to_string(); - let fq_message_name = format!( - "{}{}{}{}.{}", - if self.package.is_empty() && self.type_path.is_empty() { - "" - } else { - "." - }, - self.package.trim_matches('.'), - if self.type_path.is_empty() { "" } else { "." }, - self.type_path.join("."), - message_name, - ); + let fq_message_name = self.fq_name(&message_name); // Skip external types. if self.extern_paths.resolve_ident(&fq_message_name).is_some() { @@ -701,18 +690,7 @@ impl<'a> CodeGenerator<'a> { let enum_name = to_upper_camel(proto_enum_name); let enum_values = &desc.value; - let fq_proto_enum_name = format!( - "{}{}{}{}.{}", - if self.package.is_empty() && self.type_path.is_empty() { - "" - } else { - "." - }, - self.package.trim_matches('.'), - if self.type_path.is_empty() { "" } else { "." }, - self.type_path.join("."), - proto_enum_name, - ); + let fq_proto_enum_name = self.fq_name(proto_enum_name); if self .extern_paths @@ -1065,6 +1043,18 @@ impl<'a> CodeGenerator<'a> { .as_ref() .map_or(false, FieldOptions::deprecated) } + + /// Returns the fully-qualified name, starting with a dot + fn fq_name(&self, message_name: &str) -> String { + format!( + "{}{}{}{}.{}", + if self.package.is_empty() { "" } else { "." }, + self.package.trim_matches('.'), + if self.type_path.is_empty() { "" } else { "." }, + self.type_path.join("."), + message_name, + ) + } } /// Returns `true` if the repeated field type can be packed. diff --git a/tests/src/build.rs b/tests/src/build.rs index aec3f6458..e2b95e6c4 100644 --- a/tests/src/build.rs +++ b/tests/src/build.rs @@ -111,6 +111,10 @@ fn main() { .compile_protos(&[src.join("option_struct.proto")], includes) .unwrap(); + config + .compile_protos(&[src.join("submessage_without_package.proto")], includes) + .unwrap(); + prost_build::Config::new() .protoc_arg("--experimental_allow_proto3_optional") .compile_protos(&[src.join("proto3_presence.proto")], includes) diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 954c6b367..b95f2d77a 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -46,6 +46,8 @@ mod no_unused_results; #[cfg(feature = "std")] mod skip_debug; #[cfg(test)] +mod submessage_without_package; +#[cfg(test)] mod type_names; mod test_enum_named_option_value { diff --git a/tests/src/submessage_without_package.proto b/tests/src/submessage_without_package.proto new file mode 100644 index 000000000..c637b29bc --- /dev/null +++ b/tests/src/submessage_without_package.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +message M { + message SubMessage { + map item = 1; + } + SubMessage reply = 2; +} diff --git a/tests/src/submessage_without_package.rs b/tests/src/submessage_without_package.rs new file mode 100644 index 000000000..8f02a26e6 --- /dev/null +++ b/tests/src/submessage_without_package.rs @@ -0,0 +1,6 @@ +include!(concat!(env!("OUT_DIR"), "/_.rs")); + +#[test] +fn test_submessage_without_package() { + let _msg = M::default(); +}