Use ERROR_DEDENT instead of ERRORTOKEN for wrong dedents.

This commit is contained in:
Dave Halter
2017-07-19 20:13:51 +02:00
parent 569cb99ca7
commit 6876e1b7c0
9 changed files with 20 additions and 31 deletions

View File

@@ -13,8 +13,8 @@ import logging
from parso.utils import splitlines from parso.utils import splitlines
from parso.python.parser import Parser from parso.python.parser import Parser
from parso.python.tree import EndMarker from parso.python.tree import EndMarker
from parso.python.tokenize import (NEWLINE, TokenInfo, from parso.python.tokenize import (NEWLINE, TokenInfo, ERROR_DEDENT,
ENDMARKER, INDENT, DEDENT, ERRORTOKEN) ENDMARKER, INDENT, DEDENT)
def _get_last_line(node_or_leaf): def _get_last_line(node_or_leaf):
@@ -305,8 +305,7 @@ class DiffParser(object):
# In case of omitted_first_indent, it might not be dedented fully. # In case of omitted_first_indent, it might not be dedented fully.
# However this is a sign for us that a dedent happened. # However this is a sign for us that a dedent happened.
if typ == DEDENT \ if typ == DEDENT \
or typ == ERRORTOKEN and not string \ or typ == ERROR_DEDENT and omitted_first_indent and len(indents) == 1:
and omitted_first_indent and len(indents) == 1:
indents.pop() indents.pop()
if omitted_first_indent and not indents: if omitted_first_indent and not indents:
# We are done here, only thing that can come now is an # We are done here, only thing that can come now is an

View File

@@ -67,13 +67,13 @@ class ErrorFinder(Normalizer):
def visit_leaf(self, leaf): def visit_leaf(self, leaf):
if leaf.type == 'error_leaf': if leaf.type == 'error_leaf':
if leaf.original_type == 'indent': if leaf.original_type in ('indent', 'error_dedent'):
# Indents/Dedents itself never have a prefix. They are just # Indents/Dedents itself never have a prefix. They are just
# "pseudo" tokens that get removed by the syntax tree later. # "pseudo" tokens that get removed by the syntax tree later.
# Therefore in case of an error we also have to check for this. # Therefore in case of an error we also have to check for this.
print(repr(leaf.prefix), leaf.get_next_leaf())
spacing = list(leaf.get_next_leaf()._split_prefix())[-1] spacing = list(leaf.get_next_leaf()._split_prefix())[-1]
self._add_indentation_error("Indentation Error", spacing) self._add_indentation_error("Indentation Error", spacing)
print(leaf, repr(leaf.prefix), repr(leaf.value), leaf.get_previous_leaf())
else: else:
self._add_syntax_error("Syntax Error", leaf) self._add_syntax_error("Syntax Error", leaf)

View File

@@ -29,6 +29,11 @@ if not py_version >= 35:
tok_name[ATEQUAL] = 'ATEQUAL' tok_name[ATEQUAL] = 'ATEQUAL'
N_TOKENS += 1 N_TOKENS += 1
ERROR_DEDENT = N_TOKENS
tok_name[ERROR_DEDENT] = 'ERROR_DEDENT'
N_TOKENS += 1
# Map from operator to number (since tokenize doesn't do this) # Map from operator to number (since tokenize doesn't do this)

View File

@@ -19,7 +19,8 @@ import itertools as _itertools
from codecs import BOM_UTF8 from codecs import BOM_UTF8
from parso.python.token import (tok_name, N_TOKENS, ENDMARKER, STRING, NUMBER, opmap, from parso.python.token import (tok_name, N_TOKENS, ENDMARKER, STRING, NUMBER, opmap,
NAME, OP, ERRORTOKEN, NEWLINE, INDENT, DEDENT) NAME, OP, ERRORTOKEN, NEWLINE, INDENT, DEDENT,
ERROR_DEDENT)
from parso._compatibility import py_version from parso._compatibility import py_version
from parso.utils import splitlines from parso.utils import splitlines
@@ -41,10 +42,6 @@ else:
is_identifier = lambda s: s in namechars is_identifier = lambda s: s in namechars
COMMENT = N_TOKENS
tok_name[COMMENT] = 'COMMENT'
def group(*choices, **kwargs): def group(*choices, **kwargs):
capture = kwargs.pop('capture', False) # Python 2, arrghhhhh :( capture = kwargs.pop('capture', False) # Python 2, arrghhhhh :(
assert not kwargs assert not kwargs
@@ -318,8 +315,7 @@ def tokenize_lines(lines, version_info):
indents.append(start) indents.append(start)
while start < indents[-1]: while start < indents[-1]:
if start > indents[-2]: if start > indents[-2]:
yield TokenInfo(ERRORTOKEN, '', spos, '') yield TokenInfo(ERROR_DEDENT, '', (lnum, 0), '')
print(spos, repr(line))
break break
yield TokenInfo(DEDENT, '', spos, '') yield TokenInfo(DEDENT, '', spos, '')
indents.pop() indents.pop()

