mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 14:54:47 +08:00
isinstance checks for if/while
This commit is contained in:
@@ -60,14 +60,15 @@ Jedi supports many of the widely used Python features:
|
|||||||
- class decorators (py3k feature, are being ignored too, until I find a use
|
- class decorators (py3k feature, are being ignored too, until I find a use
|
||||||
case, that doesn't work with Jedi)
|
case, that doesn't work with Jedi)
|
||||||
- simple/usual ``sys.path`` modifications
|
- simple/usual ``sys.path`` modifications
|
||||||
|
- ``isinstance`` checks for if/while
|
||||||
|
|
||||||
However, it does not yet support (and probably will in future versions, because
|
However, it does not yet support (and probably will in future versions, because
|
||||||
they are on my todo list):
|
they are on my todo list):
|
||||||
|
|
||||||
- assert / isinstance
|
- operation support -> [3]\*3 etc.
|
||||||
- manipulations of instances outside the instance variables, without using
|
- manipulations of instances outside the instance variables, without using
|
||||||
functions
|
functions
|
||||||
- operation support -> ``__mul__``, ``__add__``, etc.
|
- assert
|
||||||
|
|
||||||
It does not support (and most probably will not in future versions):
|
It does not support (and most probably will not in future versions):
|
||||||
|
|
||||||
|
|||||||
@@ -492,3 +492,43 @@ class RelatedName(BaseOutput):
|
|||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash((self.start_pos, self.module_path))
|
return hash((self.start_pos, self.module_path))
|
||||||
|
|
||||||
|
|
||||||
|
def check_flow_information(flow, search_name):
|
||||||
|
""" Try to find out the type of a variable just with the information that
|
||||||
|
is given by the flows: e.g.
|
||||||
|
>>> if isinstance(k, str):
|
||||||
|
>>> k. # <- completion here
|
||||||
|
|
||||||
|
ensures that `k` is a string.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
assert flow.command in ['if', 'while']
|
||||||
|
assert len(flow.inits) == 1
|
||||||
|
ass = flow.inits[0].get_assignment_calls()
|
||||||
|
assert len(ass.values) == 1 and len(ass.values[0]) == 1
|
||||||
|
call = ass.values[0][0]
|
||||||
|
assert type(call) == parsing.Call and str(call.name) == 'isinstance'
|
||||||
|
assert bool(call.execution)
|
||||||
|
|
||||||
|
# isinstance check
|
||||||
|
isinst = call.execution.values
|
||||||
|
assert len(isinst) == 2
|
||||||
|
assert len(isinst[0]) == 1
|
||||||
|
assert len(isinst[1]) == 1
|
||||||
|
assert isinstance(isinst[0][0], parsing.Call)
|
||||||
|
# names fit?
|
||||||
|
assert str(isinst[0][0].name) == search_name
|
||||||
|
classes_call = isinst[1][0] # class_or_type_or_tuple
|
||||||
|
assert isinstance(classes_call, parsing.Call)
|
||||||
|
result = []
|
||||||
|
for c in evaluate.follow_call(classes_call):
|
||||||
|
if isinstance(c, evaluate.Array):
|
||||||
|
result += c.get_index_types()
|
||||||
|
else:
|
||||||
|
result.append(c)
|
||||||
|
for i, c in enumerate(result):
|
||||||
|
result[i] = evaluate.Instance(c)
|
||||||
|
return result
|
||||||
|
except AssertionError:
|
||||||
|
return []
|
||||||
|
|||||||
@@ -1118,10 +1118,11 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False,
|
|||||||
result.append(par)
|
result.append(par)
|
||||||
return result, no_break_scope
|
return result, no_break_scope
|
||||||
|
|
||||||
|
flow_scope = scope
|
||||||
result = []
|
result = []
|
||||||
# compare func uses the tuple of line/indent = line/column
|
# compare func uses the tuple of line/indent = line/column
|
||||||
comparison_func = lambda name: (name.start_pos)
|
comparison_func = lambda name: (name.start_pos)
|
||||||
for scope, name_list in scope_generator:
|
for nscope, name_list in scope_generator:
|
||||||
break_scopes = []
|
break_scopes = []
|
||||||
# here is the position stuff happening (sorting of variables)
|
# here is the position stuff happening (sorting of variables)
|
||||||
for name in sorted(name_list, key=comparison_func, reverse=True):
|
for name in sorted(name_list, key=comparison_func, reverse=True):
|
||||||
@@ -1136,7 +1137,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False,
|
|||||||
else:
|
else:
|
||||||
result += r
|
result += r
|
||||||
# for comparison we need the raw class
|
# for comparison we need the raw class
|
||||||
s = scope.base if isinstance(scope, Class) else scope
|
s = nscope.base if isinstance(nscope, Class) else nscope
|
||||||
# this means that a definition was found and is not e.g.
|
# this means that a definition was found and is not e.g.
|
||||||
# in if/else.
|
# in if/else.
|
||||||
if result and not no_break_scope:
|
if result and not no_break_scope:
|
||||||
@@ -1147,10 +1148,19 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False,
|
|||||||
if result:
|
if result:
|
||||||
break
|
break
|
||||||
|
|
||||||
if not result and isinstance(scope, Instance):
|
while flow_scope and flow_scope.isinstance(parsing.Flow):
|
||||||
|
result = dynamic.check_flow_information(flow_scope, name_str)
|
||||||
|
if result:
|
||||||
|
break
|
||||||
|
flow_scope = flow_scope.parent()
|
||||||
|
flow_scope = nscope
|
||||||
|
if result:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not result and isinstance(nscope, Instance):
|
||||||
# getattr() / __getattr__ / __getattribute__
|
# getattr() / __getattr__ / __getattribute__
|
||||||
result += check_getattr(scope, name_str)
|
result += check_getattr(nscope, name_str)
|
||||||
debug.dbg('sfn filter "%s" in %s: %s' % (name_str, scope, result))
|
debug.dbg('sfn filter "%s" in %s: %s' % (name_str, nscope, result))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def descriptor_check(result):
|
def descriptor_check(result):
|
||||||
|
|||||||
19
test/completion/isinstance.py
Normal file
19
test/completion/isinstance.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
if isinstance(i, str):
|
||||||
|
#? str()
|
||||||
|
i
|
||||||
|
|
||||||
|
if isinstance(j, (str, int)):
|
||||||
|
#? str() int()
|
||||||
|
j
|
||||||
|
|
||||||
|
while isinstance(k, (str, int)):
|
||||||
|
#? str() int()
|
||||||
|
k
|
||||||
|
|
||||||
|
if not isinstance(k, (str, int)):
|
||||||
|
#?
|
||||||
|
k
|
||||||
|
|
||||||
|
while not isinstance(k, (str, int)):
|
||||||
|
#?
|
||||||
|
k
|
||||||
Reference in New Issue
Block a user