forked from VimPlug/jedi
Delete legacy code from evaluate.
This commit is contained in:
+2
-229
@@ -69,11 +69,9 @@ backtracking algorithm.
|
|||||||
.. todo:: nonlocal statement, needed or can be ignored? (py3k)
|
.. todo:: nonlocal statement, needed or can be ignored? (py3k)
|
||||||
"""
|
"""
|
||||||
import copy
|
import copy
|
||||||
from itertools import tee, chain
|
from itertools import chain
|
||||||
|
|
||||||
from jedi._compatibility import next, hasattr, unicode
|
|
||||||
from jedi.parser import tree as pr
|
from jedi.parser import tree as pr
|
||||||
from jedi.parser.tokenize import Token
|
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.evaluate import representation as er
|
from jedi.evaluate import representation as er
|
||||||
from jedi.evaluate import imports
|
from jedi.evaluate import imports
|
||||||
@@ -86,7 +84,7 @@ from jedi.evaluate import compiled
|
|||||||
from jedi.evaluate import precedence
|
from jedi.evaluate import precedence
|
||||||
from jedi.evaluate import param
|
from jedi.evaluate import param
|
||||||
from jedi.evaluate import helpers
|
from jedi.evaluate import helpers
|
||||||
from jedi.evaluate.helpers import FakeStatement, deep_ast_copy, call_of_name
|
from jedi.evaluate.helpers import FakeStatement, call_of_name
|
||||||
|
|
||||||
|
|
||||||
class Evaluator(object):
|
class Evaluator(object):
|
||||||
@@ -153,13 +151,6 @@ class Evaluator(object):
|
|||||||
types = left
|
types = left
|
||||||
else:
|
else:
|
||||||
types = precedence.calculate(self, left, operator, types)
|
types = precedence.calculate(self, left, operator, types)
|
||||||
elif False and len(stmt.get_defined_names()) > 1 and seek_name and ass_details:
|
|
||||||
# Assignment checking is only important if the statement defines
|
|
||||||
# multiple variables.
|
|
||||||
new_result = []
|
|
||||||
for ass_expression_list, op in ass_details:
|
|
||||||
new_result += finder.find_assignments(ass_expression_list[0], result, seek_name)
|
|
||||||
result = new_result
|
|
||||||
debug.dbg('eval_statement result %s', types)
|
debug.dbg('eval_statement result %s', types)
|
||||||
return types
|
return types
|
||||||
|
|
||||||
@@ -297,162 +288,6 @@ class Evaluator(object):
|
|||||||
debug.dbg('execute result: %s in %s', types, obj)
|
debug.dbg('execute result: %s in %s', types, obj)
|
||||||
return types
|
return types
|
||||||
|
|
||||||
def eval_expression_list(self, expression_list):
|
|
||||||
"""
|
|
||||||
`expression_list` can be either `pr.Array` or `list of list`.
|
|
||||||
It is used to evaluate a two dimensional object, that has calls, arrays and
|
|
||||||
operators in it.
|
|
||||||
"""
|
|
||||||
debug.dbg('eval_expression_list: %s', expression_list)
|
|
||||||
p = precedence.create_precedence(expression_list)
|
|
||||||
return precedence.process_precedence_element(self, p) or []
|
|
||||||
|
|
||||||
def eval_statement_element(self, element):
|
|
||||||
if isinstance(element, pr.ListComprehension):
|
|
||||||
return self.eval_statement(element.stmt)
|
|
||||||
elif isinstance(element, pr.Lambda):
|
|
||||||
return [er.Function(self, element)]
|
|
||||||
# With things like params, these can also be functions...
|
|
||||||
elif isinstance(element, pr.Base) and element.isinstance(
|
|
||||||
er.Function, er.Class, er.Instance, iterable.ArrayInstance):
|
|
||||||
return [element]
|
|
||||||
# The string tokens are just operations (+, -, etc.)
|
|
||||||
elif isinstance(element, compiled.CompiledObject):
|
|
||||||
return [element]
|
|
||||||
elif isinstance(element, Token):
|
|
||||||
return []
|
|
||||||
else:
|
|
||||||
return self.eval_call(element)
|
|
||||||
|
|
||||||
def eval_call(self, call):
|
|
||||||
"""Follow a call is following a function, variable, string, etc."""
|
|
||||||
path = call.generate_call_path()
|
|
||||||
|
|
||||||
# find the statement of the Scope
|
|
||||||
s = call
|
|
||||||
while not s.parent.is_scope():
|
|
||||||
s = s.parent
|
|
||||||
scope = s.parent
|
|
||||||
return self.eval_call_path(path, scope, s.start_pos)
|
|
||||||
|
|
||||||
def eval_call_path(self, path, scope, position):
|
|
||||||
"""
|
|
||||||
Follows a path generated by `pr.StatementElement.generate_call_path()`.
|
|
||||||
"""
|
|
||||||
current = next(path)
|
|
||||||
|
|
||||||
if isinstance(current, pr.Array):
|
|
||||||
if current.type == pr.Array.NOARRAY:
|
|
||||||
try:
|
|
||||||
lst_cmp = current[0].expression_list()[0]
|
|
||||||
if not isinstance(lst_cmp, pr.ListComprehension):
|
|
||||||
raise IndexError
|
|
||||||
except IndexError:
|
|
||||||
types = list(chain.from_iterable(self.eval_statement(s)
|
|
||||||
for s in current))
|
|
||||||
else:
|
|
||||||
types = [iterable.GeneratorComprehension(self, lst_cmp)]
|
|
||||||
else:
|
|
||||||
types = [iterable.Array(self, current)]
|
|
||||||
else:
|
|
||||||
if isinstance(current, pr.Name):
|
|
||||||
# This is the first global lookup.
|
|
||||||
types = self.find_types(scope, current, position=position,
|
|
||||||
search_global=True)
|
|
||||||
else:
|
|
||||||
# for pr.Literal
|
|
||||||
types = [compiled.create(self, current.value)]
|
|
||||||
types = imports.follow_imports(self, types)
|
|
||||||
|
|
||||||
return self.follow_path(path, types, scope)
|
|
||||||
|
|
||||||
def follow_path(self, path, types, call_scope):
|
|
||||||
"""
|
|
||||||
Follows a path like::
|
|
||||||
|
|
||||||
self.follow_path(iter(['Foo', 'bar']), [a_type], from_somewhere)
|
|
||||||
|
|
||||||
to follow a call like ``module.a_type.Foo.bar`` (in ``from_somewhere``).
|
|
||||||
"""
|
|
||||||
results_new = []
|
|
||||||
iter_paths = tee(path, len(types))
|
|
||||||
|
|
||||||
for i, typ in enumerate(types):
|
|
||||||
fp = self._follow_path(iter_paths[i], typ, call_scope)
|
|
||||||
if fp is not None:
|
|
||||||
results_new += fp
|
|
||||||
else:
|
|
||||||
# This means stop iteration.
|
|
||||||
return types
|
|
||||||
return results_new
|
|
||||||
|
|
||||||
def _follow_path(self, path, typ, scope):
|
|
||||||
"""
|
|
||||||
Uses a generator and tries to complete the path, e.g.::
|
|
||||||
|
|
||||||
foo.bar.baz
|
|
||||||
|
|
||||||
`_follow_path` is only responsible for completing `.bar.baz`, the rest
|
|
||||||
is done in the `follow_call` function.
|
|
||||||
"""
|
|
||||||
# current is either an Array or a Scope.
|
|
||||||
try:
|
|
||||||
current = next(path)
|
|
||||||
except StopIteration:
|
|
||||||
return None
|
|
||||||
debug.dbg('_follow_path: %s in scope %s', current, typ)
|
|
||||||
|
|
||||||
result = []
|
|
||||||
if isinstance(current, pr.Array):
|
|
||||||
# This must be an execution, either () or [].
|
|
||||||
if current.type == pr.Array.LIST:
|
|
||||||
if hasattr(typ, 'get_index_types'):
|
|
||||||
if isinstance(typ, compiled.CompiledObject):
|
|
||||||
# CompiledObject doesn't contain an evaluator instance.
|
|
||||||
result = typ.get_index_types(self, current)
|
|
||||||
else:
|
|
||||||
result = typ.get_index_types(current)
|
|
||||||
elif current.type not in [pr.Array.DICT]:
|
|
||||||
# Scope must be a class or func - make an instance or execution.
|
|
||||||
result = self.execute(typ, current)
|
|
||||||
else:
|
|
||||||
# Curly braces are not allowed, because they make no sense.
|
|
||||||
debug.warning('strange function call with {} %s %s', current, typ)
|
|
||||||
else:
|
|
||||||
# The function must not be decorated with something else.
|
|
||||||
if typ.isinstance(er.Function):
|
|
||||||
typ = typ.get_magic_function_scope()
|
|
||||||
else:
|
|
||||||
# This is the typical lookup while chaining things.
|
|
||||||
if filter_private_variable(typ, scope, current):
|
|
||||||
return []
|
|
||||||
types = self.find_types(typ, current)
|
|
||||||
result = imports.follow_imports(self, types)
|
|
||||||
return self.follow_path(path, result, scope)
|
|
||||||
|
|
||||||
@debug.increase_indent
|
|
||||||
def execute_old(self, obj, params=()):
|
|
||||||
if obj.isinstance(er.Function):
|
|
||||||
obj = obj.get_decorated_func()
|
|
||||||
|
|
||||||
debug.dbg('execute: %s %s', obj, params)
|
|
||||||
try:
|
|
||||||
# Some stdlib functions like super(), namedtuple(), etc. have been
|
|
||||||
# hard-coded in Jedi to support them.
|
|
||||||
return stdlib.execute(self, obj, params)
|
|
||||||
except stdlib.NotInStdLib:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
func = obj.py__call__
|
|
||||||
except AttributeError:
|
|
||||||
debug.warning("no execution possible %s", obj)
|
|
||||||
return []
|
|
||||||
else:
|
|
||||||
types = func(self, params)
|
|
||||||
debug.dbg('execute result: %s in %s', types, obj)
|
|
||||||
return types
|
|
||||||
|
|
||||||
def goto_definition(self, name):
|
def goto_definition(self, name):
|
||||||
def_ = name.get_definition()
|
def_ = name.get_definition()
|
||||||
if def_.type == 'expr_stmt' and name in def_.get_defined_names():
|
if def_.type == 'expr_stmt' and name in def_.get_defined_names():
|
||||||
@@ -513,65 +348,3 @@ class Evaluator(object):
|
|||||||
else:
|
else:
|
||||||
return self.find_types(scope, name, stmt.start_pos,
|
return self.find_types(scope, name, stmt.start_pos,
|
||||||
search_global=True, is_goto=True)
|
search_global=True, is_goto=True)
|
||||||
|
|
||||||
|
|
||||||
if isinstance(par, pr.Import):
|
|
||||||
# Nowhere to goto for aliases
|
|
||||||
if par.alias == call_path[0]:
|
|
||||||
return [call_path[0]]
|
|
||||||
|
|
||||||
names = par.get_all_import_names()
|
|
||||||
if par.alias:
|
|
||||||
names = names[:-1]
|
|
||||||
# Filter names that are after our Name
|
|
||||||
removed_names = len(names) - names.index(call_path[0]) - 1
|
|
||||||
i = imports.ImportWrapper(self, par, kill_count=removed_names,
|
|
||||||
nested_resolve=True)
|
|
||||||
return i.follow(is_goto=True)
|
|
||||||
|
|
||||||
# Return the name defined in the call_path, if it's part of the
|
|
||||||
# statement name definitions. Only return, if it's one name and one
|
|
||||||
# name only. Otherwise it's a mixture between a definition and a
|
|
||||||
# reference. In this case it's just a definition. So we stay on it.
|
|
||||||
if len(call_path) == 1 and isinstance(call_path[0], pr.Name) \
|
|
||||||
and call_path[0] in par.get_defined_names():
|
|
||||||
# Named params should get resolved to their param definitions.
|
|
||||||
if pr.Array.is_type(par.parent, pr.Array.TUPLE, pr.Array.NOARRAY) \
|
|
||||||
and par.parent.previous:
|
|
||||||
call = deep_ast_copy(par.parent.previous)
|
|
||||||
# We have made a copy, so we're fine to change it.
|
|
||||||
call.next = None
|
|
||||||
while call.previous is not None:
|
|
||||||
call = call.previous
|
|
||||||
param_names = []
|
|
||||||
named_param_name = par.get_defined_names()[0]
|
|
||||||
for typ in self.eval_call(call):
|
|
||||||
if isinstance(typ, er.Class):
|
|
||||||
params = []
|
|
||||||
for init_method in typ.py__getattribute__('__init__'):
|
|
||||||
params += init_method.params
|
|
||||||
else:
|
|
||||||
params = typ.params
|
|
||||||
for param in params:
|
|
||||||
if unicode(param.get_name()) == unicode(named_param_name):
|
|
||||||
param_names.append(param.get_name())
|
|
||||||
return param_names
|
|
||||||
return [call_path[0]]
|
|
||||||
|
|
||||||
scope = par.get_parent_scope()
|
|
||||||
pos = par.start_pos
|
|
||||||
first_part, search_name_part = call_path[:-1], call_path[-1]
|
|
||||||
|
|
||||||
if first_part:
|
|
||||||
scopes = self.eval_call_path(iter(first_part), scope, pos)
|
|
||||||
search_global = False
|
|
||||||
pos = None
|
|
||||||
else:
|
|
||||||
scopes = [scope]
|
|
||||||
search_global = True
|
|
||||||
|
|
||||||
follow_res = []
|
|
||||||
for s in scopes:
|
|
||||||
follow_res += self.find_types(s, search_name_part, pos,
|
|
||||||
search_global=search_global, is_goto=True)
|
|
||||||
return follow_res
|
|
||||||
|
|||||||
Reference in New Issue
Block a user