mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-09 07:14:48 +08:00
Big refactoring: BaseDefinition._definnition changes to BaseDefinition._name, because it's a NamePart now.
This also includes changes to tests and some simplifications like deleting the old name logic of Definition.
This commit is contained in:
@@ -160,15 +160,15 @@ class Script(object):
|
|||||||
# add named params
|
# add named params
|
||||||
for call_sig in self.call_signatures():
|
for call_sig in self.call_signatures():
|
||||||
# Allow protected access, because it's a public API.
|
# Allow protected access, because it's a public API.
|
||||||
module = call_sig._definition.get_parent_until()
|
module = call_sig._name.get_parent_until()
|
||||||
# Compiled modules typically don't allow keyword arguments.
|
# Compiled modules typically don't allow keyword arguments.
|
||||||
if not isinstance(module, compiled.CompiledObject):
|
if not isinstance(module, compiled.CompiledObject):
|
||||||
for p in call_sig.params:
|
for p in call_sig.params:
|
||||||
# Allow access on _definition here, because it's a
|
# Allow access on _definition here, because it's a
|
||||||
# public API and we don't want to make the internal
|
# public API and we don't want to make the internal
|
||||||
# Name object public.
|
# Name object public.
|
||||||
if p._definition.get_definition().stars == 0: # no *args/**kwargs
|
if p._name.get_definition().stars == 0: # no *args/**kwargs
|
||||||
completions.append((p._definition.parent, p))
|
completions.append((p._name.parent, p))
|
||||||
|
|
||||||
if not path and not isinstance(user_stmt, pr.Import):
|
if not path and not isinstance(user_stmt, pr.Import):
|
||||||
# add keywords
|
# add keywords
|
||||||
|
|||||||
@@ -63,23 +63,34 @@ class BaseDefinition(object):
|
|||||||
'_sre.SRE_Pattern': 're.RegexObject',
|
'_sre.SRE_Pattern': 're.RegexObject',
|
||||||
}.items())
|
}.items())
|
||||||
|
|
||||||
def __init__(self, evaluator, definition, start_pos):
|
def __init__(self, evaluator, name, start_pos):
|
||||||
self._evaluator = evaluator
|
self._evaluator = evaluator
|
||||||
self._start_pos = start_pos
|
self._start_pos = start_pos
|
||||||
self._definition = definition
|
self._name = name
|
||||||
"""
|
"""
|
||||||
An instance of :class:`jedi.parsing_representation.Base` subclass.
|
An instance of :class:`jedi.parsing_representation.Base` subclass.
|
||||||
"""
|
"""
|
||||||
self.is_keyword = isinstance(definition, keywords.Keyword)
|
self.is_keyword = isinstance(name, keywords.Keyword)
|
||||||
|
|
||||||
# generate a path to the definition
|
# generate a path to the definition
|
||||||
self._module = definition.get_parent_until()
|
self._module = name.get_parent_until()
|
||||||
if self.in_builtin_module():
|
if self.in_builtin_module():
|
||||||
self.module_path = None
|
self.module_path = None
|
||||||
else:
|
else:
|
||||||
self.module_path = self._module.path
|
self.module_path = self._module.path
|
||||||
"""Shows the file path of a module. e.g. ``/usr/lib/python2.7/os.py``"""
|
"""Shows the file path of a module. e.g. ``/usr/lib/python2.7/os.py``"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""
|
||||||
|
Name of variable/function/class/module.
|
||||||
|
|
||||||
|
For example, for ``x = None`` it returns ``'x'``.
|
||||||
|
|
||||||
|
:rtype: str or None
|
||||||
|
"""
|
||||||
|
return unicode(self._name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def start_pos(self):
|
def start_pos(self):
|
||||||
"""
|
"""
|
||||||
@@ -142,7 +153,7 @@ class BaseDefinition(object):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
# generate the type
|
# generate the type
|
||||||
stripped = self._definition
|
stripped = self._name
|
||||||
if isinstance(stripped, er.InstanceElement):
|
if isinstance(stripped, er.InstanceElement):
|
||||||
stripped = stripped.var
|
stripped = stripped.var
|
||||||
if isinstance(stripped, (pr.Name, pr.NamePart)):
|
if isinstance(stripped, (pr.Name, pr.NamePart)):
|
||||||
@@ -165,8 +176,8 @@ class BaseDefinition(object):
|
|||||||
if x:
|
if x:
|
||||||
path.insert(0, x)
|
path.insert(0, x)
|
||||||
|
|
||||||
if not isinstance(self._definition, keywords.Keyword):
|
if not isinstance(self._name, keywords.Keyword):
|
||||||
par = self._definition.get_definition()
|
par = self._name.get_definition()
|
||||||
while par is not None:
|
while par is not None:
|
||||||
if isinstance(par, pr.Import):
|
if isinstance(par, pr.Import):
|
||||||
insert_nonnone(par.namespace)
|
insert_nonnone(par.namespace)
|
||||||
@@ -246,7 +257,7 @@ class BaseDefinition(object):
|
|||||||
Document for function f.
|
Document for function f.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
definition = self._definition
|
definition = self._name
|
||||||
if isinstance(definition, pr.NamePart):
|
if isinstance(definition, pr.NamePart):
|
||||||
definition = definition.parent.parent
|
definition = definition.parent.parent
|
||||||
if raw:
|
if raw:
|
||||||
@@ -277,7 +288,7 @@ class BaseDefinition(object):
|
|||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
"""A textual description of the object."""
|
"""A textual description of the object."""
|
||||||
return unicode(self._definition)
|
return unicode(self._name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def full_name(self):
|
def full_name(self):
|
||||||
@@ -326,15 +337,15 @@ class BaseDefinition(object):
|
|||||||
if element is name_part:
|
if element is name_part:
|
||||||
return call_path[:i + 1]
|
return call_path[:i + 1]
|
||||||
|
|
||||||
if not isinstance(self._definition, pr.NamePart):
|
if not isinstance(self._name, pr.NamePart):
|
||||||
raise TypeError('Definition is not a NamePart.')
|
raise TypeError('Definition is not a NamePart.')
|
||||||
|
|
||||||
if self.type not in ('statement', 'import'):
|
if self.type not in ('statement', 'import'):
|
||||||
# Functions, classes and modules are already fixed definitions, we
|
# Functions, classes and modules are already fixed definitions, we
|
||||||
# cannot follow them anymore.
|
# cannot follow them anymore.
|
||||||
return [self]
|
return [self]
|
||||||
stmt_or_imp = self._definition.get_parent_until((pr.Statement, pr.Import))
|
stmt_or_imp = self._name.get_parent_until((pr.Statement, pr.Import))
|
||||||
call_path = call_path_for_name_part(stmt_or_imp, self._definition)
|
call_path = call_path_for_name_part(stmt_or_imp, self._name)
|
||||||
names = self._evaluator.goto(stmt_or_imp, call_path)
|
names = self._evaluator.goto(stmt_or_imp, call_path)
|
||||||
return [Definition(self._evaluator, n) for n in names]
|
return [Definition(self._evaluator, n) for n in names]
|
||||||
|
|
||||||
@@ -343,7 +354,7 @@ class BaseDefinition(object):
|
|||||||
"""
|
"""
|
||||||
Follow both statements and imports, as far as possible.
|
Follow both statements and imports, as far as possible.
|
||||||
"""
|
"""
|
||||||
stripped = self._definition
|
stripped = self._name
|
||||||
if isinstance(stripped, (pr.Name, pr.NamePart)):
|
if isinstance(stripped, (pr.Name, pr.NamePart)):
|
||||||
stripped = stripped.get_definition()
|
stripped = stripped.get_definition()
|
||||||
|
|
||||||
@@ -388,10 +399,10 @@ class BaseDefinition(object):
|
|||||||
return [_Param(self._evaluator, p.get_name().names[-1]) for p in params]
|
return [_Param(self._evaluator, p.get_name().names[-1]) for p in params]
|
||||||
|
|
||||||
def parent(self):
|
def parent(self):
|
||||||
if isinstance(self._definition, compiled.CompiledObject):
|
if isinstance(self._name, compiled.CompiledObject):
|
||||||
non_flow = self._definition.parent
|
non_flow = self._name.parent
|
||||||
else:
|
else:
|
||||||
scope = self._definition.get_definition().get_parent_scope()
|
scope = self._name.get_definition().get_parent_scope()
|
||||||
non_flow = scope.get_parent_until(pr.Flow, reverse=True)
|
non_flow = scope.get_parent_until(pr.Flow, reverse=True)
|
||||||
return Definition(self._evaluator, non_flow.name.names[-1])
|
return Definition(self._evaluator, non_flow.name.names[-1])
|
||||||
|
|
||||||
@@ -407,7 +418,6 @@ class Completion(BaseDefinition):
|
|||||||
def __init__(self, evaluator, name, needs_dot, like_name_length, base):
|
def __init__(self, evaluator, name, needs_dot, like_name_length, base):
|
||||||
super(Completion, self).__init__(evaluator, name, name.start_pos)
|
super(Completion, self).__init__(evaluator, name, name.start_pos)
|
||||||
|
|
||||||
self._name = name
|
|
||||||
self._needs_dot = needs_dot
|
self._needs_dot = needs_dot
|
||||||
self._like_name_length = like_name_length
|
self._like_name_length = like_name_length
|
||||||
self._base = base
|
self._base = base
|
||||||
@@ -446,18 +456,6 @@ class Completion(BaseDefinition):
|
|||||||
"""
|
"""
|
||||||
return self._complete(True)
|
return self._complete(True)
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""
|
|
||||||
Similar to :attr:`complete`, but return the whole word, for
|
|
||||||
example::
|
|
||||||
|
|
||||||
isinstan
|
|
||||||
|
|
||||||
would return `isinstance`.
|
|
||||||
"""
|
|
||||||
return unicode(self._name)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name_with_symbols(self):
|
def name_with_symbols(self):
|
||||||
"""
|
"""
|
||||||
@@ -488,7 +486,7 @@ class Completion(BaseDefinition):
|
|||||||
return ''
|
return ''
|
||||||
t = self.type
|
t = self.type
|
||||||
if t == 'statement' or t == 'import':
|
if t == 'statement' or t == 'import':
|
||||||
desc = self._definition.get_definition().get_code(False)
|
desc = self._name.get_definition().get_code(False)
|
||||||
else:
|
else:
|
||||||
desc = '.'.join(unicode(p) for p in self._path())
|
desc = '.'.join(unicode(p) for p in self._path())
|
||||||
|
|
||||||
@@ -506,7 +504,7 @@ class Completion(BaseDefinition):
|
|||||||
the ``foo.docstring(fast=False)`` on every object, because it
|
the ``foo.docstring(fast=False)`` on every object, because it
|
||||||
parses all libraries starting with ``a``.
|
parses all libraries starting with ``a``.
|
||||||
"""
|
"""
|
||||||
definition = self._definition.get_definition()
|
definition = self._name.get_definition()
|
||||||
if isinstance(definition, pr.Import):
|
if isinstance(definition, pr.Import):
|
||||||
i = imports.ImportWrapper(self._evaluator, definition)
|
i = imports.ImportWrapper(self._evaluator, definition)
|
||||||
if len(i.import_path) > 1 or not fast:
|
if len(i.import_path) > 1 or not fast:
|
||||||
@@ -526,7 +524,7 @@ class Completion(BaseDefinition):
|
|||||||
The type of the completion objects. Follows imports. For a further
|
The type of the completion objects. Follows imports. For a further
|
||||||
description, look at :attr:`jedi.api.classes.BaseDefinition.type`.
|
description, look at :attr:`jedi.api.classes.BaseDefinition.type`.
|
||||||
"""
|
"""
|
||||||
definition = self._definition.get_definition()
|
definition = self._name.get_definition()
|
||||||
if isinstance(definition, pr.Import):
|
if isinstance(definition, pr.Import):
|
||||||
i = imports.ImportWrapper(self._evaluator, definition)
|
i = imports.ImportWrapper(self._evaluator, definition)
|
||||||
if len(i.import_path) <= 1:
|
if len(i.import_path) <= 1:
|
||||||
@@ -544,7 +542,7 @@ class Completion(BaseDefinition):
|
|||||||
def _follow_statements_imports(self):
|
def _follow_statements_imports(self):
|
||||||
# imports completion is very complicated and needs to be treated
|
# imports completion is very complicated and needs to be treated
|
||||||
# separately in Completion.
|
# separately in Completion.
|
||||||
definition = self._definition.get_definition()
|
definition = self._name.get_definition()
|
||||||
if definition.isinstance(pr.Import) and definition.alias is None:
|
if definition.isinstance(pr.Import) and definition.alias is None:
|
||||||
i = imports.ImportWrapper(self._evaluator, definition, True)
|
i = imports.ImportWrapper(self._evaluator, definition, True)
|
||||||
import_path = i.import_path + (unicode(self._name),)
|
import_path = i.import_path + (unicode(self._name),)
|
||||||
@@ -577,50 +575,6 @@ class Definition(use_metaclass(CachedMetaClass, BaseDefinition)):
|
|||||||
def __init__(self, evaluator, definition):
|
def __init__(self, evaluator, definition):
|
||||||
super(Definition, self).__init__(evaluator, definition, definition.start_pos)
|
super(Definition, self).__init__(evaluator, definition, definition.start_pos)
|
||||||
|
|
||||||
@property
|
|
||||||
@underscore_memoization
|
|
||||||
def name(self):
|
|
||||||
"""
|
|
||||||
Name of variable/function/class/module.
|
|
||||||
|
|
||||||
For example, for ``x = None`` it returns ``'x'``.
|
|
||||||
|
|
||||||
:rtype: str or None
|
|
||||||
"""
|
|
||||||
d = self._definition
|
|
||||||
if isinstance(d, er.InstanceElement):
|
|
||||||
d = d.var
|
|
||||||
|
|
||||||
if isinstance(d, (compiled.CompiledObject, compiled.CompiledName)):
|
|
||||||
name = d.name
|
|
||||||
elif isinstance(d, pr.Name):
|
|
||||||
name = d.names[-1]
|
|
||||||
elif isinstance(d, iterable.Array):
|
|
||||||
name = d.type
|
|
||||||
elif isinstance(d, (pr.Class, er.Class, er.Instance,
|
|
||||||
er.Function, pr.Function)):
|
|
||||||
name = d.name
|
|
||||||
elif isinstance(d, pr.Module):
|
|
||||||
name = self.module_name
|
|
||||||
elif isinstance(d, pr.Import):
|
|
||||||
try:
|
|
||||||
name = d.get_defined_names()[0].names[-1]
|
|
||||||
except (AttributeError, IndexError):
|
|
||||||
return None
|
|
||||||
elif isinstance(d, pr.Param):
|
|
||||||
name = d.get_name()
|
|
||||||
elif isinstance(d, pr.ExprStmt):
|
|
||||||
try:
|
|
||||||
expression_list = d.assignment_details[0][0]
|
|
||||||
name = expression_list[0].name.names[-1]
|
|
||||||
except IndexError:
|
|
||||||
return None
|
|
||||||
elif isinstance(d, iterable.Generator):
|
|
||||||
return None
|
|
||||||
elif isinstance(d, pr.NamePart):
|
|
||||||
name = d
|
|
||||||
return unicode(name)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
"""
|
"""
|
||||||
@@ -649,7 +603,7 @@ class Definition(use_metaclass(CachedMetaClass, BaseDefinition)):
|
|||||||
'class C'
|
'class C'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
d = self._definition
|
d = self._name
|
||||||
if isinstance(d, er.InstanceElement):
|
if isinstance(d, er.InstanceElement):
|
||||||
d = d.var
|
d = d.var
|
||||||
if isinstance(d, (pr.Name, pr.NamePart)):
|
if isinstance(d, (pr.Name, pr.NamePart)):
|
||||||
@@ -710,17 +664,17 @@ class Definition(use_metaclass(CachedMetaClass, BaseDefinition)):
|
|||||||
Returns True, if defined as a name in a statement, function or class.
|
Returns True, if defined as a name in a statement, function or class.
|
||||||
Returns False, if it's a reference to such a definition.
|
Returns False, if it's a reference to such a definition.
|
||||||
"""
|
"""
|
||||||
if isinstance(self._definition, compiled.CompiledName):
|
if isinstance(self._name, compiled.CompiledName):
|
||||||
return True
|
return True
|
||||||
if not isinstance(self._definition, pr.NamePart):
|
if not isinstance(self._name, pr.NamePart):
|
||||||
# Currently only handle NameParts. Once we have a proper API, this
|
# Currently only handle NameParts. Once we have a proper API, this
|
||||||
# will be the standard anyway.
|
# will be the standard anyway.
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
_def = self._definition.get_parent_until((pr.ExprStmt,
|
_def = self._name.get_parent_until((pr.ExprStmt,
|
||||||
pr.Import, pr.Function, pr.Class, pr.Module))
|
pr.Import, pr.Function, pr.Class, pr.Module))
|
||||||
if isinstance(_def, pr.ExprStmt):
|
if isinstance(_def, pr.ExprStmt):
|
||||||
exp_list = _def.expression_list()
|
exp_list = _def.expression_list()
|
||||||
return not exp_list or self._definition.start_pos < exp_list[0].start_pos
|
return not exp_list or self._name.start_pos < exp_list[0].start_pos
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -743,8 +697,8 @@ class CallSignature(Definition):
|
|||||||
It knows what functions you are currently in. e.g. `isinstance(` would
|
It knows what functions you are currently in. e.g. `isinstance(` would
|
||||||
return the `isinstance` function. without `(` it would return nothing.
|
return the `isinstance` function. without `(` it would return nothing.
|
||||||
"""
|
"""
|
||||||
def __init__(self, evaluator, executable, call, index, key_name):
|
def __init__(self, evaluator, executable_name, call, index, key_name):
|
||||||
super(CallSignature, self).__init__(evaluator, executable)
|
super(CallSignature, self).__init__(evaluator, executable_name)
|
||||||
self._index = index
|
self._index = index
|
||||||
self._key_name = key_name
|
self._key_name = key_name
|
||||||
self._call = call
|
self._call = call
|
||||||
@@ -759,7 +713,7 @@ class CallSignature(Definition):
|
|||||||
for i, param in enumerate(self.params):
|
for i, param in enumerate(self.params):
|
||||||
if self._key_name == param.name:
|
if self._key_name == param.name:
|
||||||
return i
|
return i
|
||||||
if self.params and self.params[-1]._definition.get_definition().stars == 2:
|
if self.params and self.params[-1]._name.get_definition().stars == 2:
|
||||||
return i
|
return i
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
@@ -768,7 +722,7 @@ class CallSignature(Definition):
|
|||||||
|
|
||||||
for i, param in enumerate(self.params):
|
for i, param in enumerate(self.params):
|
||||||
# *args case
|
# *args case
|
||||||
if param._definition.get_definition().stars == 1:
|
if param._name.get_definition().stars == 1:
|
||||||
return i
|
return i
|
||||||
return None
|
return None
|
||||||
return self._index
|
return self._index
|
||||||
@@ -794,7 +748,7 @@ class CallSignature(Definition):
|
|||||||
The name (e.g. 'isinstance') as a string.
|
The name (e.g. 'isinstance') as a string.
|
||||||
"""
|
"""
|
||||||
warnings.warn("Use name instead.", DeprecationWarning)
|
warnings.warn("Use name instead.", DeprecationWarning)
|
||||||
return unicode(self._definition.name)
|
return unicode(self.name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def module(self):
|
def module(self):
|
||||||
@@ -806,7 +760,7 @@ class CallSignature(Definition):
|
|||||||
return self._executable.get_parent_until()
|
return self._executable.get_parent_until()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s index %s>' % (type(self).__name__, self._definition,
|
return '<%s: %s index %s>' % (type(self).__name__, self._name,
|
||||||
self.index)
|
self.index)
|
||||||
|
|
||||||
|
|
||||||
@@ -832,11 +786,11 @@ class _Help(object):
|
|||||||
the future.
|
the future.
|
||||||
"""
|
"""
|
||||||
def __init__(self, definition):
|
def __init__(self, definition):
|
||||||
self._definition = definition
|
self._name = definition
|
||||||
|
|
||||||
def full(self):
|
def full(self):
|
||||||
try:
|
try:
|
||||||
return self._definition.doc
|
return self._name.doc
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return self.raw()
|
return self.raw()
|
||||||
|
|
||||||
@@ -847,6 +801,6 @@ class _Help(object):
|
|||||||
See :attr:`doc` for example.
|
See :attr:`doc` for example.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self._definition.raw_doc
|
return self._name.raw_doc
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return ''
|
return ''
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from jedi import Script
|
|||||||
|
|
||||||
def get_definition_and_evaluator(source):
|
def get_definition_and_evaluator(source):
|
||||||
d = Script(dedent(source)).goto_definitions()[0]
|
d = Script(dedent(source)).goto_definitions()[0]
|
||||||
return d._definition.parent.parent, d._evaluator
|
return d._name.parent.parent, d._evaluator
|
||||||
|
|
||||||
|
|
||||||
def test_function_execution():
|
def test_function_execution():
|
||||||
|
|||||||
@@ -26,4 +26,4 @@ asdfasdf""" + "h"
|
|||||||
def test_tokenizer_with_string_literal_backslash():
|
def test_tokenizer_with_string_literal_backslash():
|
||||||
import jedi
|
import jedi
|
||||||
c = jedi.Script("statement = u'foo\\\n'; statement").goto_definitions()
|
c = jedi.Script("statement = u'foo\\\n'; statement").goto_definitions()
|
||||||
assert c[0]._definition.parent.parent.obj == 'foo'
|
assert c[0]._name.parent.parent.obj == 'foo'
|
||||||
|
|||||||
Reference in New Issue
Block a user