forked from VimPlug/jedi
Improve a few anonymous function execution context goto issues.
This commit is contained in:
@@ -312,12 +312,10 @@ class BaseDefinition(object):
|
||||
return '.'.join(path if path[0] else path[1:])
|
||||
|
||||
def goto_assignments(self):
|
||||
try:
|
||||
tree_name = self._name.tree_name
|
||||
except AttributeError:
|
||||
if self._name.tree_name is None:
|
||||
return self
|
||||
|
||||
defs = self._evaluator.goto(self._name.parent_context, tree_name)
|
||||
defs = self._evaluator.goto(self._name.parent_context, self._name.tree_name)
|
||||
return [Definition(self._evaluator, d) for d in defs]
|
||||
|
||||
@memoize_method
|
||||
@@ -559,36 +557,34 @@ class Definition(BaseDefinition):
|
||||
|
||||
"""
|
||||
typ = self.type
|
||||
try:
|
||||
tree_name = self._name.tree_name
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
definition = tree_name.get_definition()
|
||||
tree_name = self._name.tree_name
|
||||
if typ in ('function', 'class', 'module') or tree_name is None:
|
||||
if typ == 'function':
|
||||
# For the description we want a short and a pythonic way.
|
||||
typ = 'def'
|
||||
return typ + ' ' + self._name.string_name
|
||||
|
||||
try:
|
||||
first_leaf = definition.first_leaf()
|
||||
except AttributeError:
|
||||
# `d` is already a Leaf (Name).
|
||||
first_leaf = definition
|
||||
# Remove the prefix, because that's not what we want for get_code
|
||||
# here.
|
||||
old, first_leaf.prefix = first_leaf.prefix, ''
|
||||
try:
|
||||
txt = definition.get_code()
|
||||
finally:
|
||||
first_leaf.prefix = old
|
||||
# Delete comments:
|
||||
txt = re.sub('#[^\n]+\n', ' ', txt)
|
||||
# Delete multi spaces/newlines
|
||||
txt = re.sub('\s+', ' ', txt).strip()
|
||||
if typ == 'param':
|
||||
txt = typ + ' ' + txt
|
||||
return txt
|
||||
if typ == 'function':
|
||||
# For the description we want a short and a pythonic way.
|
||||
typ = 'def'
|
||||
return typ + ' ' + self._name.string_name
|
||||
definition = tree_name.get_definition()
|
||||
|
||||
try:
|
||||
first_leaf = definition.first_leaf()
|
||||
except AttributeError:
|
||||
# `d` is already a Leaf (Name).
|
||||
first_leaf = definition
|
||||
# Remove the prefix, because that's not what we want for get_code
|
||||
# here.
|
||||
old, first_leaf.prefix = first_leaf.prefix, ''
|
||||
try:
|
||||
txt = definition.get_code()
|
||||
finally:
|
||||
first_leaf.prefix = old
|
||||
# Delete comments:
|
||||
txt = re.sub('#[^\n]+\n', ' ', txt)
|
||||
# Delete multi spaces/newlines
|
||||
txt = re.sub('\s+', ' ', txt).strip()
|
||||
if typ == 'param':
|
||||
txt = typ + ' ' + txt
|
||||
return txt
|
||||
|
||||
# TODO DELETE
|
||||
|
||||
@@ -664,12 +660,10 @@ class Definition(BaseDefinition):
|
||||
Returns True, if defined as a name in a statement, function or class.
|
||||
Returns False, if it's a reference to such a definition.
|
||||
"""
|
||||
try:
|
||||
tree_name = self._name.tree_name
|
||||
except AttributeError:
|
||||
if self._name.tree_name is None:
|
||||
return True
|
||||
else:
|
||||
return tree_name.is_definition()
|
||||
return self._name.tree_name.is_definition()
|
||||
|
||||
def __eq__(self, other):
|
||||
return self._name.start_pos == other._name.start_pos \
|
||||
@@ -708,22 +702,15 @@ class CallSignature(Definition):
|
||||
return i
|
||||
if self.params:
|
||||
param_name = self.params[-1]._name
|
||||
try:
|
||||
tree_name = param_name.tree_name
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
if tree_name.get_definition().stars == 2:
|
||||
if param_name.tree_name is not None:
|
||||
if param_name.tree_name.get_definition().stars == 2:
|
||||
return i
|
||||
return None
|
||||
|
||||
if self._index >= len(self.params):
|
||||
for i, param in enumerate(self.params):
|
||||
try:
|
||||
tree_name = param._name.tree_name
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
tree_name = param._name.tree_name
|
||||
if tree_name is not None:
|
||||
# *args case
|
||||
if tree_name.get_definition().stars == 1:
|
||||
return i
|
||||
|
||||
@@ -79,7 +79,7 @@ from jedi.evaluate import precedence
|
||||
from jedi.evaluate import param
|
||||
from jedi.evaluate import helpers
|
||||
from jedi.evaluate.filters import TreeNameDefinition
|
||||
from jedi.evaluate.instance import AnonymousInstance, AnonymousInstanceFunctionExecution
|
||||
from jedi.evaluate.instance import AnonymousInstance, BoundMethod
|
||||
|
||||
|
||||
class Evaluator(object):
|
||||
@@ -489,7 +489,10 @@ class Evaluator(object):
|
||||
return [TreeNameDefinition(context, name)]
|
||||
elif isinstance(par, (tree.Param, tree.Function, tree.Class)) and par.name is name:
|
||||
if par.type in ('funcdef', 'classdef', 'module'):
|
||||
return [context.name]
|
||||
if par.type == 'funcdef':
|
||||
return [context.function_context.name]
|
||||
else:
|
||||
return [context.name]
|
||||
return [TreeNameDefinition(context, name)]
|
||||
elif isinstance(stmt, tree.Import):
|
||||
module_names = imports.ImportWrapper(context, name).follow(is_goto=True)
|
||||
@@ -567,13 +570,17 @@ class Evaluator(object):
|
||||
|
||||
if is_funcdef:
|
||||
if isinstance(parent_context, AnonymousInstance):
|
||||
return AnonymousInstanceFunctionExecution(
|
||||
parent_context,
|
||||
parent_context.parent_context,
|
||||
scope_node
|
||||
func = BoundMethod(
|
||||
self, parent_context, parent_context.class_context,
|
||||
parent_context.parent_context, scope_node
|
||||
)
|
||||
else:
|
||||
return er.AnonymousFunctionExecution(self, parent_context, scope_node)
|
||||
func = er.FunctionContext(
|
||||
self,
|
||||
parent_context,
|
||||
scope_node
|
||||
)
|
||||
return func.get_function_execution()
|
||||
elif scope_node.type == 'classdef':
|
||||
class_context = er.ClassContext(self, scope_node, parent_context)
|
||||
if child_is_funcdef:
|
||||
|
||||
@@ -143,19 +143,20 @@ def _evaluate_for_statement_string(module_context, string):
|
||||
return []
|
||||
|
||||
from jedi.evaluate.param import ValuesArguments
|
||||
from jedi.evaluate.representation import FunctionExecutionContext
|
||||
func_context = FunctionExecutionContext(
|
||||
from jedi.evaluate.representation import FunctionContext
|
||||
function_context = FunctionContext(
|
||||
module_context.evaluator,
|
||||
module_context,
|
||||
funcdef,
|
||||
funcdef
|
||||
)
|
||||
func_execution_context = function_context.get_function_execution(
|
||||
ValuesArguments([])
|
||||
)
|
||||
|
||||
# Use the module of the param.
|
||||
# TODO this module is not the module of the param in case of a function
|
||||
# call. In that case it's the module of the function call.
|
||||
# stuffed with content from a function call.
|
||||
return list(_execute_types_in_stmt(func_context, stmt))
|
||||
return list(_execute_types_in_stmt(func_execution_context, stmt))
|
||||
|
||||
|
||||
def _execute_types_in_stmt(module_context, stmt):
|
||||
|
||||
@@ -191,6 +191,7 @@ class ImportName(AbstractNameDefinition):
|
||||
def api_type(self):
|
||||
return 'module'
|
||||
|
||||
|
||||
class SubModuleName(ImportName):
|
||||
def infer(self):
|
||||
return Importer(
|
||||
|
||||
@@ -130,10 +130,13 @@ class AbstractInstanceContext(Context):
|
||||
pass
|
||||
|
||||
def _create_init_execution(self, class_context, func_node):
|
||||
bound_method = BoundMethod(
|
||||
self.evaluator, self, class_context, self.parent_context, func_node
|
||||
)
|
||||
return InstanceFunctionExecution(
|
||||
self,
|
||||
class_context.parent_context,
|
||||
func_node,
|
||||
bound_method,
|
||||
self.var_args
|
||||
)
|
||||
|
||||
@@ -155,11 +158,11 @@ class AbstractInstanceContext(Context):
|
||||
if scope.name.value == '__init__' and parent_context == class_context:
|
||||
return self._create_init_execution(class_context, scope)
|
||||
else:
|
||||
return AnonymousInstanceFunctionExecution(
|
||||
self,
|
||||
class_context.parent_context,
|
||||
scope,
|
||||
bound_method = BoundMethod(
|
||||
self.evaluator, self, class_context,
|
||||
self.parent_context, scope
|
||||
)
|
||||
return bound_method.get_function_execution()
|
||||
else:
|
||||
raise NotImplementedError
|
||||
return class_context
|
||||
@@ -251,13 +254,13 @@ class BoundMethod(er.FunctionContext):
|
||||
self._instance = instance
|
||||
self._class_context = class_context
|
||||
|
||||
def get_function_execution(self, arguments):
|
||||
return InstanceFunctionExecution(
|
||||
self._instance,
|
||||
self.parent_context,
|
||||
self.funcdef,
|
||||
arguments
|
||||
)
|
||||
def get_function_execution(self, arguments=None):
|
||||
if arguments is None:
|
||||
return AnonymousInstanceFunctionExecution(
|
||||
self._instance, self.parent_context, self)
|
||||
else:
|
||||
return InstanceFunctionExecution(
|
||||
self._instance, self.parent_context, self, arguments)
|
||||
|
||||
|
||||
class CompiledBoundMethod(compiled.CompiledObject):
|
||||
@@ -428,17 +431,17 @@ class InstanceVarArgs(object):
|
||||
|
||||
|
||||
class InstanceFunctionExecution(er.FunctionExecutionContext):
|
||||
def __init__(self, instance, parent_context, funcdef, var_args):
|
||||
def __init__(self, instance, parent_context, function_context, var_args):
|
||||
self.instance = instance
|
||||
var_args = InstanceVarArgs(instance, funcdef, var_args)
|
||||
var_args = InstanceVarArgs(instance, function_context.funcdef, var_args)
|
||||
|
||||
super(InstanceFunctionExecution, self).__init__(
|
||||
instance.evaluator, parent_context, funcdef, var_args)
|
||||
instance.evaluator, parent_context, function_context, var_args)
|
||||
|
||||
|
||||
class AnonymousInstanceFunctionExecution(InstanceFunctionExecution):
|
||||
function_execution_filter = filters.AnonymousInstanceFunctionExecutionFilter
|
||||
|
||||
def __init__(self, instance, parent_context, funcdef):
|
||||
def __init__(self, instance, parent_context, function_context):
|
||||
super(AnonymousInstanceFunctionExecution, self).__init__(
|
||||
instance, parent_context, funcdef, None)
|
||||
instance, parent_context, function_context, None)
|
||||
|
||||
@@ -252,13 +252,12 @@ class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext)):
|
||||
else:
|
||||
return function_execution.get_return_values()
|
||||
|
||||
def get_function_execution(self, arguments):
|
||||
return FunctionExecutionContext(
|
||||
self.evaluator,
|
||||
self.parent_context,
|
||||
self.base,
|
||||
arguments
|
||||
)
|
||||
def get_function_execution(self, arguments=None):
|
||||
e = self.evaluator
|
||||
if arguments is None:
|
||||
return AnonymousFunctionExecution(e, self.parent_context, self)
|
||||
else:
|
||||
return FunctionExecutionContext(e, self.parent_context, self, arguments)
|
||||
|
||||
def py__call__(self, arguments):
|
||||
function_execution = self.get_function_execution(arguments)
|
||||
@@ -281,7 +280,7 @@ class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext)):
|
||||
anon = AnonymousFunctionExecution(
|
||||
self.evaluator,
|
||||
self.parent_context,
|
||||
self.funcdef
|
||||
self
|
||||
)
|
||||
return [ParamName(anon, param.name) for param in self.funcdef.params]
|
||||
|
||||
@@ -297,12 +296,14 @@ class FunctionExecutionContext(Executed):
|
||||
"""
|
||||
function_execution_filter = FunctionExecutionFilter
|
||||
|
||||
def __init__(self, evaluator, parent_context, funcdef, var_args):
|
||||
def __init__(self, evaluator, parent_context, function_context, var_args):
|
||||
super(FunctionExecutionContext, self).__init__(evaluator, parent_context, var_args)
|
||||
self.funcdef = funcdef
|
||||
if isinstance(funcdef, mixed.MixedObject):
|
||||
self.function_context = function_context
|
||||
self.funcdef = function_context.funcdef
|
||||
if isinstance(function_context, mixed.MixedObject):
|
||||
# The extra information in mixed is not needed anymore. We can just
|
||||
# unpack it and give it the tree object.
|
||||
raise DeprecationWarning
|
||||
funcdef = funcdef.definition
|
||||
|
||||
# Just overwrite the old version. We don't need it anymore.
|
||||
@@ -316,7 +317,7 @@ class FunctionExecutionContext(Executed):
|
||||
#self._copied_funcdef = funcdef
|
||||
|
||||
def get_node(self):
|
||||
return self.funcdef
|
||||
return self.function_context.funcdef
|
||||
|
||||
@memoize_default(default=set())
|
||||
@recursion.execution_recursion_decorator
|
||||
@@ -426,9 +427,9 @@ class FunctionExecutionContext(Executed):
|
||||
|
||||
|
||||
class AnonymousFunctionExecution(FunctionExecutionContext):
|
||||
def __init__(self, evaluator, parent_context, funcdef):
|
||||
def __init__(self, evaluator, parent_context, function_context):
|
||||
super(AnonymousFunctionExecution, self).__init__(
|
||||
evaluator, parent_context, funcdef, var_args=None)
|
||||
evaluator, parent_context, function_context, var_args=None)
|
||||
|
||||
@memoize_default(default=NO_DEFAULT)
|
||||
def get_params(self):
|
||||
|
||||
@@ -22,10 +22,10 @@ cd = e
|
||||
|
||||
#! ['module math']
|
||||
import math
|
||||
#! ['import math']
|
||||
#! ['module math']
|
||||
math
|
||||
|
||||
#! ['import math']
|
||||
#! ['module math']
|
||||
b = math
|
||||
#! ['b = math']
|
||||
b
|
||||
@@ -148,7 +148,7 @@ mod1.a
|
||||
#! ['a = 1.0']
|
||||
from import_tree.pkg.mod1 import a
|
||||
|
||||
#! ['import os']
|
||||
#! ['module os']
|
||||
from .imports import os
|
||||
|
||||
#! ['some_variable = 1']
|
||||
|
||||
Reference in New Issue
Block a user