mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 14:54:47 +08:00
Use get_qualified_names for full_name
This commit is contained in:
@@ -6,6 +6,11 @@ Changelog
|
|||||||
0.13.3 (2019-02-24)
|
0.13.3 (2019-02-24)
|
||||||
+++++++++++++++++++
|
+++++++++++++++++++
|
||||||
|
|
||||||
|
- reworked full_name
|
||||||
|
|
||||||
|
0.13.3 (2019-02-24)
|
||||||
|
+++++++++++++++++++
|
||||||
|
|
||||||
- Fixed an issue with embedded Python, see https://github.com/davidhalter/jedi-vim/issues/870
|
- Fixed an issue with embedded Python, see https://github.com/davidhalter/jedi-vim/issues/870
|
||||||
|
|
||||||
0.13.2 (2018-12-15)
|
0.13.2 (2018-12-15)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import warnings
|
|||||||
from parso.python.tree import search_ancestor
|
from parso.python.tree import search_ancestor
|
||||||
|
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi.evaluate.utils import ignored, unite
|
from jedi.evaluate.utils import unite
|
||||||
from jedi.cache import memoize_method
|
from jedi.cache import memoize_method
|
||||||
from jedi.evaluate import imports
|
from jedi.evaluate import imports
|
||||||
from jedi.evaluate import compiled
|
from jedi.evaluate import compiled
|
||||||
@@ -49,8 +49,7 @@ class BaseDefinition(object):
|
|||||||
'_io': 'io',
|
'_io': 'io',
|
||||||
'_functools': 'functools',
|
'_functools': 'functools',
|
||||||
'_sqlite3': 'sqlite3',
|
'_sqlite3': 'sqlite3',
|
||||||
'__builtin__': '',
|
'__builtin__': 'builtins',
|
||||||
'builtins': '',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_tuple_mapping = dict((tuple(k.split('.')), v) for (k, v) in {
|
_tuple_mapping = dict((tuple(k.split('.')), v) for (k, v) in {
|
||||||
@@ -162,46 +161,6 @@ class BaseDefinition(object):
|
|||||||
return context.api_type
|
return context.api_type
|
||||||
return self._name.api_type
|
return self._name.api_type
|
||||||
|
|
||||||
def _path(self):
|
|
||||||
"""The path to a module/class/function definition."""
|
|
||||||
def to_reverse():
|
|
||||||
name = self._name
|
|
||||||
if name.api_type == 'module':
|
|
||||||
try:
|
|
||||||
name = list(name.infer())[0].name
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if name.api_type in 'module':
|
|
||||||
module_contexts = name.infer()
|
|
||||||
if module_contexts:
|
|
||||||
module_context, = module_contexts
|
|
||||||
for n in reversed(module_context.py__name__().split('.')):
|
|
||||||
yield n
|
|
||||||
else:
|
|
||||||
# We don't really know anything about the path here. This
|
|
||||||
# module is just an import that would lead in an
|
|
||||||
# ImportError. So simply return the name.
|
|
||||||
yield name.string_name
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
yield name.string_name
|
|
||||||
|
|
||||||
parent_context = name.parent_context
|
|
||||||
while parent_context is not None:
|
|
||||||
try:
|
|
||||||
method = parent_context.py__name__
|
|
||||||
except AttributeError:
|
|
||||||
try:
|
|
||||||
yield parent_context.name.string_name
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
for name in reversed(method().split('.')):
|
|
||||||
yield name
|
|
||||||
parent_context = parent_context.parent_context
|
|
||||||
return reversed(list(to_reverse()))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def module_name(self):
|
def module_name(self):
|
||||||
"""
|
"""
|
||||||
@@ -301,18 +260,20 @@ class BaseDefinition(object):
|
|||||||
be ``<module 'posixpath' ...>```. However most users find the latter
|
be ``<module 'posixpath' ...>```. However most users find the latter
|
||||||
more practical.
|
more practical.
|
||||||
"""
|
"""
|
||||||
path = list(self._path())
|
if not self._name.is_context_name:
|
||||||
# TODO add further checks, the mapping should only occur on stdlib.
|
return None
|
||||||
if not path:
|
|
||||||
return None # for keywords the path is empty
|
|
||||||
|
|
||||||
with ignored(KeyError):
|
names = self._name.get_qualified_names(include_module_names=True)
|
||||||
path[0] = self._mapping[path[0]]
|
if names is None:
|
||||||
for key, repl in self._tuple_mapping.items():
|
return names
|
||||||
if tuple(path[:len(key)]) == key:
|
|
||||||
path = [repl] + path[len(key):]
|
|
||||||
|
|
||||||
return '.'.join(path if path[0] else path[1:])
|
names = list(names)
|
||||||
|
try:
|
||||||
|
names[0] = self._mapping[names[0]]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return '.'.join(names)
|
||||||
|
|
||||||
def is_stub(self):
|
def is_stub(self):
|
||||||
if not self._name.is_context_name:
|
if not self._name.is_context_name:
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ class Context(HelperContextMixin, BaseContext):
|
|||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
def get_qualified_names(self):
|
def get_qualified_names(self):
|
||||||
# Returns Optional[List[str]]
|
# Returns Optional[Tuple[str, ...]]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def is_stub(self):
|
def is_stub(self):
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ class DirectObjectAccess(object):
|
|||||||
name = try_to_get_name(type(self._obj))
|
name = try_to_get_name(type(self._obj))
|
||||||
if name is None:
|
if name is None:
|
||||||
return ()
|
return ()
|
||||||
return name.split('.')
|
return tuple(name.split('.'))
|
||||||
|
|
||||||
def dir(self):
|
def dir(self):
|
||||||
return list(map(force_unicode, dir(self._obj)))
|
return list(map(force_unicode, dir(self._obj)))
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ class FunctionAndClassBase(TreeContext):
|
|||||||
if n is None:
|
if n is None:
|
||||||
# This means that the parent class lives within a function.
|
# This means that the parent class lives within a function.
|
||||||
return None
|
return None
|
||||||
return n + [self.py__name__()]
|
return n + (self.py__name__(),)
|
||||||
elif self.parent_context.is_module():
|
elif self.parent_context.is_module():
|
||||||
return [self.py__name__()]
|
return (self.py__name__(),)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ class MethodContext(FunctionContext):
|
|||||||
names = self.class_context.get_qualified_names()
|
names = self.class_context.get_qualified_names()
|
||||||
if names is None:
|
if names is None:
|
||||||
return None
|
return None
|
||||||
return names + [self.py__name__()]
|
return names + (self.py__name__(),)
|
||||||
|
|
||||||
|
|
||||||
class FunctionExecutionContext(TreeContext):
|
class FunctionExecutionContext(TreeContext):
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ class AbstractInstanceContext(Context):
|
|||||||
def is_instance(self):
|
def is_instance(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_qualified_names(self):
|
||||||
|
return self.class_context.get_qualified_names()
|
||||||
|
|
||||||
def get_annotated_class_object(self):
|
def get_annotated_class_object(self):
|
||||||
return self.class_context # This is the default.
|
return self.class_context # This is the default.
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ class ModuleMixin(SubModuleDictMixin):
|
|||||||
it's reachable and not `None`. With this information we can add
|
it's reachable and not `None`. With this information we can add
|
||||||
qualified names on top for all context children.
|
qualified names on top for all context children.
|
||||||
"""
|
"""
|
||||||
return []
|
return ()
|
||||||
|
|
||||||
|
|
||||||
class ModuleContext(ModuleMixin, TreeContext):
|
class ModuleContext(ModuleMixin, TreeContext):
|
||||||
@@ -182,7 +182,7 @@ class ModuleContext(ModuleMixin, TreeContext):
|
|||||||
self._path = None
|
self._path = None
|
||||||
else:
|
else:
|
||||||
self._path = file_io.path
|
self._path = file_io.path
|
||||||
self.string_names = string_names
|
self.string_names = string_names # Optional[Tuple[str, ...]]
|
||||||
self.code_lines = code_lines
|
self.code_lines = code_lines
|
||||||
self.is_package = is_package
|
self.is_package = is_package
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class AbstractNameDefinition(object):
|
|||||||
return {self}
|
return {self}
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_qualified_names(self):
|
def get_qualified_names(self, include_module_names=False):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_root_context(self):
|
def get_root_context(self):
|
||||||
@@ -53,11 +53,21 @@ class AbstractTreeName(AbstractNameDefinition):
|
|||||||
self.parent_context = parent_context
|
self.parent_context = parent_context
|
||||||
self.tree_name = tree_name
|
self.tree_name = tree_name
|
||||||
|
|
||||||
def get_qualified_names(self):
|
def get_qualified_names(self, include_module_names=False):
|
||||||
|
import_node = search_ancestor(self.tree_name, 'import_name', 'import_from')
|
||||||
|
if import_node is not None:
|
||||||
|
return tuple(n.value for n in import_node.get_path_for_name(self.tree_name))
|
||||||
|
|
||||||
parent_names = self.parent_context.get_qualified_names()
|
parent_names = self.parent_context.get_qualified_names()
|
||||||
if parent_names is None:
|
if parent_names is None:
|
||||||
return None
|
return None
|
||||||
return parent_names + [self.tree_name.value]
|
parent_names += (self.tree_name.value,)
|
||||||
|
if include_module_names:
|
||||||
|
module_names = self.get_root_context().string_names
|
||||||
|
if module_names is None:
|
||||||
|
return None
|
||||||
|
return module_names + parent_names
|
||||||
|
return parent_names
|
||||||
|
|
||||||
def goto(self):
|
def goto(self):
|
||||||
return self.parent_context.evaluator.goto(self.parent_context, self.tree_name)
|
return self.parent_context.evaluator.goto(self.parent_context, self.tree_name)
|
||||||
@@ -79,8 +89,15 @@ class ContextNameMixin(object):
|
|||||||
def infer(self):
|
def infer(self):
|
||||||
return ContextSet([self._context])
|
return ContextSet([self._context])
|
||||||
|
|
||||||
def get_qualified_names(self):
|
def get_qualified_names(self, include_module_names=False):
|
||||||
return self._context.get_qualified_names()
|
qualified_names = self._context.get_qualified_names()
|
||||||
|
if qualified_names is None or not include_module_names:
|
||||||
|
return qualified_names
|
||||||
|
|
||||||
|
module_names = self.get_root_context().string_names
|
||||||
|
if module_names is None:
|
||||||
|
return None
|
||||||
|
return module_names + qualified_names
|
||||||
|
|
||||||
def get_root_context(self):
|
def get_root_context(self):
|
||||||
if self.parent_context is None: # A module
|
if self.parent_context is None: # A module
|
||||||
@@ -185,8 +202,16 @@ class ImportName(AbstractNameDefinition):
|
|||||||
self._from_module_context = parent_context
|
self._from_module_context = parent_context
|
||||||
self.string_name = string_name
|
self.string_name = string_name
|
||||||
|
|
||||||
def get_qualified_names(self):
|
def get_qualified_names(self, include_module_names=False):
|
||||||
return []
|
if include_module_names:
|
||||||
|
if self._level:
|
||||||
|
assert self._level == 1, "Everything else is not supported for now"
|
||||||
|
module_names = self._from_module_context.string_names
|
||||||
|
if module_names is None:
|
||||||
|
return module_names
|
||||||
|
return module_names + (self.string_name,)
|
||||||
|
return self.string_name
|
||||||
|
return ()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent_context(self):
|
def parent_context(self):
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class MixinTestFullName(object):
|
|||||||
self.check('import os; os.path.join', 'os.path.join')
|
self.check('import os; os.path.join', 'os.path.join')
|
||||||
|
|
||||||
def test_builtin(self):
|
def test_builtin(self):
|
||||||
self.check('TypeError', 'TypeError')
|
self.check('TypeError', 'builtins.TypeError')
|
||||||
|
|
||||||
|
|
||||||
class TestFullNameWithGotoDefinitions(MixinTestFullName, TestCase):
|
class TestFullNameWithGotoDefinitions(MixinTestFullName, TestCase):
|
||||||
|
|||||||
Reference in New Issue
Block a user