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