diff --git a/jedi/api/helpers.py b/jedi/api/helpers.py index 452b8648..b391155e 100644 --- a/jedi/api/helpers.py +++ b/jedi/api/helpers.py @@ -196,30 +196,38 @@ CallSignatureDetails = namedtuple( ) +def _get_index_and_key(node, position): + """ + Returns the amount of commas and the keyword argument string. + """ + nodes_before = [c for c in node.children if c.start_pos < position] + if nodes_before[-1].type == 'arglist': + node = nodes_before[-1] + nodes_before = [c for c in node.children if c.start_pos < position] + + key_str = None + + if nodes_before: + last = nodes_before[-1] + print('xxxxx', last) + if last.type == 'argument' and last.children[1].end_pos <= position: + # Checked if the argument + key_str = last.children[0].value + elif last == '=': + key_str = nodes_before[-2].value + + return nodes_before.count(','), key_str + + def _get_call_signature_details_from_error_node(node, position): for index, element in reversed(list(enumerate(node.children))): # `index > 0` means that it's a trailer and not an atom. if element == '(' and element.end_pos <= position and index > 0: name = element.get_previous_leaf() if name.type == 'name': - if node.children[-1].type == 'arglist': - node = node.children[-1] - children = node.children - else: - # It's an error node, we don't want to match too much, just - # until the parentheses is enough. - children = node.children[index:] - nodes_before = [c for c in children if c.start_pos < position] - key_str = None - if nodes_before: - if nodes_before[-1].type == 'argument': - key_str = nodes_before[-1].children[0].value - elif nodes_before[-1] == '=': - key_str = nodes_before[-2].value return CallSignatureDetails( element, - nodes_before.count(','), - key_str + *_get_index_and_key(node, position) ) @@ -245,8 +253,8 @@ def get_call_signature_details(module, position): if node.type == 'trailer' and node.children[0] == '(': leaf = node.get_previous_leaf() - nodes_before = [c for c in node.children if c.start_pos < position] - return CallSignatureDetails(node.children[0], nodes_before.count(','), None) + return CallSignatureDetails( + node.children[0], *_get_index_and_key(node, position)) node = node.parent diff --git a/test/test_api/test_call_signatures.py b/test/test_api/test_call_signatures.py index 22c84a4c..73f2a9a1 100644 --- a/test/test_api/test_call_signatures.py +++ b/test/test_api/test_call_signatures.py @@ -324,6 +324,15 @@ def test_keyword_argument_index(): assert get('sorted([], key=').index == 2 assert get('sorted([], no_key=a').index is None + kw_func = 'def foo(a, b): pass\nfoo(b=3, a=4)' + assert get(kw_func, column=len('foo(b')).index == 0 + assert get(kw_func, column=len('foo(b=')).index == 1 + assert get(kw_func, column=len('foo(b=3, a=')).index == 0 + + kw_func_simple = 'def foo(a, b): pass\nfoo(b=4)' + assert get(kw_func_simple, column=len('foo(b')).index == 0 + assert get(kw_func_simple, column=len('foo(b=')).index == 1 + args_func = 'def foo(*kwargs): pass\n' assert get(args_func + 'foo(a').index == 0 assert get(args_func + 'foo(a, b').index == 0 @@ -335,6 +344,7 @@ def test_keyword_argument_index(): both = 'def foo(*args, **kwargs): pass\n' assert get(both + 'foo(a=2').index == 1 assert get(both + 'foo(a=2, b=2').index == 1 + assert get(both + 'foo(a=2, b=2)', column=len('foo(b=2, a=2')).index == 1 assert get(both + 'foo(a, b, c').index == 0