From 3ad853630c6bf76a9c8fc2a15e3fc40cd52de691 Mon Sep 17 00:00:00 2001
From: Advay Mengle <advay.mengle.dev1@gmail.com>
Date: Tue, 31 Mar 2015 02:03:11 -0700
Subject: [PATCH] Generate appropriate schema doc comments from .proto files

- Add parse handling of .proto struct and field doc comments (enums and
their values were already handled)
- Add FBS generation handling of doc comments for structs, their
fields, enums, and their values (requires linking idl_gen_general in
the test binary build)
- Tested using test.proto|golden with doc comments added.  Xcode run of
flattest passes.

Change-Id: Idff64dd8064afba227174ab77d2c7be22d006628
---
 CMakeLists.txt                                    |  1 +
 build/VS2010/flattests.vcxproj                    |  3 ++-
 build/Xcode/FlatBuffers.xcodeproj/project.pbxproj |  2 ++
 src/idl_gen_fbs.cpp                               |  4 ++++
 src/idl_parser.cpp                                |  4 ++++
 tests/prototest/test.golden                       |  9 +++++++++
 tests/prototest/test.proto                        | 10 ++++++++++
 7 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a746a646..18326390 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,6 +40,7 @@ set(FlatBuffers_Tests_SRCS
   include/flatbuffers/idl.h
   include/flatbuffers/util.h
   src/idl_parser.cpp
+  src/idl_gen_general.cpp
   src/idl_gen_text.cpp
   src/idl_gen_fbs.cpp
   tests/test.cpp
diff --git a/build/VS2010/flattests.vcxproj b/build/VS2010/flattests.vcxproj
index 777282dc..96d76b13 100755
--- a/build/VS2010/flattests.vcxproj
+++ b/build/VS2010/flattests.vcxproj
@@ -268,6 +268,7 @@
     <ClInclude Include="..\..\include\flatbuffers\util.h" />
     <ClInclude Include="..\..\tests\monster_test_generated.h" />
     <ClCompile Include="..\..\src\idl_gen_fbs.cpp" />
+    <ClCompile Include="..\..\src\idl_gen_general.cpp" />
     <ClCompile Include="..\..\src\idl_parser.cpp" />
     <ClCompile Include="..\..\src\idl_gen_text.cpp" />
     <ClCompile Include="..\..\tests\test.cpp" />
@@ -275,4 +276,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/build/Xcode/FlatBuffers.xcodeproj/project.pbxproj b/build/Xcode/FlatBuffers.xcodeproj/project.pbxproj
index c484bcf5..9f11caaa 100644
--- a/build/Xcode/FlatBuffers.xcodeproj/project.pbxproj
+++ b/build/Xcode/FlatBuffers.xcodeproj/project.pbxproj
@@ -8,6 +8,7 @@
 
 /* Begin PBXBuildFile section */
 		1963D7D2A57344A3B1C1713F /* idl_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3709AC883348409592530AE6 /* idl_parser.cpp */; settings = {COMPILER_FLAGS = ""; }; };
+		5AC48C391ACA9A0A008132C5 /* idl_gen_general.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD8717A19CB937D0012A827 /* idl_gen_general.cpp */; };
 		61823BBC53544106B6DBC38E /* idl_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3709AC883348409592530AE6 /* idl_parser.cpp */; settings = {COMPILER_FLAGS = ""; }; };
 		61FF3C34FBEC4819A1C30F92 /* sample_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECCEBFFA6977404F858F9739 /* sample_text.cpp */; settings = {COMPILER_FLAGS = ""; }; };
 		8C303C591975D6A700D7C1C5 /* idl_gen_go.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C303C581975D6A700D7C1C5 /* idl_gen_go.cpp */; };
@@ -344,6 +345,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				5AC48C391ACA9A0A008132C5 /* idl_gen_general.cpp in Sources */,
 				8C6905FD19F835B400CB8866 /* idl_gen_fbs.cpp in Sources */,
 				E0680D6B5BFD484BA9D88EE8 /* idl_gen_text.cpp in Sources */,
 				61823BBC53544106B6DBC38E /* idl_parser.cpp in Sources */,
