Skip to content

Commit 070a19e

Browse files
committed
DocumentationAPI: Add padding and type
Add `class_padding`, `function_padding` and `docstring_position` in DocstyleDefinition which are now acquired from `.coalang`. Add `top_padding` and `bottom_padding` which is automatically instantiated from DocumentationExtraction. Add `docstring_type` in DocumentationComment which will automatically determine the type of docstring from DocumentationExtraction. Add supporting test cases. Related to #4200
1 parent 0f81583 commit 070a19e

File tree

9 files changed

+434
-23
lines changed

9 files changed

+434
-23
lines changed

coalib/bearlib/languages/documentation/DocstyleDefinition.py

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,19 @@ class DocstyleDefinition:
1818
Metadata = namedtuple('Metadata', ('param_start', 'param_end',
1919
'exception_start', 'exception_end',
2020
'return_sep'))
21+
ClassPadding = namedtuple('ClassPadding',
22+
('top_padding', 'bottom_padding'))
23+
FunctionPadding = namedtuple('FunctionPadding',
24+
('top_padding', 'bottom_padding'))
25+
DocstringTypeRegex = namedtuple('DocstringTypeRegex',
26+
('class_sign', 'func_sign'))
2127

2228
@enforce_signature
2329
def __init__(self, language: str, docstyle: str, markers: (Iterable, str),
24-
metadata: Metadata):
30+
metadata: Metadata, class_padding: ClassPadding,
31+
function_padding: FunctionPadding,
32+
docstring_type_regex: DocstringTypeRegex,
33+
docstring_position: str):
2534
"""
2635
Instantiates a new DocstyleDefinition.
2736
@@ -39,6 +48,18 @@ def __init__(self, language: str, docstyle: str, markers: (Iterable, str),
3948
e.g. ``param_start`` defining the start symbol of
4049
the parameter fields and ``param_end`` defining the
4150
end.
51+
:param class_padding: A namedtuple consisting of values about
52+
blank lines before and after the documentation of
53+
``docstring_type`` class.
54+
:param function_padding: A namedtuple consisting of values about
55+
blank lines before and after the documentation of
56+
``docstring_type`` function.
57+
:param docstring_type_regex: A namedtuple consisting of regex
58+
about ``class`` and ``function`` of a language, which
59+
is used to determine ``docstring_type`` of
60+
DocumentationComment.
61+
:param docstring_position: Defines the position where the regex of
62+
docstring type is present(i.e. ``top`` or ``bottom``).
4263
"""
4364
self._language = language.lower()
4465
self._docstyle = docstyle.lower()
@@ -58,6 +79,10 @@ def __init__(self, language: str, docstyle: str, markers: (Iterable, str),
5879
'actually {}).'.format(length))
5980

6081
self._metadata = metadata
82+
self._class_padding = class_padding
83+
self._function_padding = function_padding
84+
self._docstring_type_regex = docstring_type_regex
85+
self._docstring_position = docstring_position
6186

