6

We are using protobuf-net to handle our Protocol Buffer needs in a C# application. Since we share our .proto files with other, non-managed applications, we are generating our code from the .proto files (not using the code-first protobuf-net approach). In order to stay as DRY as possible, we keep a lot of interface documentation inside the .proto files themselves. We generate the C# code by means of protogen.exe, called by a project build target.

Now, is there any way to (automatically) transfer these comments into the compiled C# code?

Basically, given a .proto like this:

// This message is used to request a resource from the server
message GetResource
{
    // The identifier of the requested resource 
    required string resourceId = 1;
}

...I would like something like this (IExtensible methods omitted for readability):

/// <summary>
/// This message is used to request a resource from the server
/// </summary>
[global::System.Serializable,global::ProtoBuf.ProtoContract(Name=@"GetResource")]
public partial class GetResource : global::ProtoBuf.IExtensible
{
    public GetResource() {}

    private string _resourceId;

    /// <summary>
    /// The identifier of the requested resource 
    /// [Required] <-- Would be nice...
    /// </summary>
    [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"resourceId", 
    DataFormat = global::ProtoBuf.DataFormat.Default)]
    public string ResourceId
    {
        get { return _resourceId; }
        set { _resourceId = value; }
    }
}
Jakob Möllås
  • 4,239
  • 3
  • 33
  • 61

2 Answers2

6

Actually current version does support comments. It may be enabled with --include_source_info.

Comments are available in descriptor.Location[n].leading_comments and trailing_comments : https://code.google.com/p/protobuf/source/browse/trunk/src/google/protobuf/descriptor.proto

I've added the corresponding properties to protobuf-net Location class:

private string _leading_comments = "";
[global::ProtoBuf.ProtoMember(3, IsRequired = false, Name = @"leading_comments", DataFormat = global::ProtoBuf.DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string leading_comments
{
    get { return _leading_comments; }
    set { _leading_comments = value; }
}

private string _trailing_comments = "";
[global::ProtoBuf.ProtoMember(4, IsRequired = false, Name = @"trailing_comments", DataFormat = global::ProtoBuf.DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string trailing_comments
{
    get { return _trailing_comments; }
    set { _trailing_comments = value; }
}

And added --include_source_info to protoc call (ProtoBuf.CodeGenerator.InputFileLoader)

And locations with comments were added to xml generated:

<?xml version="1.0" encoding="utf-16"?>
<FileDescriptorSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <file>
    <FileDescriptorProto>
      <name>Test.proto</name>
      <dependency />
      <message_type>
        <DescriptorProto>
          <name>Test2</name>
          <field>
            <FieldDescriptorProto>
              <name>IntValue</name>
              <number>1</number>
              <type>TYPE_INT32</type>
            </FieldDescriptorProto>
          </field>
          <extension />
          <nested_type />
          <enum_type />
          <extension_range />
        </DescriptorProto>
      </message_type>
      <enum_type />
      <service />
      <extension />
      <source_code_info>
        <location>
...
        <Location>
            <path>
              <int>4</int>
              <int>0</int>
              <int>2</int>
              <int>0</int>
            </path>
            <span>
              <int>1</int>
              <int>0</int>
              <int>28</int>
            </span>
            <trailing_comments> some comment
</trailing_comments>
          </Location>
...
          </location>
      </source_code_info>
    </FileDescriptorProto>
  </file>
</FileDescriptorSet>

source .proto:

message Test2{
optional int32 IntValue = 1;// some comment
}

But I'm not strong in xslt to update ProtoGen/csharp.xslt to include comments into CS file generated

knst
  • 141
  • 2
  • 4
  • 1
    added feature request to protobuf-net issue racker. https://code.google.com/p/protobuf-net/issues/detail?id=372&thanks=372&ts=1366240737 – knst Apr 17 '13 at 23:20
  • Interesting, thanks! I hope this will be implemented in Protobuf-Net. It would be a great addition. – Jakob Möllås Apr 18 '13 at 07:47
3

At the current time, I believe the answer is "no". To the best of my knowledge, "protoc" (Google's tool for parsing .proto files, which is used under the hood) silently discards the comments - so there is nothing available to read from. If a custom parser was written, then yes it would be possible, but there is also a language ambiguity about which comments apply to which lines, for example:

// this probably relates to resourceId
required string resourceId = 1;

required int foo = 2; // but... is this foo? or bar?
                      // and what about this?

       // what does this relate to? and why?

// and this? what are the rules?
required int bar = 3;

So for 2 different reasons: at the moment, no. All suggestions considered, though... especially if they come with a custom parser included :)

Note that AFAIK this information is missing from most (all?) implementations for this reason. I'm happy to be corrected, though.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    Language ambiguity could be resolved by just defining a convention and sticking to it. I guess someone should make a feature request for protoc to include comments in the output, unless it is already on the list. Custom parsers are both annoying to write, and most of the ones I have seen don't implement the .proto syntax completely. – jpa Feb 13 '13 at 06:32