Skip to content

Generate valid C# for .proto files with no package or csharp_namespace#4562

Open
pepone wants to merge 1 commit intoicerpc:mainfrom
pepone:fix/protobuf-generator-empty-namespace
Open

Generate valid C# for .proto files with no package or csharp_namespace#4562
pepone wants to merge 1 commit intoicerpc:mainfrom
pepone:fix/protobuf-generator-empty-namespace

Conversation

@pepone
Copy link
Copy Markdown
Member

@pepone pepone commented Apr 27, 2026

Summary

  • When a .proto has neither package nor option csharp_namespace = ..., GetCsharpNamespace returned "" and the generator emitted namespace ; (CS1001 from the C# compiler) and global::.MyMessage for any cross-namespace reference.
  • Skip the namespace declaration when the namespace is empty, and emit global::MyMessage instead of global::.MyMessage for cross-namespace references targeting a file with no namespace. Matches Google's protoc-gen-csharp behavior of placing top-level types in the global namespace.
  • Add a .proto regression file with neither package nor csharp_namespace. Without the fix the test project fails to compile with CS1001: Identifier expected on the generated namespace ; line; with the fix it builds cleanly and all 48 Protobuf tests pass.

Fixes #4447

When neither `package` nor `option csharp_namespace = "..."` is set,
GetCsharpNamespace returned the empty string. The generator then emitted
"namespace ;" (rejected by the C# compiler) at the top of the file and
"global::.MyMessage" for any cross-namespace reference. Both are
invalid C#.

Skip the namespace declaration when the namespace is empty, and emit
"global::MyMessage" instead of "global::.MyMessage" for cross-namespace
references when the target file has no namespace. This matches Google's
protoc-gen-csharp behavior of placing top-level types in the global
namespace.

Add a regression .proto file with neither package nor csharp_namespace;
the test project's compile-time success is the regression check.
Verified empirically that without the fix the project fails to compile
with CS1001 ("Identifier expected") on line 16 of the generated file.
Copilot AI review requested due to automatic review settings April 27, 2026 16:43
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes protoc-gen-icerpc-csharp output for valid .proto files that omit both package and option csharp_namespace, ensuring generated C# compiles and matches protoc-gen-csharp behavior for global-namespace types.

Changes:

  • Skip emitting a file-scoped namespace ...; declaration when the computed C# namespace is empty.
  • Fix cross-namespace message type qualification to avoid emitting invalid global::.Type when targeting a no-namespace .proto.
  • Add a regression .proto with no package and no csharp_namespace to ensure the test project compiles.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tests/IceRpc.Protobuf.Tests/NoNamespaceTests.proto Adds a .proto schema with no namespace metadata to catch invalid generated namespace ; output during compilation.
src/IceRpc.Protobuf.Generator/Program.cs Conditionally emits the namespace declaration only when non-empty.
src/IceRpc.Protobuf.Generator/MessageDescriptorExtensions.cs Centralizes message type qualification and handles the empty-namespace case to produce valid global::Type references.

Comment on lines +3 to +5
// Intentionally has no `package` and no `option csharp_namespace`. The generator must emit valid C# in
// this case (no `namespace ;` declaration; cross-namespace references use `global::Type` rather than
// `global::.Type`).
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This regression .proto doesn’t currently exercise the cross-namespace reference scenario described in the header comment: nothing imports this file from a non-empty package/csharp_namespace, so the generator’s global::Type (vs global::.Type) path won’t be compiled/tested. Consider adding a second .proto with a non-empty package/csharp_namespace that imports this file and uses NoNamespaceMessage as an RPC input/output to ensure the generated C# contains global::NoNamespaceMessage and stays valid.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Audit-Medium] valid .proto files with no package and no csharpnamesp…

3 participants