forked from VimPlug/jedi
Start using filters for name resolution.
This commit is contained in:
47
jedi/evaluate/filters.py
Normal file
47
jedi/evaluate/filters.py
Normal file
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
Filters are objects that you can use to filter names in different scopes. They
|
||||
are needed for name resolution.
|
||||
"""
|
||||
from abc import abstractmethod
|
||||
|
||||
|
||||
def filter_scope_names(names, scope, until_position=None, name=None):
|
||||
return names
|
||||
|
||||
|
||||
class AbstractFilter(object):
|
||||
def _filter(self, names, until_position):
|
||||
if until_position is not None:
|
||||
return [n for n in names if n.start_pos < until_position]
|
||||
return names
|
||||
|
||||
@abstractmethod
|
||||
def get(self, name, until_position=None):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def values(self, until_position=None):
|
||||
pass
|
||||
|
||||
|
||||
class ParserTreeFilter(AbstractFilter):
|
||||
def __init__(self, parser_scope):
|
||||
self._parser_scope = parser_scope
|
||||
self._used_names = self._parser_scope.get_root_node().used_names
|
||||
|
||||
def _filter(self, names, until_position):
|
||||
names = super(ParserTreeFilter, self)._filter(names, until_position)
|
||||
names = [n for n in names if n.is_definition()]
|
||||
names = [n for n in names if n.get_parent_scope() == self._parser_scope]
|
||||
return names
|
||||
|
||||
def get(self, name, until_position=None):
|
||||
try:
|
||||
names = self._used_names[name]
|
||||
except KeyError:
|
||||
return []
|
||||
|
||||
return self._filter(names, until_position)
|
||||
|
||||
def values(self, name, until_position=None):
|
||||
return self._filter(self._used_names.values(), until_position)
|
||||
@@ -55,6 +55,7 @@ from jedi.evaluate import helpers
|
||||
from jedi.evaluate import param
|
||||
from jedi.evaluate import flow_analysis
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate.filters import ParserTreeFilter
|
||||
|
||||
|
||||
class Executed(tree.Base):
|
||||
@@ -206,6 +207,11 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
||||
for names_dict in self.base.names_dicts(search_global=False, is_instance=True):
|
||||
yield LazyInstanceDict(self._evaluator, self, names_dict)
|
||||
|
||||
def get_filters(self, search_global):
|
||||
raise NotImplementedError
|
||||
yield self._self_names_dict()
|
||||
yield ParserTreeFilter(self.base)
|
||||
|
||||
def py__getitem__(self, index):
|
||||
try:
|
||||
method = self.get_subscope_by_name('__getitem__')
|
||||
@@ -486,6 +492,16 @@ class Class(use_metaclass(CachedMetaClass, Wrapper)):
|
||||
else:
|
||||
yield scope.names_dict
|
||||
|
||||
def get_filters(self, search_global):
|
||||
if search_global:
|
||||
yield ParserTreeFilter(self.base)
|
||||
else:
|
||||
for scope in self.py__mro__():
|
||||
if isinstance(scope, compiled.CompiledObject):
|
||||
raise NotImplementedError
|
||||
else:
|
||||
yield ParserTreeFilter(self.base)
|
||||
|
||||
def is_class(self):
|
||||
return True
|
||||
|
||||
@@ -582,6 +598,14 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
||||
for names_dict in scope.names_dicts(False):
|
||||
yield names_dict
|
||||
|
||||
def get_filters(self, search_global):
|
||||
if search_global:
|
||||
yield ParserTreeFilter(self.base)
|
||||
else:
|
||||
scope = self.py__class__()
|
||||
for filter in scope.get_filters(search_global=False):
|
||||
yield filter
|
||||
|
||||
@Python3Method
|
||||
def py__call__(self, params):
|
||||
if self.base.is_generator():
|
||||
@@ -752,8 +776,8 @@ class FunctionExecution(Executed):
|
||||
yield result
|
||||
del evaluator.predefined_if_name_dict_dict[for_stmt]
|
||||
|
||||
def names_dicts(self, search_global):
|
||||
yield self.names_dict
|
||||
def get_filters(self, search_global):
|
||||
yield ParserTreeFilter(self.base)
|
||||
|
||||
@memoize_default(default=NO_DEFAULT)
|
||||
def _get_params(self):
|
||||
@@ -826,6 +850,19 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, tree.Module, Wrapper)):
|
||||
yield dict((str(n), [GlobalName(n)]) for n in self.base.global_names)
|
||||
yield self._sub_modules_dict()
|
||||
|
||||
def get_filters(self, search_global):
|
||||
yield ParserTreeFilter(self._module)
|
||||
# TODO
|
||||
'''
|
||||
yield self._module_attributes_dict()
|
||||
|
||||
for star_module in self.star_imports():
|
||||
yield star_module.names_dict
|
||||
|
||||
yield dict((str(n), [GlobalName(n)]) for n in self.base.global_names)
|
||||
yield self._sub_modules_dict()
|
||||
'''
|
||||
|
||||
# I'm not sure if the star import cache is really that effective anymore
|
||||
# with all the other really fast import caches. Recheck. Also we would need
|
||||
# to push the star imports into Evaluator.modules, if we reenable this.
|
||||
|
||||
@@ -125,6 +125,12 @@ class Base(object):
|
||||
def isinstance(self, *cls):
|
||||
return isinstance(self, cls)
|
||||
|
||||
def get_root_node(self):
|
||||
scope = self
|
||||
while scope.parent is not None:
|
||||
scope = scope.parent
|
||||
return scope
|
||||
|
||||
@Python3Method
|
||||
def get_parent_until(self, classes=(), reverse=False,
|
||||
include_current=True):
|
||||
|
||||
Reference in New Issue
Block a user