forked from VimPlug/jedi
moved get_names_for_scope to finder
This commit is contained in:
@@ -29,6 +29,7 @@ from jedi.evaluate import representation as er
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate import helpers
|
||||
from jedi.evaluate.finder import get_names_of_scope
|
||||
|
||||
|
||||
class NotFoundError(Exception):
|
||||
@@ -170,8 +171,9 @@ class Script(object):
|
||||
scopes = list(self._prepare_goto(path, True))
|
||||
except NotFoundError:
|
||||
scopes = []
|
||||
scope_generator = self._evaluator.get_names_of_scope(
|
||||
self._parser.user_scope(), self._pos)
|
||||
scope_generator = get_names_of_scope(self._evaluator,
|
||||
self._parser.user_scope(),
|
||||
self._pos)
|
||||
completions = []
|
||||
for scope, name_list in scope_generator:
|
||||
for c in name_list:
|
||||
|
||||
@@ -16,6 +16,7 @@ from jedi.evaluate import iterable
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.api import keywords
|
||||
from jedi.evaluate.finder import get_names_of_scope
|
||||
|
||||
|
||||
def clear_caches():
|
||||
@@ -550,8 +551,8 @@ def defined_names(evaluator, scope):
|
||||
:type scope: Scope
|
||||
:rtype: list of Definition
|
||||
"""
|
||||
pair = next(evaluator.get_names_of_scope(
|
||||
scope, star_search=False, include_builtin=False), None)
|
||||
pair = next(get_names_of_scope(evaluator, scope, star_search=False,
|
||||
include_builtin=False), None)
|
||||
names = pair[1] if pair else []
|
||||
return [Definition(evaluator, d) for d in sorted(names, key=lambda s: s.start_pos)]
|
||||
|
||||
|
||||
@@ -68,10 +68,9 @@ backtracking algorithm.
|
||||
|
||||
.. todo:: nonlocal statement, needed or can be ignored? (py3k)
|
||||
"""
|
||||
import sys
|
||||
import itertools
|
||||
|
||||
from jedi._compatibility import next, hasattr, unicode, reraise
|
||||
from jedi._compatibility import next, hasattr, unicode
|
||||
from jedi import common
|
||||
from jedi.parser import representation as pr
|
||||
from jedi import debug
|
||||
@@ -91,92 +90,6 @@ class Evaluator(object):
|
||||
self.recursion_detector = recursion.RecursionDetector()
|
||||
self.execution_recursion_detector = recursion.ExecutionRecursionDetector()
|
||||
|
||||
def get_names_of_scope(self, scope, position=None, star_search=True,
|
||||
include_builtin=True):
|
||||
"""
|
||||
Get all completions (names) possible for the current scope.
|
||||
The star search option is only here to provide an optimization. Otherwise
|
||||
the whole thing would probably start a little recursive madness.
|
||||
|
||||
This function is used to include names from outer scopes. For example,
|
||||
when the current scope is function:
|
||||
|
||||
>>> from jedi.parser import Parser
|
||||
>>> parser = Parser('''
|
||||
... x = ['a', 'b', 'c']
|
||||
... def func():
|
||||
... y = None
|
||||
... ''')
|
||||
>>> scope = parser.module.subscopes[0]
|
||||
>>> scope
|
||||
<Function: func@3-4>
|
||||
|
||||
`get_names_of_scope` is a generator. First it yields names from
|
||||
most inner scope.
|
||||
|
||||
>>> pairs = list(Evaluator().get_names_of_scope(scope))
|
||||
>>> pairs[0]
|
||||
(<Function: func@3-4>, [<Name: y@4,4>])
|
||||
|
||||
Then it yield the names from one level outer scope. For this
|
||||
example, this is the most outer scope.
|
||||
|
||||
>>> pairs[1]
|
||||
(<SubModule: None@1-4>, [<Name: x@2,0>, <Name: func@3,4>])
|
||||
|
||||
Finally, it yields names from builtin, if `include_builtin` is
|
||||
true (default).
|
||||
|
||||
>>> pairs[2] #doctest: +ELLIPSIS
|
||||
(<Builtin: ...builtin...>, [<CompiledName: ...>, ...])
|
||||
|
||||
:rtype: [(pr.Scope, [pr.Name])]
|
||||
:return: Return an generator that yields a pair of scope and names.
|
||||
"""
|
||||
in_func_scope = scope
|
||||
non_flow = scope.get_parent_until(pr.Flow, reverse=True)
|
||||
while scope:
|
||||
if isinstance(scope, pr.SubModule) and scope.parent:
|
||||
# we don't want submodules to report if we have modules.
|
||||
scope = scope.parent
|
||||
continue
|
||||
# `pr.Class` is used, because the parent is never `Class`.
|
||||
# Ignore the Flows, because the classes and functions care for that.
|
||||
# InstanceElement of Class is ignored, if it is not the start scope.
|
||||
if not (scope != non_flow and scope.isinstance(pr.Class)
|
||||
or scope.isinstance(pr.Flow)
|
||||
or scope.isinstance(er.Instance)
|
||||
and non_flow.isinstance(er.Function)
|
||||
or isinstance(scope, compiled.CompiledObject)
|
||||
and scope.type() == 'class' and in_func_scope != scope):
|
||||
try:
|
||||
if isinstance(scope, er.Instance):
|
||||
for g in scope.scope_generator():
|
||||
yield g
|
||||
else:
|
||||
yield scope, finder._get_defined_names_for_position(scope, position, in_func_scope)
|
||||
except StopIteration:
|
||||
reraise(common.MultiLevelStopIteration, sys.exc_info()[2])
|
||||
if scope.isinstance(pr.ForFlow) and scope.is_list_comp:
|
||||
# is a list comprehension
|
||||
yield scope, scope.get_set_vars(is_internal_call=True)
|
||||
|
||||
scope = scope.parent
|
||||
# This is used, because subscopes (Flow scopes) would distort the
|
||||
# results.
|
||||
if scope and scope.isinstance(er.Function, pr.Function, er.FunctionExecution):
|
||||
in_func_scope = scope
|
||||
|
||||
# Add star imports.
|
||||
if star_search:
|
||||
for s in imports.remove_star_imports(self, non_flow.get_parent_until()):
|
||||
for g in self.get_names_of_scope(s, star_search=False):
|
||||
yield g
|
||||
|
||||
# Add builtins to the global scope.
|
||||
if include_builtin:
|
||||
yield compiled.builtin, compiled.builtin.get_defined_names()
|
||||
|
||||
def find_types(self, scope, name_str, position=None, search_global=False,
|
||||
is_goto=False, resolve_decorator=True):
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import copy
|
||||
import sys
|
||||
|
||||
from jedi._compatibility import hasattr, unicode, u
|
||||
from jedi._compatibility import hasattr, unicode, u, reraise
|
||||
from jedi.parser import representation as pr
|
||||
from jedi import debug
|
||||
from jedi import common
|
||||
@@ -10,6 +11,7 @@ from jedi.evaluate import dynamic
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.evaluate import docstrings
|
||||
from jedi.evaluate import iterable
|
||||
from jedi.evaluate import imports
|
||||
|
||||
|
||||
class NameFinder(object):
|
||||
@@ -27,7 +29,7 @@ class NameFinder(object):
|
||||
|
||||
def scopes(self, search_global=False):
|
||||
if search_global:
|
||||
return self._evaluator.get_names_of_scope(self.scope, self.position)
|
||||
return get_names_of_scope(self._evaluator, self.scope, self.position)
|
||||
else:
|
||||
if isinstance(self.scope, er.Instance):
|
||||
return self.scope.scope_generator()
|
||||
@@ -361,6 +363,93 @@ def _get_defined_names_for_position(scope, position=None, start_scope=None):
|
||||
return names_new
|
||||
|
||||
|
||||
def get_names_of_scope(evaluator, scope, position=None, star_search=True, include_builtin=True):
|
||||
"""
|
||||
Get all completions (names) possible for the current scope. The star search
|
||||
option is only here to provide an optimization. Otherwise the whole thing
|
||||
would probably start a little recursive madness.
|
||||
|
||||
This function is used to include names from outer scopes. For example, when
|
||||
the current scope is function:
|
||||
|
||||
>>> from jedi.parser import Parser
|
||||
>>> parser = Parser('''
|
||||
... x = ['a', 'b', 'c']
|
||||
... def func():
|
||||
... y = None
|
||||
... ''')
|
||||
>>> scope = parser.module.subscopes[0]
|
||||
>>> scope
|
||||
<Function: func@3-4>
|
||||
|
||||
`get_names_of_scope` is a generator. First it yields names from most inner
|
||||
scope.
|
||||
|
||||
>>> from jedi.evaluate import Evaluator
|
||||
>>> pairs = list(get_names_of_scope(Evaluator(), scope))
|
||||
>>> pairs[0]
|
||||
(<Function: func@3-4>, [<Name: y@4,4>])
|
||||
|
||||
Then it yield the names from one level outer scope. For this example, this
|
||||
is the most outer scope.
|
||||
|
||||
>>> pairs[1]
|
||||
(<SubModule: None@1-4>, [<Name: x@2,0>, <Name: func@3,4>])
|
||||
|
||||
Finally, it yields names from builtin, if `include_builtin` is
|
||||
true (default).
|
||||
|
||||
>>> pairs[2] #doctest: +ELLIPSIS
|
||||
(<Builtin: ...builtin...>, [<CompiledName: ...>, ...])
|
||||
|
||||
:rtype: [(pr.Scope, [pr.Name])]
|
||||
:return: Return an generator that yields a pair of scope and names.
|
||||
"""
|
||||
in_func_scope = scope
|
||||
non_flow = scope.get_parent_until(pr.Flow, reverse=True)
|
||||
while scope:
|
||||
if isinstance(scope, pr.SubModule) and scope.parent:
|
||||
# we don't want submodules to report if we have modules.
|
||||
scope = scope.parent
|
||||
continue
|
||||
# `pr.Class` is used, because the parent is never `Class`.
|
||||
# Ignore the Flows, because the classes and functions care for that.
|
||||
# InstanceElement of Class is ignored, if it is not the start scope.
|
||||
if not (scope != non_flow and scope.isinstance(pr.Class)
|
||||
or scope.isinstance(pr.Flow)
|
||||
or scope.isinstance(er.Instance)
|
||||
and non_flow.isinstance(er.Function)
|
||||
or isinstance(scope, compiled.CompiledObject)
|
||||
and scope.type() == 'class' and in_func_scope != scope):
|
||||
try:
|
||||
if isinstance(scope, er.Instance):
|
||||
for g in scope.scope_generator():
|
||||
yield g
|
||||
else:
|
||||
yield scope, _get_defined_names_for_position(scope, position, in_func_scope)
|
||||
except StopIteration:
|
||||
reraise(common.MultiLevelStopIteration, sys.exc_info()[2])
|
||||
if scope.isinstance(pr.ForFlow) and scope.is_list_comp:
|
||||
# is a list comprehension
|
||||
yield scope, scope.get_set_vars(is_internal_call=True)
|
||||
|
||||
scope = scope.parent
|
||||
# This is used, because subscopes (Flow scopes) would distort the
|
||||
# results.
|
||||
if scope and scope.isinstance(er.Function, pr.Function, er.FunctionExecution):
|
||||
in_func_scope = scope
|
||||
|
||||
# Add star imports.
|
||||
if star_search:
|
||||
for s in imports.remove_star_imports(evaluator, non_flow.get_parent_until()):
|
||||
for g in get_names_of_scope(evaluator, s, star_search=False):
|
||||
yield g
|
||||
|
||||
# Add builtins to the global scope.
|
||||
if include_builtin:
|
||||
yield compiled.builtin, compiled.builtin.get_defined_names()
|
||||
|
||||
|
||||
def _assign_tuples(tup, results, seek_name):
|
||||
"""
|
||||
This is a normal assignment checker. In python functions and other things
|
||||
|
||||
@@ -131,8 +131,9 @@ class ImportPath(pr.Base):
|
||||
names.append(pr.Name(self.GlobalNamespace, [('path', p)],
|
||||
p, p, self.import_stmt))
|
||||
continue
|
||||
for s, scope_names in self._evaluator.get_names_of_scope(scope,
|
||||
include_builtin=False):
|
||||
from jedi.evaluate import finder
|
||||
for s, scope_names in finder.get_names_of_scope(self._evaluator,
|
||||
scope, include_builtin=False):
|
||||
for n in scope_names:
|
||||
if self.import_stmt.from_ns is None \
|
||||
or self.is_partial_import:
|
||||
|
||||
Reference in New Issue
Block a user