1
0
forked from VimPlug/jedi

Start using filters for name resolution.

This commit is contained in:
Dave Halter
2016-09-30 13:29:20 +02:00
parent a96eec8058
commit 249049b10c
3 changed files with 92 additions and 2 deletions

47
jedi/evaluate/filters.py Normal file
View 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)

View File

@@ -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.

View File

@@ -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):