forked from VimPlug/jedi
Start using names_dicts instead of scope_names_generator.
This commit is contained in:
@@ -151,6 +151,9 @@ class CompiledObject(Base):
|
|||||||
def names_dict(self):
|
def names_dict(self):
|
||||||
return LazyNamesDict(self._cls())
|
return LazyNamesDict(self._cls())
|
||||||
|
|
||||||
|
def names_dicts(self):
|
||||||
|
yield self.names_dict
|
||||||
|
|
||||||
def scope_names_generator(self, position=None, add_class_vars=True):
|
def scope_names_generator(self, position=None, add_class_vars=True):
|
||||||
yield self, self.get_defined_names()
|
yield self, self.get_defined_names()
|
||||||
|
|
||||||
|
|||||||
+40
-9
@@ -35,7 +35,8 @@ from jedi.evaluate.cache import memoize_default
|
|||||||
class NameFinder(object):
|
class NameFinder(object):
|
||||||
def __init__(self, evaluator, scope, name_str, position=None):
|
def __init__(self, evaluator, scope, name_str, position=None):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self.scope = scope
|
# Make sure that it's not just a syntax tree node.
|
||||||
|
self.scope = er.wrap(evaluator, scope)
|
||||||
self.name_str = name_str
|
self.name_str = name_str
|
||||||
self.position = position
|
self.position = position
|
||||||
|
|
||||||
@@ -62,21 +63,24 @@ class NameFinder(object):
|
|||||||
|
|
||||||
def scopes(self, search_global=False):
|
def scopes(self, search_global=False):
|
||||||
if search_global:
|
if search_global:
|
||||||
return get_names_of_scope(self._evaluator, self.scope, self.position)
|
return global_names_dict_generator(self._evaluator, self.scope, self.position)
|
||||||
else:
|
else:
|
||||||
return self.scope.scope_names_generator(self.position)
|
return ((n, None) for n in self.scope.names_dicts())
|
||||||
|
|
||||||
def names_dict_lookup(self, scope, position):
|
def names_dict_lookup(self, names_dict, position):
|
||||||
def get_param(el):
|
def get_param(el):
|
||||||
if isinstance(el.parent, pr.Param) or isinstance(el.parent.parent, pr.Param):
|
if isinstance(el.parent, pr.Param) or isinstance(el.parent.parent, pr.Param):
|
||||||
return scope.param_by_name(str(el))
|
return scope.param_by_name(str(el))
|
||||||
return el
|
return el
|
||||||
|
|
||||||
try:
|
try:
|
||||||
names = scope.names_dict[str(self.name_str)]
|
names = names_dict[str(self.name_str)]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
#print(names[0].parent, names[0].get_definition().get_parent_scope())
|
||||||
|
# Just calculate the scope from the first
|
||||||
|
scope = er.wrap(self._evaluator, names[0].get_definition().get_parent_scope())
|
||||||
if isinstance(scope, (pr.CompFor, pr.Lambda)):
|
if isinstance(scope, (pr.CompFor, pr.Lambda)):
|
||||||
return names
|
return names
|
||||||
|
|
||||||
@@ -110,10 +114,10 @@ class NameFinder(object):
|
|||||||
return [get_param(n) for n in last_names]
|
return [get_param(n) for n in last_names]
|
||||||
return last_names
|
return last_names
|
||||||
|
|
||||||
def filter_name(self, scope_names_generator, search_global=False):
|
def filter_name(self, names_dicts, search_global=False):
|
||||||
"""
|
"""
|
||||||
Filters all variables of a scope (which are defined in the
|
Searches names that are defined in a scope (the different
|
||||||
`scope_names_generator`), until the name fits.
|
`names_dicts`), until a name fits.
|
||||||
"""
|
"""
|
||||||
# TODO Now this import is really ugly. Try to remove it.
|
# TODO Now this import is really ugly. Try to remove it.
|
||||||
# It's possibly the only api dependency.
|
# It's possibly the only api dependency.
|
||||||
@@ -124,6 +128,16 @@ class NameFinder(object):
|
|||||||
return [n for n in self.scope.get_magic_function_names()
|
return [n for n in self.scope.get_magic_function_names()
|
||||||
if str(n) == str(self.name_str)]
|
if str(n) == str(self.name_str)]
|
||||||
|
|
||||||
|
scope_names_generator = []
|
||||||
|
name_list_scope = None # TODO delete
|
||||||
|
for names_dict, position in names_dicts:
|
||||||
|
#scope = parent
|
||||||
|
names = self.names_dict_lookup(names_dict, position)
|
||||||
|
if names:
|
||||||
|
break
|
||||||
|
#if isinstance(scope, (pr.Function, er.FunctionExecution)):
|
||||||
|
#position = None
|
||||||
|
|
||||||
# Need checked for now for the whole names_dict approach. That only
|
# Need checked for now for the whole names_dict approach. That only
|
||||||
# works on the first name_list_scope, the second one may be the same
|
# works on the first name_list_scope, the second one may be the same
|
||||||
# with a different name set (e.g. ModuleWrapper yields the module
|
# with a different name set (e.g. ModuleWrapper yields the module
|
||||||
@@ -170,7 +184,7 @@ class NameFinder(object):
|
|||||||
or isinstance(name_list_scope, (pr.Lambda, er.Instance, InterpreterNamespace)) \
|
or isinstance(name_list_scope, (pr.Lambda, er.Instance, InterpreterNamespace)) \
|
||||||
or isinstance(scope, compiled.CompiledObject):
|
or isinstance(scope, compiled.CompiledObject):
|
||||||
# Always reachable.
|
# Always reachable.
|
||||||
print('nons', scope)
|
print('nons', name.get_parent_scope(), self.scope)
|
||||||
names.append(name)
|
names.append(name)
|
||||||
else:
|
else:
|
||||||
print('yess', scope)
|
print('yess', scope)
|
||||||
@@ -465,6 +479,23 @@ def _check_isinstance_type(evaluator, element, search_name):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def global_names_dict_generator(evaluator, scope, position):
|
||||||
|
"""
|
||||||
|
For global lookups.
|
||||||
|
"""
|
||||||
|
while scope is not None:
|
||||||
|
for names_dict in scope.names_dicts():
|
||||||
|
yield names_dict, position
|
||||||
|
if scope.type == 'funcdef':
|
||||||
|
# The position should be reset if the current scope is a function.
|
||||||
|
position = None
|
||||||
|
scope = er.wrap(evaluator, scope.get_parent_scope())
|
||||||
|
|
||||||
|
# Add builtins to the global scope.
|
||||||
|
for names_dict in compiled.builtin.names_dicts():
|
||||||
|
yield names_dict, None
|
||||||
|
|
||||||
|
|
||||||
def get_names_of_scope(evaluator, scope, position=None, star_search=True, include_builtin=True):
|
def get_names_of_scope(evaluator, scope, position=None, star_search=True, include_builtin=True):
|
||||||
"""
|
"""
|
||||||
Get all completions (names) possible for the current scope. The star search
|
Get all completions (names) possible for the current scope. The star search
|
||||||
|
|||||||
@@ -257,6 +257,13 @@ class Array(IterableWrapper):
|
|||||||
for _, names in scope.scope_names_generator():
|
for _, names in scope.scope_names_generator():
|
||||||
yield self, names
|
yield self, names
|
||||||
|
|
||||||
|
@underscore_memoization
|
||||||
|
def names_dicts(self):
|
||||||
|
# `array.type` is a string with the type, e.g. 'list'.
|
||||||
|
scope = self._evaluator.find_types(compiled.builtin, self.type)[0]
|
||||||
|
scope = self._evaluator.execute(scope)[0] # builtins only have one class
|
||||||
|
return scope.names_dicts()
|
||||||
|
|
||||||
@common.safe_property
|
@common.safe_property
|
||||||
def parent(self):
|
def parent(self):
|
||||||
return compiled.builtin
|
return compiled.builtin
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
return helpers.FakeName(unicode(name), self, name.start_pos)
|
return helpers.FakeName(unicode(name), self, name.start_pos)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name not in ['start_pos', 'end_pos', 'get_imports',
|
if name not in ['start_pos', 'end_pos', 'get_imports', 'type',
|
||||||
'doc', 'raw_doc', 'asserts']:
|
'doc', 'raw_doc', 'asserts']:
|
||||||
raise AttributeError("Instance %s: Don't touch this (%s)!"
|
raise AttributeError("Instance %s: Don't touch this (%s)!"
|
||||||
% (self, name))
|
% (self, name))
|
||||||
@@ -355,6 +355,9 @@ class Wrapper(pr.Base):
|
|||||||
def is_class(self):
|
def is_class(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def names_dicts(self):
|
||||||
|
yield self.names_dict
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
def name(self):
|
def name(self):
|
||||||
@@ -440,7 +443,7 @@ class Class(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name not in ['start_pos', 'end_pos', 'parent', 'asserts', 'raw_doc',
|
if name not in ['start_pos', 'end_pos', 'parent', 'asserts', 'raw_doc',
|
||||||
'doc', 'get_imports', 'get_parent_until', 'get_code',
|
'doc', 'get_imports', 'get_parent_until', 'get_code',
|
||||||
'subscopes', 'names_dict']:
|
'subscopes', 'names_dict', 'type']:
|
||||||
raise AttributeError("Don't touch this: %s of %s !" % (name, self))
|
raise AttributeError("Don't touch this: %s of %s !" % (name, self))
|
||||||
return getattr(self.base, name)
|
return getattr(self.base, name)
|
||||||
|
|
||||||
@@ -625,7 +628,11 @@ class FunctionExecution(Executed):
|
|||||||
self.base.names_dict
|
self.base.names_dict
|
||||||
return LazyDict(self.base.names_dict, self._copy_list)
|
return LazyDict(self.base.names_dict, self._copy_list)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def names_dicts(self):
|
||||||
|
self.children
|
||||||
|
yield dict((k, [self._copy_dict[v] for v in values])
|
||||||
|
for k, values in self.base.names_dict.items())
|
||||||
|
|
||||||
@memoize_default(default=NO_DEFAULT)
|
@memoize_default(default=NO_DEFAULT)
|
||||||
def _get_params(self):
|
def _get_params(self):
|
||||||
@@ -669,7 +676,7 @@ class FunctionExecution(Executed):
|
|||||||
return objects
|
return objects
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name not in ['start_pos', 'end_pos', 'imports', '_sub_module']:
|
if name not in ['start_pos', 'end_pos', 'imports', '_sub_module', 'type']:
|
||||||
raise AttributeError('Tried to access %s: %s. Why?' % (name, self))
|
raise AttributeError('Tried to access %s: %s. Why?' % (name, self))
|
||||||
return getattr(self.base, name)
|
return getattr(self.base, name)
|
||||||
|
|
||||||
@@ -740,6 +747,16 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, pr.Module, Wrapper)):
|
|||||||
if sub_modules:
|
if sub_modules:
|
||||||
yield self, self._sub_modules()
|
yield self, self._sub_modules()
|
||||||
|
|
||||||
|
def names_dicts(self):
|
||||||
|
yield self.base.names_dict
|
||||||
|
yield self._module_attributes_dict()
|
||||||
|
|
||||||
|
for star_module in self.star_imports():
|
||||||
|
yield star_module.names_dict
|
||||||
|
|
||||||
|
yield dict((str(n), [n]) for n in self.base.global_names)
|
||||||
|
yield self._sub_modules_dict()
|
||||||
|
|
||||||
@cache_star_import
|
@cache_star_import
|
||||||
@memoize_default([])
|
@memoize_default([])
|
||||||
def star_imports(self):
|
def star_imports(self):
|
||||||
@@ -754,6 +771,15 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, pr.Module, Wrapper)):
|
|||||||
modules += new
|
modules += new
|
||||||
return modules
|
return modules
|
||||||
|
|
||||||
|
@memoize_default()
|
||||||
|
def _module_attributes_dict(self):
|
||||||
|
def parent_callback():
|
||||||
|
return self._evaluator.execute(compiled.create(self._evaluator, str))[0]
|
||||||
|
|
||||||
|
names = ['__file__', '__package__', '__doc__', '__name__']
|
||||||
|
# All the additional module attributes are strings.
|
||||||
|
return dict((n, [helpers.LazyName(n, parent_callback)]) for n in names)
|
||||||
|
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def _module_attributes(self):
|
def _module_attributes(self):
|
||||||
def parent_callback():
|
def parent_callback():
|
||||||
@@ -794,6 +820,32 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, pr.Module, Wrapper)):
|
|||||||
|
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
@memoize_default()
|
||||||
|
def _sub_modules_dict(self):
|
||||||
|
"""
|
||||||
|
Lists modules in the directory of this module (if this module is a
|
||||||
|
package).
|
||||||
|
"""
|
||||||
|
path = self._module.path
|
||||||
|
names = {}
|
||||||
|
if path is not None and path.endswith(os.path.sep + '__init__.py'):
|
||||||
|
mods = pkgutil.iter_modules([os.path.dirname(path)])
|
||||||
|
for module_loader, name, is_pkg in mods:
|
||||||
|
fake_n = helpers.FakeName(name)
|
||||||
|
# It's obviously a relative import to the current module.
|
||||||
|
imp = helpers.FakeImport(fake_n, self, level=1)
|
||||||
|
fake_n.parent = imp
|
||||||
|
names[name] = fake_n
|
||||||
|
|
||||||
|
# TODO add something like this in the future, its cleaner than the
|
||||||
|
# import hacks.
|
||||||
|
# ``os.path`` is a hardcoded exception, because it's a
|
||||||
|
# ``sys.modules`` modification.
|
||||||
|
#if str(self.name) == 'os':
|
||||||
|
# names.append(helpers.FakeName('path', parent=self))
|
||||||
|
|
||||||
|
return names
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return getattr(self._module, name)
|
return getattr(self._module, name)
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -139,7 +139,7 @@ class Base(object):
|
|||||||
Returns the underlying scope.
|
Returns the underlying scope.
|
||||||
"""
|
"""
|
||||||
scope = self.parent
|
scope = self.parent
|
||||||
while scope.parent is not None:
|
while scope is not None:
|
||||||
if include_flows and isinstance(scope, Flow):
|
if include_flows and isinstance(scope, Flow):
|
||||||
return scope
|
return scope
|
||||||
if scope.is_scope():
|
if scope.is_scope():
|
||||||
@@ -623,6 +623,7 @@ class SubModule(Scope, Module):
|
|||||||
"""
|
"""
|
||||||
__slots__ = ('path', 'global_names', 'used_names', '_name',
|
__slots__ = ('path', 'global_names', 'used_names', '_name',
|
||||||
'line_offset', 'use_as_parent', 'error_statement_stacks')
|
'line_offset', 'use_as_parent', 'error_statement_stacks')
|
||||||
|
type = 'file_input'
|
||||||
|
|
||||||
def __init__(self, children):
|
def __init__(self, children):
|
||||||
"""
|
"""
|
||||||
@@ -1259,6 +1260,9 @@ class CompFor(Simple):
|
|||||||
arr.append(name)
|
arr.append(name)
|
||||||
return dct
|
return dct
|
||||||
|
|
||||||
|
def names_dicts(self):
|
||||||
|
yield self.names_dict
|
||||||
|
|
||||||
def get_defined_names(self):
|
def get_defined_names(self):
|
||||||
return _defined_names(self.children[1])
|
return _defined_names(self.children[1])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user