diff options
author | Konstantina Saketou <56515303+ksaketou@users.noreply.github.com> | 2021-10-10 11:45:05 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-10 10:45:05 +0200 |
commit | f2b0c48536c008410e6c3eab51ea1042b96829e2 (patch) | |
tree | 3645b82be657071d49aff8567e833553890300a2 | |
parent | 1eaf5aa211a16607a0f15cae56a90e94555f3809 (diff) | |
download | pylint-git-f2b0c48536c008410e6c3eab51ea1042b96829e2.tar.gz |
Properly identify undocumented parameters and add new message called missing-any-param-doc (#5097)
* Correctly identify parameters with no doc and add new message
This commit fixes the problem where non documented parameters where not being
identified properly. Also, it adds a new message called ``missing-any-param-doc`` for
when a function has no parameter and type doc at all.
Adds new test cases for the ``missing-param-doc`` and ``missing-type-doc`` messages
and tests for the new message ``missing-any-param-doc``.
* Replace old messages with the new one where needed
Fix pylint's code where the new message where needed in other files instead of
triggering both missing-param-doc and missing-type-doc.
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | doc/whatsnew/2.12.rst | 7 | ||||
-rw-r--r-- | pylint/extensions/_check_docs_utils.py | 17 | ||||
-rw-r--r-- | pylint/extensions/docparams.py | 51 | ||||
-rw-r--r-- | tests/extensions/test_check_docs.py | 3 | ||||
-rw-r--r-- | tests/functional/ext/docparams.py | 4 | ||||
-rw-r--r-- | tests/functional/ext/docparams.txt | 6 | ||||
-rw-r--r-- | tests/functional/m/missing/missing_param_doc.py | 106 | ||||
-rw-r--r-- | tests/functional/m/missing/missing_param_doc.rc | 8 | ||||
-rw-r--r-- | tests/functional/m/missing/missing_param_doc.txt | 18 | ||||
-rw-r--r-- | tests/functional/u/useless/useless_type_doc.py | 1 | ||||
-rw-r--r-- | tests/functional/u/useless/useless_type_doc.txt | 8 |
12 files changed, 199 insertions, 33 deletions
@@ -11,6 +11,9 @@ Release date: TBA .. Put new features here and also in 'doc/whatsnew/2.12.rst' +* Properly identify parameters with no documentation and add new message called ``missing-any-param-doc`` + + Closes #3799 * Add checkers ``overridden-final-method`` & ``subclassed-final-class`` Closes #3197 diff --git a/doc/whatsnew/2.12.rst b/doc/whatsnew/2.12.rst index 7cdd12003..f6d99185a 100644 --- a/doc/whatsnew/2.12.rst +++ b/doc/whatsnew/2.12.rst @@ -12,6 +12,13 @@ Summary -- Release highlights New checkers ============ +* Added ``missing-any-param-doc`` triggered when a function has neither parameter nor parameter type + documentation. Undocumented parameters are now being properly identified. A warning might start to + appear unexpectedly if ``missing-param-doc`` and ``missing-type-doc`` were disabled, as a new message + ``missing-any-param-doc`` will be emitted instead. + + Closes #3799 + * Checkers for ``typing.final`` * Added ``overridden-final-method``: Emitted when a method which is annotated with ``typing.final`` is overridden diff --git a/pylint/extensions/_check_docs_utils.py b/pylint/extensions/_check_docs_utils.py index 66b4be24c..e1a7301e0 100644 --- a/pylint/extensions/_check_docs_utils.py +++ b/pylint/extensions/_check_docs_utils.py @@ -645,9 +645,17 @@ class GoogleDocstring(Docstring): if not match: continue - param_name = match.group(1) - param_type = match.group(2) - param_desc = match.group(3) + # check if parameter has description only + re_only_desc = re.search(":\n", entry) + if re_only_desc: + param_name = match.group(1) + param_desc = match.group(2) + param_type = None + else: + param_name = match.group(1) + param_type = match.group(2) + param_desc = match.group(3) + if param_type: params_with_type.add(param_name) @@ -726,8 +734,7 @@ class NumpyDocstring(GoogleDocstring): \s* (\w+) # identifier \s* : \s* (?:({GoogleDocstring.re_multiple_type})(?:,\s+optional)?)? # optional type declaration - \n # description starts on a new line - \s* (.*) # description + \s* (.*) # optional description """, re.X | re.S, ) diff --git a/pylint/extensions/docparams.py b/pylint/extensions/docparams.py index 32abedfb8..14d6ebc9f 100644 --- a/pylint/extensions/docparams.py +++ b/pylint/extensions/docparams.py @@ -145,6 +145,11 @@ class DocstringParameterChecker(BaseChecker): "useless-type-doc", "Please remove the ignored parameter type documentation.", ), + "W9021": ( + 'Missing any documentation in "%s"', + "missing-any-param-doc", + "Please add parameter and/or type documentation.", + ), } options = ( @@ -541,16 +546,6 @@ class DocstringParameterChecker(BaseChecker): if not params_with_doc and not params_with_type and accept_no_param_doc: tolerate_missing_params = True - if not tolerate_missing_params: - self._compare_missing_args( - params_with_doc, - "missing-param-doc", - self.not_needed_param_in_docstring - | expected_but_ignored_argument_names, - expected_argument_names, - warning_node, - ) - # This is before the update of param_with_type because this must check only # the type documented in a docstring, not the one using pep484 # See #4117 and #4593 @@ -568,13 +563,37 @@ class DocstringParameterChecker(BaseChecker): params_with_type.add(arg_name.name) if not tolerate_missing_params: - self._compare_missing_args( - params_with_type, - "missing-type-doc", - not_needed_type_in_docstring | expected_but_ignored_argument_names, - expected_argument_names, - warning_node, + missing_param_doc = (expected_argument_names - params_with_doc) - ( + self.not_needed_param_in_docstring | expected_but_ignored_argument_names ) + missing_type_doc = (expected_argument_names - params_with_type) - ( + not_needed_type_in_docstring | expected_but_ignored_argument_names + ) + if ( + missing_param_doc == expected_argument_names == missing_type_doc + and len(expected_argument_names) != 0 + ): + self.add_message( + "missing-any-param-doc", + args=(warning_node.name), + node=warning_node, + ) + else: + self._compare_missing_args( + params_with_doc, + "missing-param-doc", + self.not_needed_param_in_docstring + | expected_but_ignored_argument_names, + expected_argument_names, + warning_node, + ) + self._compare_missing_args( + params_with_type, + "missing-type-doc", + not_needed_type_in_docstring | expected_but_ignored_argument_names, + expected_argument_names, + warning_node, + ) self._compare_different_args( params_with_doc, diff --git a/tests/extensions/test_check_docs.py b/tests/extensions/test_check_docs.py index 1c250bc9b..04919c27b 100644 --- a/tests/extensions/test_check_docs.py +++ b/tests/extensions/test_check_docs.py @@ -325,8 +325,7 @@ class TestParamDocChecker(CheckerTestCase): """ ) with self.assertAddsMessages( - MessageTest(msg_id="missing-param-doc", node=node, args=("x, y",)), - MessageTest(msg_id="missing-type-doc", node=node, args=("x, y",)), + MessageTest(msg_id="missing-any-param-doc", node=node, args=(node.name)), ): self.checker.visit_functiondef(node) diff --git a/tests/functional/ext/docparams.py b/tests/functional/ext/docparams.py index 269686a01..8dbb0295a 100644 --- a/tests/functional/ext/docparams.py +++ b/tests/functional/ext/docparams.py @@ -16,7 +16,7 @@ def _private_func3(param1): # [missing-raises-doc] raise Exception('Example') -def public_func1(param1): # [missing-param-doc, missing-type-doc] +def public_func1(param1): # [missing-any-param-doc] """This is a test docstring without params""" print(param1) @@ -36,6 +36,6 @@ async def _async_private_func3(param1): # [missing-raises-doc] raise Exception('Example') -async def async_public_func1(param1): # [missing-param-doc, missing-type-doc] +async def async_public_func1(param1): # [missing-any-param-doc] """This is a test docstring without params""" print(param1) diff --git a/tests/functional/ext/docparams.txt b/tests/functional/ext/docparams.txt index cccc78126..7aa6631ed 100644 --- a/tests/functional/ext/docparams.txt +++ b/tests/functional/ext/docparams.txt @@ -3,12 +3,10 @@ missing-return-type-doc:4:0:_private_func1:Missing return type documentation missing-yield-doc:9:0:_private_func2:Missing yield documentation missing-yield-type-doc:9:0:_private_func2:Missing yield type documentation missing-raises-doc:14:0:_private_func3:"""Exception""" not documented as being raised -missing-param-doc:19:0:public_func1:"""param1""" missing in parameter documentation -missing-type-doc:19:0:public_func1:"""param1""" missing in parameter type documentation +missing-any-param-doc:19:0:public_func1:"Missing any documentation in ""public_func1""" missing-return-doc:24:0:_async_private_func1:Missing return documentation missing-return-type-doc:24:0:_async_private_func1:Missing return type documentation missing-yield-doc:29:0:_async_private_func2:Missing yield documentation missing-yield-type-doc:29:0:_async_private_func2:Missing yield type documentation missing-raises-doc:34:0:_async_private_func3:"""Exception""" not documented as being raised -missing-param-doc:39:0:async_public_func1:"""param1""" missing in parameter documentation -missing-type-doc:39:0:async_public_func1:"""param1""" missing in parameter type documentation +missing-any-param-doc:39:0:async_public_func1:"Missing any documentation in ""async_public_func1""" diff --git a/tests/functional/m/missing/missing_param_doc.py b/tests/functional/m/missing/missing_param_doc.py new file mode 100644 index 000000000..37c85b058 --- /dev/null +++ b/tests/functional/m/missing/missing_param_doc.py @@ -0,0 +1,106 @@ +#pylint: disable= missing-module-docstring + +def foobar1(arg1, arg2): #[missing-any-param-doc] + """function foobar ... + """ + print(arg1, arg2) + +def foobar2(arg1, arg2): #[missing-any-param-doc] + """function foobar ... + Parameters + ---------- + """ + print(arg1, arg2) + +def foobar3(arg1, arg2, arg3): #[missing-param-doc, missing-type-doc] + """function foobar ... + Parameters + ---------- + arg1: int + arg3: float + """ + print(arg1, arg2, arg3) + +def foobar4(arg1, arg2): #[missing-param-doc, missing-type-doc] + """function foobar ... + Parameters + ---------- + arg1: int + description + """ + print(arg1, arg2) + +def foobar5(arg1, arg2): #[missing-param-doc, missing-type-doc] + """function foobar ... + Parameters + ---------- + arg1: + description + arg2: str + """ + print(arg1, arg2) + +def foobar6(arg1, arg2, arg3): #[missing-param-doc, missing-type-doc] + """function foobar ... + Parameters + ---------- + arg1: int + description + arg2: int + """ + print(arg1, arg2, arg3) + +def foobar7(arg1, arg2): #[missing-any-param-doc] + """function foobar ... + Parameters + ---------- + arg1 + """ + print(arg1, arg2) + +def foobar8(arg1): #[missing-any-param-doc] + """function foobar""" + + print(arg1) + +def foobar9(arg1, arg2, arg3): #[missing-param-doc] + """function foobar ... + Parameters + ---------- + arg1: int + arg2: int + arg3: str + """ + print(arg1, arg2, arg3) + +def foobar10(arg1, arg2, arg3): #[missing-param-doc, missing-type-doc] + """function foobar ... + Parameters + ---------- + arg1: + desc1 + arg2: int + arg3: + desc3 + """ + print(arg1, arg2, arg3) + +def foobar11(arg1, arg2): #[missing-any-param-doc] + """function foobar ... + Args + ---------- + arg1 + arg2 + """ + print(arg1, arg2) + +def foobar12(arg1, arg2, arg3): #[missing-param-doc, missing-type-doc] + """function foobar ... + Args + ---------- + arg1: int + arg2: + does something + arg3 + """ + print(arg1, arg2, arg3) diff --git a/tests/functional/m/missing/missing_param_doc.rc b/tests/functional/m/missing/missing_param_doc.rc new file mode 100644 index 000000000..d4a6dc172 --- /dev/null +++ b/tests/functional/m/missing/missing_param_doc.rc @@ -0,0 +1,8 @@ +[MASTER] +load-plugins=pylint.extensions.docparams, + +[PARAMETER_DOCUMENTATION] +accept-no-param-doc=no +accept-no-raise-doc=no +accept-no-return-doc=no +accept-no-yields-doc=no diff --git a/tests/functional/m/missing/missing_param_doc.txt b/tests/functional/m/missing/missing_param_doc.txt new file mode 100644 index 000000000..b03e20072 --- /dev/null +++ b/tests/functional/m/missing/missing_param_doc.txt @@ -0,0 +1,18 @@ +missing-any-param-doc:3:0:foobar1:"Missing any documentation in ""foobar1""" +missing-any-param-doc:8:0:foobar2:"Missing any documentation in ""foobar2""" +missing-param-doc:15:0:foobar3:"""arg1, arg2, arg3"" missing in parameter documentation" +missing-type-doc:15:0:foobar3:"""arg2"" missing in parameter type documentation" +missing-param-doc:24:0:foobar4:"""arg2"" missing in parameter documentation" +missing-type-doc:24:0:foobar4:"""arg2"" missing in parameter type documentation" +missing-param-doc:33:0:foobar5:"""arg2"" missing in parameter documentation" +missing-type-doc:33:0:foobar5:"""arg1"" missing in parameter type documentation" +missing-param-doc:43:0:foobar6:"""arg2, arg3"" missing in parameter documentation" +missing-type-doc:43:0:foobar6:"""arg3"" missing in parameter type documentation" +missing-any-param-doc:53:0:foobar7:"Missing any documentation in ""foobar7""" +missing-any-param-doc:61:0:foobar8:"Missing any documentation in ""foobar8""" +missing-param-doc:66:0:foobar9:"""arg1, arg2, arg3"" missing in parameter documentation" +missing-param-doc:76:0:foobar10:"""arg2"" missing in parameter documentation" +missing-type-doc:76:0:foobar10:"""arg1, arg3"" missing in parameter type documentation" +missing-any-param-doc:88:0:foobar11:Missing any documentation in "foobar11" +missing-param-doc:97:0:foobar12:"""arg1, arg3"" missing in parameter documentation" +missing-type-doc:97:0:foobar12:"""arg2, arg3"" missing in parameter type documentation" diff --git a/tests/functional/u/useless/useless_type_doc.py b/tests/functional/u/useless/useless_type_doc.py index 6714755fd..110a7a5f5 100644 --- a/tests/functional/u/useless/useless_type_doc.py +++ b/tests/functional/u/useless/useless_type_doc.py @@ -1,3 +1,4 @@ +#pylint: disable = missing-any-param-doc """demonstrate FP with useless-type-doc""" diff --git a/tests/functional/u/useless/useless_type_doc.txt b/tests/functional/u/useless/useless_type_doc.txt index 20083ed79..9e1963e90 100644 --- a/tests/functional/u/useless/useless_type_doc.txt +++ b/tests/functional/u/useless/useless_type_doc.txt @@ -1,4 +1,4 @@ -useless-param-doc:33:0:function_useless_doc:"""_some_private_param"" useless ignored parameter documentation":HIGH -useless-type-doc:33:0:function_useless_doc:"""_some_private_param"" useless ignored parameter type documentation":HIGH -useless-param-doc:66:0:test_two:"""_new"" useless ignored parameter documentation":HIGH -useless-type-doc:66:0:test_two:"""_new"" useless ignored parameter type documentation":HIGH +useless-param-doc:34:0:function_useless_doc:"""_some_private_param"" useless ignored parameter documentation":HIGH +useless-type-doc:34:0:function_useless_doc:"""_some_private_param"" useless ignored parameter type documentation":HIGH +useless-param-doc:67:0:test_two:"""_new"" useless ignored parameter documentation":HIGH +useless-type-doc:67:0:test_two:"""_new"" useless ignored parameter type documentation":HIGH |