def generate_message_doc(message_descriptor, locations, path, name_prefix='<STR_LIT>'):
<EOL>prefixed_name = name_prefix + message_descriptor.name<EOL>print(make_subsection(prefixed_name))<EOL>location = locations[path]<EOL>if location.HasField('<STR_LIT>'):<EOL><INDENT>print(textwrap.dedent(location.leading_comments))<EOL><DEDENT>row_tuples = []<EOL>for field_index, field in enumerate(message_descriptor.field):<EOL><INDENT>field_location = locations[path + (<NUM_LIT:2>, field_index)]<EOL>if field.type not in [<NUM_LIT:11>, <NUM_LIT>]:<EOL><INDENT>type_str = TYPE_TO_STR[field.type]<EOL><DEDENT>else:<EOL><INDENT>type_str = make_link(field.type_name.lstrip('<STR_LIT:.>'))<EOL><DEDENT>row_tuples.append((<EOL>make_code(field.name),<EOL>field.number,<EOL>type_str,<EOL>LABEL_TO_STR[field.label],<EOL>textwrap.fill(get_comment_from_location(field_location), INFINITY),<EOL>))<EOL><DEDENT>print_table(('<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>'),<EOL>row_tuples)<EOL>nested_types = enumerate(message_descriptor.nested_type)<EOL>for index, nested_message_desc in nested_types:<EOL><INDENT>generate_message_doc(nested_message_desc, locations,<EOL>path + (<NUM_LIT:3>, index),<EOL>name_prefix=prefixed_name + '<STR_LIT:.>')<EOL><DEDENT>for index, nested_enum_desc in enumerate(message_descriptor.enum_type):<EOL><INDENT>generate_enum_doc(nested_enum_desc, locations, path + (<NUM_LIT:4>, index),<EOL>name_prefix=prefixed_name + '<STR_LIT:.>')<EOL><DEDENT>
Generate docs for message and nested messages and enums.

    Args:
        message_descriptor: descriptor_pb2.DescriptorProto instance for message
            to generate docs for.
        locations: Dictionary of location paths tuples to
            descriptor_pb2.SourceCodeInfo.Location instances.
        path: Path tuple to the message definition.
        name_prefix: Optional prefix for this message's name.