mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 14:54:47 +08:00
Merge branch 'names-all-scopes-false-returns-class-fields' of https://github.com/immerrr/jedi
This commit is contained in:
@@ -8,7 +8,7 @@ from contextlib import contextmanager
|
|||||||
from parso.python import tree
|
from parso.python import tree
|
||||||
|
|
||||||
from jedi._compatibility import unicode
|
from jedi._compatibility import unicode
|
||||||
from jedi.parser_utils import get_parent_scope
|
from jedi.parser_utils import get_parent_scope, is_name_of_func_or_class_def
|
||||||
|
|
||||||
|
|
||||||
def is_stdlib_path(path):
|
def is_stdlib_path(path):
|
||||||
@@ -166,13 +166,33 @@ def get_module_names(module, all_scopes):
|
|||||||
Returns a dictionary with name parts as keys and their call paths as
|
Returns a dictionary with name parts as keys and their call paths as
|
||||||
values.
|
values.
|
||||||
"""
|
"""
|
||||||
names = chain.from_iterable(module.get_used_names().values())
|
names = list(chain.from_iterable(module.get_used_names().values()))
|
||||||
if not all_scopes:
|
if not all_scopes:
|
||||||
# We have to filter all the names that don't have the module as a
|
# We have to filter all the names that don't have the module as a
|
||||||
# parent_scope. There's None as a parent, because nodes in the module
|
# parent_scope. There's None as a parent, because nodes in the module
|
||||||
# node have the parent module and not suite as all the others.
|
# node have the parent module and not suite as all the others.
|
||||||
# Therefore it's important to catch that case.
|
# Therefore it's important to catch that case.
|
||||||
names = [n for n in names if get_parent_scope(n) == module]
|
|
||||||
|
def is_module_scope_name(name):
|
||||||
|
parent_scope = get_parent_scope(name)
|
||||||
|
if is_name_of_func_or_class_def(name, parent_scope):
|
||||||
|
# XXX: In syntax tree function- and class-name nodes are immediate children of
|
||||||
|
# their respective class-definition or function-definition nodes. Technically,
|
||||||
|
# get_parent_scope(...) for them should return the parent of the definition node,
|
||||||
|
# because
|
||||||
|
#
|
||||||
|
# def foo(...): pass
|
||||||
|
#
|
||||||
|
# is equivalent to
|
||||||
|
#
|
||||||
|
# foo = lambda(...): None
|
||||||
|
#
|
||||||
|
# but that would be a big change that could break type inference, whereas for now
|
||||||
|
# this discrepancy looks like only a problem for "get_module_names".
|
||||||
|
parent_scope = parent_scope.parent
|
||||||
|
return parent_scope in (module, None)
|
||||||
|
|
||||||
|
names = [n for n in names if is_module_scope_name(n)]
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -238,6 +238,14 @@ def is_scope(node):
|
|||||||
return node.type in ('file_input', 'classdef', 'funcdef', 'lambdef', 'comp_for')
|
return node.type in ('file_input', 'classdef', 'funcdef', 'lambdef', 'comp_for')
|
||||||
|
|
||||||
|
|
||||||
|
def is_name_of_func_or_class_def(name_node, func_or_class_def_node):
|
||||||
|
"""Return True if name_node is the name of the func_or_class_def_node."""
|
||||||
|
return (
|
||||||
|
name_node.parent is func_or_class_def_node and
|
||||||
|
name_node.type == 'name' and
|
||||||
|
func_or_class_def_node.type in ('classdef', 'funcdef'))
|
||||||
|
|
||||||
|
|
||||||
def get_parent_scope(node, include_flows=False):
|
def get_parent_scope(node, include_flows=False):
|
||||||
"""
|
"""
|
||||||
Returns the underlying scope.
|
Returns the underlying scope.
|
||||||
|
|||||||
@@ -79,6 +79,22 @@ class TestDefinedNames(TestCase):
|
|||||||
self.assert_definition_names(subsubdefs, ['L3', 'f'])
|
self.assert_definition_names(subsubdefs, ['L3', 'f'])
|
||||||
self.assert_definition_names(subsubdefs[0].defined_names(), ['f'])
|
self.assert_definition_names(subsubdefs[0].defined_names(), ['f'])
|
||||||
|
|
||||||
|
def test_class_fields_with_all_scopes_false(self):
|
||||||
|
definitions = self.check_defined_names("""
|
||||||
|
from module import f
|
||||||
|
g = f(f)
|
||||||
|
class C:
|
||||||
|
h = g
|
||||||
|
|
||||||
|
def foo(x=a):
|
||||||
|
bar = x
|
||||||
|
return bar
|
||||||
|
""", ['f', 'g', 'C', 'foo'])
|
||||||
|
C_subdefs = definitions[-2].defined_names()
|
||||||
|
foo_subdefs = definitions[-1].defined_names()
|
||||||
|
self.assert_definition_names(C_subdefs, ['h'])
|
||||||
|
self.assert_definition_names(foo_subdefs, ['x', 'bar'])
|
||||||
|
|
||||||
|
|
||||||
def test_follow_imports(environment):
|
def test_follow_imports(environment):
|
||||||
# github issue #344
|
# github issue #344
|
||||||
|
|||||||
Reference in New Issue
Block a user