[csharp codegen] Handle empty base_namespace option value to fix #34113 (#34137)

Fix for https://github.com/grpc/grpc/issues/34113 - setting C# option
base_namespace to an empty string results in inconsistent behavior

Allow the `base_namespace` option in the protocol buffers C# gRPC plugin
to be specified with an empty string to make sure the plugin has the
same behaviour as the protocol buffers compiler.
pull/34196/head
tony 1 year ago committed by GitHub
parent 430d358f70
commit 157d8e23c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      src/compiler/csharp_generator_helpers.h
  2. 5
      src/compiler/csharp_plugin.cc
  3. 35
      test/csharp/codegen/csharp_codegen_base_namespace_test.sh

@ -26,6 +26,7 @@ namespace grpc_csharp_generator {
inline bool ServicesFilename(const grpc::protobuf::FileDescriptor* file,
const std::string& file_suffix,
const bool base_namespace_present,
const std::string& base_namespace,
std::string& out_file, std::string* error) {
// Support for base_namespace option is **experimental**.
@ -36,7 +37,7 @@ inline bool ServicesFilename(const grpc::protobuf::FileDescriptor* file,
// make a difference (only files with punctuation or numbers in the
// name.)
// Otherwise the behavior remains the same as before.
if (base_namespace.empty()) {
if (!base_namespace_present) {
out_file = grpc_generator::FileNameInUpperCamel(file, false) + file_suffix;
} else {
out_file = GRPC_CUSTOM_CSHARP_GETOUTPUTFILE(file, file_suffix, true,

@ -44,6 +44,7 @@ class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
bool generate_server = true;
bool internal_access = false;
std::string base_namespace = "";
bool base_namespace_present = false;
// the suffix that will get appended to the name generated from the name
// of the original .proto file
@ -62,6 +63,7 @@ class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
// The option may be removed or file names generated may change
// in the future.
base_namespace = options[i].second;
base_namespace_present = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
@ -77,7 +79,8 @@ class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
// Get output file name.
std::string file_name;
if (!grpc_csharp_generator::ServicesFilename(
file, file_suffix, base_namespace, file_name, error)) {
file, file_suffix, base_namespace_present, base_namespace,
file_name, error)) {
return false;
}
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(

@ -67,6 +67,41 @@ ls -lR ./proto_out
exit 1
}
# Run again with base_namespace option set to empty value to check that the files
# are created under a full directory structure defined by the namespace
rm -rf ${PROTO_OUT}
mkdir -p ${PROTO_OUT}
$PROTOC \
--plugin=protoc-gen-grpc-csharp=$PLUGIN \
--csharp_out=${PROTO_OUT} \
--grpc-csharp_out=${PROTO_OUT} \
--csharp_opt=base_namespace= \
--grpc-csharp_opt=base_namespace= \
-I ${DATA_DIR}/proto \
${DATA_DIR}/proto/namespacetest.proto
# log the files generated
ls -lR ./proto_out
# Verify the output files exist in the right location.
# The C# namespace option in the proto file of "Example.V1.CodegenTest"
# combined with the command line options above should mean the generated files
# are created in the output directory "Example/V1/CodegenTest"
# First file is generated by protoc.
[ -e ${PROTO_OUT}/Example/V1/CodegenTest/Namespacetest.cs ] || {
echo >&2 "missing generated output, expecting Example/V1/CodegenTest/Namespacetest.cs"
exit 1
}
# Second file is generated by the plugin.
[ -e ${PROTO_OUT}/Example/V1/CodegenTest/NamespacetestGrpc.cs ] || {
echo >&2 "missing generated output, expecting Example/V1/CodegenTest/NamespacetestGrpc.cs"
exit 1
}
# Run again without the base_namespace options to check the files are created
# in the root of the output directory

Loading…
Cancel
Save