mirror of
https://github.com/davidhalter/parso.git
synced 2025-12-08 05:34:51 +08:00
Better checking of annotations/params and nonlocals/globals.
This commit is contained in:
@@ -129,23 +129,47 @@ class Context(object):
|
|||||||
self._analyze_names(self._nonlocal_names, 'nonlocal')
|
self._analyze_names(self._nonlocal_names, 'nonlocal')
|
||||||
|
|
||||||
def _analyze_names(self, globals_or_nonlocals, type_):
|
def _analyze_names(self, globals_or_nonlocals, type_):
|
||||||
|
def raise_(message):
|
||||||
|
self._add_syntax_error(message % (base_name.value, type_), base_name)
|
||||||
|
|
||||||
|
params = []
|
||||||
|
if self.node.type == 'funcdef':
|
||||||
|
params = self.node.params
|
||||||
|
|
||||||
|
found_global_or_nonlocal = False
|
||||||
for base_name in globals_or_nonlocals:
|
for base_name in globals_or_nonlocals:
|
||||||
search = base_name.value
|
search = base_name.value
|
||||||
# Somehow Python does it the reversed way.
|
# Somehow Python does it the reversed way.
|
||||||
for name in reversed(self._used_name_dict.get(search, [])):
|
for name in reversed(self._used_name_dict.get(search, [])):
|
||||||
print(name, name.parent)
|
|
||||||
if name.start_pos > base_name.start_pos:
|
if name.start_pos > base_name.start_pos:
|
||||||
# All following names don't have to be checked.
|
# All following names don't have to be checked.
|
||||||
break
|
found_global_or_nonlocal = True
|
||||||
|
|
||||||
|
parent = name.parent
|
||||||
|
if parent.type == 'param' and parent.name == name:
|
||||||
|
# Skip those here, these definitions belong to the next
|
||||||
|
# scope.
|
||||||
|
continue
|
||||||
|
|
||||||
if name.is_definition():
|
if name.is_definition():
|
||||||
|
if parent.type == 'expr_stmt' \
|
||||||
|
and parent.children[1].type == 'annassign':
|
||||||
|
raise_("annotated name '%s' can't be %s")
|
||||||
|
break
|
||||||
|
else:
|
||||||
message = "name '%s' is assigned to before %s declaration"
|
message = "name '%s' is assigned to before %s declaration"
|
||||||
else:
|
else:
|
||||||
message = "name '%s' is used prior to %s declaration"
|
message = "name '%s' is used prior to %s declaration"
|
||||||
self._add_syntax_error(message % (name.value, type_), base_name)
|
|
||||||
|
if not found_global_or_nonlocal:
|
||||||
|
raise_(message)
|
||||||
# Only add an error for the first occurence.
|
# Only add an error for the first occurence.
|
||||||
break
|
break
|
||||||
|
|
||||||
|
for param in params:
|
||||||
|
if param.name.value == base_name.value:
|
||||||
|
raise_("name '%s' is parameter and %s"),
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def add_block(self, node):
|
def add_block(self, node):
|
||||||
self.blocks.append(node)
|
self.blocks.append(node)
|
||||||
|
|||||||
@@ -49,3 +49,8 @@ except ZeroDivisionError:
|
|||||||
|
|
||||||
class X():
|
class X():
|
||||||
nonlocal a
|
nonlocal a
|
||||||
|
|
||||||
|
|
||||||
|
def glob():
|
||||||
|
global x
|
||||||
|
y: foo = x
|
||||||
|
|||||||
@@ -176,6 +176,42 @@ def test_indentation_errors(code, positions):
|
|||||||
def glob():
|
def glob():
|
||||||
x
|
x
|
||||||
nonlocal x'''),
|
nonlocal x'''),
|
||||||
|
# Annotation issues
|
||||||
|
dedent('''
|
||||||
|
def glob():
|
||||||
|
x[0]: foo
|
||||||
|
global x'''),
|
||||||
|
dedent('''
|
||||||
|
def glob():
|
||||||
|
x.a: foo
|
||||||
|
global x'''),
|
||||||
|
dedent('''
|
||||||
|
def glob():
|
||||||
|
x: foo
|
||||||
|
global x'''),
|
||||||
|
dedent('''
|
||||||
|
def glob():
|
||||||
|
x: foo = 5
|
||||||
|
global x'''),
|
||||||
|
dedent('''
|
||||||
|
def glob():
|
||||||
|
x: foo = 5
|
||||||
|
x
|
||||||
|
global x'''),
|
||||||
|
dedent('''
|
||||||
|
def glob():
|
||||||
|
global x
|
||||||
|
x: foo = 3
|
||||||
|
'''),
|
||||||
|
# global/nonlocal + param
|
||||||
|
dedent('''
|
||||||
|
def glob(x):
|
||||||
|
global x
|
||||||
|
'''),
|
||||||
|
dedent('''
|
||||||
|
def glob(x):
|
||||||
|
nonlocal x
|
||||||
|
'''),
|
||||||
|
|
||||||
# IndentationError
|
# IndentationError
|
||||||
' foo',
|
' foo',
|
||||||
|
|||||||
Reference in New Issue
Block a user