mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 22:44:27 +08:00
Improve api class tests.
This commit is contained in:
@@ -148,6 +148,18 @@ class BaseDefinition(object):
|
||||
'function'
|
||||
|
||||
"""
|
||||
tree_name = self._name.tree_name
|
||||
resolve = False
|
||||
if tree_name is not None:
|
||||
# TODO move this to their respective names.
|
||||
definition = tree_name.get_definition()
|
||||
if definition.type == 'import_from' and \
|
||||
tree_name in definition.get_defined_names():
|
||||
resolve = True
|
||||
|
||||
if isinstance(self._name, imports.SubModuleName) or resolve:
|
||||
for context in self._name.infer():
|
||||
return context.api_type
|
||||
return self._name.api_type
|
||||
|
||||
def _path(self):
|
||||
@@ -353,7 +365,15 @@ class BaseDefinition(object):
|
||||
return [_Param(self._evaluator, n) for n in get_param_names(context)]
|
||||
|
||||
def parent(self):
|
||||
return Definition(self._evaluator, self._name.parent_context.name)
|
||||
context = self._name.parent_context
|
||||
if context is None:
|
||||
return None
|
||||
|
||||
if isinstance(context, er.FunctionExecutionContext):
|
||||
# TODO the function context should be a part of the function
|
||||
# execution context.
|
||||
context = er.FunctionContext(self._evaluator, context.parent_context, context.funcdef)
|
||||
return Definition(self._evaluator, context.name)
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s %s>" % (type(self).__name__, self.description)
|
||||
@@ -475,17 +495,6 @@ class Completion(BaseDefinition):
|
||||
else:
|
||||
return _Help(context).full()
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
"""
|
||||
The type of the completion objects. Follows imports. For a further
|
||||
description, look at :attr:`jedi.api.classes.BaseDefinition.type`.
|
||||
"""
|
||||
if self._name.api_type == 'module':
|
||||
for context in self._name.infer():
|
||||
return context.name.api_type
|
||||
return super(Completion, self).type
|
||||
|
||||
@memoize_method
|
||||
def _follow_statements_imports(self):
|
||||
# imports completion is very complicated and needs to be treated
|
||||
@@ -586,7 +595,7 @@ class Definition(BaseDefinition):
|
||||
d = self._definition
|
||||
|
||||
if isinstance(d, compiled.CompiledObject):
|
||||
typ = d.api_type()
|
||||
typ = d.api_type
|
||||
if typ == 'instance':
|
||||
typ = 'class' # The description should be similar to Py objects.
|
||||
d = typ + ' ' + d.name.get_code()
|
||||
|
||||
@@ -488,6 +488,8 @@ class Evaluator(object):
|
||||
# a name it's something you can "goto" again.
|
||||
return [TreeNameDefinition(context, name)]
|
||||
elif isinstance(par, (tree.Param, tree.Function, tree.Class)) and par.name is name:
|
||||
if par.type in ('funcdef', 'classdef', 'module'):
|
||||
return [context.name]
|
||||
return [TreeNameDefinition(context, name)]
|
||||
elif isinstance(stmt, tree.Import):
|
||||
module_names = imports.ImportWrapper(context, name).follow(is_goto=True)
|
||||
|
||||
@@ -305,10 +305,6 @@ class CompiledContextName(AbstractNameDefinition):
|
||||
self.string_name = name
|
||||
self.parent_context = parent_context
|
||||
|
||||
@property
|
||||
def api_type(self):
|
||||
return self.parent_context.api_type
|
||||
|
||||
def infer(self):
|
||||
return [self.parent_context]
|
||||
|
||||
|
||||
@@ -13,14 +13,13 @@ class AbstractNameDefinition(object):
|
||||
start_pos = None
|
||||
string_name = None
|
||||
parent_context = None
|
||||
tree_name = None
|
||||
|
||||
@abstractmethod
|
||||
def infer(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_root_context(self):
|
||||
if self.parent_context is None:
|
||||
return self
|
||||
return self.parent_context.get_root_context()
|
||||
|
||||
def __repr__(self):
|
||||
@@ -34,8 +33,12 @@ class AbstractNameDefinition(object):
|
||||
def execute_evaluated(self, *args, **kwargs):
|
||||
return unite(context.execute_evaluated(*args, **kwargs) for context in self.infer())
|
||||
|
||||
@property
|
||||
def api_type(self):
|
||||
return self.parent_context.api_type
|
||||
|
||||
class ContextName(AbstractNameDefinition):
|
||||
|
||||
class AbstractTreeName(AbstractNameDefinition):
|
||||
def __init__(self, parent_context, tree_name):
|
||||
self.parent_context = parent_context
|
||||
self.tree_name = tree_name
|
||||
@@ -48,15 +51,26 @@ class ContextName(AbstractNameDefinition):
|
||||
def start_pos(self):
|
||||
return self.tree_name.start_pos
|
||||
|
||||
|
||||
class ContextName(AbstractTreeName):
|
||||
def __init__(self, context, tree_name):
|
||||
super(ContextName, self).__init__(context.parent_context, tree_name)
|
||||
self._context = context
|
||||
|
||||
def infer(self):
|
||||
return [self.parent_context]
|
||||
return [self._context]
|
||||
|
||||
def get_root_context(self):
|
||||
if self.parent_context is None:
|
||||
return self._context
|
||||
return super(ContextName, self).get_root_context()
|
||||
|
||||
@property
|
||||
def api_type(self):
|
||||
return self.parent_context.api_type
|
||||
return self._context.api_type
|
||||
|
||||
|
||||
class TreeNameDefinition(ContextName):
|
||||
class TreeNameDefinition(AbstractTreeName):
|
||||
def get_parent_flow_context(self):
|
||||
return self.parent_context
|
||||
|
||||
@@ -77,7 +91,7 @@ class TreeNameDefinition(ContextName):
|
||||
).get(definition.type, 'statement')
|
||||
|
||||
|
||||
class ParamName(ContextName):
|
||||
class ParamName(AbstractTreeName):
|
||||
api_type = 'param'
|
||||
|
||||
def __init__(self, parent_context, tree_name):
|
||||
|
||||
@@ -166,7 +166,6 @@ def get_init_path(directory_path):
|
||||
|
||||
|
||||
class ImportName(AbstractNameDefinition):
|
||||
api_type = 'module'
|
||||
start_pos = (1, 0)
|
||||
|
||||
def __init__(self, parent_module, string_name):
|
||||
@@ -188,6 +187,9 @@ class ImportName(AbstractNameDefinition):
|
||||
def parent_context(self):
|
||||
return self.parent_module
|
||||
|
||||
@property
|
||||
def api_type(self):
|
||||
return 'module'
|
||||
|
||||
class SubModuleName(ImportName):
|
||||
def infer(self):
|
||||
|
||||
@@ -520,13 +520,16 @@ class BaseNode(Base):
|
||||
def end_pos(self):
|
||||
return self.children[-1].end_pos
|
||||
|
||||
def get_code(self, normalized=False, include_prefix=True):
|
||||
def _get_code_for_children(self, children, normalized, include_prefix):
|
||||
# TODO implement normalized (depending on context).
|
||||
if include_prefix:
|
||||
return "".join(c.get_code(normalized) for c in self.children)
|
||||
return "".join(c.get_code(normalized) for c in children)
|
||||
else:
|
||||
first = self.children[0].get_code(include_prefix=False)
|
||||
return first + "".join(c.get_code(normalized) for c in self.children[1:])
|
||||
first = children[0].get_code(include_prefix=False)
|
||||
return first + "".join(c.get_code(normalized) for c in children[1:])
|
||||
|
||||
def get_code(self, normalized=False, include_prefix=True):
|
||||
return self._get_code_for_children(self.children, normalized, include_prefix)
|
||||
|
||||
@Python3Method
|
||||
def name_for_position(self, position):
|
||||
@@ -1621,6 +1624,12 @@ class Param(BaseNode):
|
||||
default = '' if self.default is None else '=%s' % self.default.get_code()
|
||||
return '<%s: %s>' % (type(self).__name__, str(self._tfpdef()) + default)
|
||||
|
||||
def get_code(self, normalized=False, include_prefix=True):
|
||||
children = self.children
|
||||
if children[-1] == ',':
|
||||
children = children[:-1]
|
||||
return self._get_code_for_children(children, normalized, include_prefix)
|
||||
|
||||
|
||||
class CompFor(BaseNode):
|
||||
type = 'comp_for'
|
||||
|
||||
@@ -164,7 +164,7 @@ def test_param_endings():
|
||||
around them.
|
||||
"""
|
||||
sig = Script('def x(a, b=5, c=""): pass\n x(').call_signatures()[0]
|
||||
assert [p.description for p in sig.params] == ['a', 'b=5', 'c=""']
|
||||
assert [p.description for p in sig.params] == ['param a', 'param b=5', 'param c=""']
|
||||
|
||||
|
||||
class TestIsDefinition(TestCase):
|
||||
@@ -202,9 +202,8 @@ class TestIsDefinition(TestCase):
|
||||
|
||||
class TestParent(TestCase):
|
||||
def _parent(self, source, line=None, column=None):
|
||||
defs = Script(dedent(source), line, column).goto_assignments()
|
||||
assert len(defs) == 1
|
||||
return defs[0].parent()
|
||||
def_, = Script(dedent(source), line, column).goto_assignments()
|
||||
return def_.parent()
|
||||
|
||||
def test_parent(self):
|
||||
parent = self._parent('foo=1\nfoo')
|
||||
@@ -231,7 +230,7 @@ class TestParent(TestCase):
|
||||
def bar(): pass
|
||||
Foo().bar''')).completions()[0].parent()
|
||||
assert parent.name == 'Foo'
|
||||
assert parent.type == 'instance'
|
||||
assert parent.type == 'class'
|
||||
|
||||
parent = Script('str.join').completions()[0].parent()
|
||||
assert parent.name == 'str'
|
||||
@@ -287,27 +286,27 @@ class TestGotoAssignments(TestCase):
|
||||
def test_import(self):
|
||||
nms = names('from json import load', references=True)
|
||||
assert nms[0].name == 'json'
|
||||
assert nms[0].type == 'import'
|
||||
assert nms[0].type == 'module'
|
||||
n = nms[0].goto_assignments()[0]
|
||||
assert n.name == 'json'
|
||||
assert n.type == 'module'
|
||||
|
||||
assert nms[1].name == 'load'
|
||||
assert nms[1].type == 'import'
|
||||
assert nms[1].type == 'function'
|
||||
n = nms[1].goto_assignments()[0]
|
||||
assert n.name == 'load'
|
||||
assert n.type == 'function'
|
||||
|
||||
nms = names('import os; os.path', references=True)
|
||||
assert nms[0].name == 'os'
|
||||
assert nms[0].type == 'import'
|
||||
assert nms[0].type == 'module'
|
||||
n = nms[0].goto_assignments()[0]
|
||||
assert n.name == 'os'
|
||||
assert n.type == 'module'
|
||||
|
||||
n = nms[2].goto_assignments()[0]
|
||||
assert n.name == 'path'
|
||||
assert n.type == 'import'
|
||||
assert n.type == 'module'
|
||||
|
||||
nms = names('import os.path', references=True)
|
||||
n = nms[0].goto_assignments()[0]
|
||||
@@ -322,17 +321,21 @@ class TestGotoAssignments(TestCase):
|
||||
def test_import_alias(self):
|
||||
nms = names('import json as foo', references=True)
|
||||
assert nms[0].name == 'json'
|
||||
assert nms[0].type == 'import'
|
||||
assert nms[0].type == 'module'
|
||||
assert nms[0]._name.tree_name.get_definition().type == 'import_name'
|
||||
n = nms[0].goto_assignments()[0]
|
||||
assert n.name == 'json'
|
||||
assert n.type == 'module'
|
||||
assert n._name.tree_name.get_definition().type == 'file_input'
|
||||
|
||||
assert nms[1].name == 'foo'
|
||||
assert nms[1].type == 'import'
|
||||
assert nms[1].type == 'module'
|
||||
assert nms[1]._name.tree_name.get_definition().type == 'import_name'
|
||||
ass = nms[1].goto_assignments()
|
||||
assert len(ass) == 1
|
||||
assert ass[0].name == 'json'
|
||||
assert ass[0].type == 'module'
|
||||
assert ass[0]._name.tree_name.get_definition().type == 'file_input'
|
||||
|
||||
|
||||
def test_added_equals_to_params():
|
||||
|
||||
Reference in New Issue
Block a user