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 param
|
||||||
from jedi.evaluate import flow_analysis
|
from jedi.evaluate import flow_analysis
|
||||||
from jedi.evaluate import imports
|
from jedi.evaluate import imports
|
||||||
|
from jedi.evaluate.filters import ParserTreeFilter
|
||||||
|
|
||||||
|
|
||||||
class Executed(tree.Base):
|
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):
|
for names_dict in self.base.names_dicts(search_global=False, is_instance=True):
|
||||||
yield LazyInstanceDict(self._evaluator, self, names_dict)
|
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):
|
def py__getitem__(self, index):
|
||||||
try:
|
try:
|
||||||
method = self.get_subscope_by_name('__getitem__')
|
method = self.get_subscope_by_name('__getitem__')
|
||||||
@@ -486,6 +492,16 @@ class Class(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
else:
|
else:
|
||||||
yield scope.names_dict
|
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):
|
def is_class(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -582,6 +598,14 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
for names_dict in scope.names_dicts(False):
|
for names_dict in scope.names_dicts(False):
|
||||||
yield names_dict
|
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
|
@Python3Method
|
||||||
def py__call__(self, params):
|
def py__call__(self, params):
|
||||||
if self.base.is_generator():
|
if self.base.is_generator():
|
||||||
@@ -752,8 +776,8 @@ class FunctionExecution(Executed):
|
|||||||
yield result
|
yield result
|
||||||
del evaluator.predefined_if_name_dict_dict[for_stmt]
|
del evaluator.predefined_if_name_dict_dict[for_stmt]
|
||||||
|
|
||||||
def names_dicts(self, search_global):
|
def get_filters(self, search_global):
|
||||||
yield self.names_dict
|
yield ParserTreeFilter(self.base)
|
||||||
|
|
||||||
@memoize_default(default=NO_DEFAULT)
|
@memoize_default(default=NO_DEFAULT)
|
||||||
def _get_params(self):
|
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 dict((str(n), [GlobalName(n)]) for n in self.base.global_names)
|
||||||
yield self._sub_modules_dict()
|
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
|
# 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
|
# 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.
|
# to push the star imports into Evaluator.modules, if we reenable this.
|
||||||
|
|||||||
@@ -125,6 +125,12 @@ class Base(object):
|
|||||||
def isinstance(self, *cls):
|
def isinstance(self, *cls):
|
||||||
return 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
|
@Python3Method
|
||||||
def get_parent_until(self, classes=(), reverse=False,
|
def get_parent_until(self, classes=(), reverse=False,
|
||||||
include_current=True):
|
include_current=True):
|
||||||
|
|||||||
Reference in New Issue
Block a user