From 0a3bf9eecf1ce93de6d23176fd6f80dbf9481f00 Mon Sep 17 00:00:00 2001 From: William Smith <87392567+william-smith-skydio@users.noreply.github.com> Date: Thu, 12 Oct 2023 08:13:40 -0700 Subject: [PATCH] [prost] Fix handling of message names with acronyms (#2193) For example, the message name `SomeAPI`. Internally protoc-gen-prost [converts](https://github.com/neoeinstein/protoc-gen-prost/blob/1a6d3593622af18b75a4a79f545f8530cdaf444f/protoc-gen-tonic/src/util.rs#L14) this to upper camel case, but rules_rust is not doing that when populating the `--extern_path` args. The result is that when a message with an acroynym in its name is included in another proto file, the generated code has a type name with the wrong casing. Without this fix, the added test fails to build like this: ``` error[E0412]: cannot find type `NameWithCAPS` in module `camel_case_proto::camel_case` --> bazel-out/k8-fastbuild/bin/proto/prost/private/tests/camel_case/another_proto.lib.rs:9:75 | 9 | pub inner: ::core::option::Option<::camel_case_proto::camel_case::NameWithCAPS>, | ^^^^^^^^^^^^ help: a struct with a similar name exists: `NameWithCaps` --> bazel-out/k8-fastbuild/bin/proto/prost/private/tests/camel_case/camel_case_proto.lib.rs:7:5 | = note: similarly named struct `NameWithCaps` defined here error: aborting due to previous error ``` --- proto/prost/private/protoc_wrapper.rs | 4 +- .../private/tests/camel_case/BUILD.bazel | 37 +++++++++++++++++++ .../private/tests/camel_case/another.proto | 9 +++++ .../private/tests/camel_case/camel_case.proto | 7 ++++ .../tests/camel_case/camel_case_test.rs | 8 ++++ 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 proto/prost/private/tests/camel_case/BUILD.bazel create mode 100644 proto/prost/private/tests/camel_case/another.proto create mode 100644 proto/prost/private/tests/camel_case/camel_case.proto create mode 100644 proto/prost/private/tests/camel_case/camel_case_test.rs diff --git a/proto/prost/private/protoc_wrapper.rs b/proto/prost/private/protoc_wrapper.rs index bf74ae635b..384c41f7fa 100644 --- a/proto/prost/private/protoc_wrapper.rs +++ b/proto/prost/private/protoc_wrapper.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use std::process; use std::{env, fmt}; -use heck::ToSnakeCase; +use heck::{ToSnakeCase, ToUpperCamelCase}; use prost::Message; use prost_types::{ DescriptorProto, EnumDescriptorProto, FileDescriptorProto, FileDescriptorSet, @@ -351,7 +351,7 @@ fn message_type_to_extern_paths( extern_paths.insert( proto_path.join(message_type_name), - rust_path.join(message_type_name), + rust_path.join(&message_type_name.to_upper_camel_case()), ); let name_lower = message_type_name.to_lowercase(); diff --git a/proto/prost/private/tests/camel_case/BUILD.bazel b/proto/prost/private/tests/camel_case/BUILD.bazel new file mode 100644 index 0000000000..1720ad28ef --- /dev/null +++ b/proto/prost/private/tests/camel_case/BUILD.bazel @@ -0,0 +1,37 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") +load("//proto/prost:defs.bzl", "rust_prost_library") +load("//rust:defs.bzl", "rust_test") + +package(default_visibility = ["//proto/prost/private/tests:__subpackages__"]) + +proto_library( + name = "camel_case_proto", + srcs = [ + "camel_case.proto", + ], + strip_import_prefix = "/proto/prost/private/tests/camel_case", +) + +proto_library( + name = "another_proto", + srcs = [ + "another.proto", + ], + deps = [ + ":camel_case_proto", + ], +) + +rust_prost_library( + name = "another_proto_rust", + proto = ":another_proto", +) + +rust_test( + name = "camel_case_test", + srcs = ["camel_case_test.rs"], + edition = "2021", + deps = [ + ":another_proto_rust", + ], +) diff --git a/proto/prost/private/tests/camel_case/another.proto b/proto/prost/private/tests/camel_case/another.proto new file mode 100644 index 0000000000..186cfcf8c3 --- /dev/null +++ b/proto/prost/private/tests/camel_case/another.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package another; + +import "camel_case.proto"; + +message Another { + camel_case.NameWithCAPS inner = 1; +} diff --git a/proto/prost/private/tests/camel_case/camel_case.proto b/proto/prost/private/tests/camel_case/camel_case.proto new file mode 100644 index 0000000000..e472ddf5a8 --- /dev/null +++ b/proto/prost/private/tests/camel_case/camel_case.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package camel_case; + +message NameWithCAPS { + string name = 1; +} diff --git a/proto/prost/private/tests/camel_case/camel_case_test.rs b/proto/prost/private/tests/camel_case/camel_case_test.rs new file mode 100644 index 0000000000..cc555680e8 --- /dev/null +++ b/proto/prost/private/tests/camel_case/camel_case_test.rs @@ -0,0 +1,8 @@ +//! Tests that strange casings of message names are handled correctly. + +use another_proto::another::Another; + +#[test] +fn test_nested_messages() { + let _a = Another::default(); +}