6287
@property
6388
def language(self):
@@ -127,6 +152,48 @@ def metadata(self):
127152
"""
128153
return self._metadata
129154

155+
@property
156+
def class_padding(self):
157+
"""
158+
A namedtuple ``ClassPadding`` consisting of values about blank lines
159+
before and after the documentation of ``docstring_type`` class.
160+
161+
These values are official standard of following blank lines before and
162+
after the documentation of ``docstring_type`` class.
163+
"""
164+
return self._class_padding
165+
166+
@property
167+
def function_padding(self):
168+
"""
169+
A namedtuple ``FunctionPadding`` consisting of values about blank
170+
lines before and after the documentation of ``docstring_type``
171+
function.
172+
173+
These values are official standard of following blank lines before and
174+
after the documentation of ``docstring_type`` function.
175+
"""
176+
return self._function_padding
177+
178+
@property
179+
def docstring_type_regex(self):
180+
"""
181+
A namedtuple ``DocstringTypeRegex`` consisting of regex about ``class``
182+
and ``function`` of a language, which is used to determine
183+
``docstring_type`` of DocumentationComment.
184+
"""
185+
return self._docstring_type_regex
186+
187+
@property
188+
def docstring_position(self):
189+
"""
190+
Defines the position, where the regex of docstring type is present.
191+
Depending on different languages the docstrings are present below or
192+
above the defined class or function. This expicitly defines where the
193+
class regex or function regex is present(i.e. ``top`` or ``bottom``).
194+
"""
195+
return self._docstring_position
196+
130197
@classmethod
131198
@enforce_signature
132199
def load(cls, language: str, docstyle: str, coalang_dir=None):
@@ -186,13 +253,44 @@ def load(cls, language: str, docstyle: str, coalang_dir=None):
186253
metadata = cls.Metadata(*(str(docstyle_settings.get(req_setting, ''))
187254
for req_setting in metadata_settings))
188255

256+
try:
257+
class_padding = cls.ClassPadding(
258+
*(int(padding) for padding in tuple(
259+
docstyle_settings['class_padding'])))
260+
except IndexError:
261+
class_padding = cls.ClassPadding('', '')
262+
263+
try:
264+
function_padding = cls.FunctionPadding(
265+
*(int(padding) for padding in tuple(
266+
docstyle_settings['function_padding'])))
267+
except IndexError:
268+
function_padding = cls.FunctionPadding('', '')
269+
270+
try:
271+
docstring_type_regex = cls.DocstringTypeRegex(
272+
*(str(sign) for sign in tuple(
273+
docstyle_settings['docstring_type_regex'])))
274+
except IndexError:
275+
docstring_type_regex = cls.DocstringTypeRegex('', '')
276+
277+
try:
278+
docstring_position = docstyle_settings['docstring_position'].value
279+
except IndexError:
280+
docstring_position = ''
281+
282+
ignore_keys = (('class_padding', 'function_padding',
283+
'docstring_type_regex', 'docstring_position') +
284+
metadata_settings)
285+
189286
marker_sets = (tuple(value)
190287
for key, value in
191288
docstyle_settings.contents.items()
192-
if key not in metadata_settings and
289+
if key not in ignore_keys and
193290
not key.startswith('comment'))
194291

195-
return cls(language, docstyle, marker_sets, metadata)
292+
return cls(language, docstyle, marker_sets, metadata, class_padding,
293+
function_padding, docstring_type_regex, docstring_position)
196294

197295
@staticmethod
198296
def get_available_definitions():

coalib/bearlib/languages/documentation/DocumentationComment.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class DocumentationComment:
1919
Description = namedtuple('Description', 'desc')
2020
top_padding = 0
2121
bottom_padding = 0
22+
docstring_type = 'others'
2223

2324
def __init__(self, documentation, docstyle_definition,
2425
indent, marker, position):

coalib/bearlib/languages/documentation/DocumentationExtraction.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from coalib.bearlib.languages.documentation.DocumentationComment import (
44
DocumentationComment, MalformedComment)
55
from coalib.results.TextPosition import TextPosition
6+
from coalib.results.TextRange import TextRange
67
from textwrap import dedent
78

89

@@ -267,5 +268,64 @@ def extract_documentation_with_markers(content, docstyle_definition):
267268
start_line = doc.range.start.line - 1
268269
ignore_string_match = ignore_regex.search(content[start_line])
269270

271+
# Instantiate padding
272+
top_padding = 0
273+
bottom_padding = 0
274+
# minus 2 because we want to check the line before the marker.
275+
start_index = doc.range.start.line - 2
276+
end_index = doc.range.end.line
277+
while start_index >= 0 and not content[start_index].strip():
278+
top_padding += 1
279+
start_index -= 1
280+
# If the end_index is instantiated above the len(content) i.e.
281+
# In case where ending marker of docstring is at the last line.
282+
# Then the doc.bottom_padding will be default to 0. This will also
283+
# prevent IndexError raised by content[end_index].
284+
while end_index < len(content) and not content[end_index].strip():
285+
# This condition will take place if theres an inline docstring
286+
# following documentation.
287+
if ((doc.marker[2]+'\n') != content[end_index-1][-4:]
288+
and bottom_padding == 0):
289+
break
290+
bottom_padding += 1
291+
end_index += 1
292+
293+
class_regex = re.compile(
294+
doc.docstyle_definition.docstring_type_regex.class_sign)
295+
function_regex = re.compile(
296+
doc.docstyle_definition.docstring_type_regex.func_sign)
297+
298+
# End line differs when mid marker and end marker is different
299+
if doc.marker[1] == doc.marker[2]:
300+
end_index = end_index - 1
301+
302+
# Check for docstring_position and then check for class regex
303+
# and function regex to define the type of docstring.
304+
if doc.docstyle_definition.docstring_position == 'top':
305+
if class_regex.search(content[start_index]):
306+
doc.docstring_type = 'class'
307+
elif function_regex.search(content[start_index]):
308+
doc.docstring_type = 'function'
309+
elif doc.docstyle_definition.docstring_position == 'bottom':
310+
if (end_index < len(content) and
311+
class_regex.search(content[end_index])):
312+
doc.docstring_type = 'class'
313+
elif (end_index < len(content) and
314+
function_regex.search(content[end_index])):
315+
doc.docstring_type = 'function'
316+
317+
# Disabled automatic padding for docstring_type='others' as this
318+
# will cause overlapping of range in consecutive docstrings. Which
319+
# diff.replace() is unable to handle.
320+
if doc.docstring_type != 'others':
321+
doc.top_padding = top_padding
322+
doc.bottom_padding = bottom_padding
323+
324+
doc.range = TextRange.from_values(
325+
start_index + 2,
326+
1 if top_padding > 0 else doc.range.start.column,
327+
end_index,
328+
1 if bottom_padding > 0 else doc.range.end.column)
329+
270330
if ignore_string_match:
271331
yield doc

coalib/bearlib/languages/documentation/default.coalang

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ param_end = :
55
exception_start = :raises\ # here's a space
66
exception_end = :
77
return_sep = :return:
8+
docstring_type_regex = class, def # defines class and function signature.
9+
docstring_position = top # defines position where docstring regex is found.
10+
class_padding = 0, 1
11+
function_padding = 0, 0
812

913
[PYTHON3]
1014
doc-marker = """, , """
@@ -13,6 +17,10 @@ param_end = :
1317
exception_start = :raises\ # here's a space
1418
exception_end = :
1519
return_sep = :return:
20+
docstring_type_regex = class, def # defines class and function signature.
21+
docstring_position = top # defines position where docstring regex is found.
22+
class_padding = 0, 1
23+
function_padding = 0, 0
1624

1725
[JAVA]
1826
doc-marker1 = /**, \ *, \ */

coalib/bearlib/languages/documentation/doxygen.coalang

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ param_end = \ # here's a space
3939
exception_start = @raises\ # here's a space
4040
exception_end = \ # here's a space
4141
return_sep = @return\ # here's a space
42+
docstring_type_regex = class, def # defines class and function signature.
43+
docstring_position = bottom # defines position where docstring regex is found.
44+
class_padding = 1, 0
45+
function_padding = 1, 0
4246

4347
[PYTHON3]
4448
doc-marker1 = """, , """
@@ -48,6 +52,10 @@ param_end = \ # here's a space
4852
exception_start = @raises\ # here's a space
4953
exception_end = \ # here's a space
5054
return_sep = @return\ # here's a space
55+
docstring_type_regex = class, def # defines class and function signature.
56+
docstring_position = bottom # defines position where docstring regex is found.
57+
class_padding = 1, 0
58+
function_padding = 1, 0
5159

5260
[TCL]
5361
doc-marker = \#\#, \#, \#

0 commit comments

Comments
 (0)