Failed Conditions
Pull Request — master (#1098)
by Mischa
02:01
created

coalib.bearlib.languages.documentation.DocstyleDefinition   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 151
Duplicated Lines 0 %
Metric Value
dl 0
loc 151
rs 10
wmc 12

5 Methods

Rating   Name   Duplication   Size   Complexity  
A docstyle() 0 9 1
B __init__() 0 27 4
A language() 0 9 1
B markers() 0 38 1
B load() 0 52 5
1
import os.path
2
3
from coalib.misc.Compatability import FileNotFoundError
4
from coalib.misc.Decorators import generate_eq, generate_repr
5
from coalib.parsing.ConfParser import ConfParser
6
7
8
@generate_repr()
9
@generate_eq("language", "docstyle", "markers")
10
class DocstyleDefinition:
11
    """
12
    The DocstyleDefinition class holds values that identify a certain type of
13
    documentation comment (for which language, documentation style/tool used
14
    etc.).
15
    """
16
17
    # TODO: Allow flattened tuple when providing a single marker_set. TEST THAT!
18
    # TODO: Type checks? This class is not involved in critical processes, a
19
    #       robust user friendly frontend would be good... TEST THAT!
20
    def __init__(self, language, docstyle, markers):
21
        """
22
        Instantiates a new DocstyleDefinition.
23
24
        :param language: The programming language of the documentation comment.
25
                         For example `"CPP"` for C++ or `"PYTHON3"` for
26
                         Python 3.
27
                         The given string is automatically lowered, so passing
28
                         i.e. "CPP" or "cpp" makes no difference.
29
        :param docstyle: The documentation style/tool used to document code.
30
                         For example `"default"` or `"doxygen"`.
31
                         The given string is automatically lowered, so passing
32
                         i.e. "default" or "DEFAULT" makes no difference.
33
        :param markers:  An iterable of marker/delimiter string iterables that
34
                         identify a documentation comment. See `markers`
35
                         property for more details on markers.
36
        """
37
        self._language = language.lower()
38
        self._docstyle = docstyle.lower()
39
        self._markers = tuple(tuple(marker_set) for marker_set in markers)
40
41
        # Check marker set dimensions.
42
        for marker_set in self._markers:
43
            length = len(marker_set)
44
            if length != 3:
45
                raise ValueError("Length of a given marker set was not 3 (was "
46
                                 "actually {}).".format(length))
47
48
    @property
49
    def language(self):
50
        """
51
        The programming language.
52
53
        :return: A lower-case string defining the programming language (i.e.
54
                 "cpp" or "python").
55
        """
56
        return self._language
57
58
    @property
59
    def docstyle(self):
60
        """
61
        The documentation style/tool used to document code.
62
63
        :return: A lower-case string defining the docstyle (i.e. "default" or
64
                 "doxygen").
65
        """
66
        return self._docstyle
67
68
    @property
69
    def markers(self):
70
        """
71
        A tuple of marker sets that identify a documentation comment.
72
73
        Marker sets consist of 3 entries where the first is the start-marker,
74
        the second one the each-line marker and the last one the end-marker.
75
        For example a marker tuple with a single marker set
76
        `(("/**", "*", "*/"),)` would match following documentation comment:
77
78
        ```
79
        /**
80
         * This is documentation.
81
         */
82
        ```
83
84
        It's also possible to supply an empty each-line marker
85
        (`("/**", "", "*/")`):
86
87
        ```
88
        /**
89
         This is more documentation.
90
         */
91
        ```
92
93
        Markers are matched "greedy", that means it will match as many
94
        each-line markers as possible. I.e. for `("///", "///", "///")`):
95
96
        ```
97
        /// Brief documentation.
98
        ///
99
        /// Detailed documentation.
100
        ```
101
102
        :return: A tuple of marker/delimiter string tuples that identify a
103
                 documentation comment.
104
        """
105
        return self._markers
106
107
    @classmethod
108
    def load(cls, language, docstyle):
109
        """
110
        Returns a `DocstyleDefinition` defined for the given language and
111
        docstyle from the coala docstyle definition files.
112
113
        The marker settings are loaded from the according coalang-files. Each
114
        setting inside them are considered a marker setting.
115
116
        :param language:           The programming language. For example
117
                                   `"CPP"` for C++ or `"PYTHON3"` for Python 3.
118
                                   The given string is automatically lowered,
119
                                   so passing i.e. "CPP" or "cpp" makes no
120
                                   difference.
121
        :param docstyle:           The documentation style/tool used. For
122
                                   example `"default"` or `"doxygen"`.
123
                                   The given string is automatically lowered,
124
                                   so passing i.e. "default" or "DEFAULT" makes
125
                                   no difference.
126
        :raises FileNotFoundError: Raised when the given docstyle was not
127
                                   found. This is a compatability exception
128
                                   from `coalib.misc.Compatability` module.
129
        :raises KeyError:          Raised when the given language is not
130
                                   defined for given docstyle.
131
        :return:                   The `DocstyleDefinition` for giving language
132
                                   and docstyle.
133
        """
134
135
        docstyle = docstyle.lower()
136
137
        language_config_parser = ConfParser(remove_empty_iter_elements=False)
138
        try:
139
            docstyle_settings = language_config_parser.parse(
140
                os.path.dirname(__file__) + "/" + docstyle + ".coalang")
141
        except FileNotFoundError as ex:
142
            raise type(ex)("Docstyle definition " + repr(docstyle) + " not "
143
                           "found.")
144
145
        language = language.lower()
146
147
        try:
148
            docstyle_settings = docstyle_settings[language]
149
        except KeyError:
150
            raise KeyError("Language {} is not defined for docstyle {}."
151
                           .format(repr(language), repr(docstyle)))
152
153
        marker_sets = (tuple(value)
154
                       for key, value in
155
                           filter(lambda kv: not kv[0].startswith("comment"),
156
                                  docstyle_settings.contents.items()))
157
158
        return cls(language, docstyle, marker_sets)
159