Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserving proto comments when generating C# with protobuf-net

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; }
    }
}
like image 244
Jakob Möllås Avatar asked Feb 12 '13 10:02

Jakob Möllås


2 Answers

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

like image 155
knst Avatar answered Nov 15 '22 12:11

knst


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.

like image 35
Marc Gravell Avatar answered Nov 15 '22 12:11

Marc Gravell