mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-20 20:41:13 +08:00
follow_definition function for completions. fixes #54
This commit is contained in:
@@ -5,11 +5,12 @@ import os
|
|||||||
|
|
||||||
import settings
|
import settings
|
||||||
import evaluate
|
import evaluate
|
||||||
|
import imports
|
||||||
import parsing
|
import parsing
|
||||||
import keywords
|
import keywords
|
||||||
|
|
||||||
|
|
||||||
class BaseOutput(object):
|
class BaseDefinition(object):
|
||||||
_mapping = {'posixpath': 'os.path',
|
_mapping = {'posixpath': 'os.path',
|
||||||
'riscospath': 'os.path',
|
'riscospath': 'os.path',
|
||||||
'ntpath': 'os.path',
|
'ntpath': 'os.path',
|
||||||
@@ -41,7 +42,7 @@ class BaseOutput(object):
|
|||||||
stripped = self.definition
|
stripped = self.definition
|
||||||
if isinstance(self.definition, evaluate.InstanceElement):
|
if isinstance(self.definition, evaluate.InstanceElement):
|
||||||
stripped = self.definition.var
|
stripped = self.definition.var
|
||||||
self.type = type(stripped).__name__
|
return type(stripped).__name__
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self):
|
||||||
@@ -92,7 +93,7 @@ class BaseOutput(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
raise NotImplementedError('Base Class')
|
return str(self.definition)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def full_name(self):
|
def full_name(self):
|
||||||
@@ -115,7 +116,7 @@ class BaseOutput(object):
|
|||||||
return "<%s %s>" % (type(self).__name__, self.description)
|
return "<%s %s>" % (type(self).__name__, self.description)
|
||||||
|
|
||||||
|
|
||||||
class Completion(BaseOutput):
|
class Completion(BaseDefinition):
|
||||||
""" `Completion` objects are returned from `Script.complete`. Providing
|
""" `Completion` objects are returned from `Script.complete`. Providing
|
||||||
some useful functions for IDE's. """
|
some useful functions for IDE's. """
|
||||||
def __init__(self, name, needs_dot, like_name_length, base):
|
def __init__(self, name, needs_dot, like_name_length, base):
|
||||||
@@ -126,6 +127,8 @@ class Completion(BaseOutput):
|
|||||||
self.like_name_length = like_name_length
|
self.like_name_length = like_name_length
|
||||||
self.base = base
|
self.base = base
|
||||||
|
|
||||||
|
self._followed_definitions = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def complete(self):
|
def complete(self):
|
||||||
""" Delievers the rest of the word, e.g. completing `isinstance`
|
""" Delievers the rest of the word, e.g. completing `isinstance`
|
||||||
@@ -172,11 +175,33 @@ class Completion(BaseOutput):
|
|||||||
line_nr = '' if self.in_builtin_module else '@%s' % self.line_nr
|
line_nr = '' if self.in_builtin_module else '@%s' % self.line_nr
|
||||||
return '%s: %s%s' % (t, desc, line_nr)
|
return '%s: %s%s' % (t, desc, line_nr)
|
||||||
|
|
||||||
|
def follow_definition(self):
|
||||||
|
""" Returns you the original definitions. I strongly recommend not
|
||||||
|
using it for your completions, because it might slow down Jedi. If you
|
||||||
|
want to read only a few objects (<=20). I think it might be useful,
|
||||||
|
especially to get the original docstrings.
|
||||||
|
The basic problem of this function is that it follows all results. This
|
||||||
|
means with 1000 completions (e.g. numpy), it's just PITA slow.
|
||||||
|
"""
|
||||||
|
if self._followed_definitions is None:
|
||||||
|
if self.definition.isinstance(parsing.Statement):
|
||||||
|
defs = evaluate.follow_statement(self.definition)
|
||||||
|
elif self.definition.isinstance(parsing.Import):
|
||||||
|
defs = imports.strip_imports([self.definition])
|
||||||
|
else:
|
||||||
|
return [self]
|
||||||
|
|
||||||
|
self._followed_definitions = \
|
||||||
|
[BaseDefinition(d, start_pos=None) for d in defs]
|
||||||
|
evaluate.clear_caches()
|
||||||
|
|
||||||
|
return self._followed_definitions
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s>' % (type(self).__name__, self.name)
|
return '<%s: %s>' % (type(self).__name__, self.name)
|
||||||
|
|
||||||
|
|
||||||
class Definition(BaseOutput):
|
class Definition(BaseDefinition):
|
||||||
""" These are the objects returned by either `Script.goto` or
|
""" These are the objects returned by either `Script.goto` or
|
||||||
`Script.get_definition`. """
|
`Script.get_definition`. """
|
||||||
def __init__(self, definition):
|
def __init__(self, definition):
|
||||||
@@ -223,7 +248,7 @@ class Definition(BaseOutput):
|
|||||||
return "%s:%s%s" % (self.module_name, self.description, position)
|
return "%s:%s%s" % (self.module_name, self.description, position)
|
||||||
|
|
||||||
|
|
||||||
class RelatedName(BaseOutput):
|
class RelatedName(BaseDefinition):
|
||||||
def __init__(self, name_part, scope):
|
def __init__(self, name_part, scope):
|
||||||
super(RelatedName, self).__init__(scope, name_part.start_pos)
|
super(RelatedName, self).__init__(scope, name_part.start_pos)
|
||||||
self.name_part = name_part
|
self.name_part = name_part
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import unittest
|
|||||||
from os.path import abspath, dirname
|
from os.path import abspath, dirname
|
||||||
import time
|
import time
|
||||||
import functools
|
import functools
|
||||||
|
import itertools
|
||||||
|
|
||||||
sys.path.insert(0, abspath(dirname(abspath(__file__)) + '/../jedi'))
|
sys.path.insert(0, abspath(dirname(abspath(__file__)) + '/../jedi'))
|
||||||
os.chdir(os.path.dirname(os.path.abspath(__file__)) + '/../jedi')
|
os.chdir(os.path.dirname(os.path.abspath(__file__)) + '/../jedi')
|
||||||
@@ -244,13 +245,14 @@ class TestRegression(Base):
|
|||||||
s = self.complete("import os; os.P_")
|
s = self.complete("import os; os.P_")
|
||||||
assert 'P_NOWAIT' in [i.word for i in s]
|
assert 'P_NOWAIT' in [i.word for i in s]
|
||||||
|
|
||||||
def test_follow_imports_if_possible(self):
|
def test_follow_definition(self):
|
||||||
""" github issue #45 """
|
""" github issue #45 """
|
||||||
s = self.complete("from datetime import timedelta; timedelta")
|
c = self.complete("from datetime import timedelta; timedelta")
|
||||||
# type can also point to import, but there will be additional
|
# type can also point to import, but there will be additional
|
||||||
# attributes
|
# attributes
|
||||||
types = [r.type for r in s]
|
objs = itertools.chain.from_iterable(r.follow_definition() for r in c)
|
||||||
#assert 'Import' not in types and 'Class' in types
|
types = [o.type for o in objs]
|
||||||
|
assert 'Import' not in types and 'Class' in types
|
||||||
|
|
||||||
|
|
||||||
class TestFeature(Base):
|
class TestFeature(Base):
|
||||||
|
|||||||
Reference in New Issue
Block a user