diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 8fd6bb99..08325f59 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -179,7 +179,7 @@ class Evaluator(object): yield builtin_scope, builtin_scope.get_defined_names() def find_types(self, scope, name_str, position=None, search_global=False, - is_goto=False, resolve_decorator=True): + is_goto=False, resolve_decorator=True): """ This is the search function. The most important part to debug. `remove_statements` and `filter_statements` really are the core part of @@ -191,7 +191,7 @@ class Evaluator(object): f = finder.NameFinder(self, scope, name_str, position) scopes = f.scopes(search_global) if is_goto: - return f.filter_name(scopes, is_goto=is_goto) + return f.names_to_types(f.filter_name(scopes, is_goto=is_goto)) return f.find(scopes, resolve_decorator) @memoize_default(default=(), evaluator_is_first_arg=True) @@ -311,7 +311,7 @@ class Evaluator(object): if isinstance(current, pr.NamePart): # This is the first global lookup. scopes = self.find_types(scope, current, position=position, - search_global=True) + search_global=True) else: # for pr.Literal scopes = self.find_types(builtin.Builtin.scope, current.type_as_string()) diff --git a/jedi/evaluate/dynamic.py b/jedi/evaluate/dynamic.py index b2195e32..494f34ce 100644 --- a/jedi/evaluate/dynamic.py +++ b/jedi/evaluate/dynamic.py @@ -57,9 +57,7 @@ from jedi import cache from jedi.common import source_to_unicode from jedi.parser import representation as pr from jedi import settings -from jedi.parser import fast as fast_parser from jedi.evaluate.cache import memoize_default -from jedi.evaluate import iterable # This is something like the sys.path, but only for searching params. It means # that this is the order in which Jedi searches params. @@ -179,8 +177,8 @@ def search_params(evaluator, param): from jedi.evaluate import representation as er for scope in scopes: s = evaluator.find_types(scope, func_name, position=pos, - search_global=not first, - resolve_decorator=False) + search_global=not first, + resolve_decorator=False) c = [getattr(escope, 'base_func', None) or escope.base for escope in s diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 47f63593..c9fcae49 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -204,7 +204,6 @@ class NameFinder(object): Filters all variables of a scope (which are defined in the `scope_generator`), until the name fits. """ - flow_scope = self.scope result = [] # compare func uses the tuple of line/indent = line/column comparison_func = lambda name: (name.start_pos) @@ -235,6 +234,17 @@ class NameFinder(object): if result: break + if not result and isinstance(nscope, er.Instance): + # __getattr__ / __getattribute__ + result += self._check_getattr(nscope) + debug.dbg('sfn filter "%s" in (%s-%s): %s@%s' + % (self.name_str, self.scope, nscope, u(result), self.position)) + return result + + def names_to_types(self, names): + result = names + # This adds additional types + flow_scope = self.scope while flow_scope: # TODO check if result is in scope -> no evaluation necessary n = check_flow_information(self._evaluator, flow_scope, @@ -244,23 +254,14 @@ class NameFinder(object): break flow_scope = flow_scope.parent - if not result and isinstance(nscope, er.Instance): - # __getattr__ / __getattribute__ - result += self._check_getattr(nscope) - debug.dbg('sfn filter "%s" in (%s-%s): %s@%s' - % (self.name_str, self.scope, nscope, u(result), self.position)) return result - def find(self, scopes, resolve_decorator=True): - filtered = self.filter_name(scopes) - return self._resolve_descriptors(self._remove_statements(filtered, -resolve_decorator)) def _check_getattr(self, inst): """Checks for both __getattr__ and __getattribute__ methods""" result = [] - # str is important to lose the NamePart! module = builtin.Builtin.scope + # str is important to lose the NamePart! name = pr.String(module, "'%s'" % self.name_str, (0, 0), (0, 0), inst) with common.ignored(KeyError): result = inst.execute_subscope_by_name('__getattr__', [name]) @@ -273,6 +274,12 @@ resolve_decorator)) result = inst.execute_subscope_by_name('__getattribute__', [name]) return result + def find(self, scopes, resolve_decorator=True): + filtered = self.filter_name(scopes) + filtered = self.names_to_types(filtered) + return self._resolve_descriptors(self._remove_statements(filtered, +resolve_decorator)) + def scopes(self, search_global=False): if search_global: return self._evaluator.get_names_of_scope(self.scope, self.position)