Source code for coalib.bearlib.languages.documentation.DocumentationComment

from collections import namedtuple

from coala_utils.decorators import generate_eq, generate_repr


@generate_repr()
@generate_eq('documentation', 'language', 'docstyle',
             'indent', 'marker', 'range')
[docs]class DocumentationComment: """ The DocumentationComment holds information about a documentation comment inside source-code, like position etc. """ Parameter = namedtuple('Parameter', 'name, desc') ReturnValue = namedtuple('ReturnValue', 'desc') Description = namedtuple('Description', 'desc') def __init__(self, documentation, docstyle_definition, indent, marker, range): """ Instantiates a new DocumentationComment. :param documentation: The documentation text. :param docstyle_definition: The ``DocstyleDefinition`` instance that defines what docstyle is being used in the documentation. :param indent: The string of indentation used in front of the first marker of the documentation. :param marker: The three-element tuple with marker strings, that identified this documentation comment. :param range: The position range of type ``TextRange``. """ self.documentation = documentation self.docstyle_definition = docstyle_definition self.indent = indent self.marker = marker self.range = range def __str__(self): return self.documentation @property def language(self): return self.docstyle_definition.language @property def docstyle(self): return self.docstyle_definition.docstyle @property def metadata(self): return self.docstyle_definition.metadata
[docs] def parse(self): """ Parses documentation independent of language and docstyle. :return: The list of all the parsed sections of the documentation. Every section is a namedtuple of either ``Description`` or ``Parameter`` or ``ReturnValue``. :raises NotImplementedError: When no parsing method is present for the given language and docstyle. """ if self.language == 'python' and self.docstyle == 'default': return self._parse_documentation_with_symbols( (':param ', ':'), ':return:') elif self.language == 'python' and self.docstyle == 'doxygen': return self._parse_documentation_with_symbols( ('@param ', ' '), '@return ') elif self.language == 'java' and self.docstyle == 'default': return self._parse_documentation_with_symbols( ('@param ', ' '), '@return ') elif self.language == 'golang' and self.docstyle == 'golang': # golang does not have param, return markers return self.documentation.splitlines(keepends=True) else: raise NotImplementedError( 'Documentation parsing for {0.language!r} in {0.docstyle!r}' ' has not been implemented yet'.format(self))
def _parse_documentation_with_symbols(self, param_identifiers, return_identifiers): """ Parses documentation based on parameter and return symbols. :param param_identifiers: A tuple of two strings with which a parameter starts and ends. :param return_identifiers: The string with which a return description starts. :return: The list of all the parsed sections of the documentation. Every section is a namedtuple of either ``Description`` or ``Parameter`` or ``ReturnValue``. """ lines = self.documentation.splitlines(keepends=True) parse_mode = self.Description cur_param = '' desc = '' parsed = [] for line in lines: stripped_line = line.strip() if stripped_line.startswith(param_identifiers[0]): parse_mode = self.Parameter param_offset = line.find( param_identifiers[0]) + len(param_identifiers[0]) splitted = line[param_offset:].split(param_identifiers[1], 1) cur_param = splitted[0].strip() param_desc = splitted[1] parsed.append(self.Parameter(name=cur_param, desc=param_desc)) elif stripped_line.startswith(return_identifiers): parse_mode = self.ReturnValue return_offset = line.find( return_identifiers) + len(return_identifiers) retval_desc = line[return_offset:] parsed.append(self.ReturnValue(desc=retval_desc)) elif parse_mode == self.ReturnValue: retval_desc += line parsed.pop() parsed.append(self.ReturnValue(desc=retval_desc)) elif parse_mode == self.Parameter: param_desc += line parsed.pop() parsed.append(self.Parameter(name=cur_param, desc=param_desc)) else: desc += line # This is inside a try-except for cases where the list # is empty and has nothing to pop. try: parsed.pop() except IndexError: pass parsed.append(self.Description(desc=desc)) return parsed @classmethod
[docs] def from_metadata(cls, doccomment, docstyle_definition, marker, indent, range): r""" Assembles a list of parsed documentation comment metadata. This function just assembles the documentation comment itself, without the markers and indentation. >>> from coalib.bearlib.languages.documentation.DocumentationComment \ ... import DocumentationComment >>> from coalib.bearlib.languages.documentation.DocstyleDefinition \ ... import DocstyleDefinition >>> from coalib.results.TextRange import TextRange >>> Description = DocumentationComment.Description >>> Parameter = DocumentationComment.Parameter >>> python_default = DocstyleDefinition.load("python3", "default") >>> parsed_doc = [Description(desc='\nDescription\n'), ... Parameter(name='age', desc=' Age\n')] >>> str(DocumentationComment.from_metadata( ... parsed_doc, python_default, ... python_default.markers[0], 4, ... TextRange.from_values(0, 0, 0, 0))) '\nDescription\n:param age: Age\n' :param doccomment: The list of parsed documentation comment metadata. :param docstyle_definition: The ``DocstyleDefinition`` instance that defines what docstyle is being used in a documentation comment. :param marker: The markers to be used in the documentation comment. :param indent: The indentation to be used in the documentation comment. :param range: The range of the documentation comment. :return: A ``DocumentationComment`` instance of the assembled documentation. """ assembled_doc = '' for section in doccomment: section_desc = section.desc.splitlines(keepends=True) if isinstance(section, cls.Parameter): assembled_doc += (docstyle_definition.metadata.param_start + section.name + docstyle_definition.metadata.param_end) elif isinstance(section, cls.ReturnValue): assembled_doc += docstyle_definition.metadata.return_sep assembled_doc += ''.join(section_desc) return DocumentationComment(assembled_doc, docstyle_definition, indent, marker, range)
[docs] def assemble(self): """ Assembles parsed documentation to the original documentation. This function assembles the whole documentation comment, with the given markers and indentation. """ lines = self.documentation.splitlines(keepends=True) assembled = self.indent + self.marker[0] if len(lines) == 0: return self.marker[0] + self.marker[2] assembled += lines[0] assembled += ''.join('\n' if line == '\n' and not self.marker[1] else self.indent + self.marker[1] + line for line in lines[1:]) return (assembled + (self.indent if lines[-1][-1] == '\n' else '') + self.marker[2])