mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 06:24:27 +08:00
Fix all call signature tests.
This commit is contained in:
@@ -291,14 +291,14 @@ class Script(object):
|
||||
# self.source, self._pos)
|
||||
definitions = helpers.evaluate_goto_definition(
|
||||
self._evaluator,
|
||||
call_signature_details.leaf
|
||||
call_signature_details.bracket_leaf.get_previous_leaf()
|
||||
)
|
||||
debug.speed('func_call followed')
|
||||
|
||||
return [classes.CallSignature(self._evaluator, d.name,
|
||||
call_signature_details.leaf.start_pos,
|
||||
call_signature_details.bracket_leaf.start_pos,
|
||||
call_signature_details.call_index,
|
||||
call_signature_details.keyword_name)
|
||||
call_signature_details.keyword_name_str)
|
||||
for d in definitions if hasattr(d, 'py__call__')]
|
||||
|
||||
def _analysis(self):
|
||||
|
||||
@@ -629,10 +629,10 @@ class CallSignature(Definition):
|
||||
It knows what functions you are currently in. e.g. `isinstance(` would
|
||||
return the `isinstance` function. without `(` it would return nothing.
|
||||
"""
|
||||
def __init__(self, evaluator, executable_name, bracket_start_pos, index, key_name):
|
||||
def __init__(self, evaluator, executable_name, bracket_start_pos, index, key_name_str):
|
||||
super(CallSignature, self).__init__(evaluator, executable_name)
|
||||
self._index = index
|
||||
self._key_name = key_name
|
||||
self._key_name_str = key_name_str
|
||||
self._bracket_start_pos = bracket_start_pos
|
||||
|
||||
@property
|
||||
@@ -641,9 +641,9 @@ class CallSignature(Definition):
|
||||
The Param index of the current call.
|
||||
Returns None if the index cannot be found in the curent call.
|
||||
"""
|
||||
if self._key_name is not None:
|
||||
if self._key_name_str is not None:
|
||||
for i, param in enumerate(self.params):
|
||||
if self._key_name == param.name:
|
||||
if self._key_name_str == param.name:
|
||||
return i
|
||||
if self.params and self.params[-1]._name.get_definition().stars == 2:
|
||||
return i
|
||||
|
||||
@@ -192,7 +192,7 @@ def evaluate_goto_definition(evaluator, leaf):
|
||||
|
||||
CallSignatureDetails = namedtuple(
|
||||
'CallSignatureDetails',
|
||||
['leaf', 'call_index', 'keyword_name']
|
||||
['bracket_leaf', 'call_index', 'keyword_name_str']
|
||||
)
|
||||
|
||||
|
||||
@@ -202,8 +202,25 @@ def _get_call_signature_details_from_error_node(node, position):
|
||||
if element == '(' and element.end_pos <= position and index > 0:
|
||||
name = element.get_previous_leaf()
|
||||
if name.type == 'name':
|
||||
nodes_before = [c for c in node.children[index:] if c.start_pos < position]
|
||||
return CallSignatureDetails(name, nodes_before.count(','), None)
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
def get_call_signature_details(module, position):
|
||||
@@ -214,8 +231,12 @@ def get_call_signature_details(module, position):
|
||||
# Now that we know where we are in the syntax tree, we start to look at
|
||||
# parents for possible function definitions.
|
||||
node = leaf.parent
|
||||
name = None
|
||||
while node is not None:
|
||||
if node.type in ('funcdef', 'classdef'):
|
||||
# Don't show call signatures if there's stuff before it that just
|
||||
# makes it feel strange to have a call signature.
|
||||
return None
|
||||
|
||||
for n in node.children:
|
||||
if n.start_pos < position and n.type == 'error_node':
|
||||
result = _get_call_signature_details_from_error_node(n, position)
|
||||
@@ -223,9 +244,9 @@ def get_call_signature_details(module, position):
|
||||
return result
|
||||
|
||||
if node.type == 'trailer' and node.children[0] == '(':
|
||||
name = node.get_previous_sibling()
|
||||
leaf = node.get_previous_leaf()
|
||||
nodes_before = [c for c in node.children if c.start_pos < position]
|
||||
return CallSignatureDetails(name, nodes_before.count(','), None)
|
||||
return CallSignatureDetails(node.children[0], nodes_before.count(','), None)
|
||||
|
||||
node = node.parent
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class TestCallSignatures(TestCase):
|
||||
|
||||
if not signatures:
|
||||
assert expected_name is None, \
|
||||
'There are no signatures, but %s expected.' % expected_name
|
||||
'There are no signatures, but `%s` expected.' % expected_name
|
||||
else:
|
||||
assert signatures[0].name == expected_name
|
||||
assert signatures[0].index == expected_index
|
||||
@@ -73,10 +73,11 @@ class TestCallSignatures(TestCase):
|
||||
|
||||
run("import time; abc = time; abc.sleep(", 'sleep', 0)
|
||||
|
||||
def test_issue_57(self):
|
||||
# jedi #57
|
||||
s = "def func(alpha, beta): pass\n" \
|
||||
"func(alpha='101',"
|
||||
run(s, 'func', 0, column=13, line=2)
|
||||
self._run_simple(s, 'func', 0, column=13, line=2)
|
||||
|
||||
def test_flows(self):
|
||||
# jedi-vim #9
|
||||
@@ -178,9 +179,7 @@ class TestCallSignatures(TestCase):
|
||||
def test_whitespace_before_bracket(self):
|
||||
self._run('str (', 'str', 0)
|
||||
self._run('str (";', 'str', 0)
|
||||
# TODO this is not actually valid Python, the newline token should be
|
||||
# ignored.
|
||||
self._run('str\n(', 'str', 0)
|
||||
self._run('str\n(', None)
|
||||
|
||||
def test_brackets_in_string_literals(self):
|
||||
self._run('str (" (', 'str', 0)
|
||||
@@ -191,7 +190,8 @@ class TestCallSignatures(TestCase):
|
||||
Function definitions (and other tokens that cannot exist within call
|
||||
signatures) should break and not be able to return a call signature.
|
||||
"""
|
||||
assert not Script('str(\ndef x').call_signatures()
|
||||
assert not self._run('str(\ndef x', 'str', 0)
|
||||
assert not Script('str(\ndef x(): pass').call_signatures()
|
||||
|
||||
def test_flow_call(self):
|
||||
assert not Script('if (1').call_signatures()
|
||||
@@ -316,11 +316,12 @@ def test_completion_interference():
|
||||
assert Script('open(').call_signatures()
|
||||
|
||||
|
||||
def test_signature_index():
|
||||
def get(source):
|
||||
return Script(source).call_signatures()[0]
|
||||
def test_keyword_argument_index():
|
||||
def get(source, column=None):
|
||||
return Script(source, column=column).call_signatures()[0]
|
||||
|
||||
assert get('sorted([], key=a').index == 2
|
||||
assert get('sorted([], key=').index == 2
|
||||
assert get('sorted([], no_key=a').index is None
|
||||
|
||||
args_func = 'def foo(*kwargs): pass\n'
|
||||
|
||||
Reference in New Issue
Block a user