diff --git a/jedi/parser/tree.py b/jedi/parser/tree.py index 3a874f73..10fbeccd 100644 --- a/jedi/parser/tree.py +++ b/jedi/parser/tree.py @@ -952,23 +952,28 @@ def _create_params(parent, argslist_list): if first.type in ('name', 'tfpdef'): if check_python2_nested_param(first): - return [] + return [first] else: return [Param([first], parent)] + elif first == '*': + return [first] else: # argslist is a `typedargslist` or a `varargslist`. children = first.children - params = [] + new_children = [] 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 == ',': - new_children = children[start:end] - if new_children: # Could as well be comma and then end. - if check_python2_nested_param(new_children[0]): - continue - params.append(Param(new_children, parent)) + param_children = children[start:end] + if param_children: # Could as well be comma and then end. + if check_python2_nested_param(param_children[0]): + new_children += param_children + elif param_children[0] == '*' and param_children[1] == ',': + new_children += param_children + else: + new_children.append(Param(param_children, parent)) start = end - return params + return new_children class Function(ClassOrFunc): @@ -995,8 +1000,7 @@ class Function(ClassOrFunc): @property def params(self): - # Contents of parameter lit minus the leading and the trailing . - return self.children[2].children[1:-1] + return [p for p in self.children[2].children if p.type == 'param'] @property def name(self): diff --git a/test/test_parser/test_param_splitting.py b/test/test_parser/test_param_splitting.py new file mode 100644 index 00000000..175df448 --- /dev/null +++ b/test/test_parser/test_param_splitting.py @@ -0,0 +1,34 @@ +''' +To make the life of any analysis easier, we are generating Param objects +instead of simple parser objects. +''' + +from textwrap import dedent + +from jedi.parser import Parser, load_grammar + + +def assert_params(param_string, **wanted_dct): + source = dedent(''' + def x(%s): + pass + ''') % param_string + + parser = Parser(load_grammar(), dedent(source)) + funcdef = parser.get_parsed_node().subscopes[0] + dct = dict((p.name.value, p.default and p.default.get_code()) + for p in funcdef.params) + assert dct == wanted_dct + assert parser.get_parsed_node().get_code() == source + + +def test_split_params_with_separation_star(): + assert_params('x, y=1, *, z=3', x=None, y='1', z='3') + assert_params('*, x', x=None) + assert_params('*') + + +def test_split_params_with_stars(): + assert_params('x, *args', x=None, args=None) + assert_params('**kwargs', kwargs=None) + assert_params('*args, **kwargs', args=None, kwargs=None)