Fix comments generation for submessages (#788)
diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py
index b7cddde..b04df1c 100755
--- a/generator/nanopb_generator.py
+++ b/generator/nanopb_generator.py
@@ -286,17 +286,17 @@
     FIELD = 2
     MESSAGE = 4
     ENUM = 5
+    NESTED_TYPE = 3
+    NESTED_ENUM = 4
 
-    def __init__(self, element_type, index, comments = None, parent = ()):
+    def __init__(self, path, comments = None):
         '''
-        element_type is a predefined value for each element type in proto file.
-            For example, message == 4, enum == 5, service == 6
-        index is the N-th occurrence of the `path` in the proto file.
-            For example, 4-th message in the proto file or 2-nd enum etc ...
+        path is a tuple containing integers (type, index, ...)
         comments is a dictionary mapping between element path & SourceCodeInfo.Location
             (contains information about source comments).
         '''
-        self.element_path = parent + (element_type, index)
+        assert(isinstance(path, tuple))
+        self.element_path = path
         self.comments = comments or {}
 
     def get_member_comments(self, index):
@@ -332,14 +332,14 @@
 
 
 class Enum(ProtoElement):
-    def __init__(self, names, desc, enum_options, index, comments):
+    def __init__(self, names, desc, enum_options, element_path, comments):
         '''
         desc is EnumDescriptorProto
         index is the index of this enum element inside the file
         comments is a dictionary mapping between element path & SourceCodeInfo.Location
             (contains information about source comments)
         '''
-        super(Enum, self).__init__(ProtoElement.ENUM, index, comments)
+        super(Enum, self).__init__(element_path, comments)
 
         self.options = enum_options
         self.names = names
@@ -455,9 +455,9 @@
     macro_x_param = 'X'
     macro_a_param = 'a'
 
-    def __init__(self, struct_name, desc, field_options, parent_path = (), index = None, comments = None):
+    def __init__(self, struct_name, desc, field_options, element_path = (), comments = None):
         '''desc is FieldDescriptorProto'''
-        ProtoElement.__init__(self, ProtoElement.FIELD, index, comments, parent_path)
+        ProtoElement.__init__(self, element_path, comments)
         self.tag = desc.number
         self.struct_name = struct_name
         self.union_name = None
@@ -470,7 +470,6 @@
         self.data_item_size = None
         self.ctype = None
         self.fixed_count = False
-        self.index = index
         self.callback_datatype = field_options.callback_datatype
         self.math_include_required = False
         self.sort_by_tag = field_options.sort_by_tag
@@ -968,8 +967,8 @@
         else:
             self.skip = False
             self.rules = 'REQUIRED' # We don't really want the has_field for extensions
-            # currently no support for comments for extension fields => provide 0, {}
-            self.msg = Message(self.fullname + "extmsg", None, field_options, 0, {})
+            # currently no support for comments for extension fields => provide (), {}
+            self.msg = Message(self.fullname + "extmsg", None, field_options, (), {})
             self.msg.fields.append(self)
 
     def tags(self):
@@ -1020,7 +1019,6 @@
         self.allocation = 'ONEOF'
         self.default = None
         self.rules = 'ONEOF'
-        self.index = None
         self.anonymous = oneof_options.anonymous_oneof
         self.sort_by_tag = oneof_options.sort_by_tag
         self.has_msg_cb = False
@@ -1123,8 +1121,8 @@
 
 
 class Message(ProtoElement):
-    def __init__(self, names, desc, message_options, index, comments):
-        super(Message, self).__init__(ProtoElement.MESSAGE, index, comments)
+    def __init__(self, names, desc, message_options, element_path, comments):
+        super(Message, self).__init__(element_path, comments)
         self.name = names
         self.fields = []
         self.oneofs = {}
@@ -1174,7 +1172,7 @@
             if field_options.descriptorsize > self.descriptorsize:
                 self.descriptorsize = field_options.descriptorsize
 
-            field = Field(self.name, f, field_options, self.element_path, index, self.comments)
+            field = Field(self.name, f, field_options, self.element_path + (ProtoElement.FIELD, index), self.comments)
             if hasattr(f, 'oneof_index') and f.HasField('oneof_index'):
                 if hasattr(f, 'proto3_optional') and f.proto3_optional:
                     no_unions.append(f.oneof_index)
@@ -1476,21 +1474,24 @@
 #                    Processing of entire .proto files
 # ---------------------------------------------------------------------------
 
-def iterate_messages(desc, flatten = False, names = Names()):
-    '''Recursively find all messages. For each, yield name, DescriptorProto.'''
+def iterate_messages(desc, flatten = False, names = Names(), comment_path = ()):
+    '''Recursively find all messages. For each, yield name, DescriptorProto, comment_path.'''
     if hasattr(desc, 'message_type'):
         submsgs = desc.message_type
+        comment_path += (ProtoElement.MESSAGE,)
     else:
         submsgs = desc.nested_type
+        comment_path += (ProtoElement.NESTED_TYPE,)
 
-    for submsg in submsgs:
+    for idx, submsg in enumerate(submsgs):
         sub_names = names + submsg.name
+        sub_path = comment_path + (idx,)
         if flatten:
-            yield Names(submsg.name), submsg
+            yield Names(submsg.name), submsg, sub_path
         else:
-            yield sub_names, submsg
+            yield sub_names, submsg, sub_path
 
-        for x in iterate_messages(submsg, flatten, sub_names):
+        for x in iterate_messages(submsg, flatten, sub_names, sub_path):
             yield x
 
 def iterate_extensions(desc, flatten = False, names = Names()):
@@ -1500,7 +1501,7 @@
     for extension in desc.extension:
         yield names, extension
 
-    for subname, subdesc in iterate_messages(desc, flatten, names):
+    for subname, subdesc, comment_path in iterate_messages(desc, flatten, names):
         for extension in subdesc.extension:
             yield subname, extension
 
@@ -1654,9 +1655,10 @@
         for index, enum in enumerate(self.fdesc.enum_type):
             name = self.manglenames.create_name(enum.name)
             enum_options = get_nanopb_suboptions(enum, self.file_options, name)
-            self.enums.append(Enum(name, enum, enum_options, index, self.comment_locations))
+            enum_path = (ProtoElement.ENUM, index)
+            self.enums.append(Enum(name, enum, enum_options, enum_path, self.comment_locations))
 
-        for index, (names, message) in enumerate(iterate_messages(self.fdesc, self.manglenames.flatten)):
+        for names, message, comment_path in iterate_messages(self.fdesc, self.manglenames.flatten):
             name = self.manglenames.create_name(names)
             message_options = get_nanopb_suboptions(message, self.file_options, name)
 
@@ -1668,11 +1670,12 @@
                 if field.type in (FieldD.TYPE_MESSAGE, FieldD.TYPE_ENUM):
                     field.type_name = self.manglenames.mangle_field_typename(field.type_name)
 
-            self.messages.append(Message(name, message, message_options, index, self.comment_locations))
+            self.messages.append(Message(name, message, message_options, comment_path, self.comment_locations))
             for index, enum in enumerate(message.enum_type):
                 name = self.manglenames.create_name(names + enum.name)
                 enum_options = get_nanopb_suboptions(enum, message_options, name)
-                self.enums.append(Enum(name, enum, enum_options, index, self.comment_locations))
+                enum_path = comment_path + (ProtoElement.NESTED_ENUM, index)
+                self.enums.append(Enum(name, enum, enum_options, enum_path, self.comment_locations))
 
         for names, extension in iterate_extensions(self.fdesc, self.manglenames.flatten):
             name = self.manglenames.create_name(names + extension.name)
diff --git a/tests/comments/comments.expected b/tests/comments/comments.expected
index 0d96dc2..ae22a92 100644
--- a/tests/comments/comments.expected
+++ b/tests/comments/comments.expected
@@ -8,3 +8,7 @@
 m2member4.*m2comment4
 m2oneof10.*m2oneof10_comment
 m2oneof5.*m2oneof5_comment
+A.*A_comment
+B.*B_comment
+C.*C_comment
+subfield.*subfield_comment
diff --git a/tests/comments/comments.proto b/tests/comments/comments.proto
index 0dba90f..0f952ce 100644
--- a/tests/comments/comments.proto
+++ b/tests/comments/comments.proto
@@ -27,3 +27,17 @@
         int32 m2oneof5 = 5; // m2oneof5_comment
     }
 }
+
+message Message3
+{
+    message SubMessage {
+        required int32 subfield = 1; // subfield_comment
+
+        enum SubEnum
+        {
+            A = 0; /// A_comment
+            B = 1; /// B_comment
+            C = 2; /// C_comment
+        }
+    }
+}