Fix keyword handling in prost wrapper (#2888)
## What?
Fixes Prost: Handling of reserved keywords in package names is broken
#2884
## How?
Added escaping on Rust keywords in proto package names
diff --git a/proto/prost/private/protoc_wrapper.rs b/proto/prost/private/protoc_wrapper.rs
index 9c41892..e473ad7 100644
--- a/proto/prost/private/protoc_wrapper.rs
+++ b/proto/prost/private/protoc_wrapper.rs
@@ -280,13 +280,13 @@
/// Join a path to the end of the module path.
fn join(&self, path: &str) -> RustModulePath {
if self.0.is_empty() {
- return RustModulePath(path.to_string());
+ return RustModulePath(escape_keyword(path.to_string()));
}
if path.is_empty() {
return self.clone();
}
- RustModulePath(format!("{}::{}", self.0, path))
+ RustModulePath(format!("{}::{}", self.0, escape_keyword(path.to_string())))
}
}
@@ -298,7 +298,7 @@
impl From<&str> for RustModulePath {
fn from(path: &str) -> Self {
- RustModulePath(path.to_string())
+ RustModulePath(escape_keyword(path.to_string()))
}
}
@@ -310,7 +310,7 @@
crate_name: &str,
) -> Result<BTreeMap<ProtoPath, RustModulePath>, String> {
let mut extern_paths = BTreeMap::new();
- let rust_path = RustModulePath(crate_name.to_string());
+ let rust_path = RustModulePath(escape_keyword(crate_name.to_string()));
for file in descriptor_set.file.iter() {
descriptor_set_file_to_extern_paths(&mut extern_paths, &rust_path, file);
@@ -326,7 +326,9 @@
file: &FileDescriptorProto,
) {
let package = file.package.clone().unwrap_or_default();
- let rust_path = rust_path.join(&snake_cased_package_name(&package).replace('.', "::"));
+ let rust_path = package.split('.').fold(rust_path.clone(), |acc, part| {
+ acc.join(&snake_cased_package_name(part))
+ });
let proto_path = ProtoPath(package);
for message_type in file.message_type.iter() {
diff --git a/proto/prost/private/tests/keywords/BUILD.bazel b/proto/prost/private/tests/keywords/BUILD.bazel
index 415301e..af598ae 100644
--- a/proto/prost/private/tests/keywords/BUILD.bazel
+++ b/proto/prost/private/tests/keywords/BUILD.bazel
@@ -5,10 +5,22 @@
package(default_visibility = ["//proto/prost/private/tests:__subpackages__"])
proto_library(
+ name = "imported_keyword_proto",
+ srcs = [
+ "imported_keyword.proto",
+ ],
+ strip_import_prefix = "/proto/prost/private/tests/keywords",
+)
+
+proto_library(
name = "mod_named_mod_proto",
srcs = [
"mod_named_mod.proto",
],
+ strip_import_prefix = "/proto/prost/private/tests/keywords",
+ deps = [
+ ":imported_keyword_proto",
+ ],
)
rust_prost_library(
@@ -16,11 +28,17 @@
proto = ":mod_named_mod_proto",
)
+rust_prost_library(
+ name = "imported_keyword_rs_proto",
+ proto = ":imported_keyword_proto",
+)
+
rust_test(
name = "mod_named_mod_test",
srcs = ["mod_named_mod_test.rs"],
edition = "2021",
deps = [
+ ":imported_keyword_rs_proto",
":mod_named_mod_rs_proto",
],
)
diff --git a/proto/prost/private/tests/keywords/imported_keyword.proto b/proto/prost/private/tests/keywords/imported_keyword.proto
new file mode 100644
index 0000000..9c987f9
--- /dev/null
+++ b/proto/prost/private/tests/keywords/imported_keyword.proto
@@ -0,0 +1,7 @@
+syntax = "proto3";
+
+package imported.type;
+
+message B {
+ string name = 1;
+}
diff --git a/proto/prost/private/tests/keywords/mod_named_mod.proto b/proto/prost/private/tests/keywords/mod_named_mod.proto
index 8e6e66f..cede9ae 100644
--- a/proto/prost/private/tests/keywords/mod_named_mod.proto
+++ b/proto/prost/private/tests/keywords/mod_named_mod.proto
@@ -2,6 +2,9 @@
package mod;
+import "imported_keyword.proto";
+
message A {
string name = 1;
+ imported.type.B b = 2;
}
diff --git a/proto/prost/private/tests/keywords/mod_named_mod_test.rs b/proto/prost/private/tests/keywords/mod_named_mod_test.rs
index 4b326a6..12ecf88 100644
--- a/proto/prost/private/tests/keywords/mod_named_mod_test.rs
+++ b/proto/prost/private/tests/keywords/mod_named_mod_test.rs
@@ -1,11 +1,15 @@
//! Tests module names that are keywords.
+use imported_keyword_proto::imported::r#type::B;
use mod_named_mod_proto::r#mod::A;
#[test]
fn test_nested_messages() {
let a = A {
name: "a".to_string(),
+ b: Some(B {
+ name: "b".to_string(),
+ }),
};
assert_eq!(a.name, "a");