forked from VimPlug/jedi
Merge branch 'refactoring'
This commit is contained in:
@@ -28,19 +28,19 @@ from jedi.api import helpers
|
||||
from jedi.api.completion import Completion
|
||||
from jedi.api.environment import InterpreterEnvironment
|
||||
from jedi.api.project import get_default_project, Project
|
||||
from jedi.evaluate import Evaluator
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate import usages
|
||||
from jedi.evaluate.arguments import try_iter_content
|
||||
from jedi.evaluate.helpers import get_module_names, evaluate_call_of_leaf
|
||||
from jedi.evaluate.sys_path import transform_path_to_dotted
|
||||
from jedi.evaluate.names import TreeNameDefinition, ParamName
|
||||
from jedi.evaluate.syntax_tree import tree_name_to_contexts
|
||||
from jedi.evaluate.context import ModuleContext
|
||||
from jedi.evaluate.base_context import ContextSet
|
||||
from jedi.evaluate.context.iterable import unpack_tuple_to_dict
|
||||
from jedi.evaluate.gradual.conversion import convert_names, convert_contexts
|
||||
from jedi.evaluate.gradual.utils import load_proper_stub_module
|
||||
from jedi.inference import InferenceState
|
||||
from jedi.inference import imports
|
||||
from jedi.inference import usages
|
||||
from jedi.inference.arguments import try_iter_content
|
||||
from jedi.inference.helpers import get_module_names, infer_call_of_leaf
|
||||
from jedi.inference.sys_path import transform_path_to_dotted
|
||||
from jedi.inference.names import TreeNameDefinition, ParamName
|
||||
from jedi.inference.syntax_tree import tree_name_to_values
|
||||
from jedi.inference.value import ModuleValue
|
||||
from jedi.inference.base_value import ValueSet
|
||||
from jedi.inference.value.iterable import unpack_tuple_to_dict
|
||||
from jedi.inference.gradual.conversion import convert_names, convert_values
|
||||
from jedi.inference.gradual.utils import load_proper_stub_module
|
||||
|
||||
# Jedi uses lots and lots of recursion. By setting this a little bit higher, we
|
||||
# can remove some "maximum recursion depth" errors.
|
||||
@@ -62,7 +62,7 @@ class Script(object):
|
||||
|
||||
- if `sys_path` parameter is ``None`` and ``VIRTUAL_ENV`` environment
|
||||
variable is defined, ``sys.path`` for the specified environment will be
|
||||
guessed (see :func:`jedi.evaluate.sys_path.get_venv_path`) and used for
|
||||
guessed (see :func:`jedi.inference.sys_path.get_venv_path`) and used for
|
||||
the script;
|
||||
|
||||
- otherwise ``sys.path`` will match that of |jedi|.
|
||||
@@ -111,11 +111,11 @@ class Script(object):
|
||||
# TODO deprecate and remove sys_path from the Script API.
|
||||
if sys_path is not None:
|
||||
project._sys_path = sys_path
|
||||
self._evaluator = Evaluator(
|
||||
self._inference_state = InferenceState(
|
||||
project, environment=environment, script_path=self.path
|
||||
)
|
||||
debug.speed('init')
|
||||
self._module_node, source = self._evaluator.parse_and_get_code(
|
||||
self._module_node, source = self._inference_state.parse_and_get_code(
|
||||
code=source,
|
||||
path=self.path,
|
||||
encoding=encoding,
|
||||
@@ -156,7 +156,7 @@ class Script(object):
|
||||
is_package = False
|
||||
if self.path is not None:
|
||||
import_names, is_p = transform_path_to_dotted(
|
||||
self._evaluator.get_sys_path(add_parent_paths=False),
|
||||
self._inference_state.get_sys_path(add_parent_paths=False),
|
||||
self.path
|
||||
)
|
||||
if import_names is not None:
|
||||
@@ -170,7 +170,7 @@ class Script(object):
|
||||
if self.path is not None and self.path.endswith('.pyi'):
|
||||
# We are in a stub file. Try to load the stub properly.
|
||||
stub_module = load_proper_stub_module(
|
||||
self._evaluator,
|
||||
self._inference_state,
|
||||
file_io,
|
||||
names,
|
||||
self._module_node
|
||||
@@ -181,22 +181,25 @@ class Script(object):
|
||||
if names is None:
|
||||
names = ('__main__',)
|
||||
|
||||
module = ModuleContext(
|
||||
self._evaluator, self._module_node, file_io,
|
||||
module = ModuleValue(
|
||||
self._inference_state, self._module_node, file_io,
|
||||
string_names=names,
|
||||
code_lines=self._code_lines,
|
||||
is_package=is_package,
|
||||
)
|
||||
if names[0] not in ('builtins', '__builtin__', 'typing'):
|
||||
# These modules are essential for Jedi, so don't overwrite them.
|
||||
self._evaluator.module_cache.add(names, ContextSet([module]))
|
||||
self._inference_state.module_cache.add(names, ValueSet([module]))
|
||||
return module
|
||||
|
||||
def _get_module_context(self):
|
||||
return self._get_module().as_context()
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s: %s %r>' % (
|
||||
self.__class__.__name__,
|
||||
repr(self._orig_path),
|
||||
self._evaluator.environment,
|
||||
self._inference_state.environment,
|
||||
)
|
||||
|
||||
def completions(self):
|
||||
@@ -209,7 +212,7 @@ class Script(object):
|
||||
"""
|
||||
with debug.increase_indent_cm('completions'):
|
||||
completion = Completion(
|
||||
self._evaluator, self._get_module(), self._code_lines,
|
||||
self._inference_state, self._get_module_context(), self._code_lines,
|
||||
self._pos, self.call_signatures
|
||||
)
|
||||
return completion.completions()
|
||||
@@ -239,16 +242,16 @@ class Script(object):
|
||||
if leaf is None:
|
||||
return []
|
||||
|
||||
context = self._evaluator.create_context(self._get_module(), leaf)
|
||||
context = self._get_module_context().create_context(leaf)
|
||||
|
||||
contexts = helpers.evaluate_goto_definition(self._evaluator, context, leaf)
|
||||
contexts = convert_contexts(
|
||||
contexts,
|
||||
values = helpers.infer_goto_definition(self._inference_state, context, leaf)
|
||||
values = convert_values(
|
||||
values,
|
||||
only_stubs=only_stubs,
|
||||
prefer_stubs=prefer_stubs,
|
||||
)
|
||||
|
||||
defs = [classes.Definition(self._evaluator, c.name) for c in contexts]
|
||||
defs = [classes.Definition(self._inference_state, c.name) for c in values]
|
||||
# The additional set here allows the definitions to become unique in an
|
||||
# API sense. In the internals we want to separate more things than in
|
||||
# the API.
|
||||
@@ -276,10 +279,10 @@ class Script(object):
|
||||
|
||||
def _goto_assignments(self, follow_imports, follow_builtin_imports,
|
||||
only_stubs=False, prefer_stubs=False):
|
||||
def filter_follow_imports(names, check):
|
||||
def filter_follow_imports(names):
|
||||
for name in names:
|
||||
if check(name):
|
||||
new_names = list(filter_follow_imports(name.goto(), check))
|
||||
if name.is_import():
|
||||
new_names = list(filter_follow_imports(name.goto()))
|
||||
found_builtin = False
|
||||
if follow_builtin_imports:
|
||||
for new_name in new_names:
|
||||
@@ -299,18 +302,18 @@ class Script(object):
|
||||
# Without a name we really just want to jump to the result e.g.
|
||||
# executed by `foo()`, if we the cursor is after `)`.
|
||||
return self.goto_definitions(only_stubs=only_stubs, prefer_stubs=prefer_stubs)
|
||||
context = self._evaluator.create_context(self._get_module(), tree_name)
|
||||
names = list(self._evaluator.goto(context, tree_name))
|
||||
context = self._get_module_context().create_context(tree_name)
|
||||
names = list(self._inference_state.goto(context, tree_name))
|
||||
|
||||
if follow_imports:
|
||||
names = filter_follow_imports(names, lambda name: name.is_import())
|
||||
names = filter_follow_imports(names)
|
||||
names = convert_names(
|
||||
names,
|
||||
only_stubs=only_stubs,
|
||||
prefer_stubs=prefer_stubs,
|
||||
)
|
||||
|
||||
defs = [classes.Definition(self._evaluator, d) for d in set(names)]
|
||||
defs = [classes.Definition(self._inference_state, d) for d in set(names)]
|
||||
return helpers.sorted_definitions(defs)
|
||||
|
||||
def usages(self, additional_module_paths=(), **kwargs):
|
||||
@@ -340,9 +343,9 @@ class Script(object):
|
||||
# Must be syntax
|
||||
return []
|
||||
|
||||
names = usages.usages(self._get_module(), tree_name)
|
||||
names = usages.usages(self._get_module_context(), tree_name)
|
||||
|
||||
definitions = [classes.Definition(self._evaluator, n) for n in names]
|
||||
definitions = [classes.Definition(self._inference_state, n) for n in names]
|
||||
if not include_builtins:
|
||||
definitions = [d for d in definitions if not d.in_builtin_module()]
|
||||
return helpers.sorted_definitions(definitions)
|
||||
@@ -368,12 +371,9 @@ class Script(object):
|
||||
if call_details is None:
|
||||
return []
|
||||
|
||||
context = self._evaluator.create_context(
|
||||
self._get_module(),
|
||||
call_details.bracket_leaf
|
||||
)
|
||||
context = self._get_module_context().create_context(call_details.bracket_leaf)
|
||||
definitions = helpers.cache_call_signatures(
|
||||
self._evaluator,
|
||||
self._inference_state,
|
||||
context,
|
||||
call_details.bracket_leaf,
|
||||
self._code_lines,
|
||||
@@ -381,21 +381,21 @@ class Script(object):
|
||||
)
|
||||
debug.speed('func_call followed')
|
||||
|
||||
# TODO here we use stubs instead of the actual contexts. We should use
|
||||
# the signatures from stubs, but the actual contexts, probably?!
|
||||
return [classes.CallSignature(self._evaluator, signature, call_details)
|
||||
# TODO here we use stubs instead of the actual values. We should use
|
||||
# the signatures from stubs, but the actual values, probably?!
|
||||
return [classes.CallSignature(self._inference_state, signature, call_details)
|
||||
for signature in definitions.get_signatures()]
|
||||
|
||||
def _analysis(self):
|
||||
self._evaluator.is_analysis = True
|
||||
self._evaluator.analysis_modules = [self._module_node]
|
||||
module = self._get_module()
|
||||
self._inference_state.is_analysis = True
|
||||
self._inference_state.analysis_modules = [self._module_node]
|
||||
module = self._get_module_context()
|
||||
try:
|
||||
for node in get_executable_nodes(self._module_node):
|
||||
context = module.create_context(node)
|
||||
if node.type in ('funcdef', 'classdef'):
|
||||
# Resolve the decorators.
|
||||
tree_name_to_contexts(self._evaluator, context, node.children[1])
|
||||
tree_name_to_values(self._inference_state, context, node.children[1])
|
||||
elif isinstance(node, tree.Import):
|
||||
import_names = set(node.get_defined_names())
|
||||
if node.is_nested():
|
||||
@@ -403,22 +403,22 @@ class Script(object):
|
||||
for n in import_names:
|
||||
imports.infer_import(context, n)
|
||||
elif node.type == 'expr_stmt':
|
||||
types = context.eval_node(node)
|
||||
types = context.infer_node(node)
|
||||
for testlist in node.children[:-1:2]:
|
||||
# Iterate tuples.
|
||||
unpack_tuple_to_dict(context, types, testlist)
|
||||
else:
|
||||
if node.type == 'name':
|
||||
defs = self._evaluator.goto_definitions(context, node)
|
||||
defs = self._inference_state.goto_definitions(context, node)
|
||||
else:
|
||||
defs = evaluate_call_of_leaf(context, node)
|
||||
defs = infer_call_of_leaf(context, node)
|
||||
try_iter_content(defs)
|
||||
self._evaluator.reset_recursion_limitations()
|
||||
self._inference_state.reset_recursion_limitations()
|
||||
|
||||
ana = [a for a in self._evaluator.analysis if self.path == a.path]
|
||||
ana = [a for a in self._inference_state.analysis if self.path == a.path]
|
||||
return sorted(set(ana), key=lambda x: x.line)
|
||||
finally:
|
||||
self._evaluator.is_analysis = False
|
||||
self._inference_state.is_analysis = False
|
||||
|
||||
|
||||
class Interpreter(Script):
|
||||
@@ -467,16 +467,20 @@ class Interpreter(Script):
|
||||
super(Interpreter, self).__init__(source, environment=environment,
|
||||
_project=Project(os.getcwd()), **kwds)
|
||||
self.namespaces = namespaces
|
||||
self._evaluator.allow_descriptor_getattr = self._allow_descriptor_getattr_default
|
||||
self._inference_state.allow_descriptor_getattr = self._allow_descriptor_getattr_default
|
||||
|
||||
def _get_module(self):
|
||||
return interpreter.MixedModuleContext(
|
||||
self._evaluator,
|
||||
self._module_node,
|
||||
self.namespaces,
|
||||
@cache.memoize_method
|
||||
def _get_module_context(self):
|
||||
tree_module_value = ModuleValue(
|
||||
self._inference_state, self._module_node,
|
||||
file_io=KnownContentFileIO(self.path, self._code),
|
||||
string_names=('__main__',),
|
||||
code_lines=self._code_lines,
|
||||
)
|
||||
return interpreter.MixedModuleContext(
|
||||
tree_module_value,
|
||||
self.namespaces,
|
||||
)
|
||||
|
||||
|
||||
def names(source=None, path=None, encoding='utf-8', all_scopes=False,
|
||||
@@ -511,10 +515,10 @@ def names(source=None, path=None, encoding='utf-8', all_scopes=False,
|
||||
|
||||
# Set line/column to a random position, because they don't matter.
|
||||
script = Script(source, line=1, column=0, path=path, encoding=encoding, environment=environment)
|
||||
module_context = script._get_module()
|
||||
module_context = script._get_module_context()
|
||||
defs = [
|
||||
classes.Definition(
|
||||
script._evaluator,
|
||||
script._inference_state,
|
||||
create_name(name)
|
||||
) for name in get_module_names(script._module_node, all_scopes)
|
||||
]
|
||||
|
||||
@@ -9,15 +9,13 @@ import warnings
|
||||
|
||||
from jedi import settings
|
||||
from jedi import debug
|
||||
from jedi.evaluate.utils import unite
|
||||
from jedi.inference.utils import unite
|
||||
from jedi.cache import memoize_method
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.evaluate.imports import ImportName
|
||||
from jedi.evaluate.context import FunctionExecutionContext
|
||||
from jedi.evaluate.gradual.typeshed import StubModuleContext
|
||||
from jedi.evaluate.gradual.conversion import convert_names, convert_contexts
|
||||
from jedi.evaluate.base_context import ContextSet
|
||||
from jedi.inference import imports
|
||||
from jedi.inference.imports import ImportName
|
||||
from jedi.inference.gradual.typeshed import StubModuleValue
|
||||
from jedi.inference.gradual.conversion import convert_names, convert_values
|
||||
from jedi.inference.base_value import ValueSet
|
||||
from jedi.api.keywords import KeywordName
|
||||
|
||||
|
||||
@@ -25,20 +23,20 @@ def _sort_names_by_start_pos(names):
|
||||
return sorted(names, key=lambda s: s.start_pos or (0, 0))
|
||||
|
||||
|
||||
def defined_names(evaluator, context):
|
||||
def defined_names(inference_state, context):
|
||||
"""
|
||||
List sub-definitions (e.g., methods in class).
|
||||
|
||||
:type scope: Scope
|
||||
:rtype: list of Definition
|
||||
"""
|
||||
filter = next(context.get_filters(search_global=True))
|
||||
filter = next(context.get_filters())
|
||||
names = [name for name in filter.values()]
|
||||
return [Definition(evaluator, n) for n in _sort_names_by_start_pos(names)]
|
||||
return [Definition(inference_state, n) for n in _sort_names_by_start_pos(names)]
|
||||
|
||||
|
||||
def _contexts_to_definitions(contexts):
|
||||
return [Definition(c.evaluator, c.name) for c in contexts]
|
||||
def _values_to_definitions(values):
|
||||
return [Definition(c.inference_state, c.name) for c in values]
|
||||
|
||||
|
||||
class BaseDefinition(object):
|
||||
@@ -62,8 +60,8 @@ class BaseDefinition(object):
|
||||
'argparse._ActionsContainer': 'argparse.ArgumentParser',
|
||||
}.items())
|
||||
|
||||
def __init__(self, evaluator, name):
|
||||
self._evaluator = evaluator
|
||||
def __init__(self, inference_state, name):
|
||||
self._inference_state = inference_state
|
||||
self._name = name
|
||||
"""
|
||||
An instance of :class:`parso.python.tree.Name` subclass.
|
||||
@@ -71,7 +69,7 @@ class BaseDefinition(object):
|
||||
self.is_keyword = isinstance(self._name, KeywordName)
|
||||
|
||||
@memoize_method
|
||||
def _get_module(self):
|
||||
def _get_module_context(self):
|
||||
# This can take a while to complete, because in the worst case of
|
||||
# imports (consider `import a` completions), we need to load all
|
||||
# modules starting with a first.
|
||||
@@ -80,11 +78,11 @@ class BaseDefinition(object):
|
||||
@property
|
||||
def module_path(self):
|
||||
"""Shows the file path of a module. e.g. ``/usr/lib/python2.7/os.py``"""
|
||||
module = self._get_module()
|
||||
module = self._get_module_context()
|
||||
if module.is_stub() or not module.is_compiled():
|
||||
# Compiled modules should not return a module path even if they
|
||||
# have one.
|
||||
return self._get_module().py__file__()
|
||||
return self._get_module_context().py__file__()
|
||||
|
||||
return None
|
||||
|
||||
@@ -97,7 +95,7 @@ class BaseDefinition(object):
|
||||
|
||||
:rtype: str or None
|
||||
"""
|
||||
return self._name.string_name
|
||||
return self._name.get_public_name()
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
@@ -167,8 +165,8 @@ class BaseDefinition(object):
|
||||
resolve = True
|
||||
|
||||
if isinstance(self._name, imports.SubModuleName) or resolve:
|
||||
for context in self._name.infer():
|
||||
return context.api_type
|
||||
for value in self._name.infer():
|
||||
return value.api_type
|
||||
return self._name.api_type
|
||||
|
||||
@property
|
||||
@@ -183,14 +181,14 @@ class BaseDefinition(object):
|
||||
>>> print(d.module_name) # doctest: +ELLIPSIS
|
||||
json
|
||||
"""
|
||||
return self._get_module().name.string_name
|
||||
return self._get_module_context().py__name__()
|
||||
|
||||
def in_builtin_module(self):
|
||||
"""Whether this is a builtin module."""
|
||||
if isinstance(self._get_module(), StubModuleContext):
|
||||
return any(isinstance(context, compiled.CompiledObject)
|
||||
for context in self._get_module().non_stub_context_set)
|
||||
return isinstance(self._get_module(), compiled.CompiledObject)
|
||||
value = self._get_module_context().get_value()
|
||||
if isinstance(value, StubModuleValue):
|
||||
return any(v.is_compiled() for v in value.non_stub_value_set)
|
||||
return value.is_compiled()
|
||||
|
||||
@property
|
||||
def line(self):
|
||||
@@ -244,7 +242,7 @@ class BaseDefinition(object):
|
||||
@property
|
||||
def description(self):
|
||||
"""A textual description of the object."""
|
||||
return self._name.string_name
|
||||
return self._name.get_public_name()
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
@@ -270,7 +268,7 @@ class BaseDefinition(object):
|
||||
be ``<module 'posixpath' ...>```. However most users find the latter
|
||||
more practical.
|
||||
"""
|
||||
if not self._name.is_context_name:
|
||||
if not self._name.is_value_name:
|
||||
return None
|
||||
|
||||
names = self._name.get_qualified_names(include_module_names=True)
|
||||
@@ -286,7 +284,7 @@ class BaseDefinition(object):
|
||||
return '.'.join(names)
|
||||
|
||||
def is_stub(self):
|
||||
if not self._name.is_context_name:
|
||||
if not self._name.is_value_name:
|
||||
return False
|
||||
|
||||
return self._name.get_root_context().is_stub()
|
||||
@@ -298,7 +296,7 @@ class BaseDefinition(object):
|
||||
def _goto_assignments(self, only_stubs=False, prefer_stubs=False):
|
||||
assert not (only_stubs and prefer_stubs)
|
||||
|
||||
if not self._name.is_context_name:
|
||||
if not self._name.is_value_name:
|
||||
return []
|
||||
|
||||
names = convert_names(
|
||||
@@ -306,7 +304,7 @@ class BaseDefinition(object):
|
||||
only_stubs=only_stubs,
|
||||
prefer_stubs=prefer_stubs,
|
||||
)
|
||||
return [self if n == self._name else Definition(self._evaluator, n)
|
||||
return [self if n == self._name else Definition(self._inference_state, n)
|
||||
for n in names]
|
||||
|
||||
def infer(self, **kwargs): # Python 2...
|
||||
@@ -316,20 +314,20 @@ class BaseDefinition(object):
|
||||
def _infer(self, only_stubs=False, prefer_stubs=False):
|
||||
assert not (only_stubs and prefer_stubs)
|
||||
|
||||
if not self._name.is_context_name:
|
||||
if not self._name.is_value_name:
|
||||
return []
|
||||
|
||||
# First we need to make sure that we have stub names (if possible) that
|
||||
# we can follow. If we don't do that, we can end up with the inferred
|
||||
# results of Python objects instead of stubs.
|
||||
names = convert_names([self._name], prefer_stubs=True)
|
||||
contexts = convert_contexts(
|
||||
ContextSet.from_sets(n.infer() for n in names),
|
||||
values = convert_values(
|
||||
ValueSet.from_sets(n.infer() for n in names),
|
||||
only_stubs=only_stubs,
|
||||
prefer_stubs=prefer_stubs,
|
||||
)
|
||||
resulting_names = [c.name for c in contexts]
|
||||
return [self if n == self._name else Definition(self._evaluator, n)
|
||||
resulting_names = [c.name for c in values]
|
||||
return [self if n == self._name else Definition(self._inference_state, n)
|
||||
for n in resulting_names]
|
||||
|
||||
@property
|
||||
@@ -343,10 +341,10 @@ class BaseDefinition(object):
|
||||
"""
|
||||
# Only return the first one. There might be multiple one, especially
|
||||
# with overloading.
|
||||
for context in self._name.infer():
|
||||
for signature in context.get_signatures():
|
||||
for value in self._name.infer():
|
||||
for signature in value.get_signatures():
|
||||
return [
|
||||
Definition(self._evaluator, n)
|
||||
Definition(self._inference_state, n)
|
||||
for n in signature.get_param_names(resolve_stars=True)
|
||||
]
|
||||
|
||||
@@ -357,16 +355,16 @@ class BaseDefinition(object):
|
||||
raise AttributeError('There are no params defined on this.')
|
||||
|
||||
def parent(self):
|
||||
if not self._name.is_context_name:
|
||||
if not self._name.is_value_name:
|
||||
return None
|
||||
|
||||
context = self._name.parent_context
|
||||
if context is None:
|
||||
return None
|
||||
|
||||
if isinstance(context, FunctionExecutionContext):
|
||||
context = context.function_context
|
||||
return Definition(self._evaluator, context.name)
|
||||
while context.name is None:
|
||||
# Happens for comprehension contexts
|
||||
context = context.parent_context
|
||||
return Definition(self._inference_state, context.name)
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s %sname=%r, description=%r>" % (
|
||||
@@ -386,7 +384,7 @@ class BaseDefinition(object):
|
||||
:return str: Returns the line(s) of code or an empty string if it's a
|
||||
builtin.
|
||||
"""
|
||||
if not self._name.is_context_name or self.in_builtin_module():
|
||||
if not self._name.is_value_name or self.in_builtin_module():
|
||||
return ''
|
||||
|
||||
lines = self._name.get_root_context().code_lines
|
||||
@@ -396,10 +394,10 @@ class BaseDefinition(object):
|
||||
return ''.join(lines[start_index:index + after + 1])
|
||||
|
||||
def get_signatures(self):
|
||||
return [Signature(self._evaluator, s) for s in self._name.infer().get_signatures()]
|
||||
return [Signature(self._inference_state, s) for s in self._name.infer().get_signatures()]
|
||||
|
||||
def execute(self):
|
||||
return _contexts_to_definitions(self._name.infer().execute_evaluated())
|
||||
return _values_to_definitions(self._name.infer().execute_with_values())
|
||||
|
||||
|
||||
class Completion(BaseDefinition):
|
||||
@@ -407,8 +405,8 @@ class Completion(BaseDefinition):
|
||||
`Completion` objects are returned from :meth:`api.Script.completions`. They
|
||||
provide additional information about a completion.
|
||||
"""
|
||||
def __init__(self, evaluator, name, stack, like_name_length):
|
||||
super(Completion, self).__init__(evaluator, name)
|
||||
def __init__(self, inference_state, name, stack, like_name_length):
|
||||
super(Completion, self).__init__(inference_state, name)
|
||||
|
||||
self._like_name_length = like_name_length
|
||||
self._stack = stack
|
||||
@@ -429,7 +427,7 @@ class Completion(BaseDefinition):
|
||||
# TODO this doesn't work for nested calls.
|
||||
append += '='
|
||||
|
||||
name = self._name.string_name
|
||||
name = self._name.get_public_name()
|
||||
if like_name:
|
||||
name = name[self._like_name_length:]
|
||||
return name + append
|
||||
@@ -485,7 +483,7 @@ class Completion(BaseDefinition):
|
||||
return Definition.description.__get__(self)
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s: %s>' % (type(self).__name__, self._name.string_name)
|
||||
return '<%s: %s>' % (type(self).__name__, self._name.get_public_name())
|
||||
|
||||
@memoize_method
|
||||
def follow_definition(self):
|
||||
@@ -512,8 +510,8 @@ class Definition(BaseDefinition):
|
||||
*Definition* objects are returned from :meth:`api.Script.goto_assignments`
|
||||
or :meth:`api.Script.goto_definitions`.
|
||||
"""
|
||||
def __init__(self, evaluator, definition):
|
||||
super(Definition, self).__init__(evaluator, definition)
|
||||
def __init__(self, inference_state, definition):
|
||||
super(Definition, self).__init__(inference_state, definition)
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
@@ -553,7 +551,7 @@ class Definition(BaseDefinition):
|
||||
if typ == 'function':
|
||||
# For the description we want a short and a pythonic way.
|
||||
typ = 'def'
|
||||
return typ + ' ' + self._name.string_name
|
||||
return typ + ' ' + self._name.get_public_name()
|
||||
|
||||
definition = tree_name.get_definition() or tree_name
|
||||
# Remove the prefix, because that's not what we want for get_code
|
||||
@@ -588,7 +586,7 @@ class Definition(BaseDefinition):
|
||||
"""
|
||||
defs = self._name.infer()
|
||||
return sorted(
|
||||
unite(defined_names(self._evaluator, d) for d in defs),
|
||||
unite(defined_names(self._inference_state, d.as_context()) for d in defs),
|
||||
key=lambda s: s._name.start_pos or (0, 0)
|
||||
)
|
||||
|
||||
@@ -606,13 +604,13 @@ class Definition(BaseDefinition):
|
||||
return self._name.start_pos == other._name.start_pos \
|
||||
and self.module_path == other.module_path \
|
||||
and self.name == other.name \
|
||||
and self._evaluator == other._evaluator
|
||||
and self._inference_state == other._inference_state
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self._name.start_pos, self.module_path, self.name, self._evaluator))
|
||||
return hash((self._name.start_pos, self.module_path, self.name, self._inference_state))
|
||||
|
||||
|
||||
class Signature(Definition):
|
||||
@@ -621,8 +619,8 @@ class Signature(Definition):
|
||||
It knows what functions you are currently in. e.g. `isinstance(` would
|
||||
return the `isinstance` function. without `(` it would return nothing.
|
||||
"""
|
||||
def __init__(self, evaluator, signature):
|
||||
super(Signature, self).__init__(evaluator, signature.name)
|
||||
def __init__(self, inference_state, signature):
|
||||
super(Signature, self).__init__(inference_state, signature.name)
|
||||
self._signature = signature
|
||||
|
||||
@property
|
||||
@@ -630,7 +628,7 @@ class Signature(Definition):
|
||||
"""
|
||||
:return list of ParamDefinition:
|
||||
"""
|
||||
return [ParamDefinition(self._evaluator, n)
|
||||
return [ParamDefinition(self._inference_state, n)
|
||||
for n in self._signature.get_param_names(resolve_stars=True)]
|
||||
|
||||
def to_string(self):
|
||||
@@ -644,8 +642,8 @@ class CallSignature(Signature):
|
||||
return the `isinstance` function with its params. Without `(` it would
|
||||
return nothing.
|
||||
"""
|
||||
def __init__(self, evaluator, signature, call_details):
|
||||
super(CallSignature, self).__init__(evaluator, signature)
|
||||
def __init__(self, inference_state, signature, call_details):
|
||||
super(CallSignature, self).__init__(inference_state, signature)
|
||||
self._call_details = call_details
|
||||
self._signature = signature
|
||||
|
||||
@@ -680,7 +678,7 @@ class ParamDefinition(Definition):
|
||||
"""
|
||||
:return list of Definition:
|
||||
"""
|
||||
return _contexts_to_definitions(self._name.infer_default())
|
||||
return _values_to_definitions(self._name.infer_default())
|
||||
|
||||
def infer_annotation(self, **kwargs):
|
||||
"""
|
||||
@@ -689,7 +687,7 @@ class ParamDefinition(Definition):
|
||||
:param execute_annotation: If False, the values are not executed and
|
||||
you get classes instead of instances.
|
||||
"""
|
||||
return _contexts_to_definitions(self._name.infer_annotation(**kwargs))
|
||||
return _values_to_definitions(self._name.infer_annotation(ignore_stars=True, **kwargs))
|
||||
|
||||
def to_string(self):
|
||||
return self._name.to_string()
|
||||
@@ -709,10 +707,10 @@ class ParamDefinition(Definition):
|
||||
return self._name.get_kind()
|
||||
|
||||
|
||||
def _format_signatures(context):
|
||||
def _format_signatures(value):
|
||||
return '\n'.join(
|
||||
signature.to_string()
|
||||
for signature in context.get_signatures()
|
||||
for signature in value.get_signatures()
|
||||
)
|
||||
|
||||
|
||||
@@ -725,7 +723,7 @@ class _Help(object):
|
||||
self._name = definition
|
||||
|
||||
@memoize_method
|
||||
def _get_contexts(self, fast):
|
||||
def _get_values(self, fast):
|
||||
if isinstance(self._name, ImportName) and fast:
|
||||
return {}
|
||||
|
||||
@@ -742,20 +740,20 @@ class _Help(object):
|
||||
"""
|
||||
full_doc = ''
|
||||
# Using the first docstring that we see.
|
||||
for context in self._get_contexts(fast=fast):
|
||||
for value in self._get_values(fast=fast):
|
||||
if full_doc:
|
||||
# In case we have multiple contexts, just return all of them
|
||||
# In case we have multiple values, just return all of them
|
||||
# separated by a few dashes.
|
||||
full_doc += '\n' + '-' * 30 + '\n'
|
||||
|
||||
doc = context.py__doc__()
|
||||
doc = value.py__doc__()
|
||||
|
||||
signature_text = ''
|
||||
if self._name.is_context_name:
|
||||
if self._name.is_value_name:
|
||||
if not raw:
|
||||
signature_text = _format_signatures(context)
|
||||
if not doc and context.is_stub():
|
||||
for c in convert_contexts(ContextSet({context}), ignore_compiled=False):
|
||||
signature_text = _format_signatures(value)
|
||||
if not doc and value.is_stub():
|
||||
for c in convert_values(ValueSet({value}), ignore_compiled=False):
|
||||
doc = c.py__doc__()
|
||||
if doc:
|
||||
break
|
||||
|
||||
@@ -11,11 +11,11 @@ from jedi.api import classes
|
||||
from jedi.api import helpers
|
||||
from jedi.api import keywords
|
||||
from jedi.api.file_name import file_name_completions
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate.helpers import evaluate_call_of_leaf, parse_dotted_names
|
||||
from jedi.evaluate.filters import get_global_filters
|
||||
from jedi.evaluate.gradual.conversion import convert_contexts
|
||||
from jedi.parser_utils import get_statement_of_position, cut_value_at_position
|
||||
from jedi.inference import imports
|
||||
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
|
||||
from jedi.inference.context import get_global_filters
|
||||
from jedi.inference.gradual.conversion import convert_values
|
||||
from jedi.parser_utils import cut_value_at_position
|
||||
|
||||
|
||||
def get_call_signature_param_names(call_signatures):
|
||||
@@ -28,7 +28,7 @@ def get_call_signature_param_names(call_signatures):
|
||||
yield p._name
|
||||
|
||||
|
||||
def filter_names(evaluator, completion_names, stack, like_name):
|
||||
def filter_names(inference_state, completion_names, stack, like_name):
|
||||
comp_dct = {}
|
||||
if settings.case_insensitive_completion:
|
||||
like_name = like_name.lower()
|
||||
@@ -39,7 +39,7 @@ def filter_names(evaluator, completion_names, stack, like_name):
|
||||
|
||||
if string.startswith(like_name):
|
||||
new = classes.Completion(
|
||||
evaluator,
|
||||
inference_state,
|
||||
name,
|
||||
stack,
|
||||
len(like_name)
|
||||
@@ -52,28 +52,12 @@ def filter_names(evaluator, completion_names, stack, like_name):
|
||||
yield new
|
||||
|
||||
|
||||
def get_user_scope(module_context, position):
|
||||
def get_user_context(module_context, position):
|
||||
"""
|
||||
Returns the scope in which the user resides. This includes flows.
|
||||
"""
|
||||
user_stmt = get_statement_of_position(module_context.tree_node, position)
|
||||
if user_stmt is None:
|
||||
def scan(scope):
|
||||
for s in scope.children:
|
||||
if s.start_pos <= position <= s.end_pos:
|
||||
if isinstance(s, (tree.Scope, tree.Flow)) \
|
||||
or s.type in ('async_stmt', 'async_funcdef'):
|
||||
return scan(s) or s
|
||||
elif s.type in ('suite', 'decorated'):
|
||||
return scan(s)
|
||||
return None
|
||||
|
||||
scanned_node = scan(module_context.tree_node)
|
||||
if scanned_node:
|
||||
return module_context.create_context(scanned_node, node_is_context=True)
|
||||
return module_context
|
||||
else:
|
||||
return module_context.create_context(user_stmt)
|
||||
leaf = module_context.tree_node.get_leaf_for_position(position, include_prefixes=True)
|
||||
return module_context.create_context(leaf)
|
||||
|
||||
|
||||
def get_flow_scope_node(module_node, position):
|
||||
@@ -85,10 +69,11 @@ def get_flow_scope_node(module_node, position):
|
||||
|
||||
|
||||
class Completion:
|
||||
def __init__(self, evaluator, module, code_lines, position, call_signatures_callback):
|
||||
self._evaluator = evaluator
|
||||
self._module_context = module
|
||||
self._module_node = module.tree_node
|
||||
def __init__(self, inference_state, module_context, code_lines, position,
|
||||
call_signatures_callback):
|
||||
self._inference_state = inference_state
|
||||
self._module_context = module_context
|
||||
self._module_node = module_context.tree_node
|
||||
self._code_lines = code_lines
|
||||
|
||||
# The first step of completions is to get the name
|
||||
@@ -104,25 +89,25 @@ class Completion:
|
||||
string, start_leaf = _extract_string_while_in_string(leaf, self._position)
|
||||
if string is not None:
|
||||
completions = list(file_name_completions(
|
||||
self._evaluator, self._module_context, start_leaf, string,
|
||||
self._inference_state, self._module_context, start_leaf, string,
|
||||
self._like_name, self._call_signatures_callback,
|
||||
self._code_lines, self._original_position
|
||||
))
|
||||
if completions:
|
||||
return completions
|
||||
|
||||
completion_names = self._get_context_completions(leaf)
|
||||
completion_names = self._get_value_completions(leaf)
|
||||
|
||||
completions = filter_names(self._evaluator, completion_names,
|
||||
completions = filter_names(self._inference_state, completion_names,
|
||||
self.stack, self._like_name)
|
||||
|
||||
return sorted(completions, key=lambda x: (x.name.startswith('__'),
|
||||
x.name.startswith('_'),
|
||||
x.name.lower()))
|
||||
|
||||
def _get_context_completions(self, leaf):
|
||||
def _get_value_completions(self, leaf):
|
||||
"""
|
||||
Analyzes the context that a completion is made in and decides what to
|
||||
Analyzes the value that a completion is made in and decides what to
|
||||
return.
|
||||
|
||||
Technically this works by generating a parser stack and analysing the
|
||||
@@ -135,7 +120,7 @@ class Completion:
|
||||
- In params (also lambda): no completion before =
|
||||
"""
|
||||
|
||||
grammar = self._evaluator.grammar
|
||||
grammar = self._inference_state.grammar
|
||||
self.stack = stack = None
|
||||
|
||||
try:
|
||||
@@ -149,7 +134,7 @@ class Completion:
|
||||
# completions since this probably just confuses the user.
|
||||
return []
|
||||
|
||||
# If we don't have a context, just use global completion.
|
||||
# If we don't have a value, just use global completion.
|
||||
return self._global_completions()
|
||||
|
||||
allowed_transitions = \
|
||||
@@ -208,7 +193,7 @@ class Completion:
|
||||
if nodes and nodes[-1] in ('as', 'def', 'class'):
|
||||
# No completions for ``with x as foo`` and ``import x as foo``.
|
||||
# Also true for defining names as a class or function.
|
||||
return list(self._get_class_context_completions(is_function=True))
|
||||
return list(self._get_class_value_completions(is_function=True))
|
||||
elif "import_stmt" in nonterminals:
|
||||
level, names = parse_dotted_names(nodes, "import_from" in nonterminals)
|
||||
|
||||
@@ -223,7 +208,7 @@ class Completion:
|
||||
completion_names += self._trailer_completions(dot.get_previous_leaf())
|
||||
else:
|
||||
completion_names += self._global_completions()
|
||||
completion_names += self._get_class_context_completions(is_function=False)
|
||||
completion_names += self._get_class_value_completions(is_function=False)
|
||||
|
||||
if 'trailer' in nonterminals:
|
||||
call_signatures = self._call_signatures_callback()
|
||||
@@ -234,17 +219,16 @@ class Completion:
|
||||
def _get_keyword_completion_names(self, allowed_transitions):
|
||||
for k in allowed_transitions:
|
||||
if isinstance(k, str) and k.isalpha():
|
||||
yield keywords.KeywordName(self._evaluator, k)
|
||||
yield keywords.KeywordName(self._inference_state, k)
|
||||
|
||||
def _global_completions(self):
|
||||
context = get_user_scope(self._module_context, self._position)
|
||||
context = get_user_context(self._module_context, self._position)
|
||||
debug.dbg('global completion scope: %s', context)
|
||||
flow_scope_node = get_flow_scope_node(self._module_node, self._position)
|
||||
filters = get_global_filters(
|
||||
self._evaluator,
|
||||
context,
|
||||
self._position,
|
||||
origin_scope=flow_scope_node
|
||||
flow_scope_node
|
||||
)
|
||||
completion_names = []
|
||||
for filter in filters:
|
||||
@@ -252,52 +236,43 @@ class Completion:
|
||||
return completion_names
|
||||
|
||||
def _trailer_completions(self, previous_leaf):
|
||||
user_context = get_user_scope(self._module_context, self._position)
|
||||
evaluation_context = self._evaluator.create_context(
|
||||
self._module_context, previous_leaf
|
||||
)
|
||||
contexts = evaluate_call_of_leaf(evaluation_context, previous_leaf)
|
||||
user_value = get_user_context(self._module_context, self._position)
|
||||
inferred_context = self._module_context.create_context(previous_leaf)
|
||||
values = infer_call_of_leaf(inferred_context, previous_leaf)
|
||||
completion_names = []
|
||||
debug.dbg('trailer completion contexts: %s', contexts, color='MAGENTA')
|
||||
for context in contexts:
|
||||
for filter in context.get_filters(
|
||||
search_global=False,
|
||||
origin_scope=user_context.tree_node):
|
||||
debug.dbg('trailer completion values: %s', values, color='MAGENTA')
|
||||
for value in values:
|
||||
for filter in value.get_filters(origin_scope=user_value.tree_node):
|
||||
completion_names += filter.values()
|
||||
|
||||
python_contexts = convert_contexts(contexts)
|
||||
for c in python_contexts:
|
||||
if c not in contexts:
|
||||
for filter in c.get_filters(
|
||||
search_global=False,
|
||||
origin_scope=user_context.tree_node):
|
||||
python_values = convert_values(values)
|
||||
for c in python_values:
|
||||
if c not in values:
|
||||
for filter in c.get_filters(origin_scope=user_value.tree_node):
|
||||
completion_names += filter.values()
|
||||
return completion_names
|
||||
|
||||
def _get_importer_names(self, names, level=0, only_modules=True):
|
||||
names = [n.value for n in names]
|
||||
i = imports.Importer(self._evaluator, names, self._module_context, level)
|
||||
return i.completion_names(self._evaluator, only_modules=only_modules)
|
||||
i = imports.Importer(self._inference_state, names, self._module_context, level)
|
||||
return i.completion_names(self._inference_state, only_modules=only_modules)
|
||||
|
||||
def _get_class_context_completions(self, is_function=True):
|
||||
def _get_class_value_completions(self, is_function=True):
|
||||
"""
|
||||
Autocomplete inherited methods when overriding in child class.
|
||||
"""
|
||||
leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
|
||||
cls = tree.search_ancestor(leaf, 'classdef')
|
||||
if isinstance(cls, (tree.Class, tree.Function)):
|
||||
# Complete the methods that are defined in the super classes.
|
||||
random_context = self._module_context.create_context(
|
||||
cls,
|
||||
node_is_context=True
|
||||
)
|
||||
else:
|
||||
if cls is None:
|
||||
return
|
||||
|
||||
# Complete the methods that are defined in the super classes.
|
||||
class_value = self._module_context.create_value(cls)
|
||||
|
||||
if cls.start_pos[1] >= leaf.start_pos[1]:
|
||||
return
|
||||
|
||||
filters = random_context.get_filters(search_global=False, is_instance=True)
|
||||
filters = class_value.get_filters(is_instance=True)
|
||||
# The first dict is the dictionary of class itself.
|
||||
next(filters)
|
||||
for filter in filters:
|
||||
|
||||
@@ -10,8 +10,8 @@ from collections import namedtuple
|
||||
|
||||
from jedi._compatibility import highest_pickle_protocol, which
|
||||
from jedi.cache import memoize_method, time_cache
|
||||
from jedi.evaluate.compiled.subprocess import CompiledSubprocess, \
|
||||
EvaluatorSameProcess, EvaluatorSubprocess
|
||||
from jedi.inference.compiled.subprocess import CompiledSubprocess, \
|
||||
InferenceStateSameProcess, InferenceStateSubprocess
|
||||
|
||||
import parso
|
||||
|
||||
@@ -109,8 +109,8 @@ class Environment(_BaseEnvironment):
|
||||
version = '.'.join(str(i) for i in self.version_info)
|
||||
return '<%s: %s in %s>' % (self.__class__.__name__, version, self.path)
|
||||
|
||||
def get_evaluator_subprocess(self, evaluator):
|
||||
return EvaluatorSubprocess(evaluator, self._get_subprocess())
|
||||
def get_inference_state_subprocess(self, inference_state):
|
||||
return InferenceStateSubprocess(inference_state, self._get_subprocess())
|
||||
|
||||
@memoize_method
|
||||
def get_sys_path(self):
|
||||
@@ -140,8 +140,8 @@ class SameEnvironment(_SameEnvironmentMixin, Environment):
|
||||
|
||||
|
||||
class InterpreterEnvironment(_SameEnvironmentMixin, _BaseEnvironment):
|
||||
def get_evaluator_subprocess(self, evaluator):
|
||||
return EvaluatorSameProcess(evaluator)
|
||||
def get_inference_state_subprocess(self, inference_state):
|
||||
return InferenceStateSameProcess(inference_state)
|
||||
|
||||
def get_sys_path(self):
|
||||
return sys.path
|
||||
@@ -286,7 +286,7 @@ def find_virtualenvs(paths=None, **kwargs):
|
||||
for path in os.listdir(directory):
|
||||
path = os.path.join(directory, path)
|
||||
if path in _used_paths:
|
||||
# A path shouldn't be evaluated twice.
|
||||
# A path shouldn't be inferred twice.
|
||||
continue
|
||||
_used_paths.add(path)
|
||||
|
||||
|
||||
@@ -1,37 +1,13 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from jedi._compatibility import FileNotFoundError, force_unicode, scandir
|
||||
from jedi.evaluate.names import AbstractArbitraryName
|
||||
from jedi.inference.names import AbstractArbitraryName
|
||||
from jedi.api import classes
|
||||
from jedi.evaluate.helpers import get_str_or_none
|
||||
from jedi.inference.helpers import get_str_or_none
|
||||
from jedi.parser_utils import get_string_quote
|
||||
|
||||
|
||||
if sys.version_info < (3,6) or True:
|
||||
"""
|
||||
A super-minimal shim around listdir that behave like
|
||||
scandir for the information we need.
|
||||
"""
|
||||
class DirEntry:
|
||||
|
||||
def __init__(self, name, basepath):
|
||||
self.name = name
|
||||
self.basepath = basepath
|
||||
|
||||
def is_dir(self):
|
||||
path_for_name = os.path.join(self.basepath, self.name)
|
||||
return os.path.isdir(path_for_name)
|
||||
|
||||
def scandir(dir):
|
||||
return [DirEntry(name, dir) for name in os.listdir(dir)]
|
||||
else:
|
||||
from os import scandir
|
||||
|
||||
|
||||
|
||||
|
||||
def file_name_completions(evaluator, module_context, start_leaf, string,
|
||||
def file_name_completions(inference_state, module_context, start_leaf, string,
|
||||
like_name, call_signatures_callback, code_lines, position):
|
||||
# First we want to find out what can actually be changed as a name.
|
||||
like_name_length = len(os.path.basename(string) + like_name)
|
||||
@@ -54,7 +30,7 @@ def file_name_completions(evaluator, module_context, start_leaf, string,
|
||||
is_in_os_path_join = False
|
||||
else:
|
||||
string = to_be_added + string
|
||||
base_path = os.path.join(evaluator.project._path, string)
|
||||
base_path = os.path.join(inference_state.project._path, string)
|
||||
try:
|
||||
listed = scandir(base_path)
|
||||
except FileNotFoundError:
|
||||
@@ -77,8 +53,8 @@ def file_name_completions(evaluator, module_context, start_leaf, string,
|
||||
name += os.path.sep
|
||||
|
||||
yield classes.Completion(
|
||||
evaluator,
|
||||
FileName(evaluator, name[len(must_start_with) - like_name_length:]),
|
||||
inference_state,
|
||||
FileName(inference_state, name[len(must_start_with) - like_name_length:]),
|
||||
stack=None,
|
||||
like_name_length=like_name_length
|
||||
)
|
||||
@@ -109,10 +85,10 @@ def _add_strings(context, nodes, add_slash=False):
|
||||
string = ''
|
||||
first = True
|
||||
for child_node in nodes:
|
||||
contexts = context.eval_node(child_node)
|
||||
if len(contexts) != 1:
|
||||
values = context.infer_node(child_node)
|
||||
if len(values) != 1:
|
||||
return None
|
||||
c, = contexts
|
||||
c, = values
|
||||
s = get_str_or_none(c)
|
||||
if s is None:
|
||||
return None
|
||||
@@ -125,7 +101,7 @@ def _add_strings(context, nodes, add_slash=False):
|
||||
|
||||
class FileName(AbstractArbitraryName):
|
||||
api_type = u'path'
|
||||
is_context_name = False
|
||||
is_value_name = False
|
||||
|
||||
|
||||
def _add_os_path_join(module_context, start_leaf, bracket_start):
|
||||
@@ -140,10 +116,10 @@ def _add_os_path_join(module_context, start_leaf, bracket_start):
|
||||
|
||||
if start_leaf.type == 'error_leaf':
|
||||
# Unfinished string literal, like `join('`
|
||||
context_node = start_leaf.parent
|
||||
index = context_node.children.index(start_leaf)
|
||||
value_node = start_leaf.parent
|
||||
index = value_node.children.index(start_leaf)
|
||||
if index > 0:
|
||||
error_node = context_node.children[index - 1]
|
||||
error_node = value_node.children[index - 1]
|
||||
if error_node.type == 'error_node' and len(error_node.children) >= 2:
|
||||
index = -2
|
||||
if error_node.children[-1].type == 'arglist':
|
||||
|
||||
@@ -9,10 +9,10 @@ from parso.python.parser import Parser
|
||||
from parso.python import tree
|
||||
|
||||
from jedi._compatibility import u, Parameter
|
||||
from jedi.evaluate.base_context import NO_CONTEXTS
|
||||
from jedi.evaluate.syntax_tree import eval_atom
|
||||
from jedi.evaluate.helpers import evaluate_call_of_leaf
|
||||
from jedi.evaluate.compiled import get_string_context_set
|
||||
from jedi.inference.base_value import NO_VALUES
|
||||
from jedi.inference.syntax_tree import infer_atom
|
||||
from jedi.inference.helpers import infer_call_of_leaf
|
||||
from jedi.inference.compiled import get_string_value_set
|
||||
from jedi.cache import call_signature_time_cache
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ def _get_code_for_stack(code_lines, leaf, position):
|
||||
if is_after_newline:
|
||||
if user_stmt.start_pos[1] > position[1]:
|
||||
# This means that it's actually a dedent and that means that we
|
||||
# start without context (part of a suite).
|
||||
# start without value (part of a suite).
|
||||
return u('')
|
||||
|
||||
# This is basically getting the relevant lines.
|
||||
@@ -136,25 +136,25 @@ def get_stack_at_position(grammar, code_lines, leaf, pos):
|
||||
)
|
||||
|
||||
|
||||
def evaluate_goto_definition(evaluator, context, leaf):
|
||||
def infer_goto_definition(inference_state, context, leaf):
|
||||
if leaf.type == 'name':
|
||||
# In case of a name we can just use goto_definition which does all the
|
||||
# magic itself.
|
||||
return evaluator.goto_definitions(context, leaf)
|
||||
return inference_state.goto_definitions(context, leaf)
|
||||
|
||||
parent = leaf.parent
|
||||
definitions = NO_CONTEXTS
|
||||
definitions = NO_VALUES
|
||||
if parent.type == 'atom':
|
||||
# e.g. `(a + b)`
|
||||
definitions = context.eval_node(leaf.parent)
|
||||
definitions = context.infer_node(leaf.parent)
|
||||
elif parent.type == 'trailer':
|
||||
# e.g. `a()`
|
||||
definitions = evaluate_call_of_leaf(context, leaf)
|
||||
definitions = infer_call_of_leaf(context, leaf)
|
||||
elif isinstance(leaf, tree.Literal):
|
||||
# e.g. `"foo"` or `1.0`
|
||||
return eval_atom(context, leaf)
|
||||
return infer_atom(context, leaf)
|
||||
elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'):
|
||||
return get_string_context_set(evaluator)
|
||||
return get_string_value_set(inference_state)
|
||||
return definitions
|
||||
|
||||
|
||||
@@ -376,7 +376,7 @@ def get_call_signature_details(module, position):
|
||||
|
||||
|
||||
@call_signature_time_cache("call_signatures_validity")
|
||||
def cache_call_signatures(evaluator, context, bracket_leaf, code_lines, user_pos):
|
||||
def cache_call_signatures(inference_state, context, bracket_leaf, code_lines, user_pos):
|
||||
"""This function calculates the cache key."""
|
||||
line_index = user_pos[0] - 1
|
||||
|
||||
@@ -390,8 +390,8 @@ def cache_call_signatures(evaluator, context, bracket_leaf, code_lines, user_pos
|
||||
yield None # Don't cache!
|
||||
else:
|
||||
yield (module_path, before_bracket, bracket_leaf.start_pos)
|
||||
yield evaluate_goto_definition(
|
||||
evaluator,
|
||||
yield infer_goto_definition(
|
||||
inference_state,
|
||||
context,
|
||||
bracket_leaf.get_previous_leaf(),
|
||||
)
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
TODO Some parts of this module are still not well documented.
|
||||
"""
|
||||
|
||||
from jedi.evaluate.context import ModuleContext
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.evaluate.compiled import mixed
|
||||
from jedi.evaluate.compiled.access import create_access_path
|
||||
from jedi.evaluate.base_context import ContextWrapper
|
||||
from jedi.inference import compiled
|
||||
from jedi.inference.compiled import mixed
|
||||
from jedi.inference.compiled.access import create_access_path
|
||||
from jedi.inference.context import ModuleContext
|
||||
|
||||
|
||||
def _create(evaluator, obj):
|
||||
def _create(inference_state, obj):
|
||||
return compiled.create_from_access_path(
|
||||
evaluator, create_access_path(evaluator, obj)
|
||||
inference_state, create_access_path(inference_state, obj)
|
||||
)
|
||||
|
||||
|
||||
@@ -20,28 +19,20 @@ class NamespaceObject(object):
|
||||
self.__dict__ = dct
|
||||
|
||||
|
||||
class MixedModuleContext(ContextWrapper):
|
||||
type = 'mixed_module'
|
||||
|
||||
def __init__(self, evaluator, tree_module, namespaces, file_io, code_lines):
|
||||
module_context = ModuleContext(
|
||||
evaluator, tree_module,
|
||||
file_io=file_io,
|
||||
string_names=('__main__',),
|
||||
code_lines=code_lines
|
||||
)
|
||||
super(MixedModuleContext, self).__init__(module_context)
|
||||
class MixedModuleContext(ModuleContext):
|
||||
def __init__(self, tree_module_value, namespaces):
|
||||
super(MixedModuleContext, self).__init__(tree_module_value)
|
||||
self._namespace_objects = [NamespaceObject(n) for n in namespaces]
|
||||
|
||||
def get_filters(self, *args, **kwargs):
|
||||
for filter in self._wrapped_context.get_filters(*args, **kwargs):
|
||||
for filter in self._value.as_context().get_filters(*args, **kwargs):
|
||||
yield filter
|
||||
|
||||
for namespace_obj in self._namespace_objects:
|
||||
compiled_object = _create(self.evaluator, namespace_obj)
|
||||
compiled_object = _create(self.inference_state, namespace_obj)
|
||||
mixed_object = mixed.MixedObject(
|
||||
compiled_object=compiled_object,
|
||||
tree_context=self._wrapped_context
|
||||
tree_value=self._value
|
||||
)
|
||||
for filter in mixed_object.get_filters(*args, **kwargs):
|
||||
yield filter
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import pydoc
|
||||
|
||||
from jedi.evaluate.utils import ignored
|
||||
from jedi.evaluate.names import AbstractArbitraryName
|
||||
from jedi.inference.utils import ignored
|
||||
from jedi.inference.names import AbstractArbitraryName
|
||||
|
||||
try:
|
||||
from pydoc_data import topics as pydoc_topics
|
||||
@@ -15,24 +15,24 @@ except ImportError:
|
||||
pydoc_topics = None
|
||||
|
||||
|
||||
def get_operator(evaluator, string, pos):
|
||||
return Keyword(evaluator, string, pos)
|
||||
def get_operator(inference_state, string, pos):
|
||||
return Keyword(inference_state, string, pos)
|
||||
|
||||
|
||||
class KeywordName(AbstractArbitraryName):
|
||||
api_type = u'keyword'
|
||||
|
||||
def infer(self):
|
||||
return [Keyword(self.evaluator, self.string_name, (0, 0))]
|
||||
return [Keyword(self.inference_state, self.string_name, (0, 0))]
|
||||
|
||||
|
||||
class Keyword(object):
|
||||
api_type = u'keyword'
|
||||
|
||||
def __init__(self, evaluator, name, pos):
|
||||
self.name = KeywordName(evaluator, name)
|
||||
def __init__(self, inference_state, name, pos):
|
||||
self.name = KeywordName(inference_state, name)
|
||||
self.start_pos = pos
|
||||
self.parent = evaluator.builtins_module
|
||||
self.parent = inference_state.builtins_module
|
||||
|
||||
@property
|
||||
def names(self):
|
||||
@@ -44,7 +44,7 @@ class Keyword(object):
|
||||
|
||||
def get_signatures(self):
|
||||
# TODO this makes no sense, I think Keyword should somehow merge with
|
||||
# Context to make it easier for the api/classes.py to deal with all
|
||||
# Value to make it easier for the api/classes.py to deal with all
|
||||
# of it.
|
||||
return []
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ from jedi.api.environment import SameEnvironment, \
|
||||
get_cached_default_environment
|
||||
from jedi.api.exceptions import WrongVersion
|
||||
from jedi._compatibility import force_unicode
|
||||
from jedi.evaluate.sys_path import discover_buildout_paths
|
||||
from jedi.evaluate.cache import evaluator_as_method_param_cache
|
||||
from jedi.inference.sys_path import discover_buildout_paths
|
||||
from jedi.inference.cache import inference_state_as_method_param_cache
|
||||
from jedi.common.utils import traverse_parents
|
||||
|
||||
_CONFIG_FOLDER = '.jedi'
|
||||
@@ -77,8 +77,8 @@ class Project(object):
|
||||
|
||||
py2_comp(path, **kwargs)
|
||||
|
||||
@evaluator_as_method_param_cache()
|
||||
def _get_base_sys_path(self, evaluator, environment=None):
|
||||
@inference_state_as_method_param_cache()
|
||||
def _get_base_sys_path(self, inference_state, environment=None):
|
||||
if self._sys_path is not None:
|
||||
return self._sys_path
|
||||
|
||||
@@ -93,8 +93,8 @@ class Project(object):
|
||||
pass
|
||||
return sys_path
|
||||
|
||||
@evaluator_as_method_param_cache()
|
||||
def _get_sys_path(self, evaluator, environment=None, add_parent_paths=True):
|
||||
@inference_state_as_method_param_cache()
|
||||
def _get_sys_path(self, inference_state, environment=None, add_parent_paths=True):
|
||||
"""
|
||||
Keep this method private for all users of jedi. However internally this
|
||||
one is used like a public method.
|
||||
@@ -102,15 +102,15 @@ class Project(object):
|
||||
suffixed = []
|
||||
prefixed = []
|
||||
|
||||
sys_path = list(self._get_base_sys_path(evaluator, environment))
|
||||
sys_path = list(self._get_base_sys_path(inference_state, environment))
|
||||
if self._smart_sys_path:
|
||||
prefixed.append(self._path)
|
||||
|
||||
if evaluator.script_path is not None:
|
||||
suffixed += discover_buildout_paths(evaluator, evaluator.script_path)
|
||||
if inference_state.script_path is not None:
|
||||
suffixed += discover_buildout_paths(inference_state, inference_state.script_path)
|
||||
|
||||
if add_parent_paths:
|
||||
traversed = list(traverse_parents(evaluator.script_path))
|
||||
traversed = list(traverse_parents(inference_state.script_path))
|
||||
|
||||
# AFAIK some libraries have imports like `foo.foo.bar`, which
|
||||
# leads to the conclusion to by default prefer longer paths
|
||||
|
||||
Reference in New Issue
Block a user