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):
|
def _create_params(parent, argslist_list):
|
||||||
"""
|
"""
|
||||||
TODO DOC
|
`argslist_list` is a list that can contain an argslist as a first item, but
|
||||||
This is a function to hack the general parser structure.
|
most not. It's basically the items between the parameter brackets (which is
|
||||||
Preparing the replacement of *argslist with a list of Params.
|
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 []
|
return []
|
||||||
|
|
||||||
if argslist_list[0].type == 'name':
|
if first.type in ('name', 'tfpdef'):
|
||||||
return [Param([argslist_list[0]], parent)]
|
if check_python2_nested_param(first):
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
return [Param([first], parent)]
|
||||||
else: # argslist is a `typedargslist` or a `varargslist`.
|
else: # argslist is a `typedargslist` or a `varargslist`.
|
||||||
children = argslist_list[0].children
|
children = first.children
|
||||||
params = []
|
params = []
|
||||||
start = 0
|
start = 0
|
||||||
# Start with offset 1, because the end is higher.
|
# Start with offset 1, because the end is higher.
|
||||||
for end, child in enumerate(children + [None], 1):
|
for end, child in enumerate(children + [None], 1):
|
||||||
if child is None or child == ',':
|
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
|
start = end
|
||||||
return params
|
return params
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import sys
|
||||||
|
|
||||||
import jedi
|
import jedi
|
||||||
from jedi._compatibility import u, is_py3
|
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!
|
# at all. We just want to make sure that the module end_pos is correct!
|
||||||
assert func.end_pos == (3, 0)
|
assert func.end_pos == (3, 0)
|
||||||
assert m.end_pos == (2, 2)
|
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