forked from VimPlug/jedi
basic refactoring, of function executions super() is not working yet
This commit is contained in:
@@ -664,8 +664,32 @@ class Evaluator(object):
|
|||||||
position=position))
|
position=position))
|
||||||
return self.follow_path(path, set(result), scope, position=position)
|
return self.follow_path(path, set(result), scope, position=position)
|
||||||
|
|
||||||
def execute(self, scope, params, evaluate_generator=False):
|
def execute(self, obj, params, evaluate_generator=False):
|
||||||
return er.Execution(self, scope, params).get_return_types(evaluate_generator)
|
if obj.isinstance(er.Function):
|
||||||
|
obj = obj.get_decorated_func()
|
||||||
|
|
||||||
|
if obj.isinstance(er.Class):
|
||||||
|
# There maybe executions of executions.
|
||||||
|
return [er.Instance(self, obj, params)]
|
||||||
|
elif isinstance(obj, er.Generator):
|
||||||
|
return obj.iter_content()
|
||||||
|
else:
|
||||||
|
stmts = []
|
||||||
|
try:
|
||||||
|
obj.returns # Test if it is a function
|
||||||
|
except AttributeError:
|
||||||
|
if hasattr(obj, 'execute_subscope_by_name'):
|
||||||
|
try:
|
||||||
|
stmts = obj.execute_subscope_by_name('__call__', params)
|
||||||
|
except KeyError:
|
||||||
|
debug.warning("no __call__ func available", obj)
|
||||||
|
else:
|
||||||
|
debug.warning("no execution possible", obj)
|
||||||
|
else:
|
||||||
|
stmts = er.Execution(self, obj, params).get_return_types(evaluate_generator)
|
||||||
|
|
||||||
|
debug.dbg('execute: %s in %s' % (stmts, self))
|
||||||
|
return imports.strip_imports(self, stmts)
|
||||||
|
|
||||||
def goto(self, stmt, call_path=None):
|
def goto(self, stmt, call_path=None):
|
||||||
if call_path is None:
|
if call_path is None:
|
||||||
|
|||||||
@@ -14,12 +14,11 @@ from __future__ import with_statement
|
|||||||
import copy
|
import copy
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from jedi._compatibility import use_metaclass, next, hasattr, unicode
|
from jedi._compatibility import use_metaclass, next, unicode
|
||||||
from jedi.parser import representation as pr
|
from jedi.parser import representation as pr
|
||||||
from jedi import helpers
|
from jedi import helpers
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import common
|
from jedi import common
|
||||||
from jedi.evaluate import imports
|
|
||||||
from jedi.evaluate import builtin
|
from jedi.evaluate import builtin
|
||||||
from jedi.evaluate import recursion
|
from jedi.evaluate import recursion
|
||||||
from jedi.evaluate.cache import memoize_default, CachedMetaClass
|
from jedi.evaluate.cache import memoize_default, CachedMetaClass
|
||||||
@@ -39,18 +38,11 @@ class Executable(pr.IsScope):
|
|||||||
self.var_args = var_args
|
self.var_args = var_args
|
||||||
|
|
||||||
def get_parent_until(self, *args, **kwargs):
|
def get_parent_until(self, *args, **kwargs):
|
||||||
return self._decorated.get_parent_until(*args, **kwargs)
|
return self.base.get_parent_until(*args, **kwargs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent(self):
|
def parent(self):
|
||||||
return self._decorated.parent
|
return self.base.parent
|
||||||
|
|
||||||
@property
|
|
||||||
def _decorated(self):
|
|
||||||
"""
|
|
||||||
Instance doesn't care about decorators and Execution overrides this
|
|
||||||
"""
|
|
||||||
return self.base
|
|
||||||
|
|
||||||
|
|
||||||
class Instance(use_metaclass(CachedMetaClass, Executable)):
|
class Instance(use_metaclass(CachedMetaClass, Executable)):
|
||||||
@@ -363,9 +355,9 @@ class Function(use_metaclass(CachedMetaClass, pr.IsScope)):
|
|||||||
debug.warning('no wrappers found', self.base_func)
|
debug.warning('no wrappers found', self.base_func)
|
||||||
return None
|
return None
|
||||||
if len(wrappers) > 1:
|
if len(wrappers) > 1:
|
||||||
|
# TODO resolve issue with multiple wrappers -> multiple types
|
||||||
debug.warning('multiple wrappers found', self.base_func,
|
debug.warning('multiple wrappers found', self.base_func,
|
||||||
wrappers)
|
wrappers)
|
||||||
# This is here, that the wrapper gets executed.
|
|
||||||
f = wrappers[0]
|
f = wrappers[0]
|
||||||
|
|
||||||
debug.dbg('decorator end', f)
|
debug.dbg('decorator end', f)
|
||||||
@@ -420,20 +412,11 @@ class Execution(Executable):
|
|||||||
else:
|
else:
|
||||||
return [stmt] # just some arbitrary object
|
return [stmt] # just some arbitrary object
|
||||||
|
|
||||||
@property
|
|
||||||
@memoize_default(None)
|
|
||||||
def _decorated(self):
|
|
||||||
"""Get the decorated version of the input"""
|
|
||||||
base = self.base
|
|
||||||
if self.base.isinstance(Function):
|
|
||||||
base = base.get_decorated_func()
|
|
||||||
return base
|
|
||||||
|
|
||||||
@memoize_default(default=())
|
@memoize_default(default=())
|
||||||
@recursion.execution_recursion_decorator
|
@recursion.execution_recursion_decorator
|
||||||
def get_return_types(self, evaluate_generator=False):
|
def get_return_types(self, evaluate_generator=False):
|
||||||
""" Get the return types of a function. """
|
""" Get the return types of a function. """
|
||||||
base = self._decorated
|
base = self.base
|
||||||
stmts = []
|
stmts = []
|
||||||
if base.parent == builtin.Builtin.scope \
|
if base.parent == builtin.Builtin.scope \
|
||||||
and not isinstance(base, (Generator, Array)):
|
and not isinstance(base, (Generator, Array)):
|
||||||
@@ -464,7 +447,7 @@ class Execution(Executable):
|
|||||||
objects = self._follow_var_arg(0)
|
objects = self._follow_var_arg(0)
|
||||||
return [o.base for o in objects if isinstance(o, Instance)]
|
return [o.base for o in objects if isinstance(o, Instance)]
|
||||||
elif func_name == 'super':
|
elif func_name == 'super':
|
||||||
# TODO make this able to detect multiple inheritance supers
|
# TODO make this able to detect multiple inheritance super
|
||||||
accept = (pr.Function,)
|
accept = (pr.Function,)
|
||||||
func = self.var_args.get_parent_until(accept)
|
func = self.var_args.get_parent_until(accept)
|
||||||
if func.isinstance(*accept):
|
if func.isinstance(*accept):
|
||||||
@@ -477,29 +460,7 @@ class Execution(Executable):
|
|||||||
return [Instance(self._evaluator, su[0])]
|
return [Instance(self._evaluator, su[0])]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if base.isinstance(Class):
|
return self._get_function_returns(base, evaluate_generator)
|
||||||
# There maybe executions of executions.
|
|
||||||
return [Instance(self._evaluator, base, self.var_args)]
|
|
||||||
elif isinstance(base, Generator):
|
|
||||||
return base.iter_content()
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
base.returns # Test if it is a function
|
|
||||||
except AttributeError:
|
|
||||||
if hasattr(base, 'execute_subscope_by_name'):
|
|
||||||
try:
|
|
||||||
stmts = base.execute_subscope_by_name('__call__',
|
|
||||||
self.var_args)
|
|
||||||
except KeyError:
|
|
||||||
debug.warning("no __call__ func available", base)
|
|
||||||
else:
|
|
||||||
debug.warning("no execution possible", base)
|
|
||||||
else:
|
|
||||||
stmts = self._get_function_returns(base, evaluate_generator)
|
|
||||||
|
|
||||||
debug.dbg('exec result: %s in %s' % (stmts, self))
|
|
||||||
|
|
||||||
return imports.strip_imports(self._evaluator, stmts)
|
|
||||||
|
|
||||||
def _get_function_returns(self, func, evaluate_generator):
|
def _get_function_returns(self, func, evaluate_generator):
|
||||||
""" A normal Function execution """
|
""" A normal Function execution """
|
||||||
@@ -531,7 +492,7 @@ class Execution(Executable):
|
|||||||
parent = self.var_args.parent
|
parent = self.var_args.parent
|
||||||
start_pos = self.var_args.start_pos
|
start_pos = self.var_args.start_pos
|
||||||
else:
|
else:
|
||||||
parent = self._decorated
|
parent = self.base
|
||||||
start_pos = 0, 0
|
start_pos = 0, 0
|
||||||
|
|
||||||
new_param = copy.copy(param)
|
new_param = copy.copy(param)
|
||||||
@@ -558,15 +519,15 @@ class Execution(Executable):
|
|||||||
|
|
||||||
result = []
|
result = []
|
||||||
start_offset = 0
|
start_offset = 0
|
||||||
if isinstance(self._decorated, InstanceElement):
|
if isinstance(self.base, InstanceElement):
|
||||||
# Care for self -> just exclude it and add the instance
|
# Care for self -> just exclude it and add the instance
|
||||||
start_offset = 1
|
start_offset = 1
|
||||||
self_name = copy.copy(self._decorated.params[0].get_name())
|
self_name = copy.copy(self.base.params[0].get_name())
|
||||||
self_name.parent = self._decorated.instance
|
self_name.parent = self.base.instance
|
||||||
result.append(self_name)
|
result.append(self_name)
|
||||||
|
|
||||||
param_dict = {}
|
param_dict = {}
|
||||||
for param in self._decorated.params:
|
for param in self.base.params:
|
||||||
param_dict[str(param.get_name())] = param
|
param_dict[str(param.get_name())] = param
|
||||||
# There may be calls, which don't fit all the params, this just ignores
|
# There may be calls, which don't fit all the params, this just ignores
|
||||||
# it.
|
# it.
|
||||||
@@ -575,7 +536,7 @@ class Execution(Executable):
|
|||||||
non_matching_keys = []
|
non_matching_keys = []
|
||||||
keys_used = set()
|
keys_used = set()
|
||||||
keys_only = False
|
keys_only = False
|
||||||
for param in self._decorated.params[start_offset:]:
|
for param in self.base.params[start_offset:]:
|
||||||
# The value and key can both be null. There, the defaults apply.
|
# The value and key can both be null. There, the defaults apply.
|
||||||
# args / kwargs will just be empty arrays / dicts, respectively.
|
# args / kwargs will just be empty arrays / dicts, respectively.
|
||||||
# Wrong value count is just ignored. If you try to test cases that
|
# Wrong value count is just ignored. If you try to test cases that
|
||||||
@@ -719,7 +680,7 @@ class Execution(Executable):
|
|||||||
execution.
|
execution.
|
||||||
"""
|
"""
|
||||||
# Copy all these lists into this local function.
|
# Copy all these lists into this local function.
|
||||||
attr = getattr(self._decorated, prop)
|
attr = getattr(self.base, prop)
|
||||||
objects = []
|
objects = []
|
||||||
for element in attr:
|
for element in attr:
|
||||||
if element is None:
|
if element is None:
|
||||||
@@ -735,7 +696,7 @@ class Execution(Executable):
|
|||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name not in ['start_pos', 'end_pos', 'imports', '_sub_module']:
|
if name not in ['start_pos', 'end_pos', 'imports', '_sub_module']:
|
||||||
raise AttributeError('Tried to access %s: %s. Why?' % (name, self))
|
raise AttributeError('Tried to access %s: %s. Why?' % (name, self))
|
||||||
return getattr(self._decorated, name)
|
return getattr(self.base, name)
|
||||||
|
|
||||||
@memoize_default(None)
|
@memoize_default(None)
|
||||||
@common.rethrow_uncaught
|
@common.rethrow_uncaught
|
||||||
@@ -777,7 +738,7 @@ class Execution(Executable):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s of %s>" % \
|
return "<%s of %s>" % \
|
||||||
(type(self).__name__, self._decorated)
|
(type(self).__name__, self.base)
|
||||||
|
|
||||||
|
|
||||||
class Generator(use_metaclass(CachedMetaClass, pr.Base, Iterable)):
|
class Generator(use_metaclass(CachedMetaClass, pr.Base, Iterable)):
|
||||||
|
|||||||
Reference in New Issue
Block a user