Completed
Pull Request — master (#1098)
by Mischa
02:06
created

coalib.bearlib.languages.documentation.DocstyleDefinition   A

Complexity

Total Complexity 12

Size/Duplication

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

5 Methods

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