From 5c0b2d7aae65c191e4e80f9fa30f27d7f4def25a Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 14 Oct 2016 18:09:29 +0200 Subject: [PATCH] Fixed a lot of class tests. --- jedi/evaluate/filters.py | 17 +++++++++++------ jedi/evaluate/representation.py | 19 ++++++++++++++----- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/jedi/evaluate/filters.py b/jedi/evaluate/filters.py index b12398a1..68d9b2c8 100644 --- a/jedi/evaluate/filters.py +++ b/jedi/evaluate/filters.py @@ -44,8 +44,8 @@ class AbstractUsedNamesFilter(AbstractFilter): return list(self._filter(names)) def values(self): - names = [name for name_list in self._used_names.values() for name in name_list] - return self._filter(names) + return [name for name_list in self._used_names.values() + for name in self._filter(name_list)] class ParserTreeFilter(AbstractUsedNamesFilter): @@ -127,11 +127,16 @@ def get_global_filters(evaluator, context, until_position): """ Returns all filters in order of priority for name resolution. """ + in_func = False while context is not None: - for filter in context.get_filters(search_global=True, until_position=until_position): - yield filter - if context.type == 'funcdef': - until_position = None + if not (context.type == 'classdef' and in_func): + # Names in methods cannot be resolved within the class. + for filter in context.get_filters(search_global=True, until_position=until_position): + yield filter + if context.type == 'funcdef': + # The position should be reset if the current scope is a function. + until_position = None + in_func = True node = context.get_parent_scope() context = evaluator.wrap(node) diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index 4dc4a9f6..7e9f1b73 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -91,6 +91,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)): # (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(): # compare the module path with the builtin name. @@ -103,7 +104,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)): except KeyError: pass else: - evaluator.execute(method, self.var_args) + self._init_execution = evaluator.execute(method, self.var_args) def is_class(self): return False @@ -129,8 +130,11 @@ class Instance(use_metaclass(CachedMetaClass, Executed)): return None @memoize_default() - def _get_method_execution(self, func): - func = get_instance_el(self._evaluator, self, func, True) + def _get_init_execution(self): + try: + func = self.get_subscope_by_name('__init__') + except KeyError: + return None return FunctionExecution(self._evaluator, func, self.var_args) def _get_func_self_name(self, func): @@ -162,7 +166,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)): # __init__ decorators should generally just be ignored, # because to follow them and their self variables is too # complicated. - sub = self._get_method_execution(sub) + sub = self._get_init_execution() for name_list in sub.names_dict.values(): for name in name_list: if name.value == self_name and name.get_previous_sibling() is None: @@ -321,6 +325,11 @@ class SelfNameFilter(InstanceClassFilter): and len(trailer.children) == 2 \ and trailer.children[0] == '.': if name.is_definition(): + init_execution = self._instance._get_init_execution() + # Hopefully we can somehow change this. + if init_execution is not None and \ + init_execution.start_pos < name.start_pos < init_execution.end_pos: + name = init_execution.name_for_position(name.start_pos) yield get_instance_el(self._evaluator, self._instance, name) @@ -386,7 +395,7 @@ class InstanceElement(use_metaclass(CachedMetaClass, tree.Base)): def parent(self): par = self.var.parent if isinstance(par, Class) and par == self.instance.base \ - or not isinstance(self.instance.base, tree.Class) \ + or not isinstance(self.instance.base, (tree.Class, Class)) \ or isinstance(par, tree.Class) \ and par == self.instance.base.base: par = self.instance