forked from VimPlug/jedi
Add a filter for global names.
This commit is contained in:
@@ -6,14 +6,15 @@ from abc import abstractmethod
|
|||||||
|
|
||||||
from jedi.parser.tree import search_ancestor
|
from jedi.parser.tree import search_ancestor
|
||||||
from jedi.evaluate import flow_analysis
|
from jedi.evaluate import flow_analysis
|
||||||
|
from jedi.common import to_list
|
||||||
|
|
||||||
|
|
||||||
class AbstractFilter(object):
|
class AbstractFilter(object):
|
||||||
|
_until_position = None
|
||||||
|
|
||||||
def __init__(self, origin_scope=None):
|
def __init__(self, origin_scope=None):
|
||||||
self._origin_scope = origin_scope
|
self._origin_scope = origin_scope
|
||||||
|
|
||||||
_until_position = None
|
|
||||||
|
|
||||||
def _filter(self, names):
|
def _filter(self, names):
|
||||||
if self._until_position is not None:
|
if self._until_position is not None:
|
||||||
return [n for n in names if n.start_pos < self._until_position]
|
return [n for n in names if n.start_pos < self._until_position]
|
||||||
@@ -21,32 +22,46 @@ class AbstractFilter(object):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get(self, name):
|
def get(self, name):
|
||||||
pass
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def values(self):
|
def values(self):
|
||||||
pass
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class ParserTreeFilter(AbstractFilter):
|
class AbstractUsedNamesFilter(AbstractFilter):
|
||||||
def __init__(self, parser_scope, until_position=None, origin_scope=None):
|
def __init__(self, parser_scope, origin_scope=None):
|
||||||
super(ParserTreeFilter, self).__init__(origin_scope)
|
super(AbstractUsedNamesFilter, self).__init__(origin_scope)
|
||||||
self._parser_scope = parser_scope
|
self._parser_scope = parser_scope
|
||||||
self._used_names = self._parser_scope.get_root_node().used_names
|
self._used_names = self._parser_scope.get_root_node().used_names
|
||||||
|
|
||||||
|
def get(self, name):
|
||||||
|
try:
|
||||||
|
names = self._used_names[str(name)]
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return list(self._filter(names))
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
return self._filter(self._used_names.values())
|
||||||
|
|
||||||
|
|
||||||
|
class ParserTreeFilter(AbstractUsedNamesFilter):
|
||||||
|
def __init__(self, evaluator, parser_scope, until_position=None, origin_scope=None):
|
||||||
|
super(ParserTreeFilter, self).__init__(parser_scope, origin_scope)
|
||||||
self._until_position = until_position
|
self._until_position = until_position
|
||||||
self._origin_scope = origin_scope
|
self._evaluator = evaluator
|
||||||
|
|
||||||
def _filter(self, names):
|
def _filter(self, names):
|
||||||
names = super(ParserTreeFilter, self)._filter(names)
|
names = super(ParserTreeFilter, self)._filter(names)
|
||||||
names = [n for n in names if n.is_definition()]
|
names = [n for n in names if n.is_definition()]
|
||||||
names = [n for n in names if n.parent.get_parent_scope() == self._parser_scope]
|
names = [n for n in names if n.parent.get_parent_scope() == self._parser_scope]
|
||||||
|
|
||||||
return list(self._check_flows(sorted(names, key=lambda name: name.start_pos)))
|
return list(self._check_flows(names))
|
||||||
|
|
||||||
def _check_flows(self, names):
|
def _check_flows(self, names):
|
||||||
for name in names:
|
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):
|
||||||
yield name
|
|
||||||
continue
|
|
||||||
stmt = name.get_definition()
|
stmt = name.get_definition()
|
||||||
name_scope = self._evaluator.wrap(stmt.get_parent_scope())
|
name_scope = self._evaluator.wrap(stmt.get_parent_scope())
|
||||||
check = flow_analysis.break_check(self._evaluator, name_scope,
|
check = flow_analysis.break_check(self._evaluator, name_scope,
|
||||||
@@ -57,22 +72,12 @@ class ParserTreeFilter(AbstractFilter):
|
|||||||
if check is flow_analysis.REACHABLE:
|
if check is flow_analysis.REACHABLE:
|
||||||
break
|
break
|
||||||
|
|
||||||
def get(self, name):
|
|
||||||
try:
|
|
||||||
names = self._used_names[str(name)]
|
|
||||||
except KeyError:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return self._filter(names)
|
|
||||||
|
|
||||||
def values(self):
|
|
||||||
return self._filter(self._used_names.values())
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionExecutionFilter(ParserTreeFilter):
|
class FunctionExecutionFilter(ParserTreeFilter):
|
||||||
def __init__(self, parser_scope, executed_function, param_by_name,
|
def __init__(self, evaluator, parser_scope, executed_function, param_by_name,
|
||||||
until_position=None, origin_scope=None):
|
until_position=None, origin_scope=None):
|
||||||
super(FunctionExecutionFilter, self).__init__(
|
super(FunctionExecutionFilter, self).__init__(
|
||||||
|
evaluator,
|
||||||
parser_scope,
|
parser_scope,
|
||||||
until_position,
|
until_position,
|
||||||
origin_scope
|
origin_scope
|
||||||
@@ -89,6 +94,17 @@ class FunctionExecutionFilter(ParserTreeFilter):
|
|||||||
return names
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalNameFilter(AbstractUsedNamesFilter):
|
||||||
|
def __init__(self, parser_scope, origin_scope=None):
|
||||||
|
super(GlobalNameFilter, self).__init__(parser_scope)
|
||||||
|
|
||||||
|
@to_list
|
||||||
|
def _filter(self, names):
|
||||||
|
for name in names:
|
||||||
|
if name.parent.type == 'global_stmt':
|
||||||
|
yield name
|
||||||
|
|
||||||
|
|
||||||
def get_global_filters(evaluator, context, until_position):
|
def get_global_filters(evaluator, context, until_position):
|
||||||
"""
|
"""
|
||||||
Returns all filters in order of priority for name resolution.
|
Returns all filters in order of priority for name resolution.
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ def _name_to_types(evaluator, name, scope):
|
|||||||
elif typ.type == 'global_stmt':
|
elif typ.type == 'global_stmt':
|
||||||
for s in _get_global_stmt_scopes(evaluator, typ, name):
|
for s in _get_global_stmt_scopes(evaluator, typ, name):
|
||||||
finder = NameFinder(evaluator, s, str(name))
|
finder = NameFinder(evaluator, s, str(name))
|
||||||
names_dicts = finder.scopes(search_global=True)
|
names_dicts = finder.get_filters(search_global=True)
|
||||||
# For global_stmt lookups, we only need the first possible scope,
|
# For global_stmt lookups, we only need the first possible scope,
|
||||||
# which means the function itself.
|
# which means the function itself.
|
||||||
names_dicts = [next(names_dicts)]
|
names_dicts = [next(names_dicts)]
|
||||||
|
|||||||
@@ -55,7 +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, FunctionExecutionFilter
|
from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, GlobalNameFilter
|
||||||
|
|
||||||
|
|
||||||
class Executed(tree.Base):
|
class Executed(tree.Base):
|
||||||
@@ -208,8 +208,12 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
yield LazyInstanceDict(self._evaluator, self, names_dict)
|
yield LazyInstanceDict(self._evaluator, self, names_dict)
|
||||||
|
|
||||||
def get_filters(self, search_global, until_position=None, origin_scope=None):
|
def get_filters(self, search_global, until_position=None, origin_scope=None):
|
||||||
#for s in self.base.py__mro__():
|
for cls in self.base.py__mro__():
|
||||||
#yield self._self_names_dict()
|
if isinstance(cls, compiled.CompiledObject):
|
||||||
|
yield SelfNameFilter(self._evaluator, self, cls, origin_scope)
|
||||||
|
else:
|
||||||
|
yield SelfNameFilter(self._evaluator, self, cls.base, origin_scope)
|
||||||
|
|
||||||
for cls in self.base.py__mro__():
|
for cls in self.base.py__mro__():
|
||||||
if isinstance(cls, compiled.CompiledObject):
|
if isinstance(cls, compiled.CompiledObject):
|
||||||
yield CompiledInstanceClassFilter(self._evaluator, self, cls, origin_scope)
|
yield CompiledInstanceClassFilter(self._evaluator, self, cls, origin_scope)
|
||||||
@@ -286,10 +290,10 @@ class CompiledInstanceClassFilter(compiled.CompiledObjectFilter):
|
|||||||
class InstanceClassFilter(ParserTreeFilter):
|
class InstanceClassFilter(ParserTreeFilter):
|
||||||
def __init__(self, evaluator, instance, parser_scope, origin_scope):
|
def __init__(self, evaluator, instance, parser_scope, origin_scope):
|
||||||
super(InstanceClassFilter, self).__init__(
|
super(InstanceClassFilter, self).__init__(
|
||||||
parser_scope,
|
evaluator=evaluator,
|
||||||
|
parser_scope=parser_scope,
|
||||||
origin_scope=origin_scope
|
origin_scope=origin_scope
|
||||||
)
|
)
|
||||||
self._evaluator = evaluator
|
|
||||||
self._instance = instance
|
self._instance = instance
|
||||||
|
|
||||||
def _filter(self, names):
|
def _filter(self, names):
|
||||||
@@ -298,6 +302,21 @@ class InstanceClassFilter(ParserTreeFilter):
|
|||||||
for name in names]
|
for name in names]
|
||||||
|
|
||||||
|
|
||||||
|
class SelfNameFilter(InstanceClassFilter):
|
||||||
|
def _filter(self, names):
|
||||||
|
names = self._filter_self_names(names)
|
||||||
|
return list(self._check_flows(names))
|
||||||
|
|
||||||
|
def _filter_self_names(self, names):
|
||||||
|
for name in names:
|
||||||
|
trailer = name.parent
|
||||||
|
if tree.is_node(trailer, 'trailer') \
|
||||||
|
and len(trailer.children) == 2 \
|
||||||
|
and trailer.children[0] == '.':
|
||||||
|
if name.is_definition():
|
||||||
|
yield get_instance_el(self._evaluator, self._instance, name)
|
||||||
|
|
||||||
|
|
||||||
class LazyInstanceDict(object):
|
class LazyInstanceDict(object):
|
||||||
def __init__(self, evaluator, instance, dct):
|
def __init__(self, evaluator, instance, dct):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
@@ -360,6 +379,7 @@ class InstanceElement(use_metaclass(CachedMetaClass, tree.Base)):
|
|||||||
def parent(self):
|
def parent(self):
|
||||||
par = self.var.parent
|
par = self.var.parent
|
||||||
if isinstance(par, Class) and par == self.instance.base \
|
if isinstance(par, Class) and par == self.instance.base \
|
||||||
|
or not isinstance(self.instance.base, tree.Class) \
|
||||||
or isinstance(par, tree.Class) \
|
or isinstance(par, tree.Class) \
|
||||||
and par == self.instance.base.base:
|
and par == self.instance.base.base:
|
||||||
par = self.instance
|
par = self.instance
|
||||||
@@ -529,13 +549,13 @@ class Class(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
|
|
||||||
def get_filters(self, search_global, until_position=None, is_instance=False):
|
def get_filters(self, search_global, until_position=None, is_instance=False):
|
||||||
if search_global:
|
if search_global:
|
||||||
yield ParserTreeFilter(self.base, until_position)
|
yield ParserTreeFilter(self._evaluator, self.base, until_position)
|
||||||
else:
|
else:
|
||||||
for scope in self.py__mro__():
|
for scope in self.py__mro__():
|
||||||
if isinstance(scope, compiled.CompiledObject):
|
if isinstance(scope, compiled.CompiledObject):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
else:
|
else:
|
||||||
yield ParserTreeFilter(self.base)
|
yield ParserTreeFilter(self._evaluator, self.base)
|
||||||
|
|
||||||
def is_class(self):
|
def is_class(self):
|
||||||
return True
|
return True
|
||||||
@@ -635,7 +655,7 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
|
|
||||||
def get_filters(self, search_global, until_position=None):
|
def get_filters(self, search_global, until_position=None):
|
||||||
if search_global:
|
if search_global:
|
||||||
yield ParserTreeFilter(self.base, until_position)
|
yield ParserTreeFilter(self._evaluator, self.base, until_position)
|
||||||
else:
|
else:
|
||||||
scope = self.py__class__()
|
scope = self.py__class__()
|
||||||
for filter in scope.get_filters(search_global=False):
|
for filter in scope.get_filters(search_global=False):
|
||||||
@@ -813,7 +833,7 @@ class FunctionExecution(Executed):
|
|||||||
del evaluator.predefined_if_name_dict_dict[for_stmt]
|
del evaluator.predefined_if_name_dict_dict[for_stmt]
|
||||||
|
|
||||||
def get_filters(self, search_global, until_position=None):
|
def get_filters(self, search_global, until_position=None):
|
||||||
yield FunctionExecutionFilter(self._original_function,
|
yield FunctionExecutionFilter(self._evaluator, self._original_function,
|
||||||
self._copied_funcdef,
|
self._copied_funcdef,
|
||||||
self.param_by_name,
|
self.param_by_name,
|
||||||
until_position)
|
until_position)
|
||||||
@@ -890,7 +910,8 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, tree.Module, Wrapper)):
|
|||||||
yield self._sub_modules_dict()
|
yield self._sub_modules_dict()
|
||||||
|
|
||||||
def get_filters(self, search_global, until_position=None):
|
def get_filters(self, search_global, until_position=None):
|
||||||
yield ParserTreeFilter(self._module, until_position)
|
yield ParserTreeFilter(self._evaluator, self._module, until_position)
|
||||||
|
yield GlobalNameFilter(self._module)
|
||||||
# TODO
|
# TODO
|
||||||
'''
|
'''
|
||||||
yield self._module_attributes_dict()
|
yield self._module_attributes_dict()
|
||||||
|
|||||||
Reference in New Issue
Block a user