1
0
forked from VimPlug/jedi

A lot of small improvements.

This commit is contained in:
Dave Halter
2016-10-22 17:40:42 +02:00
parent 4ccfbb4962
commit 2e6603cc2e
16 changed files with 174 additions and 149 deletions

View File

@@ -56,38 +56,17 @@ from jedi.evaluate import param
from jedi.evaluate import flow_analysis
from jedi.evaluate import imports
from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, \
GlobalNameFilter, DictFilter
GlobalNameFilter, DictFilter, ContextName
from jedi.evaluate.context import Context
class Context(object):
def __init__(self, evaluator, parent_context=None):
self._evaluator = evaluator
self.parent_context = parent_context
def get_parent_flow_context(self):
return self.parent_context
def get_root_context(self):
context = self
while True:
if context.parent_context is None:
return context
context = context.parent_context
class FlowContext(Context):
def get_parent_flow_context(self):
if 1:
return self.parent_context
class Executed(Context, tree.Base):
class Executed(Context):
"""
An instance is also an executable - because __init__ is called
:param var_args: The param input array, consist of a parser node or a list.
"""
def __init__(self, evaluator, base, var_args=()):
self._evaluator = evaluator
def __init__(self, evaluator, parent_context, base, var_args):
super(Executed, self).__init__(evaluator, parent_context=parent_context)
self.base = base
self.var_args = var_args
@@ -97,25 +76,21 @@ class Executed(Context, tree.Base):
def get_parent_until(self, *args, **kwargs):
return tree.Base.get_parent_until(self, *args, **kwargs)
@common.safe_property
def parent(self):
return self.base.parent
class Instance(use_metaclass(CachedMetaClass, Executed)):
"""
This class is used to evaluate instances.
"""
def __init__(self, evaluator, base, var_args, is_generated=False):
super(Instance, self).__init__(evaluator, base, var_args)
def __init__(self, evaluator, parent_context, base, var_args, is_generated=False):
super(Instance, self).__init__(evaluator, parent_context, base, var_args)
self.decorates = None
# Generated instances are classes that are just generated by self
# (No var_args) used.
self.is_generated = is_generated
self._init_execution = None
if base.name.get_code() in ['list', 'set'] \
and evaluator.BUILTINS == base.get_parent_until():
if base.name.string_name in ['list', 'set'] \
and evaluator.BUILTINS == parent_context.get_root_context():
# compare the module path with the builtin name.
self.var_args = iterable.check_array_instances(evaluator, self)
elif not is_generated:
@@ -157,7 +132,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
func = self.get_subscope_by_name('__init__')
except KeyError:
return None
return FunctionExecution(self._evaluator, func, self.var_args)
return FunctionExecution(self._evaluator, self, func, self.var_args)
def _get_func_self_name(self, func):
"""
@@ -280,8 +255,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
@property
@underscore_memoization
def name(self):
name = self.base.name
return helpers.FakeName(unicode(name), self, name.start_pos)
return ContextName(self, self.base.name)
def __getattr__(self, name):
if name not in ['start_pos', 'end_pos', 'get_imports', 'type',
@@ -400,6 +374,7 @@ def get_instance_el(evaluator, instance, var, is_class_var=False):
in quite a lot of cases, which includes Nodes like ``power``, that need to
know where a self name comes from for example.
"""
return var
if isinstance(var, tree.Name):
parent = get_instance_el(evaluator, instance, var.parent, is_class_var)
return InstanceName(var, parent)
@@ -465,8 +440,7 @@ class InstanceElement(use_metaclass(CachedMetaClass, tree.Base)):
@property
@memoize_default()
def name(self):
name = self.var.name
return helpers.FakeName(unicode(name), self, name.start_pos)
return ContextName(self.var.name, self)
def __iter__(self):
for el in self.var.__iter__():
@@ -519,7 +493,7 @@ class Wrapper(tree.Base):
@underscore_memoization
def name(self):
name = self.base.name
return helpers.FakeName(unicode(name), self, name.start_pos)
return ContextName(self, name)
class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
@@ -574,7 +548,7 @@ class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
return [compiled.create(self._evaluator, object)]
def py__call__(self, params):
return set([Instance(self._evaluator, self, params)])
return set([Instance(self._evaluator, self.parent_context, self, params)])
def py__class__(self):
return compiled.create(self._evaluator, type)
@@ -628,13 +602,13 @@ class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
return "<e%s of %s>" % (type(self).__name__, self.base)
class Function(use_metaclass(CachedMetaClass, Wrapper)):
class Function(use_metaclass(CachedMetaClass, Context, Wrapper)):
"""
Needed because of decorators. Decorators are evaluated here.
"""
def __init__(self, evaluator, func, is_decorated=False):
def __init__(self, evaluator, parent_context, func, is_decorated=False):
""" This should not be called directly """
self._evaluator = evaluator
super(Function, self).__init__(evaluator, parent_context)
self.base = self.base_func = func
self.is_decorated = is_decorated
# A property that is set by the decorator resolution.
@@ -716,7 +690,7 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
if self.base.is_generator():
return set([iterable.Generator(self._evaluator, self, params)])
else:
return FunctionExecution(self._evaluator, self, params).get_return_types()
return FunctionExecution(self._evaluator, self.parent_context, self, params).get_return_types()
@memoize_default()
def py__annotations__(self):
@@ -767,24 +741,24 @@ class FunctionExecution(Executed):
"""
type = 'funcdef'
def __init__(self, evaluator, base, *args, **kwargs):
super(FunctionExecution, self).__init__(evaluator, base, *args, **kwargs)
def __init__(self, evaluator, parent_context, base, var_args):
super(FunctionExecution, self).__init__(evaluator, parent_context, base, var_args)
self._copy_dict = {}
self._original_function = funcdef = base.base_func
self._original_function = funcdef = base
if isinstance(funcdef, mixed.MixedObject):
# The extra information in mixed is not needed anymore. We can just
# unpack it and give it the tree object.
funcdef = funcdef.definition
# Just overwrite the old version. We don't need it anymore.
funcdef = helpers.deep_ast_copy(funcdef, new_elements=self._copy_dict)
for child in funcdef.children:
if child.type not in ('operator', 'keyword'):
#funcdef = helpers.deep_ast_copy(funcdef, new_elements=self._copy_dict)
#for child in funcdef.children:
#if child.type not in ('operator', 'keyword'):
# Not all nodes are properly copied by deep_ast_copy.
child.parent = self
self.children = funcdef.children
self.names_dict = funcdef.names_dict
self._copied_funcdef = funcdef
#child.parent = self
#self.children = funcdef.children
#self.names_dict = funcdef.names_dict
#self._copied_funcdef = funcdef
@memoize_default(default=set())
@recursion.execution_recursion_decorator
@@ -940,6 +914,7 @@ class GlobalName(helpers.FakeName):
We need to mark global names somehow. Otherwise they are just normal
names that are not definitions.
"""
raise NotImplementedError
super(GlobalName, self).__init__(name.value, name.parent,
name.start_pos, is_definition=True)
@@ -1010,7 +985,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, tree.Module, Wrapper)):
@property
@memoize_default()
def name(self):
return helpers.FakeName(unicode(self.base.name), self, (1, 0))
return ContextName(self, self.base.name)
def _get_init_directory(self):
"""
@@ -1101,6 +1076,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, tree.Module, Wrapper)):
if path is not None and path.endswith(os.path.sep + '__init__.py'):
mods = pkgutil.iter_modules([os.path.dirname(path)])
for module_loader, name, is_pkg in mods:
raise NotImplementedError
fake_n = helpers.FakeName(name)
# It's obviously a relative import to the current module.
imp = helpers.FakeImport(fake_n, self, level=1)