forked from VimPlug/jedi
fix a lot of the dynamic issues
This commit is contained in:
@@ -424,8 +424,8 @@ class Evaluator(object):
|
|||||||
|
|
||||||
while flow_scope:
|
while flow_scope:
|
||||||
# TODO check if result is in scope -> no evaluation necessary
|
# TODO check if result is in scope -> no evaluation necessary
|
||||||
n = dynamic.check_flow_information(flow_scope, name_str,
|
n = dynamic.check_flow_information(self, flow_scope,
|
||||||
position)
|
name_str, position)
|
||||||
if n:
|
if n:
|
||||||
result = n
|
result = n
|
||||||
break
|
break
|
||||||
|
|||||||
+26
-20
@@ -192,6 +192,7 @@ def search_params(evaluator, param):
|
|||||||
if first:
|
if first:
|
||||||
scopes = evaluator.follow_call_path(iter(first), scope, pos)
|
scopes = evaluator.follow_call_path(iter(first), scope, pos)
|
||||||
pos = None
|
pos = None
|
||||||
|
from jedi.evaluate import representation as er
|
||||||
for scope in scopes:
|
for scope in scopes:
|
||||||
s = evaluator.find_name(scope, func_name, position=pos,
|
s = evaluator.find_name(scope, func_name, position=pos,
|
||||||
search_global=not first,
|
search_global=not first,
|
||||||
@@ -248,7 +249,7 @@ def search_params(evaluator, param):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def check_array_additions(array):
|
def check_array_additions(evaluator, array):
|
||||||
""" Just a mapper function for the internal _check_array_additions """
|
""" Just a mapper function for the internal _check_array_additions """
|
||||||
if not pr.Array.is_type(array._array, pr.Array.LIST, pr.Array.SET):
|
if not pr.Array.is_type(array._array, pr.Array.LIST, pr.Array.SET):
|
||||||
# TODO also check for dict updates
|
# TODO also check for dict updates
|
||||||
@@ -296,8 +297,8 @@ def _scan_statement(stmt, search_name, assignment_details=False):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@memoize_default([])
|
@memoize_default([], evaluator_is_first_arg=True)
|
||||||
def _check_array_additions(compare_array, module, is_list):
|
def _check_array_additions(evaluator, compare_array, module, is_list):
|
||||||
"""
|
"""
|
||||||
Checks if a `pr.Array` has "add" statements:
|
Checks if a `pr.Array` has "add" statements:
|
||||||
>>> a = [""]
|
>>> a = [""]
|
||||||
@@ -324,7 +325,7 @@ def _check_array_additions(compare_array, module, is_list):
|
|||||||
position = c.start_pos
|
position = c.start_pos
|
||||||
scope = c.get_parent_until(pr.IsScope)
|
scope = c.get_parent_until(pr.IsScope)
|
||||||
|
|
||||||
found = evaluate.follow_call_path(backtrack_path, scope, position)
|
found = evaluator.follow_call_path(backtrack_path, scope, position)
|
||||||
if not compare_array in found:
|
if not compare_array in found:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -333,20 +334,22 @@ def _check_array_additions(compare_array, module, is_list):
|
|||||||
continue # no params: just ignore it
|
continue # no params: just ignore it
|
||||||
if add_name in ['append', 'add']:
|
if add_name in ['append', 'add']:
|
||||||
for param in params:
|
for param in params:
|
||||||
result += evaluate.follow_statement(param)
|
result += evaluator.follow_statement(param)
|
||||||
elif add_name in ['insert']:
|
elif add_name in ['insert']:
|
||||||
try:
|
try:
|
||||||
second_param = params[1]
|
second_param = params[1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
result += evaluate.follow_statement(second_param)
|
result += evaluator.follow_statement(second_param)
|
||||||
elif add_name in ['extend', 'update']:
|
elif add_name in ['extend', 'update']:
|
||||||
for param in params:
|
for param in params:
|
||||||
iterators = evaluate.follow_statement(param)
|
iterators = evaluator.follow_statement(param)
|
||||||
result += evaluate.get_iterator_types(iterators)
|
result += evaluator.get_iterator_types(iterators)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
from jedi.evaluate import representation as er
|
||||||
|
|
||||||
def get_execution_parent(element, *stop_classes):
|
def get_execution_parent(element, *stop_classes):
|
||||||
""" Used to get an Instance/Execution parent """
|
""" Used to get an Instance/Execution parent """
|
||||||
if isinstance(element, er.Array):
|
if isinstance(element, er.Array):
|
||||||
@@ -387,21 +390,21 @@ def _check_array_additions(compare_array, module, is_list):
|
|||||||
if isinstance(comp_arr_parent, er.InstanceElement):
|
if isinstance(comp_arr_parent, er.InstanceElement):
|
||||||
stmt = er.InstanceElement(comp_arr_parent.instance, stmt)
|
stmt = er.InstanceElement(comp_arr_parent.instance, stmt)
|
||||||
|
|
||||||
if evaluate.follow_statement.push_stmt(stmt):
|
if evaluator.follow_statement.push_stmt(stmt):
|
||||||
# check recursion
|
# check recursion
|
||||||
continue
|
continue
|
||||||
res += check_calls(_scan_statement(stmt, n), n)
|
res += check_calls(_scan_statement(stmt, n), n)
|
||||||
evaluate.follow_statement.pop_stmt()
|
evaluator.follow_statement.pop_stmt()
|
||||||
# reset settings
|
# reset settings
|
||||||
settings.dynamic_params_for_other_modules = temp_param_add
|
settings.dynamic_params_for_other_modules = temp_param_add
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def check_array_instances(instance):
|
def check_array_instances(evaluator, instance):
|
||||||
"""Used for set() and list() instances."""
|
"""Used for set() and list() instances."""
|
||||||
if not settings.dynamic_arrays_instances:
|
if not settings.dynamic_arrays_instances:
|
||||||
return instance.var_args
|
return instance.var_args
|
||||||
ai = ArrayInstance(instance)
|
ai = ArrayInstance(evaluator, instance)
|
||||||
return [ai]
|
return [ai]
|
||||||
|
|
||||||
|
|
||||||
@@ -411,7 +414,8 @@ class ArrayInstance(pr.Base):
|
|||||||
This is definitely a hack, but a good one :-)
|
This is definitely a hack, but a good one :-)
|
||||||
It makes it possible to use set/list conversions.
|
It makes it possible to use set/list conversions.
|
||||||
"""
|
"""
|
||||||
def __init__(self, instance):
|
def __init__(self, evaluator, instance):
|
||||||
|
self._evaluator = evaluator
|
||||||
self.instance = instance
|
self.instance = instance
|
||||||
self.var_args = instance.var_args
|
self.var_args = instance.var_args
|
||||||
|
|
||||||
@@ -421,8 +425,9 @@ class ArrayInstance(pr.Base):
|
|||||||
lists/sets are too complicated too handle that.
|
lists/sets are too complicated too handle that.
|
||||||
"""
|
"""
|
||||||
items = []
|
items = []
|
||||||
|
from jedi.evaluate import representation as er
|
||||||
for stmt in self.var_args:
|
for stmt in self.var_args:
|
||||||
for typ in evaluate.follow_statement(stmt):
|
for typ in self._evaluator.follow_statement(stmt):
|
||||||
if isinstance(typ, er.Instance) and len(typ.var_args):
|
if isinstance(typ, er.Instance) and len(typ.var_args):
|
||||||
array = typ.var_args[0]
|
array = typ.var_args[0]
|
||||||
if isinstance(array, ArrayInstance):
|
if isinstance(array, ArrayInstance):
|
||||||
@@ -435,7 +440,7 @@ class ArrayInstance(pr.Base):
|
|||||||
'ArrayInstance recursion',
|
'ArrayInstance recursion',
|
||||||
self.var_args)
|
self.var_args)
|
||||||
continue
|
continue
|
||||||
items += evaluate.get_iterator_types([typ])
|
items += self._evaluator.get_iterator_types([typ])
|
||||||
|
|
||||||
# TODO check if exclusion of tuple is a problem here.
|
# TODO check if exclusion of tuple is a problem here.
|
||||||
if isinstance(self.var_args, tuple) or self.var_args.parent is None:
|
if isinstance(self.var_args, tuple) or self.var_args.parent is None:
|
||||||
@@ -447,7 +452,7 @@ class ArrayInstance(pr.Base):
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
def check_flow_information(flow, search_name, pos):
|
def check_flow_information(evaluator, flow, search_name, pos):
|
||||||
""" Try to find out the type of a variable just with the information that
|
""" Try to find out the type of a variable just with the information that
|
||||||
is given by the flows: e.g. It is also responsible for assert checks.::
|
is given by the flows: e.g. It is also responsible for assert checks.::
|
||||||
|
|
||||||
@@ -463,17 +468,18 @@ def check_flow_information(flow, search_name, pos):
|
|||||||
for ass in reversed(flow.asserts):
|
for ass in reversed(flow.asserts):
|
||||||
if pos is None or ass.start_pos > pos:
|
if pos is None or ass.start_pos > pos:
|
||||||
continue
|
continue
|
||||||
result = _check_isinstance_type(ass, search_name)
|
result = _check_isinstance_type(evaluator, ass, search_name)
|
||||||
if result:
|
if result:
|
||||||
break
|
break
|
||||||
|
|
||||||
if isinstance(flow, pr.Flow) and not result:
|
if isinstance(flow, pr.Flow) and not result:
|
||||||
if flow.command in ['if', 'while'] and len(flow.inputs) == 1:
|
if flow.command in ['if', 'while'] and len(flow.inputs) == 1:
|
||||||
result = _check_isinstance_type(flow.inputs[0], search_name)
|
result = _check_isinstance_type(evaluator, flow.inputs[0], search_name)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _check_isinstance_type(stmt, search_name):
|
def _check_isinstance_type(evaluator, stmt, search_name):
|
||||||
|
from jedi.evaluate import representation as er
|
||||||
try:
|
try:
|
||||||
commands = stmt.get_commands()
|
commands = stmt.get_commands()
|
||||||
# this might be removed if we analyze and, etc
|
# this might be removed if we analyze and, etc
|
||||||
@@ -496,7 +502,7 @@ def _check_isinstance_type(stmt, search_name):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for c in evaluate.follow_call(classes[0]):
|
for c in evaluator.follow_call(classes[0]):
|
||||||
if isinstance(c, er.Array):
|
if isinstance(c, er.Array):
|
||||||
result += c.get_index_types()
|
result += c.get_index_types()
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class Instance(use_metaclass(CachedMetaClass, Executable)):
|
|||||||
if str(base.name) in ['list', 'set'] \
|
if str(base.name) in ['list', 'set'] \
|
||||||
and builtin.Builtin.scope == base.get_parent_until():
|
and builtin.Builtin.scope == base.get_parent_until():
|
||||||
# compare the module path with the builtin name.
|
# compare the module path with the builtin name.
|
||||||
self.var_args = dynamic.check_array_instances(self)
|
self.var_args = dynamic.check_array_instances(evaluator, self)
|
||||||
else:
|
else:
|
||||||
# need to execute the __init__ function, because the dynamic param
|
# need to execute the __init__ function, because the dynamic param
|
||||||
# searching needs it.
|
# searching needs it.
|
||||||
@@ -785,8 +785,8 @@ class Execution(Executable):
|
|||||||
class Generator(use_metaclass(CachedMetaClass, pr.Base, Iterable)):
|
class Generator(use_metaclass(CachedMetaClass, pr.Base, Iterable)):
|
||||||
""" Cares for `yield` statements. """
|
""" Cares for `yield` statements. """
|
||||||
def __init__(self, evaluator, func, var_args):
|
def __init__(self, evaluator, func, var_args):
|
||||||
# Need evaluator for `CachedMetaClass`.
|
|
||||||
super(Generator, self).__init__()
|
super(Generator, self).__init__()
|
||||||
|
self._evaluator = evaluator
|
||||||
self.func = func
|
self.func = func
|
||||||
self.var_args = var_args
|
self.var_args = var_args
|
||||||
|
|
||||||
@@ -860,7 +860,7 @@ class Array(use_metaclass(CachedMetaClass, pr.Base, Iterable)):
|
|||||||
return self.get_exact_index_types(index.var_args[0])
|
return self.get_exact_index_types(index.var_args[0])
|
||||||
|
|
||||||
result = list(self._follow_values(self._array.values))
|
result = list(self._follow_values(self._array.values))
|
||||||
result += dynamic.check_array_additions(self)
|
result += dynamic.check_array_additions(evaluator, self)
|
||||||
return set(result)
|
return set(result)
|
||||||
|
|
||||||
def get_exact_index_types(self, mixed_index):
|
def get_exact_index_types(self, mixed_index):
|
||||||
|
|||||||
Reference in New Issue
Block a user