|
6 | 6 | from collections import namedtuple
|
7 | 7 | from itertools import chain, takewhile
|
8 | 8 | from re import compile as re
|
| 9 | +from textwrap import dedent |
9 | 10 |
|
10 | 11 | from . import violations
|
11 | 12 | from .config import IllegalConfiguration
|
@@ -122,6 +123,8 @@ class ConventionChecker:
|
122 | 123 | r"\s*"
|
123 | 124 | # Followed by a colon
|
124 | 125 | r":"
|
| 126 | + # Might have a new line and leading whitespace |
| 127 | + r"\n?\s*" |
125 | 128 | # Followed by 1 or more characters - which is the docstring for the parameter
|
126 | 129 | ".+"
|
127 | 130 | )
|
@@ -843,10 +846,38 @@ def _check_args_section(docstring, definition, context):
|
843 | 846 | * The section documents all function arguments (D417)
|
844 | 847 | except `self` or `cls` if it is a method.
|
845 | 848 |
|
| 849 | + Documentation for each arg should start at the same indentation |
| 850 | + level. For example, in this case x and y are distinguishable:: |
| 851 | +
|
| 852 | + Args: |
| 853 | + x: Lorem ipsum dolor sit amet |
| 854 | + y: Ut enim ad minim veniam |
| 855 | +
|
| 856 | + In the case below, we only recognize x as a documented parameter |
| 857 | + because the rest of the content is indented as if it belongs |
| 858 | + to the description for x:: |
| 859 | +
|
| 860 | + Args: |
| 861 | + x: Lorem ipsum dolor sit amet |
| 862 | + y: Ut enim ad minim veniam |
846 | 863 | """
|
847 | 864 | docstring_args = set()
|
848 |
| - for line in context.following_lines: |
849 |
| - match = ConventionChecker.GOOGLE_ARGS_REGEX.match(line) |
| 865 | + # normalize leading whitespace |
| 866 | + args_content = dedent("\n".join(context.following_lines)).strip() |
| 867 | + |
| 868 | + args_sections = [] |
| 869 | + for line in args_content.splitlines(keepends=True): |
| 870 | + if not line[:1].isspace(): |
| 871 | + # This line is the start of documentation for the next |
| 872 | + # parameter because it doesn't start with any whitespace. |
| 873 | + args_sections.append(line) |
| 874 | + else: |
| 875 | + # This is a continuation of documentation for the last |
| 876 | + # parameter because it does start with whitespace. |
| 877 | + args_sections[-1] += line |
| 878 | + |
| 879 | + for section in args_sections: |
| 880 | + match = ConventionChecker.GOOGLE_ARGS_REGEX.match(section) |
850 | 881 | if match:
|
851 | 882 | docstring_args.add(match.group(1))
|
852 | 883 | yield from ConventionChecker._check_missing_args(
|
|
0 commit comments