Cache used names definition finding per evaluator

This commit is contained in:
Dave Halter
2018-12-14 09:20:42 +01:00
parent b6cb1fb72d
commit d1be92ac80

View File

@@ -11,6 +11,7 @@ from jedi.evaluate import flow_analysis
from jedi.evaluate.base_context import ContextSet, Context from jedi.evaluate.base_context import ContextSet, Context
from jedi.parser_utils import get_parent_scope from jedi.parser_utils import get_parent_scope
from jedi.evaluate.utils import to_list from jedi.evaluate.utils import to_list
from jedi.evaluate.cache import evaluator_function_cache
class AbstractNameDefinition(object): class AbstractNameDefinition(object):
@@ -188,28 +189,44 @@ class NameWrapper(object):
return '%s(%s)' % (self.__class__.__name__, self._wrapped_name) return '%s(%s)' % (self.__class__.__name__, self._wrapped_name)
@evaluator_function_cache()
def _get_definition_names(evaluator, module_node, name_key):
try:
names = module_node.get_used_names()[name_key]
except KeyError:
return []
return [name for name in names if name.is_definition()]
class AbstractUsedNamesFilter(AbstractFilter): class AbstractUsedNamesFilter(AbstractFilter):
name_class = TreeNameDefinition name_class = TreeNameDefinition
def __init__(self, context, parser_scope): def __init__(self, context, parser_scope):
self._parser_scope = parser_scope self._parser_scope = parser_scope
self._used_names = self._parser_scope.get_root_node().get_used_names() self._module_node = self._parser_scope.get_root_node()
self._used_names = self._module_node.get_used_names()
self.context = context self.context = context
def get(self, name): def get(self, name):
try: #print(self, self.context, name, type(self).__name__)
names = self._used_names[name] #import traceback, sys; traceback.print_stack(file=sys.stdout)
except KeyError: return self._convert_names(self._filter(
return [] _get_definition_names(self.context.evaluator, self._module_node, name)
))
return self._convert_names(self._filter(names))
def _convert_names(self, names): def _convert_names(self, names):
return [self.name_class(self.context, name) for name in names] return [self.name_class(self.context, name) for name in names]
def values(self): def values(self):
return self._convert_names(name for name_list in self._used_names.values() evaluator = self.context.evaluator
for name in self._filter(name_list)) module_node = self._module_node
return self._convert_names(
name
for name_key in self._used_names
for name in self._filter(
_get_definition_names(evaluator, module_node, name_key)
)
)
def __repr__(self): def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self.context) return '<%s: %s>' % (self.__class__.__name__, self.context)
@@ -238,8 +255,6 @@ class ParserTreeFilter(AbstractUsedNamesFilter):
return list(self._check_flows(names)) return list(self._check_flows(names))
def _is_name_reachable(self, name): def _is_name_reachable(self, name):
if not name.is_definition():
return False
parent = name.parent parent = name.parent
if parent.type == 'trailer': if parent.type == 'trailer':
return False return False
@@ -288,12 +303,25 @@ class GlobalNameFilter(AbstractUsedNamesFilter):
def __init__(self, context, parser_scope): def __init__(self, context, parser_scope):
super(GlobalNameFilter, self).__init__(context, parser_scope) super(GlobalNameFilter, self).__init__(context, parser_scope)
def get(self, name):
try:
names = self._used_names[name]
except KeyError:
return []
return self._convert_names(self._filter(names))
@to_list @to_list
def _filter(self, names): def _filter(self, names):
for name in names: for name in names:
if name.parent.type == 'global_stmt': if name.parent.type == 'global_stmt':
yield name yield name
def values(self):
return self._convert_names(
name for name_list in self._used_names.values()
for name in self._filter(name_list)
)
class DictFilter(AbstractFilter): class DictFilter(AbstractFilter):
def __init__(self, dct): def __init__(self, dct):