1
0
forked from VimPlug/jedi

Rewrite get_definitions using evaluate.get_names_of_scope

- Definition.names is changed to Definition.name.
- TestGetDefinitions.test_nested_definitions fails.
This commit is contained in:
Takafumi Arakaki
2013-02-23 23:39:45 +01:00
parent 1eccf2f765
commit 3fbe7e9ff4
2 changed files with 44 additions and 53 deletions

View File

@@ -7,9 +7,8 @@ interesting information about completion and goto operations.
import re import re
import os import os
import warnings import warnings
import itertools
from _compatibility import unicode from _compatibility import unicode, reduce
import cache import cache
import dynamic import dynamic
import recursion import recursion
@@ -59,6 +58,9 @@ class BaseDefinition(object):
def __init__(self, definition, start_pos): def __init__(self, definition, start_pos):
self.start_pos = start_pos self.start_pos = start_pos
self.definition = definition self.definition = definition
"""
An instance of :class:`jedi.parsing_representation.Base` subclass.
"""
self.is_keyword = isinstance(definition, keywords.Keyword) self.is_keyword = isinstance(definition, keywords.Keyword)
# generate a path to the definition # generate a path to the definition
@@ -273,44 +275,38 @@ class Definition(BaseDefinition):
super(Definition, self).__init__(definition, definition.start_pos) super(Definition, self).__init__(definition, definition.start_pos)
@property @property
def names(self): def name(self):
""" """
Name of variable/function/class/module. Name of variable/function/class/module.
For example, for ``isinstance`` it returns ``['isinstance']``. For example, for ``x = None`` it returns ``'x'``.
As it is possible to have multiple definition in a statement,
this attribute returns a list of string.
:rtype: list of str :rtype: str or None
""" """
d = self.definition d = self.definition
if isinstance(d, er.InstanceElement): if isinstance(d, er.InstanceElement):
d = d.var d = d.var
if isinstance(d, pr.Name):
d = d.parent
if isinstance(d, er.Array): if isinstance(d, pr.Name):
return [unicode(d.type)] return d.names[-1] if d.names else None
elif isinstance(d, er.Array):
return unicode(d.type)
elif isinstance(d, (pr.Class, er.Class, er.Instance, elif isinstance(d, (pr.Class, er.Class, er.Instance,
er.Function, pr.Function)): er.Function, pr.Function)):
return [unicode(d.name)] return unicode(d.name)
elif isinstance(d, pr.Module): elif isinstance(d, pr.Module):
return [self.module_name] return self.module_name
elif isinstance(d, pr.Import): elif isinstance(d, pr.Import):
def getname(name): try:
try: return d.get_defined_names()[0].names[-1]
return [name.names[-1]] except AttributeError, IndexError:
except AttributeError: return None
return []
return list(itertools.chain(*map(getname, d.get_defined_names())))
elif isinstance(d, pr.Statement): elif isinstance(d, pr.Statement):
def getname(assignment): try:
try: return d.assignment_details[0][1].values[0][0].name.names[-1]
return [assignment[1].values[0][0].name.names[-1]] except IndexError:
except IndexError: return None
return [] return None
return list(itertools.chain(*map(getname, d.assignment_details)))
return []
@property @property
def description(self): def description(self):
@@ -364,7 +360,12 @@ class Definition(BaseDefinition):
:rtype: list of Definition :rtype: list of Definition
""" """
return get_definitions(self.definition) d = self.definition
if isinstance(d, er.InstanceElement):
d = d.var
if isinstance(d, pr.Name):
d = d.parent
return get_definitions(d)
def get_definitions(scope): def get_definitions(scope):
@@ -374,15 +375,10 @@ def get_definitions(scope):
:type scope: Scope :type scope: Scope
:rtype: list of Definition :rtype: list of Definition
""" """
def is_definition(s): tuples = evaluate.get_names_of_scope(
return isinstance(s, (pr.Import, pr.Function, pr.Class)) or \ scope, star_search=False, include_builtin=False)
isinstance(s, pr.Statement) and s.assignment_details names = reduce(lambda x, y: x + y[1], tuples, [])
scopes = [] return list(map(Definition, sorted(names, key=lambda s: s.start_pos)))
scopes.extend(scope.imports)
scopes.extend(scope.statements)
scopes.extend(scope.subscopes)
dscopes = sorted(filter(is_definition, scopes), key=lambda s: s.start_pos)
return list(map(Definition, dscopes))
class RelatedName(BaseDefinition): class RelatedName(BaseDefinition):

View File

@@ -402,28 +402,23 @@ class TestGetDefinitions(TestBase):
pass pass
data = None data = None
""") """)
assert len(definitions) == 4 self.assertEqual([d.name for d in definitions],
assert definitions[0].names == ['module'] ['module', 'Class', 'func', 'data'])
assert definitions[1].names == ['Class']
assert definitions[2].names == ['func']
assert definitions[3].names == ['data']
def test_multiple_assignment(self): def test_multiple_assignment(self):
definitions = api.get_definitions(""" definitions = api.get_definitions("""
x = y = None x = y = None
""") """)
assert len(definitions) == 1 self.assertEqual([d.name for d in definitions],
assert definitions[0].names == ['x', 'y'] ['x', 'y'])
def test_multiple_imports(self): def test_multiple_imports(self):
definitions = api.get_definitions(""" definitions = api.get_definitions("""
from module import a, b from module import a, b
from another_module import * from another_module import *
""") """)
assert len(definitions) == 3 self.assertEqual([d.name for d in definitions],
assert definitions[0].names == ['a'] ['a', 'b'])
assert definitions[1].names == ['b']
assert definitions[2].names == []
def test_nested_definitions(self): def test_nested_definitions(self):
definitions = api.get_definitions(""" definitions = api.get_definitions("""
@@ -433,13 +428,13 @@ class TestGetDefinitions(TestBase):
def g(): def g():
pass pass
""") """)
assert len(definitions) == 1 self.assertEqual([d.name for d in definitions],
assert definitions[0].names == ['Class'] ['Class'])
subdefinitions = definitions[0].get_definitions() subdefinitions = definitions[0].get_definitions()
assert subdefinitions[0].names == ['f'] self.assertEqual([d.name for d in subdefinitions],
assert subdefinitions[1].names == ['g'] ['f', 'g'])
assert subdefinitions[0].full_name == 'Class.f' self.assertEqual([d.full_name for d in subdefinitions],
assert subdefinitions[1].full_name == 'Class.g' ['Class.f', 'Class.g'])
class TestSpeed(TestBase): class TestSpeed(TestBase):