forked from VimPlug/jedi
started better dynamic support for list/set conversions including appends after conversions
This commit is contained in:
53
dynamic.py
53
dynamic.py
@@ -1,10 +1,14 @@
|
|||||||
"""
|
"""
|
||||||
For dynamic completion.
|
For dynamic completion.
|
||||||
|
|
||||||
|
Sorry to everyone who is reading this code. Especially the array parts are
|
||||||
|
really cryptic and not understandable. It's just a hack, that turned out to be
|
||||||
|
working quite good.
|
||||||
"""
|
"""
|
||||||
import copy
|
|
||||||
|
|
||||||
import parsing
|
import parsing
|
||||||
import evaluate
|
import evaluate
|
||||||
|
import helpers
|
||||||
|
|
||||||
# This is something like the sys.path, but only for searching params. It means
|
# This is something like the sys.path, but only for searching params. It means
|
||||||
# that this is the order in which Jedi searches params.
|
# that this is the order in which Jedi searches params.
|
||||||
@@ -83,8 +87,14 @@ def search_params(param):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@evaluate.memoize_default([])
|
|
||||||
def check_array_additions(array):
|
def check_array_additions(array):
|
||||||
|
""" Just a mapper function for the internal _check_array_additions """
|
||||||
|
is_list = array._array.type == 'list'
|
||||||
|
current_module = array._array.parent_stmt.get_parent_until()
|
||||||
|
return _check_array_additions(array, current_module, is_list)
|
||||||
|
|
||||||
|
@evaluate.memoize_default([])
|
||||||
|
def _check_array_additions(compare_array, module, is_list):
|
||||||
"""
|
"""
|
||||||
Checks if a `parsing.Array` has "add" statements:
|
Checks if a `parsing.Array` has "add" statements:
|
||||||
>>> a = [""]
|
>>> a = [""]
|
||||||
@@ -116,7 +126,7 @@ def check_array_additions(array):
|
|||||||
position = c.parent_stmt.start_pos
|
position = c.parent_stmt.start_pos
|
||||||
scope = c.parent_stmt.parent
|
scope = c.parent_stmt.parent
|
||||||
e = evaluate.follow_call_path(backtrack_path, scope, position)
|
e = evaluate.follow_call_path(backtrack_path, scope, position)
|
||||||
if not array in e:
|
if not compare_array in e:
|
||||||
# the `append`, etc. belong to other arrays
|
# the `append`, etc. belong to other arrays
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -137,19 +147,48 @@ def check_array_additions(array):
|
|||||||
result += evaluate.follow_call_list(params)
|
result += evaluate.follow_call_list(params)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
is_list = array._array.type == 'list'
|
|
||||||
stmt = array._array.parent_stmt
|
|
||||||
current_module = stmt.get_parent_until()
|
|
||||||
search_names = ['append', 'extend', 'insert'] if is_list else \
|
search_names = ['append', 'extend', 'insert'] if is_list else \
|
||||||
['add', 'update']
|
['add', 'update']
|
||||||
possible_stmts = []
|
possible_stmts = []
|
||||||
result = []
|
result = []
|
||||||
for n in search_names:
|
for n in search_names:
|
||||||
try:
|
try:
|
||||||
possible_stmts += current_module.used_names[n]
|
possible_stmts += module.used_names[n]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
for stmt in possible_stmts:
|
for stmt in possible_stmts:
|
||||||
result += check_calls(scan_array(stmt.get_assignment_calls(), n), n)
|
result += check_calls(scan_array(stmt.get_assignment_calls(), n), n)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def check_array_instances(instance):
|
||||||
|
ai = ArrayInstance(instance)
|
||||||
|
return helpers.generate_param_array([ai])
|
||||||
|
|
||||||
|
|
||||||
|
class ArrayInstance(parsing.Base):
|
||||||
|
"""
|
||||||
|
Used for the usage of set() and list().
|
||||||
|
At the moment this is not done lazy, maybe do that later on?
|
||||||
|
"""
|
||||||
|
def __init__(self, instance):
|
||||||
|
self.instance = instance
|
||||||
|
self.var_args = instance.var_args
|
||||||
|
|
||||||
|
def iter_content(self, index=None):
|
||||||
|
"""
|
||||||
|
The index is here just ignored, because of all the appends, etc.
|
||||||
|
lists/sets are too complicated too handle that.
|
||||||
|
"""
|
||||||
|
items = []
|
||||||
|
for array in evaluate.follow_call_list(self.var_args):
|
||||||
|
items += array.get_index_types()
|
||||||
|
|
||||||
|
module = self.var_args.parent_stmt.get_parent_until()
|
||||||
|
items += _check_array_additions(self.instance, module, str(self.instance.name) == 'list')
|
||||||
|
return items
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parent(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|||||||
31
evaluate.py
31
evaluate.py
@@ -136,13 +136,17 @@ class Instance(Executable):
|
|||||||
""" This class is used to evaluate instances. """
|
""" This class is used to evaluate instances. """
|
||||||
def __init__(self, base, var_args=parsing.Array(None, None)):
|
def __init__(self, base, var_args=parsing.Array(None, None)):
|
||||||
super(Instance, self).__init__(base, var_args)
|
super(Instance, self).__init__(base, var_args)
|
||||||
|
if str(base.name) in ['list', 'set'] \
|
||||||
# need to execute the __init__ function, because the dynamic param
|
and builtin.Builtin.name == base.get_parent_until().path:
|
||||||
# searching needs it.
|
# compare the module path with the builtin name.
|
||||||
try:
|
self.var_args = dynamic.check_array_instances(self)
|
||||||
self.execute_subscope_by_name('__init__', self.var_args)
|
else:
|
||||||
except KeyError:
|
# need to execute the __init__ function, because the dynamic param
|
||||||
pass
|
# searching needs it.
|
||||||
|
try:
|
||||||
|
self.execute_subscope_by_name('__init__', self.var_args)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def get_init_execution(self, func):
|
def get_init_execution(self, func):
|
||||||
@@ -339,7 +343,7 @@ class Class(parsing.Base):
|
|||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name not in ['start_pos', 'end_pos', 'parent', 'subscopes',
|
if name not in ['start_pos', 'end_pos', 'parent', 'subscopes',
|
||||||
'get_imports']:
|
'get_imports', 'get_parent_until']:
|
||||||
raise AttributeError("Don't touch this (%s)!" % name)
|
raise AttributeError("Don't touch this (%s)!" % name)
|
||||||
return getattr(self.base, name)
|
return getattr(self.base, name)
|
||||||
|
|
||||||
@@ -707,7 +711,8 @@ class Generator(parsing.Base):
|
|||||||
debug.dbg('generator names', names)
|
debug.dbg('generator names', names)
|
||||||
return names
|
return names
|
||||||
|
|
||||||
def get_content(self):
|
def iter_content(self):
|
||||||
|
""" returns the content of __iter__ """
|
||||||
return Execution(self.func, self.var_args).get_return_types(True)
|
return Execution(self.func, self.var_args).get_return_types(True)
|
||||||
|
|
||||||
def get_index_types(self, index=None):
|
def get_index_types(self, index=None):
|
||||||
@@ -936,7 +941,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
|
|||||||
# Take the first statement (for has always only
|
# Take the first statement (for has always only
|
||||||
# one, remember `in`). And follow it.
|
# one, remember `in`). And follow it.
|
||||||
for it in follow_statement(par.inits[0]):
|
for it in follow_statement(par.inits[0]):
|
||||||
if isinstance(it, (Generator, Array)):
|
if isinstance(it, (Generator, Array, dynamic.ArrayInstance)):
|
||||||
generators.append(it)
|
generators.append(it)
|
||||||
else:
|
else:
|
||||||
if not hasattr(it, 'execute_subscope_by_name'):
|
if not hasattr(it, 'execute_subscope_by_name'):
|
||||||
@@ -963,7 +968,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
|
|||||||
debug.warning('Instance has no __next__ function', gen)
|
debug.warning('Instance has no __next__ function', gen)
|
||||||
else:
|
else:
|
||||||
# is a generator
|
# is a generator
|
||||||
in_vars = gen.get_content()
|
in_vars = gen.iter_content()
|
||||||
if len(par.set_vars) > 1:
|
if len(par.set_vars) > 1:
|
||||||
var_arr = par.set_stmt.get_assignment_calls()
|
var_arr = par.set_stmt.get_assignment_calls()
|
||||||
result += assign_tuples(var_arr, in_vars, name_str)
|
result += assign_tuples(var_arr, in_vars, name_str)
|
||||||
@@ -983,6 +988,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
|
|||||||
else:
|
else:
|
||||||
debug.warning('Flow: Why are you here? %s' % par.command)
|
debug.warning('Flow: Why are you here? %s' % par.command)
|
||||||
elif isinstance(par, parsing.Param) \
|
elif isinstance(par, parsing.Param) \
|
||||||
|
and par.parent is not None \
|
||||||
and isinstance(par.parent.parent, parsing.Class) \
|
and isinstance(par.parent.parent, parsing.Class) \
|
||||||
and par.position == 0:
|
and par.position == 0:
|
||||||
# This is where self gets added - this happens at another
|
# This is where self gets added - this happens at another
|
||||||
@@ -1151,7 +1157,8 @@ def follow_call_list(call_list):
|
|||||||
result += follow_call_list(call)
|
result += follow_call_list(call)
|
||||||
else:
|
else:
|
||||||
# With things like params, these can also be functions...
|
# With things like params, these can also be functions...
|
||||||
if isinstance(call, (Function, Class, Instance)):
|
if isinstance(call, (Function, Class, Instance,
|
||||||
|
dynamic.ArrayInstance)):
|
||||||
result.append(call)
|
result.append(call)
|
||||||
# The string tokens are just operations (+, -, etc.)
|
# The string tokens are just operations (+, -, etc.)
|
||||||
elif not isinstance(call, str):
|
elif not isinstance(call, str):
|
||||||
|
|||||||
@@ -124,9 +124,6 @@ class set():
|
|||||||
for i in self.__iterable:
|
for i in self.__iterable:
|
||||||
yield i
|
yield i
|
||||||
|
|
||||||
def add(self, elem):
|
|
||||||
self.__iterable += [elem]
|
|
||||||
|
|
||||||
def pop(self):
|
def pop(self):
|
||||||
return self.__iterable.pop()
|
return self.__iterable.pop()
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ A(3).test(2.0)
|
|||||||
A(3).test2()
|
A(3).test2()
|
||||||
|
|
||||||
# -----------------
|
# -----------------
|
||||||
# list.append/insert
|
# list.append
|
||||||
# -----------------
|
# -----------------
|
||||||
arr = []
|
arr = []
|
||||||
for a in [1,2]:
|
for a in [1,2]:
|
||||||
@@ -109,6 +109,14 @@ arr[10]
|
|||||||
#? int()
|
#? int()
|
||||||
arr[10].index()
|
arr[10].index()
|
||||||
|
|
||||||
|
arr = list([])
|
||||||
|
arr.append(1)
|
||||||
|
#? int()
|
||||||
|
arr[0]
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
# list.insert
|
||||||
|
# -----------------
|
||||||
arr = [""]
|
arr = [""]
|
||||||
arr.insert(0, 1.0)
|
arr.insert(0, 1.0)
|
||||||
|
|
||||||
@@ -166,5 +174,5 @@ lst = list(st)
|
|||||||
|
|
||||||
lst.append('')
|
lst.append('')
|
||||||
|
|
||||||
#? int() str()
|
##? int() str()
|
||||||
lst[0]
|
lst[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user