From 569cb99ca75621e4407fd0cf4f708388065c526d Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Wed, 19 Jul 2017 18:45:58 +0200 Subject: [PATCH] Start scanning for indentation errors. --- parso/python/normalizer.py | 13 ++++++++++++- parso/python/tree.py | 13 +++++++++++++ test/normalizer_issue_files/E11.py | 2 +- test/test_python_errors.py | 17 +++++++++++++---- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/parso/python/normalizer.py b/parso/python/normalizer.py index bac0ce7..0a0d7cc 100644 --- a/parso/python/normalizer.py +++ b/parso/python/normalizer.py @@ -67,10 +67,21 @@ class ErrorFinder(Normalizer): def visit_leaf(self, leaf): if leaf.type == 'error_leaf': - self._add_syntax_error("Syntax Error", leaf) + if leaf.original_type == 'indent': + # Indents/Dedents itself never have a prefix. They are just + # "pseudo" tokens that get removed by the syntax tree later. + # Therefore in case of an error we also have to check for this. + spacing = list(leaf.get_next_leaf()._split_prefix())[-1] + self._add_indentation_error("Indentation Error", spacing) + print(leaf, repr(leaf.prefix), repr(leaf.value), leaf.get_previous_leaf()) + else: + self._add_syntax_error("Syntax Error", leaf) return '' + def _add_indentation_error(self, message, spacing): + self._add_error(903, message, spacing) + def _add_syntax_error(self, message, node): self._add_error(901, message, node) diff --git a/parso/python/tree.py b/parso/python/tree.py index 7afddb0..0f541b4 100644 --- a/parso/python/tree.py +++ b/parso/python/tree.py @@ -103,6 +103,19 @@ class PythonLeaf(PythonMixin, Leaf): def _split_prefix(self): return split_prefix(self, self.get_start_pos_of_prefix()) + def get_start_pos_of_prefix(self): + # TODO it is really ugly that we have to override it. Maybe change + # indent error leafs somehow? No idea how, though. + previous_leaf = self.get_previous_leaf() + if previous_leaf is not None and previous_leaf.type == 'error_leaf' \ + and previous_leaf.original_type == 'indent': + previous_leaf = previous_leaf.get_previous_leaf() + + if previous_leaf is None: + return self.line - self.prefix.count('\n'), 0 # It's the first leaf. + return previous_leaf.end_pos + + class _LeafWithoutNewlines(PythonLeaf): """ diff --git a/test/normalizer_issue_files/E11.py b/test/normalizer_issue_files/E11.py index 9e82c86..9b97f39 100644 --- a/test/normalizer_issue_files/E11.py +++ b/test/normalizer_issue_files/E11.py @@ -15,7 +15,7 @@ if False: pass print print -#: E901:4 +#: E903:0 print mimetype = 'application/x-directory' #: E111:5 diff --git a/test/test_python_errors.py b/test/test_python_errors.py index 660e10d..803bce9 100644 --- a/test/test_python_errors.py +++ b/test/test_python_errors.py @@ -14,6 +14,11 @@ def _get_error_list(code, version=None): return list(tree._get_normalizer_issues(config)) +def assert_comparison(code, error_code, positions): + errors = [(error.start_pos, error.code) for error in _get_error_list(code)] + assert [(pos, error_code) for pos in positions] == errors + + @pytest.mark.parametrize( ('code', 'positions'), [ ('1 +', [(1, 3)]), @@ -34,9 +39,13 @@ def _get_error_list(code, version=None): ] ) def test_syntax_errors(code, positions): - errors = [(error.start_pos, error.code) for error in _get_error_list(code)] - assert [(pos, 901) for pos in positions] == errors + assert_comparison(code, 901, positions) -def test_indentation_errors(): - pass +@pytest.mark.parametrize( + ('code', 'positions'), [ + (' 1', [(1, 0)]), + ] +) +def test_indentation_errors(code, positions): + assert_comparison(code, 903, positions)