Create a better cache to avoid the amount of get_definition/is_definition calls in parso

This commit is contained in:
Dave Halter
2019-06-18 09:15:16 +02:00
parent 38232fe133
commit f2f54f2864

View File

@@ -3,6 +3,7 @@ Filters are objects that you can use to filter names in different scopes. They
are needed for name resolution. are needed for name resolution.
""" """
from abc import abstractmethod from abc import abstractmethod
import weakref
from parso.tree import search_ancestor from parso.tree import search_ancestor
@@ -15,6 +16,7 @@ from jedi.evaluate.utils import to_list
from jedi.evaluate.cache import evaluator_function_cache from jedi.evaluate.cache import evaluator_function_cache
from jedi.evaluate.names import TreeNameDefinition, ParamName, AbstractNameDefinition from jedi.evaluate.names import TreeNameDefinition, ParamName, AbstractNameDefinition
_definition_name_cache = weakref.WeakKeyDictionary()
class AbstractFilter(object): class AbstractFilter(object):
_until_position = None _until_position = None
@@ -49,13 +51,18 @@ class FilterWrapper(object):
return self.wrap_names(self._wrapped_filter.values()) return self.wrap_names(self._wrapped_filter.values())
@evaluator_function_cache() def _get_definition_names(used_names, name_key):
def _get_definition_names(evaluator, module_node, name_key):
try: try:
names = module_node.get_used_names()[name_key] for_module = _definition_name_cache[used_names]
except KeyError: except KeyError:
return [] for_module = _definition_name_cache[used_names] = {}
return [name for name in names if name.is_definition()]
try:
return for_module[name_key]
except KeyError:
names = used_names.get(name_key, ())
result = for_module[name_key] = tuple(name for name in names if name.is_definition())
return result
class AbstractUsedNamesFilter(AbstractFilter): class AbstractUsedNamesFilter(AbstractFilter):
@@ -71,20 +78,18 @@ class AbstractUsedNamesFilter(AbstractFilter):
#print(self, self.context, name, type(self).__name__) #print(self, self.context, name, type(self).__name__)
#import traceback, sys; traceback.print_stack(file=sys.stdout) #import traceback, sys; traceback.print_stack(file=sys.stdout)
return self._convert_names(self._filter( return self._convert_names(self._filter(
_get_definition_names(self.context.evaluator, self._module_node, name) _get_definition_names(self._used_names, name)
)) ))
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):
evaluator = self.context.evaluator
module_node = self._module_node
return self._convert_names( return self._convert_names(
name name
for name_key in self._used_names for name_key in self._used_names
for name in self._filter( for name in self._filter(
_get_definition_names(evaluator, module_node, name_key) _get_definition_names(self._used_names, name_key)
) )
) )