forked from VimPlug/jedi
Autocomplete inherited methods when overriding in child class. Fixes #458.
This commit is contained in:
@@ -157,6 +157,12 @@ class Completion:
|
|||||||
elif nodes and nodes[-1] in ('as', 'def', 'class'):
|
elif nodes and nodes[-1] in ('as', 'def', 'class'):
|
||||||
# No completions for ``with x as foo`` and ``import x as foo``.
|
# No completions for ``with x as foo`` and ``import x as foo``.
|
||||||
# Also true for defining names as a class or function.
|
# Also true for defining names as a class or function.
|
||||||
|
leaf = self._module.get_leaf_for_position(self._position)
|
||||||
|
cls = leaf.get_parent_until(tree.Class)
|
||||||
|
if isinstance(cls, (tree.Class, tree.Function)):
|
||||||
|
# Complete the methods that are defined in the super classes.
|
||||||
|
cls = self._evaluator.wrap(cls)
|
||||||
|
return list(self._get_class_context_completions(cls))
|
||||||
return []
|
return []
|
||||||
elif symbol_names[-1] == 'trailer' and nodes[-1] == '.':
|
elif symbol_names[-1] == 'trailer' and nodes[-1] == '.':
|
||||||
dot = self._module.get_leaf_for_position(self._position)
|
dot = self._module.get_leaf_for_position(self._position)
|
||||||
@@ -229,3 +235,16 @@ class Completion:
|
|||||||
names = [str(n) for n in names]
|
names = [str(n) for n in names]
|
||||||
i = imports.Importer(self._evaluator, names, self._module, level)
|
i = imports.Importer(self._evaluator, names, self._module, level)
|
||||||
return i.completion_names(self._evaluator, only_modules=only_modules)
|
return i.completion_names(self._evaluator, only_modules=only_modules)
|
||||||
|
|
||||||
|
def _get_class_context_completions(self, cls):
|
||||||
|
"""
|
||||||
|
Autocomplete inherited methods when overriding in child class.
|
||||||
|
"""
|
||||||
|
names_dicts = cls.names_dicts(search_global=False, is_instance=True)
|
||||||
|
# The first dict is the dictionary of class itself.
|
||||||
|
next(names_dicts)
|
||||||
|
for names_dict in names_dicts:
|
||||||
|
for values in names_dict.values():
|
||||||
|
for value in values:
|
||||||
|
if value.parent.type == 'funcdef':
|
||||||
|
yield value
|
||||||
|
|||||||
@@ -123,8 +123,8 @@ class CompiledObject(Base):
|
|||||||
return 'classdef'
|
return 'classdef'
|
||||||
elif inspect.ismodule(cls):
|
elif inspect.ismodule(cls):
|
||||||
return 'file_input'
|
return 'file_input'
|
||||||
elif inspect.isbuiltin(cls) or inspect.ismethod(cls) \
|
elif inspect.isbuiltin(cls) or inspect.ismethod(cls) or \
|
||||||
or inspect.ismethoddescriptor(cls):
|
inspect.ismethoddescriptor(cls):
|
||||||
return 'funcdef'
|
return 'funcdef'
|
||||||
|
|
||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
@@ -137,7 +137,8 @@ class CompiledObject(Base):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def _get_class(self):
|
def _get_class(self):
|
||||||
if not fake.is_class_instance(self.obj):
|
if not fake.is_class_instance(self.obj) or \
|
||||||
|
inspect.ismethoddescriptor(self.obj): # slots
|
||||||
return self.obj
|
return self.obj
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
30
test/blabla_test_documentation.py
Normal file
30
test/blabla_test_documentation.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# todo probably remove test_integration_keyword
|
||||||
|
|
||||||
|
def test_keyword_doc():
|
||||||
|
r = list(Script("or", 1, 1).goto_definitions())
|
||||||
|
assert len(r) == 1
|
||||||
|
assert len(r[0].doc) > 100
|
||||||
|
|
||||||
|
r = list(Script("asfdasfd", 1, 1).goto_definitions())
|
||||||
|
assert len(r) == 0
|
||||||
|
|
||||||
|
k = Script("fro").completions()[0]
|
||||||
|
imp_start = '\nThe ``import'
|
||||||
|
assert k.raw_doc.startswith(imp_start)
|
||||||
|
assert k.doc.startswith(imp_start)
|
||||||
|
|
||||||
|
|
||||||
|
def test_blablabla():
|
||||||
|
defs = Script("import").goto_definitions()
|
||||||
|
assert len(defs) == 1 and [1 for d in defs if d.doc]
|
||||||
|
# unrelated to #44
|
||||||
|
|
||||||
|
|
||||||
|
def test_operator_doc(self):
|
||||||
|
r = list(Script("a == b", 1, 3).goto_definitions())
|
||||||
|
assert len(r) == 1
|
||||||
|
assert len(r[0].doc) > 100
|
||||||
|
|
||||||
|
def test_lambda():
|
||||||
|
defs = Script('lambda x: x', column=0).goto_definitions()
|
||||||
|
assert [d.type for d in defs] == ['keyword']
|
||||||
22
test/completion/context.py
Normal file
22
test/completion/context.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
class X():
|
||||||
|
def func(self, foo):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Y(X):
|
||||||
|
def actual_function(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
#? []
|
||||||
|
def actual_function
|
||||||
|
#? ['func']
|
||||||
|
def f
|
||||||
|
|
||||||
|
#? []
|
||||||
|
def __class__
|
||||||
|
|
||||||
|
#? ['__repr__']
|
||||||
|
def __repr__
|
||||||
|
|
||||||
|
#? []
|
||||||
|
def mro
|
||||||
Reference in New Issue
Block a user