diff options
Diffstat (limited to 'pylint/extensions/confusing_elif.py')
-rw-r--r-- | pylint/extensions/confusing_elif.py | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/pylint/extensions/confusing_elif.py b/pylint/extensions/confusing_elif.py new file mode 100644 index 000000000..f61be02f9 --- /dev/null +++ b/pylint/extensions/confusing_elif.py @@ -0,0 +1,55 @@ +# Copyright (c) 2021 Andreas Finkler <andi.finkler@gmail.com> + +# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# For details: https://github.com/PyCQA/pylint/blob/master/COPYING + +import astroid + +from pylint.checkers import BaseChecker +from pylint.checkers.utils import check_messages +from pylint.interfaces import IAstroidChecker +from pylint.lint import PyLinter + + +class ConfusingConsecutiveElifChecker(BaseChecker): + """Checks if "elif" is used right after an indented block that finishes with "if" or "elif" itself.""" + + __implements__ = IAstroidChecker + + name = "confusing-elif-checker" + priority = -1 + msgs = { + "R5601": ( + "Consecutive elif with differing indentation level, consider creating a function to separate the inner elif", + "confusing-consecutive-elif", + "Used when an elif statement follows right after an indented block which itself ends with if or elif. " + "It may not be ovious if the elif statement was willingly or mistakenly unindented. " + "Extracting the indented if statement into a separate function might avoid confusion and prevent errors.", + ) + } + + @check_messages("confusing-consecutive-elif") + def visit_if(self, node: astroid.If): + body_ends_with_if = isinstance( + node.body[-1], astroid.If + ) and self._has_no_else_clause(node.body[-1]) + if node.has_elif_block() and body_ends_with_if: + self.add_message("confusing-consecutive-elif", node=node.orelse[0]) + + @staticmethod + def _has_no_else_clause(node: astroid.If): + orelse = node.orelse + while orelse and isinstance(orelse[0], astroid.If): + orelse = orelse[0].orelse + if not orelse or isinstance(orelse[0], astroid.If): + return True + return False + + +def register(linter: PyLinter): + """This required method auto registers the checker. + + :param linter: The linter to register the checker to. + :type linter: pylint.lint.PyLinter + """ + linter.register_checker(ConfusingConsecutiveElifChecker(linter)) |