Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a checker for excessive indentation. #87

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions sphinxlint/checkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,39 @@ def check_block(block_lineno, block):
yield from errors


_find_leading_spaces = re.compile(r'^\s*').match
# finds lines that start with bullets, numbers, and directives' ".."
_find_list_starters = re.compile(r'^\s*(?:[-+*•‣⁃]|\d+[).]|\(\d+\)|#\.|\.\.)\s+'
r'(?!index)').match
Comment on lines +490 to +491
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This currently combines unnumbered and numbered lists with directives, however we might have to handle them differently, since there are more restrictions for things nested under lists than under directives.



@checker(".rst")
def check_excessive_indentation(file, lines, options=None):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous checker is called bad_dedent, so this could be called bad_indent. However indent sounds more generic since it might refer to both indentation and dedentation, whereas this checker only deals with excessive indentation.

"""Check for nested blocks indented more than they should.

|Unnecessarily indented list:
|
| * this will be rendered in a blockquote
|
| .. note: this too
"""
errors = []
last_ind_level = 0
for lineno, line in enumerate(hide_non_rst_blocks(lines), start=1):
# print(line, end='')
if not line.strip():
continue
curr_ind_level = len(_find_leading_spaces(line).group())
# look for nested lists/directives with excessive indentation
if curr_ind_level > last_ind_level and _find_list_starters(line):
errors.append((lineno, "Excessive indentation in nested section"))
# update the indentation level to ignore "* ", "1. ", ".. ", etc.
if m := _find_list_starters(line):
ezio-melotti marked this conversation as resolved.
Show resolved Hide resolved
curr_ind_level = len(m.group())
last_ind_level = curr_ind_level
yield from errors


_has_dangling_hyphen = re.compile(r".*[a-z]-$").match


Expand Down
64 changes: 64 additions & 0 deletions tests/fixtures/xfail/excessive-indentation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
.. expect: 15: Excessive indentation in nested section (excessive-indentation)
.. expect: 20: Excessive indentation in nested section (excessive-indentation)
.. expect: 26: Excessive indentation in nested section (excessive-indentation)
.. expect: 30: Excessive indentation in nested section (excessive-indentation)
.. expect: 35: Excessive indentation in nested section (excessive-indentation)
.. expect: 42: Excessive indentation in nested section (excessive-indentation)
.. expect: 49: Excessive indentation in nested section (excessive-indentation)
.. expect: 51: Excessive indentation in nested section (excessive-indentation)
.. expect: 53: Excessive indentation in nested section (excessive-indentation)
.. expect: 57: Excessive indentation in nested section (excessive-indentation)


The most common mistakes is indenting lists and directives under a paragraph:

* This list shouldn't be indented
* Otherwise it's rendered inside a blockquote

Directives also shouldn't be indented under a paragraph:

.. note:: like this one



* Nested lists should be indented properly

* the bullet of this list should have been under the N

* Same goes for directives

.. note:: this should have been under the S


.. note::

* the opposite is also true
* lists nested under directives
* should be indented properly
* (but maybe they don't have to?)

.. note::

.. note:: this is also not allowed atm, but maybe it should
Comment on lines +33 to +42
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are currently detected as errors, but technically they could be ok and they should be allowed. (see previous comment too)



There are also other types of lists:

* bullet lists

- bullet lists with different bullets

1. numbered lists

2) more numbered lists

(3) numbered lists with more parentheses

#. autonumbered lists


Each of these should give an error, since they are all indented wrong.

Numbered lists that start with letters (a. b. c. ...)
and roman numerals (I. II. III. ...) are only supported by Sphinx 7+
so we just ignore them
54 changes: 54 additions & 0 deletions tests/fixtures/xpass/excessive-indentation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
A paragraph indented under another paragraph will create a blockquote
and that's usually ok:

This is an intentional blockquote


In some cases you also have indented directives like ".. index:" that
don't produce any output, so we ignore those too:

.. index:: ignore

This is also because they might appear in a list like:

(1)
.. index:: first item

This is the first item of the list

(2)
.. index:: second item

This is the second item of the list


Properly indented nested lists and directives are also ok:

* A list item that contains multiple lines or paragraphs
should work fine as long as the indentation level is correct

In this case everything is ok.

* The nested list should be indented under the T:

* like this
* and this

* The start of the list is where the T is:

* so this should be indented further
* and this too


* We can also have a directive nested inside a list:

.. note:: like this


.. note::

Having text properly indented under a directive is ok

.. note::

.. note:: Nesting directives is fine too if they are properly indented
Loading