forked from VimPlug/jedi
Python 2 allows tuple unpacking in parameter definitions. Jedi just ignores such constructs, since they are really rare and not the future.
This commit is contained in:
@@ -710,23 +710,44 @@ class Class(ClassOrFunc):
|
||||
|
||||
def _create_params(parent, argslist_list):
|
||||
"""
|
||||
TODO DOC
|
||||
This is a function to hack the general parser structure.
|
||||
Preparing the replacement of *argslist with a list of Params.
|
||||
`argslist_list` is a list that can contain an argslist as a first item, but
|
||||
most not. It's basically the items between the parameter brackets (which is
|
||||
at most one item).
|
||||
This function modifies the parser structure. It generates `Param` objects
|
||||
from the normal ast. Those param objects do not exist in a normal ast, but
|
||||
make the evaluation of the ast tree so much easier.
|
||||
You could also say that this function replaces the argslist node with a
|
||||
list of Param objects.
|
||||
"""
|
||||
if not argslist_list:
|
||||
def check_python2_nested_param(node):
|
||||
"""
|
||||
Python 2 allows params to look like ``def x(a, (b, c))``, which is
|
||||
basically a way of unpacking tuples in params. Python 3 has ditched
|
||||
this behavior. Jedi currently just ignores those constructs.
|
||||
"""
|
||||
return node.type == 'tfpdef' and node.children[0] == '('
|
||||
|
||||
try:
|
||||
first = argslist_list[0]
|
||||
except IndexError:
|
||||
return []
|
||||
|
||||
if argslist_list[0].type == 'name':
|
||||
return [Param([argslist_list[0]], parent)]
|
||||
if first.type in ('name', 'tfpdef'):
|
||||
if check_python2_nested_param(first):
|
||||
return []
|
||||
else:
|
||||
return [Param([first], parent)]
|
||||
else: # argslist is a `typedargslist` or a `varargslist`.
|
||||
children = argslist_list[0].children
|
||||
children = first.children
|
||||
params = []
|
||||
start = 0
|
||||
# Start with offset 1, because the end is higher.
|
||||
for end, child in enumerate(children + [None], 1):
|
||||
if child is None or child == ',':
|
||||
params.append(Param(children[start:end], parent))
|
||||
new_children = children[start:end]
|
||||
if check_python2_nested_param(new_children[0]):
|
||||
continue
|
||||
params.append(Param(new_children, parent))
|
||||
start = end
|
||||
return params
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
|
||||
import jedi
|
||||
from jedi._compatibility import u, is_py3
|
||||
@@ -180,3 +181,24 @@ def test_end_pos_error_correction():
|
||||
# at all. We just want to make sure that the module end_pos is correct!
|
||||
assert func.end_pos == (3, 0)
|
||||
assert m.end_pos == (2, 2)
|
||||
|
||||
|
||||
def test_param_splitting():
|
||||
"""
|
||||
Jedi splits parameters into params, this is not what the grammar does,
|
||||
but Jedi does this to simplify argument parsing.
|
||||
"""
|
||||
def check(src, result):
|
||||
# Python 2 tuple params should be ignored for now.
|
||||
grammar = load_grammar('grammar%s.%s' % sys.version_info[:2])
|
||||
m = Parser(grammar, u(src)).module
|
||||
if is_py3:
|
||||
assert not m.subscopes
|
||||
else:
|
||||
# We don't want b and c to be a part of the param enumeration. Just
|
||||
# ignore them, because it's not what we want to support in the
|
||||
# future.
|
||||
assert [str(param.name) for param in m.subscopes[0].params] == result
|
||||
|
||||
check('def x(a, (b, c)):\n pass', ['a'])
|
||||
check('def x((b, c)):\n pass', [])
|
||||
|
||||
Reference in New Issue
Block a user