1
0
forked from VimPlug/jedi

Working on __init__.

This commit is contained in:
Dave Halter
2016-11-06 18:28:04 +01:00
parent 82667b85b9
commit afac66d82c
4 changed files with 72 additions and 9 deletions

View File

@@ -515,15 +515,24 @@ class Evaluator(object):
return element return element
def create_context(self, module_context, node): def create_context(self, module_context, node):
def from_scope_node(scope_node): def from_scope_node(scope_node, child_is_funcdef=None):
is_funcdef = scope_node.type == 'funcdef'
parent_context = None parent_context = None
parent_scope = scope_node.get_parent_scope() parent_scope = scope_node.get_parent_scope()
if parent_scope is not None: if parent_scope is not None:
parent_context = from_scope_node(parent_scope) parent_context = from_scope_node(parent_scope, child_is_funcdef=is_funcdef)
# TODO this whole procedure just ignores decorators
if scope_node == module_context.module_node: if scope_node == module_context.module_node:
return module_context return module_context
elif scope_node.type == 'funcdef': elif is_funcdef:
return er.AnonymousFunctionExecution(self, parent_context, scope_node) return er.AnonymousFunctionExecution(self, parent_context, scope_node)
elif scope_node.type == 'classdef':
if child_is_funcdef:
# anonymous instance
raise NotImplementedError
else:
return er.ClassContext(self, scope_node, parent_context)
raise DeprecationWarning raise DeprecationWarning
return self.wrap(scope, parent_context=parent_context) return self.wrap(scope, parent_context=parent_context)

View File

@@ -258,6 +258,13 @@ class CompiledObject(Context):
def get_imports(self): def get_imports(self):
return [] # Builtins don't have imports return [] # Builtins don't have imports
@property
def classdef(self):
"""
This is used to be able to work with compiled fakes.
"""
return self
class CompiledName(AbstractNameDefinition): class CompiledName(AbstractNameDefinition):
def __init__(self, evaluator, parent_context, name): def __init__(self, evaluator, parent_context, name):

View File