View File

@@ -108,7 +108,7 @@ class PythonLeaf(PythonMixin, Leaf):
# indent error leafs somehow? No idea how, though. # indent error leafs somehow? No idea how, though.
previous_leaf = self.get_previous_leaf() previous_leaf = self.get_previous_leaf()
if previous_leaf is not None and previous_leaf.type == 'error_leaf' \ if previous_leaf is not None and previous_leaf.type == 'error_leaf' \
and previous_leaf.original_type == 'indent': and previous_leaf.original_type in ('indent', 'error_dedent'):
previous_leaf = previous_leaf.get_previous_leaf() previous_leaf = previous_leaf.get_previous_leaf()
if previous_leaf is None: if previous_leaf is None:

View File

@@ -1,7 +1,7 @@
for a in 'abc': for a in 'abc':
for b in 'xyz': for b in 'xyz':
hello(a) # indented with 8 spaces hello(a) # indented with 8 spaces
#: E901:1 #: E903:0
hello(b) # indented with 1 tab hello(b) # indented with 1 tab
if True: if True:
#: E101:0 #: E101:0

View File

@@ -112,7 +112,6 @@ def test_ellipsis_py2(each_py2_version):
module = parse('[0][...]', version=each_py2_version, error_recovery=False) module = parse('[0][...]', version=each_py2_version, error_recovery=False)
expr = module.children[0] expr = module.children[0]
trailer = expr.children[-1] trailer = expr.children[-1]
print(expr)
subscript = trailer.children[1] subscript = trailer.children[1]
assert subscript.type == 'subscript' assert subscript.type == 'subscript'
assert [leaf.value for leaf in subscript.children] == ['.', '.', '.'] assert [leaf.value for leaf in subscript.children] == ['.', '.', '.']

View File

@@ -45,6 +45,7 @@ def test_syntax_errors(code, positions):
@pytest.mark.parametrize( @pytest.mark.parametrize(
('code', 'positions'), [ ('code', 'positions'), [
(' 1', [(1, 0)]), (' 1', [(1, 0)]),
('def x():\n 1\n 2', [(3, 0)]),
] ]
) )
def test_indentation_errors(code, positions): def test_indentation_errors(code, positions):

View File

@@ -7,7 +7,7 @@ import pytest
from parso._compatibility import py_version from parso._compatibility import py_version
from parso.utils import splitlines, parse_version_string from parso.utils import splitlines, parse_version_string
from parso.python.token import ( from parso.python.token import (
NAME, NEWLINE, STRING, INDENT, DEDENT, ERRORTOKEN, ENDMARKER) NAME, NEWLINE, STRING, INDENT, DEDENT, ERRORTOKEN, ENDMARKER, ERROR_DEDENT)
from parso.python import tokenize from parso.python import tokenize
from parso import parse from parso import parse
from parso.python.tokenize import TokenInfo from parso.python.tokenize import TokenInfo
@@ -212,23 +212,12 @@ def test_endmarker_end_pos():
check('a\\') check('a\\')
@pytest.mark.parametrize(
('code', 'types'), [
(' foo', ['error_leaf', 'name'])
]
)
def test_indentation(code, types):
return
actual_types = [t.type for t in _get_token_list(code)]
print(actual_types)
assert False
@pytest.mark.parametrize( @pytest.mark.parametrize(
('code', 'types'), [ ('code', 'types'), [
(' foo', [INDENT, NAME, DEDENT]), (' foo', [INDENT, NAME, DEDENT]),
(' foo\n bar', [INDENT, NAME, NEWLINE, ERRORTOKEN, NAME, DEDENT]), (' foo\n bar', [INDENT, NAME, NEWLINE, ERROR_DEDENT, NAME, DEDENT]),
(' foo\n bar \n baz', [INDENT, NAME, NEWLINE, ERRORTOKEN, NAME, (' foo\n bar \n baz', [INDENT, NAME, NEWLINE, ERROR_DEDENT, NAME,
NEWLINE, ERRORTOKEN, NAME, DEDENT]), NEWLINE, ERROR_DEDENT, NAME, DEDENT]),
(' foo\nbar', [INDENT, NAME, NEWLINE, DEDENT, NAME]), (' foo\nbar', [INDENT, NAME, NEWLINE, DEDENT, NAME]),
] ]
) )