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

coalib.bearlib.languages.documentation.DocstyleDefinition   A

Complexity

Total Complexity 12

Size/Duplication

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

5 Methods

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