1
0
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:
Dave Halter
2015-03-24 15:02:07 +01:00
parent 61683cb83e
commit 0de5a0f412
2 changed files with 51 additions and 8 deletions

View File

@@ -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

View File

@@ -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', [])