Skip to content

Commit 89b5913

Browse files
committed
DocumentationStyleBear: Add blankline support
DocumentationStyleBear now checks for blankline before and after the docstring and fixes them. Related to coala/coala#4200
1 parent 1e451a2 commit 89b5913

11 files changed

+130
-18
lines changed

bears/documentation/DocumentationStyleBear.py

+43-16
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ class DocumentationStyleBear(DocBaseClass, LocalBear):
2121
CAN_FIX = {'Documentation'}
2222

2323
def process_documentation(self,
24-
parsed,
24+
doc_comment: DocumentationComment,
2525
allow_missing_func_desc: str=False,
2626
indent_size: int=4,
2727
expand_one_liners: str=False):
2828
"""
2929
This fixes the parsed documentation comment.
3030
31-
:param parsed:
32-
Contains parsed documentation comment.
31+
:param doc_comment:
32+
Contains instance of DocumentationComment.
3333
:param allow_missing_func_desc:
3434
When set ``True`` this will allow functions with missing
3535
descriptions, allowing functions to start with params.
@@ -40,6 +40,7 @@ def process_documentation(self,
4040
:return:
4141
A tuple of fixed parsed documentation comment and warning_desc.
4242
"""
43+
parsed = doc_comment.parse()
4344
# Assuming that the first element is always the only main
4445
# description.
4546
metadata = iter(parsed)
@@ -92,7 +93,36 @@ def process_documentation(self,
9293
new_desc = new_desc.rstrip() + '\n'
9394

9495
new_metadata.append(m._replace(desc=new_desc.lstrip(' ')))
95-
return (new_metadata, warning_desc)
96+
97+
new_comment = DocumentationComment.from_metadata(
98+
new_metadata, doc_comment.docstyle_definition,
99+
doc_comment.marker, doc_comment.indent, doc_comment.position)
100+
101+
# Instantiate default padding.
102+
class_padding = doc_comment.docstyle_definition.class_padding
103+
function_padding = doc_comment.docstyle_definition.function_padding
104+
# Check if default padding exist in the coalang file.
105+
if (class_padding != DocstyleDefinition.ClassPadding('', '') and
106+
function_padding != DocstyleDefinition.FunctionPadding(
107+
'', '')):
108+
# Check docstring_type
109+
if doc_comment.docstring_type == 'class':
110+
new_comment.top_padding = class_padding.top_padding
111+
new_comment.bottom_padding = class_padding.bottom_padding
112+
elif doc_comment.docstring_type == 'function':
113+
new_comment.top_padding = function_padding.top_padding
114+
new_comment.bottom_padding = function_padding.bottom_padding
115+
else:
116+
# Keep paddings as they are originally.
117+
new_comment.top_padding = doc_comment.top_padding
118+
new_comment.bottom_padding = doc_comment.bottom_padding
119+
else:
120+
# If there's no default paddings defined. Keep padding as
121+
# they are originally.
122+
new_comment.top_padding = doc_comment.top_padding
123+
new_comment.bottom_padding = doc_comment.bottom_padding
124+
125+
return (new_comment, warning_desc)
96126

97127
def run(self, filename, file, language: str,
98128
docstyle: str='default', allow_missing_func_desc: str=False,
@@ -131,18 +161,15 @@ def run(self, filename, file, language: str,
131161
file=filename,
132162
line=doc_comment.line + 1)
133163
else:
134-
parsed = doc_comment.parse()
135-
136-
(new_metadata, warning_desc) = self.process_documentation(
137-
parsed, allow_missing_func_desc, indent_size,
138-
expand_one_liners)
139-
140-
new_comment = DocumentationComment.from_metadata(
141-
new_metadata, doc_comment.docstyle_definition,
142-
doc_comment.marker, doc_comment.indent,
143-
doc_comment.position)
144-
145-
if new_comment != doc_comment:
164+
(new_comment, warning_desc) = self.process_documentation(
165+
doc_comment, allow_missing_func_desc,
166+
indent_size, expand_one_liners)
167+
168+
# Cache cleared so a fresh docstring is assembled
169+
doc_comment.assemble.cache_clear()
170+
# Assembled docstring check, because paddings are only
171+
# amended after assemble()
172+
if new_comment.assemble() != doc_comment.assemble():
146173
# Something changed, let's apply a result.
147174
diff = self.generate_diff(file, doc_comment, new_comment)
148175
yield Result(

tests/documentation/DocumentationStyleBearTest.py

+2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ class DocumentationStyleBearTest(unittest.TestCase):
7878
test_good2 = test('good_file2.py.test', 'good_file2.py.test')
7979
test_good3 = test('good_file3.py.test', 'good_file3.py.test',
8080
{'allow_missing_func_desc': 'True'})
81+
test_bad_java = test('bad_file.java.test', 'bad_file.java.test.correct',
82+
{'language': 'java'})
8183

8284
test_malformed_comment_python = test_MalformedComment(
8385
['"""\n',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class HelloWorld {
2+
3+
/**
4+
*Java docstyle test.
5+
*There's no official standard for how paddings are in java.
6+
*Hence, in this case paddings are preserved as original.
7+
*
8+
*@param name the name to which to say hello
9+
*@raises IOException throws IOException
10+
*@return the concatenated string
11+
*/
12+
public String sayHello(String name) throws IOException {
13+
return "Hello, " + name;
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class HelloWorld {
2+
3+
/**
4+
*Java docstyle test.
5+
*There's no official standard for how paddings are in java.
6+
*Hence, in this case paddings are preserved as original.
7+
*
8+
*@param name
9+
* the name to which to say hello
10+
*@raises IOException
11+
* throws IOException
12+
*@return
13+
* the concatenated string
14+
*/
15+
public String sayHello(String name) throws IOException {
16+
return "Hello, " + name;
17+
}
18+
}

tests/documentation/test_files/DocumentationStyleBear/bad_file2.py.test

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ def docstring_testcase(dummy):
1414
def docstring_singleliner():
1515
""" This is singleliner docstring. """
1616

17+
return None
1718

1819
def docstring_inline():
1920
"""

tests/documentation/test_files/DocumentationStyleBear/bad_file2.py.test.correct

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def docstring_singleliner():
1717
"""
1818
This is singleliner docstring.
1919
"""
20-
20+
return None
2121

2222
def docstring_inline():
2323
"""

tests/documentation/test_files/DocumentationStyleBear/bad_file3.py.test

+2
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ class docstring_if_indented():
3030
"""
3131
This is `if` indented block function.
3232
"""
33+
return None
3334
else:
3435
def hello_venus(self):
3536
"""This is `if` indented block function."""
37+
return None
3638

3739

3840
def docstring_inner_function(dummy):

tests/documentation/test_files/DocumentationStyleBear/bad_file3.py.test.correct

+2
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ class docstring_if_indented():
4141
"""
4242
This is `if` indented block function.
4343
"""
44+
return None
4445
else:
4546
def hello_venus(self):
4647
"""
4748
This is `if` indented block function.
4849
"""
50+
return None
4951

5052

5153
def docstring_inner_function(dummy):

tests/documentation/test_files/DocumentationStyleBear/bad_file4.py.test

+25
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,28 @@ def docstring_missing_descriptions(a, b, x):
77
:return:"""
88

99
return a * x + b
10+
11+
12+
class docstring_class_improper_paddings(dummy):
13+
14+
"""
15+
Docstring has improper paddings. `class` type docstrings
16+
should be followed by 1 blank line at the bottom.
17+
18+
:param dummy:
19+
dummy description.
20+
"""
21+
22+
23+
def docstring_function_improper_paddings:
24+
25+
"""
26+
Docstring has improper paddings. `function` type docstrings
27+
should never be followed by any blank lines.
28+
29+
:return:
30+
None
31+
"""
32+
33+
34+
return None

tests/documentation/test_files/DocumentationStyleBear/bad_file4.py.test.correct

+20-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,24 @@ def docstring_missing_descriptions(a, b, x):
88
:param x:
99
:return:
1010
"""
11-
1211
return a * x + b
12+
13+
14+
class docstring_class_improper_paddings(dummy):
15+
"""
16+
Docstring has improper paddings. `class` type docstrings
17+
should be followed by 1 blank line at the bottom.
18+
19+
:param dummy:
20+
dummy description.
21+
"""
22+
23+
def docstring_function_improper_paddings:
24+
"""
25+
Docstring has improper paddings. `function` type docstrings
26+
should never be followed by any blank lines.
27+
28+
:return:
29+
None
30+
"""
31+
return None

tests/documentation/test_files/DocumentationStyleBear/good_file3.py.test

+1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ def docstring_missing_description(dummy):
44
a function starting with `param`
55
in this case allow_missing_func_desc = True
66
"""
7+
return None
78

89
"""This is one-liner docstring"""

0 commit comments

Comments
 (0)