mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-09 23:34:45 +08:00
completions on jedi now don't run into almost endless loop anymore
This commit is contained in:
34
dynamic.py
34
dynamic.py
@@ -111,12 +111,16 @@ def search_params(param):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def check_array_additions(array):
|
def check_array_additions(array):
|
||||||
""" Just a mapper function for the internal _check_array_additions """
|
""" Just a mapper function for the internal _check_array_additions """
|
||||||
|
if array._array.type not in ['list', 'tuple']:
|
||||||
|
# TODO also check for dict updates
|
||||||
|
return []
|
||||||
|
|
||||||
is_list = array._array.type == 'list'
|
is_list = array._array.type == 'list'
|
||||||
current_module = array._array.parent_stmt().get_parent_until()
|
current_module = array._array.parent_stmt().get_parent_until()
|
||||||
return _check_array_additions(array, current_module, is_list)
|
res = _check_array_additions(array, current_module, is_list)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
@evaluate.memoize_default([])
|
@evaluate.memoize_default([])
|
||||||
@@ -154,7 +158,16 @@ def _check_array_additions(compare_array, module, is_list):
|
|||||||
|
|
||||||
position = c.parent_stmt().start_pos
|
position = c.parent_stmt().start_pos
|
||||||
scope = c.parent_stmt().parent()
|
scope = c.parent_stmt().parent()
|
||||||
|
|
||||||
|
# Special assignments should not be evaluated in this case. This
|
||||||
|
# would cause big recursion problems, because in cases like the
|
||||||
|
# code of jedi itself, += something is called and this call leads
|
||||||
|
# to many other things including params, which are not defined.
|
||||||
|
# This would lead again to dynamic param completion, and so on.
|
||||||
|
# In the end the definition is needed, and that's not with `+=`.
|
||||||
|
settings.evaluate_special_assignments = False
|
||||||
found = evaluate.follow_call_path(backtrack_path, scope, position)
|
found = evaluate.follow_call_path(backtrack_path, scope, position)
|
||||||
|
settings.evaluate_special_assignments = True
|
||||||
if not compare_array in found:
|
if not compare_array in found:
|
||||||
# Check if the original scope is an execution. If it is, one
|
# Check if the original scope is an execution. If it is, one
|
||||||
# can search for the same statement, that is in the module
|
# can search for the same statement, that is in the module
|
||||||
@@ -244,37 +257,20 @@ class ArrayInstance(parsing.Base):
|
|||||||
lists/sets are too complicated too handle that.
|
lists/sets are too complicated too handle that.
|
||||||
"""
|
"""
|
||||||
items = []
|
items = []
|
||||||
#print 'ic', self.var_args, self.var_args.parent_stmt()
|
|
||||||
stmt = self.var_args.parent_stmt()
|
|
||||||
#if evaluate.follow_statement.push_stmt(stmt):
|
|
||||||
# check recursion
|
|
||||||
#return []
|
|
||||||
#if stmt.get_parent_until() == builtin.Builtin.scope:
|
|
||||||
#evaluate.follow_statement.push(stmt)
|
|
||||||
for array in evaluate.follow_call_list(self.var_args):
|
for array in evaluate.follow_call_list(self.var_args):
|
||||||
if isinstance(array, evaluate.Instance) and len(array.var_args):
|
if isinstance(array, evaluate.Instance) and len(array.var_args):
|
||||||
temp = array.var_args[0][0]
|
temp = array.var_args[0][0]
|
||||||
if isinstance(temp, ArrayInstance):
|
if isinstance(temp, ArrayInstance):
|
||||||
#print items, self, id(self.var_args), id(self.var_args.parent_stmt()), array
|
|
||||||
# prevent recursions
|
# prevent recursions
|
||||||
# TODO compare Modules
|
# TODO compare Modules
|
||||||
#if evaluate.follow_statement.push_stmt(stmt):
|
|
||||||
# check recursion
|
|
||||||
# continue
|
|
||||||
if self.var_args.start_pos != temp.var_args.start_pos:
|
if self.var_args.start_pos != temp.var_args.start_pos:
|
||||||
items += temp.iter_content()
|
items += temp.iter_content()
|
||||||
else:
|
else:
|
||||||
debug.warning('ArrayInstance recursion', self.var_args)
|
debug.warning('ArrayInstance recursion', self.var_args)
|
||||||
print 'yippie'
|
|
||||||
#evaluate.follow_statement.pop_stmt()
|
|
||||||
continue
|
continue
|
||||||
items += evaluate.get_iterator_types([array])
|
items += evaluate.get_iterator_types([array])
|
||||||
|
|
||||||
#if stmt.get_parent_until() == builtin.Builtin.scope:
|
|
||||||
#evaluate.follow_statement.pop()
|
|
||||||
#print 'ic finish', self.var_args
|
|
||||||
module = self.var_args.parent_stmt().get_parent_until()
|
module = self.var_args.parent_stmt().get_parent_until()
|
||||||
is_list = str(self.instance.name) == 'list'
|
is_list = str(self.instance.name) == 'list'
|
||||||
items += _check_array_additions(self.instance, module, is_list)
|
items += _check_array_additions(self.instance, module, is_list)
|
||||||
#evaluate.follow_statement.pop_stmt()
|
|
||||||
return items
|
return items
|
||||||
|
|||||||
22
evaluate.py
22
evaluate.py
@@ -30,6 +30,7 @@ import builtin
|
|||||||
import imports
|
import imports
|
||||||
import helpers
|
import helpers
|
||||||
import dynamic
|
import dynamic
|
||||||
|
import settings
|
||||||
|
|
||||||
memoize_caches = []
|
memoize_caches = []
|
||||||
statement_path = []
|
statement_path = []
|
||||||
@@ -407,7 +408,7 @@ class Function(parsing.Base):
|
|||||||
return f
|
return f
|
||||||
|
|
||||||
def get_decorated_func(self):
|
def get_decorated_func(self):
|
||||||
if self._decorated_func == None:
|
if self._decorated_func is None:
|
||||||
raise DecoratorNotFound()
|
raise DecoratorNotFound()
|
||||||
if self._decorated_func == self.base_func:
|
if self._decorated_func == self.base_func:
|
||||||
return self
|
return self
|
||||||
@@ -723,6 +724,7 @@ class Generator(parsing.Base):
|
|||||||
|
|
||||||
def iter_content(self):
|
def iter_content(self):
|
||||||
""" returns the content of __iter__ """
|
""" returns the content of __iter__ """
|
||||||
|
#print self, follow_statement.node_statements()
|
||||||
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):
|
||||||
@@ -833,7 +835,7 @@ class ArrayElement(object):
|
|||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
# Set access privileges:
|
# Set access privileges:
|
||||||
if name not in ['parent', 'names', 'start_pos', 'end_pos']:
|
if name not in ['parent', 'names', 'start_pos', 'end_pos', 'get_code']:
|
||||||
raise AttributeError('Strange access: %s.' % name)
|
raise AttributeError('Strange access: %s.' % name)
|
||||||
return getattr(self.name, name)
|
return getattr(self.name, name)
|
||||||
|
|
||||||
@@ -848,12 +850,13 @@ def get_defined_names_for_position(obj, position=None, start_scope=None):
|
|||||||
names = obj.get_defined_names()
|
names = obj.get_defined_names()
|
||||||
# Instances have special rules, always return all the possible completions,
|
# Instances have special rules, always return all the possible completions,
|
||||||
# because class variables are always valid and the `self.` variables, too.
|
# because class variables are always valid and the `self.` variables, too.
|
||||||
if not position or isinstance(obj, Instance) or start_scope != obj \
|
if not position or isinstance(obj, (Instance, Array)) \
|
||||||
|
or start_scope != obj \
|
||||||
and isinstance(start_scope, (parsing.Function, Execution)):
|
and isinstance(start_scope, (parsing.Function, Execution)):
|
||||||
return names
|
return names
|
||||||
names_new = []
|
names_new = []
|
||||||
for n in names:
|
for n in names:
|
||||||
if (n.start_pos) < position:
|
if n.start_pos < position:
|
||||||
names_new.append(n)
|
names_new.append(n)
|
||||||
return names_new
|
return names_new
|
||||||
|
|
||||||
@@ -1089,7 +1092,7 @@ def get_iterator_types(inputs):
|
|||||||
# __iter__ returned an instance.
|
# __iter__ returned an instance.
|
||||||
name = '__next__' if is_py3k() else 'next'
|
name = '__next__' if is_py3k() else 'next'
|
||||||
try:
|
try:
|
||||||
result += it.execute_subscope_by_name(name)
|
result += gen.execute_subscope_by_name(name)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
debug.warning('Instance has no __next__ function', gen)
|
debug.warning('Instance has no __next__ function', gen)
|
||||||
else:
|
else:
|
||||||
@@ -1152,8 +1155,12 @@ def assign_tuples(tup, results, seek_name):
|
|||||||
def follow_statement(stmt, seek_name=None):
|
def follow_statement(stmt, seek_name=None):
|
||||||
"""
|
"""
|
||||||
:param stmt: contains a statement
|
:param stmt: contains a statement
|
||||||
:param scope: contains a scope. If not given, takes the parent of stmt.
|
|
||||||
"""
|
"""
|
||||||
|
if not settings.evaluate_special_assignments:
|
||||||
|
det = stmt.assignment_details
|
||||||
|
if det and det[0][0] != '=':
|
||||||
|
return []
|
||||||
|
|
||||||
statement_path.append(stmt) # important to know for the goto function
|
statement_path.append(stmt) # important to know for the goto function
|
||||||
|
|
||||||
debug.dbg('follow_stmt %s (%s)' % (stmt, seek_name))
|
debug.dbg('follow_stmt %s (%s)' % (stmt, seek_name))
|
||||||
@@ -1225,6 +1232,9 @@ def follow_call(call):
|
|||||||
""" Follow a call is following a function, variable, string, etc. """
|
""" Follow a call is following a function, variable, string, etc. """
|
||||||
scope = call.parent_stmt().parent()
|
scope = call.parent_stmt().parent()
|
||||||
path = call.generate_call_path()
|
path = call.generate_call_path()
|
||||||
|
path = list(path)
|
||||||
|
#print 'p', scope, path
|
||||||
|
path = iter(path)
|
||||||
|
|
||||||
position = call.parent_stmt().start_pos
|
position = call.parent_stmt().start_pos
|
||||||
return follow_call_path(path, scope, position)
|
return follow_call_path(path, scope, position)
|
||||||
|
|||||||
10
settings.py
10
settings.py
@@ -1,4 +1,14 @@
|
|||||||
|
# ----------------
|
||||||
|
# global settings
|
||||||
|
# ----------------
|
||||||
|
|
||||||
dynamic_arrays_instances = True
|
dynamic_arrays_instances = True
|
||||||
dynamic_array_additions = True
|
dynamic_array_additions = True
|
||||||
dynamic_params = True
|
dynamic_params = True
|
||||||
|
|
||||||
|
# ----------------
|
||||||
|
# internally used:
|
||||||
|
# ----------------
|
||||||
|
|
||||||
|
# evaluation of +=, -=, /=, etc.
|
||||||
|
evaluate_special_assignments = True
|
||||||
|
|||||||
10
test/completion/thirdparty/jedi_.py
vendored
10
test/completion/thirdparty/jedi_.py
vendored
@@ -14,21 +14,21 @@ scopes, path, dot, like = \
|
|||||||
source_path, True)
|
source_path, True)
|
||||||
|
|
||||||
# has problems with that (sometimes) very deep nesting.
|
# has problems with that (sometimes) very deep nesting.
|
||||||
##? set()
|
#? set()
|
||||||
el = scopes
|
el = scopes
|
||||||
|
|
||||||
# get_names_for_scope is also recursion stuff
|
# get_names_for_scope is also recursion stuff
|
||||||
##? tuple()
|
#? tuple()
|
||||||
el = list(evaluate.get_names_for_scope())[0]
|
el = list(evaluate.get_names_for_scope())[0]
|
||||||
|
|
||||||
##? int() parsing.Module()
|
#? int() parsing.Module()
|
||||||
el = list(evaluate.get_names_for_scope(1))[0][0]
|
el = list(evaluate.get_names_for_scope(1))[0][0]
|
||||||
#? parsing.Module()
|
#? parsing.Module()
|
||||||
el = list(evaluate.get_names_for_scope())[0][0]
|
el = list(evaluate.get_names_for_scope())[0][0]
|
||||||
|
|
||||||
##? list()
|
#? list()
|
||||||
el = list(evaluate.get_names_for_scope(1))[0][1]
|
el = list(evaluate.get_names_for_scope(1))[0][1]
|
||||||
##? list()
|
#? list()
|
||||||
el = list(evaluate.get_names_for_scope())[0][1]
|
el = list(evaluate.get_names_for_scope())[0][1]
|
||||||
|
|
||||||
# TODO here should stand evaluate.Instance() and so on.
|
# TODO here should stand evaluate.Instance() and so on.
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ arr2 = [1,2,3]
|
|||||||
#? ['append']
|
#? ['append']
|
||||||
arr2.app
|
arr2.app
|
||||||
|
|
||||||
|
#? int()
|
||||||
|
arr.count(1)
|
||||||
|
|
||||||
# -----------------
|
# -----------------
|
||||||
# dicts
|
# dicts
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|||||||
Reference in New Issue
Block a user