forked from VimPlug/jedi
Fix some issues with Definition.parent()
This commit is contained in:
@@ -7,6 +7,8 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
from parso.python.tree import search_ancestor
|
||||||
|
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.inference.utils import unite
|
from jedi.inference.utils import unite
|
||||||
@@ -368,12 +370,28 @@ class BaseDefinition(object):
|
|||||||
if not self._name.is_value_name:
|
if not self._name.is_value_name:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
context = self._name.parent_context
|
if self.type in ('function', 'class', 'param') and self._name.tree_name is not None:
|
||||||
|
# Since the parent_context doesn't really match what the user
|
||||||
|
# thinks of that the parent is here, we do these cases separately.
|
||||||
|
# The reason for this is the following:
|
||||||
|
# - class: Nested classes parent_context is always the
|
||||||
|
# parent_context of the most outer one.
|
||||||
|
# - function: Functions in classes have the module as
|
||||||
|
# parent_context.
|
||||||
|
# - param: The parent_context of a param is not its function but
|
||||||
|
# e.g. the outer class or module.
|
||||||
|
cls_or_func_node = self._name.tree_name.get_definition()
|
||||||
|
parent = search_ancestor(cls_or_func_node, 'funcdef', 'classdef', 'file_input')
|
||||||
|
context = self._get_module_context().create_value(parent).as_context()
|
||||||
|
else:
|
||||||
|
context = self._name.parent_context
|
||||||
|
|
||||||
if context is None:
|
if context is None:
|
||||||
return None
|
return None
|
||||||
while context.name is None:
|
while context.name is None:
|
||||||
# Happens for comprehension contexts
|
# Happens for comprehension contexts
|
||||||
context = context.parent_context
|
context = context.parent_context
|
||||||
|
|
||||||
return Definition(self._inference_state, context.name)
|
return Definition(self._inference_state, context.name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ def test_parent_on_function(Script):
|
|||||||
assert parent.type == 'module'
|
assert parent.type == 'module'
|
||||||
|
|
||||||
|
|
||||||
def test_parent_on_completion(Script):
|
def test_parent_on_completion_and_else(Script):
|
||||||
script = Script(dedent('''\
|
script = Script(dedent('''\
|
||||||
class Foo():
|
class Foo():
|
||||||
def bar(name): name
|
def bar(name): name
|
||||||
@@ -287,14 +287,19 @@ def test_parent_on_completion(Script):
|
|||||||
assert parent.name == 'Foo'
|
assert parent.name == 'Foo'
|
||||||
assert parent.type == 'class'
|
assert parent.type == 'class'
|
||||||
|
|
||||||
param, = script.goto(line=2)
|
param, name, = [d for d in script.names(all_scopes=True, references=True)
|
||||||
parent = param.parent()
|
if d.name == 'name']
|
||||||
|
parent = name.parent()
|
||||||
|
assert parent.name == 'bar'
|
||||||
|
assert parent.type == 'function'
|
||||||
|
parent = name.parent().parent()
|
||||||
assert parent.name == 'Foo'
|
assert parent.name == 'Foo'
|
||||||
assert parent.type == 'class'
|
assert parent.type == 'class'
|
||||||
|
|
||||||
name, = [d for d in script.names(all_scopes=True, references=True)
|
|
||||||
if d.name == 'name' and d.type == 'statement']
|
|
||||||
parent = param.parent()
|
parent = param.parent()
|
||||||
|
assert parent.name == 'bar'
|
||||||
|
assert parent.type == 'function'
|
||||||
|
parent = param.parent().parent()
|
||||||
assert parent.name == 'Foo'
|
assert parent.name == 'Foo'
|
||||||
assert parent.type == 'class'
|
assert parent.type == 'class'
|
||||||
|
|
||||||
@@ -303,6 +308,28 @@ def test_parent_on_completion(Script):
|
|||||||
assert parent.type == 'class'
|
assert parent.type == 'class'
|
||||||
|
|
||||||
|
|
||||||
|
def test_parent_on_closure(Script):
|
||||||
|
script = Script(dedent('''\
|
||||||
|
class Foo():
|
||||||
|
def bar(name):
|
||||||
|
def inner(): foo
|
||||||
|
return inner'''))
|
||||||
|
|
||||||
|
names = script.names(all_scopes=True, references=True)
|
||||||
|
inner_func, inner_reference = filter(lambda d: d.name == 'inner', names)
|
||||||
|
foo, = filter(lambda d: d.name == 'foo', names)
|
||||||
|
|
||||||
|
assert foo.parent().name == 'inner'
|
||||||
|
assert foo.parent().parent().name == 'bar'
|
||||||
|
assert foo.parent().parent().parent().name == 'Foo'
|
||||||
|
assert foo.parent().parent().parent().parent().name == ''
|
||||||
|
|
||||||
|
assert inner_func.parent().name == 'bar'
|
||||||
|
assert inner_func.parent().parent().name == 'Foo'
|
||||||
|
assert inner_reference.parent().name == 'bar'
|
||||||
|
assert inner_reference.parent().parent().name == 'Foo'
|
||||||
|
|
||||||
|
|
||||||
def test_parent_on_comprehension(Script):
|
def test_parent_on_comprehension(Script):
|
||||||
ns = Script('''\
|
ns = Script('''\
|
||||||
def spam():
|
def spam():
|
||||||
|
|||||||
Reference in New Issue
Block a user