diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 61df5edf..87643644 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -85,7 +85,7 @@ class NameFinder(object): if unicode(self.name_str) != name.get_code(): continue - stmt = name.parent + stmt = name.get_definition() scope = stmt.parent if scope in break_scopes: continue @@ -219,7 +219,7 @@ class NameFinder(object): flow_scope = flow_scope.parent for name in names: - typ = name.parent + typ = name.get_definition() if typ.isinstance(pr.ForFlow): types += self._handle_for_loops(typ) elif isinstance(typ, pr.Param): diff --git a/jedi/evaluate/helpers.py b/jedi/evaluate/helpers.py index ab3688b5..7a66488b 100644 --- a/jedi/evaluate/helpers.py +++ b/jedi/evaluate/helpers.py @@ -309,6 +309,9 @@ class FakeName(pr.Name): names = [(name_or_names, p)] super(FakeName, self).__init__(FakeSubModule, names, p, p, parent) + def get_definition(self): + return self.parent + class LazyName(FakeName): def __init__(self, name, parent_callback): diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index eaf578c7..1a7585dc 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -232,8 +232,9 @@ class ArrayMethod(IterableWrapper): def __getattr__(self, name): # Set access privileges: - if name not in ['parent', 'names', 'start_pos', 'end_pos', 'get_code']: - raise AttributeError('Strange accesson %s: %s.' % (self, name)) + if name not in ['parent', 'names', 'start_pos', 'end_pos', 'get_code', + 'get_definition']: + raise AttributeError('Strange access on %s: %s.' % (self, name)) return getattr(self.name, name) def get_parent_until(self): diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index b8928a0c..6f331638 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -270,6 +270,9 @@ class InstanceElement(use_metaclass(CachedMetaClass, pr.Base)): def get_parent_until(self, *args, **kwargs): return pr.Simple.get_parent_until(self, *args, **kwargs) + def get_definition(self): + return self.get_parent_until((pr.Statement, pr.IsScope, pr.Import)) + def get_decorated_func(self): """ Needed because the InstanceElement should not be stripped """ func = self.var.get_decorated_func() diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index 118c0653..1645e16a 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -39,7 +39,7 @@ import re from inspect import cleandoc from jedi._compatibility import (next, Python3Method, encoding, unicode, - is_py3, u, literal_eval) + is_py3, u, literal_eval, use_metaclass) from jedi import common from jedi import debug from jedi import cache @@ -222,6 +222,15 @@ class Simple(Base): (type(self).__name__, code, self.start_pos[0], self.start_pos[1]) +class IsScopeMeta(type): + def __instancecheck__(self, other): + return other.is_scope() + + +class IsScope(use_metaclass(IsScopeMeta)): + pass + + class Scope(Simple, DocstringMixin): """ Super class for the parser tree, which represents the state of a python @@ -1463,8 +1472,8 @@ class NamePart(object): def get_code(self): return self._string - def get_parent_stmt(self): - return self.parent.parent_stmt() + def get_definition(self): + return self.parent.get_definition() def get_parent_until(self, *args, **kwargs): return self.parent.get_parent_until(*args, **kwargs) @@ -1504,8 +1513,9 @@ class Name(Simple): """ Returns the names in a full string format """ return self._get_code - def get_parent_stmt(self): - return self.get_parent_until(ExprStmt) + def get_definition(self): + # TODO This is way to complicated, simplify this with a new parser. + return self.get_parent_until((Statement, IsScope, Import)) @property def end_pos(self):