diff --git a/parso/python/parser.py b/parso/python/parser.py index 88cd299..d89f30f 100644 --- a/parso/python/parser.py +++ b/parso/python/parser.py @@ -129,7 +129,7 @@ class Parser(BaseParser): or token.type == DEDENT and '\n' not in last_leaf.value and '\r' not in last_leaf.value): # In Python statements need to end with a newline. But since it's - # possible (and valid in Python ) that there's no newline at the + # possible (and valid in Python) that there's no newline at the # end of a file, we have to recover even if the user doesn't want # error recovery. if self.stack[-1].dfa.from_rule == 'simple_stmt': @@ -208,6 +208,7 @@ class Parser(BaseParser): o = self._omit_dedent_list if o and o[-1] == self._indent_counter: o.pop() + self._indent_counter -= 1 continue self._indent_counter -= 1 diff --git a/test/test_diff_parser.py b/test/test_diff_parser.py index c8275d7..d7e6b89 100644 --- a/test/test_diff_parser.py +++ b/test/test_diff_parser.py @@ -39,6 +39,23 @@ def _check_error_leaves_nodes(node): return None +def _assert_modules_are_equal(node1, node2): + try: + children1 = node1.children + except AttributeError: + assert not hasattr(node2, 'children'), (node1, node2) + assert node1.value == node2.value + return + else: + try: + children2 = node2.children + except AttributeError: + assert False, (node1, node2) + assert len(children1) == len(children2), (children1, children2) + for n1, n2 in zip(children1, children2): + _assert_modules_are_equal(n1, n2) + + class Differ(object): grammar = load_grammar() @@ -69,6 +86,9 @@ class Differ(object): _assert_valid_graph(new_module) + without_diff_parser_module = parse(code) + #_assert_modules_are_equal(new_module, without_diff_parser_module) + error_node = _check_error_leaves_nodes(new_module) assert expect_error_leaves == (error_node is not None), error_node if parsers is not ANY: @@ -1129,7 +1149,7 @@ def test_dont_copy_dedents_in_beginning(differ): ''') differ.initialize(code1) differ.parse(code2, copies=1, parsers=1, expect_error_leaves=True) - differ.parse(code1, parsers=2) + differ.parse(code1, parsers=1, copies=1) def test_dont_copy_error_leaves(differ): @@ -1199,8 +1219,8 @@ def test_some_other_indentation_issues(differ): a ''') differ.initialize(code1) - differ.parse(code2, copies=2, parsers=1, expect_error_leaves=True) - differ.parse(code1, copies=2, parsers=2) + differ.parse(code2, copies=0, parsers=1, expect_error_leaves=True) + differ.parse(code1, copies=2, parsers=1) def test_open_bracket_case1(differ): diff --git a/test/test_error_recovery.py b/test/test_error_recovery.py index b7d897d..161e72f 100644 --- a/test/test_error_recovery.py +++ b/test/test_error_recovery.py @@ -1,3 +1,5 @@ +from textwrap import dedent + from parso import parse, load_grammar @@ -83,3 +85,46 @@ def test_invalid_token_in_fstr(): assert error1.type == 'error_leaf' assert error2.value == '"' assert error2.type == 'error_leaf' + + +def test_dedent_issues1(): + code = dedent('''\ + class C: + @property + f + g + end + ''') + module = load_grammar(version='3.8').parse(code) + klass, endmarker = module.children + suite = klass.children[-1] + assert suite.children[2].type == 'error_leaf' + assert suite.children[3].get_code(include_prefix=False) == 'f\n' + assert suite.children[5].get_code(include_prefix=False) == 'g\n' + assert suite.type == 'suite' + + +def test_dedent_issues2(): + code = dedent('''\ + class C: + @property + if 1: + g + else: + h + end + ''') + module = load_grammar(version='3.8').parse(code) + klass, endmarker = module.children + suite = klass.children[-1] + assert suite.children[2].type == 'error_leaf' + if_ = suite.children[3] + assert if_.children[0] == 'if' + assert if_.children[3].type == 'suite' + assert if_.children[3].get_code() == '\n g\n' + assert if_.children[4] == 'else' + assert if_.children[6].type == 'suite' + assert if_.children[6].get_code() == '\n h\n' + + assert suite.children[4].get_code(include_prefix=False) == 'end\n' + assert suite.type == 'suite'