@@ -5,6 +5,8 @@ from jedi import debug
from jedi.evaluate import compiled from jedi.evaluate import compiled
from jedi.evaluate.filters import ParserTreeFilter, ContextName, TreeNameDefinition from jedi.evaluate.filters import ParserTreeFilter, ContextName, TreeNameDefinition
from jedi.evaluate.context import Context from jedi.evaluate.context import Context
from jedi.evaluate.cache import memoize_default
from jedi.evaluate import representation as er
class AbstractInstanceContext(Context): class AbstractInstanceContext(Context):
@@ -91,13 +93,13 @@ class AbstractInstanceContext(Context):
if isinstance(cls, compiled.CompiledObject): if isinstance(cls, compiled.CompiledObject):
yield SelfNameFilter(self.evaluator, self, cls, origin_scope) yield SelfNameFilter(self.evaluator, self, cls, origin_scope)
else: else:
yield SelfNameFilter(self.evaluator, self, cls.classdef, origin_scope) yield SelfNameFilter(self.evaluator, self, cls, origin_scope)
for cls in self._class_context.py__mro__(): for cls in self._class_context.py__mro__():
if isinstance(cls, compiled.CompiledObject): if isinstance(cls, compiled.CompiledObject):
yield CompiledInstanceClassFilter(self.evaluator, self, cls) yield CompiledInstanceClassFilter(self.evaluator, self, cls)
else: else:
yield InstanceClassFilter(self.evaluator, self, cls.classdef, origin_scope) yield InstanceClassFilter(self.evaluator, self, cls, origin_scope)
def py__getitem__(self, index): def py__getitem__(self, index):
try: try:
@@ -149,6 +151,31 @@ class TreeInstance(AbstractInstanceContext):
def name(self): def name(self):
return ContextName(self, self._class_context.name) return ContextName(self, self._class_context.name)
@memoize_default()
def create_instance_context(self, class_context, node):
scope = node.get_parent_scope()
if scope == class_context.classdef:
return self
else:
parent_context = self.create_instance_context(class_context, scope)
if scope.type == 'funcdef':
if scope.name.value == '__init__' and parent_context == self:
return er.FunctionExecutionContext(
self.evaluator,
self.parent_context,
scope,
self.var_args
)
else:
return er.AnonymousFunctionExecution(
self.evaluator,
self.parent_context,
scope,
)
else:
raise NotImplementedError
return class_context
class CompiledInstanceClassFilter(compiled.CompiledObjectFilter): class CompiledInstanceClassFilter(compiled.CompiledObjectFilter):
def __init__(self, evaluator, instance, compiled_object): def __init__(self, evaluator, instance, compiled_object):
@@ -190,13 +217,14 @@ class InstanceNameDefinition(TreeNameDefinition):
class InstanceClassFilter(ParserTreeFilter): class InstanceClassFilter(ParserTreeFilter):
name_class = InstanceNameDefinition name_class = InstanceNameDefinition
def __init__(self, evaluator, context, parser_scope, origin_scope): def __init__(self, evaluator, context, class_context, origin_scope):
super(InstanceClassFilter, self).__init__( super(InstanceClassFilter, self).__init__(
evaluator=evaluator, evaluator=evaluator,
context=context, context=context,
parser_scope=parser_scope, parser_scope=class_context.classdef,
origin_scope=origin_scope origin_scope=origin_scope
) )
self._class_context = class_context
def _equals_origin_scope(self): def _equals_origin_scope(self):
node = self._origin_scope node = self._origin_scope
@@ -217,6 +245,9 @@ class InstanceClassFilter(ParserTreeFilter):
def _check_flows(self, names): def _check_flows(self, names):
return names return names
def _convert_names(self, names):
return [LazyInstanceName(self._context, self._class_context, name) for name in names]
class SelfNameFilter(InstanceClassFilter): class SelfNameFilter(InstanceClassFilter):
def _filter(self, names): def _filter(self, names):
@@ -234,9 +265,25 @@ class SelfNameFilter(InstanceClassFilter):
and len(trailer.children) == 2 \ and len(trailer.children) == 2 \
and trailer.children[0] == '.': and trailer.children[0] == '.':
if name.is_definition() and self._access_possible(name): if name.is_definition() and self._access_possible(name):
init_execution = self._context._get_init_execution() yield name
continue
init_execution = self._context.get_init_function()
# Hopefully we can somehow change this. # Hopefully we can somehow change this.
if init_execution is not None and \ if init_execution is not None and \
init_execution.start_pos < name.start_pos < init_execution.end_pos: init_execution.start_pos < name.start_pos < init_execution.end_pos:
name = init_execution.name_for_position(name.start_pos) name = init_execution.name_for_position(name.start_pos)
yield name yield name
class LazyInstanceName(TreeNameDefinition):
"""
This name calculates the parent_context lazily.
"""
def __init__(self, instance, class_context, name):
self._instance = instance
self._class_context = class_context
self.name = name
@property
def parent_context(self):
return self._instance.create_instance_context(self._class_context, self.name)

View File

@@ -59,7 +59,6 @@ from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, \
GlobalNameFilter, DictFilter, ContextName GlobalNameFilter, DictFilter, ContextName
from jedi.evaluate.dynamic import search_params from jedi.evaluate.dynamic import search_params
from jedi.evaluate import context from jedi.evaluate import context
from jedi.evaluate.instance import TreeInstance
class Executed(context.TreeContext): class Executed(context.TreeContext):
@@ -468,6 +467,7 @@ class ClassContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper))
return [context.LazyKnownContext(compiled.create(self.evaluator, object))] return [context.LazyKnownContext(compiled.create(self.evaluator, object))]
def py__call__(self, params): def py__call__(self, params):
from jedi.evaluate.instance import TreeInstance
return set([TreeInstance(self.evaluator, self.parent_context, self, params)]) return set([TreeInstance(self.evaluator, self.parent_context, self, params)])
def py__class__(self): def py__class__(self):