diff --git a/src/idl_gen_fbs.cpp b/src/idl_gen_fbs.cpp
index e89f922c..270fd251 100644
--- a/src/idl_gen_fbs.cpp
+++ b/src/idl_gen_fbs.cpp
@@ -61,11 +61,13 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name,
   for (auto enum_def_it = parser.enums_.vec.begin();
            enum_def_it != parser.enums_.vec.end(); ++enum_def_it) {
     EnumDef &enum_def = **enum_def_it;
+    GenComment(enum_def.doc_comment, &schema, nullptr);
     schema += "enum " + enum_def.name + " : ";
     schema += GenType(enum_def.underlying_type) + " {\n";
     for (auto it = enum_def.vals.vec.begin();
          it != enum_def.vals.vec.end(); ++it) {
       auto &ev = **it;
+      GenComment(ev.doc_comment, &schema, nullptr, "  ");
       schema += "  " + ev.name + " = " + NumToString(ev.value) + ",\n";
     }
     schema += "}\n\n";
@@ -74,10 +76,12 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name,
   for (auto it = parser.structs_.vec.begin();
            it != parser.structs_.vec.end(); ++it) {
     StructDef &struct_def = **it;
+    GenComment(struct_def.doc_comment, &schema, nullptr);
     schema += "table " + struct_def.name + " {\n";
     for (auto field_it = struct_def.fields.vec.begin();
              field_it != struct_def.fields.vec.end(); ++field_it) {
       auto &field = **field_it;
+      GenComment(field.doc_comment, &schema, nullptr, "  ");
       schema += "  " + field.name + ":" + GenType(field.value.type);
       if (field.value.constant != "0") schema += " = " + field.value.constant;
       if (field.required) schema += " (required)";
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index f64fb795..f520c765 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -991,10 +991,13 @@ void Parser::ParseProtoDecl() {
     // These are identical in syntax to FlatBuffer's namespace decl.
     ParseNamespace();
   } else if (attribute_ == "message") {
+    std::vector<std::string> struct_comment = doc_comment_;
     Next();
     auto &struct_def = StartStruct();
+    struct_def.doc_comment = struct_comment;
     Expect('{');
     while (token_ != '}') {
+      std::vector<std::string> field_comment = doc_comment_;
       // Parse the qualifier.
       bool required = false;
       bool repeated = false;
@@ -1021,6 +1024,7 @@ void Parser::ParseProtoDecl() {
       Expect('=');
       Expect(kTokenIntegerConstant);
       auto &field = AddField(struct_def, name, type);
+      field.doc_comment = field_comment;
       field.required = required;
       // See if there's a default specified.
       if (IsNext('[')) {
diff --git a/tests/prototest/test.golden b/tests/prototest/test.golden
index 82ac3bc2..767a8bc0 100644
--- a/tests/prototest/test.golden
+++ b/tests/prototest/test.golden
@@ -2,28 +2,37 @@
 
 namespace proto.test;
 
+/// Enum doc comment.
 enum ProtoEnum : short {
   FOO = 1,
+  /// Enum 2nd value doc comment misaligned.
   BAR = 5,
 }
 
 table OtherMessage {
   a:double;
+  /// doc comment for b.
   b:float = 3.14149;
 }
 
+/// 2nd table doc comment with
+/// many lines.
 table ProtoMessage {
   c:int = 16;
   d:long;
   p:uint;
   e:ulong;
+  /// doc comment for f.
   f:int = -1;
   g:long;
   h:uint;
   q:ulong;
   i:int;
   j:long;
+  /// doc comment for k.
   k:bool;
+  /// doc comment for l on 2
+  /// lines
   l:string (required);
   m:string;
   n:OtherMessage;
diff --git a/tests/prototest/test.proto b/tests/prototest/test.proto
index d29b3c1b..0ca4a2a6 100644
--- a/tests/prototest/test.proto
+++ b/tests/prototest/test.proto
@@ -5,28 +5,38 @@ package proto.test;
 option some_option = is_ignored;
 import "some_other_schema.proto";
 
+/// Enum doc comment.
 enum ProtoEnum {
   FOO = 1;
+/// Enum 2nd value doc comment misaligned.
   BAR = 5;
 }
 
+// Ignored non-doc comment.
 message OtherMessage {
   optional double a = 26;
+  /// doc comment for b.
   optional float b = 32 [default = 3.14149];
 }
 
+/// 2nd table doc comment with
+/// many lines.
 message ProtoMessage {
   optional int32 c = 12 [default = 16];
   optional int64 d = 1 [default = 0];
   optional uint32 p = 1;
   optional uint64 e = 2;
+  /// doc comment for f.
   optional sint32 f = 3 [default = -1];
   optional sint64 g = 4;
   optional fixed32 h = 5;
   optional fixed64 q = 6;
   optional sfixed32 i = 7;
   optional sfixed64 j = 8;
+  /// doc comment for k.
   optional bool k = 9;
+  /// doc comment for l on 2
+  /// lines
   required string l = 10;
   optional bytes m = 11;
   optional OtherMessage n = 12;
-- 
GitLab