Improve a few anonymous function execution context goto issues.

This commit is contained in:
Dave Halter
2016-12-04 22:35:23 +01:00
parent 6f4cd7e6d3
commit 641ecedcd2
7 changed files with 94 additions and 94 deletions

View File

@@ -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,11 +557,13 @@ class Definition(BaseDefinition):
""" """
typ = self.type typ = self.type
try:
tree_name = self._name.tree_name tree_name = self._name.tree_name
except AttributeError: if typ in ('function', 'class', 'module') or tree_name is None:
pass if typ == 'function':
else: # For the description we want a short and a pythonic way.
typ = 'def'
return typ + ' ' + self._name.string_name
definition = tree_name.get_definition() definition = tree_name.get_definition()
try: try:
@@ -585,10 +585,6 @@ class Definition(BaseDefinition):
if typ == 'param': if typ == 'param':
txt = typ + ' ' + txt txt = typ + ' ' + txt
return 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
# 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
except AttributeError: if tree_name is not None:
pass
else:
# *args case # *args case
if tree_name.get_definition().stars == 1: if tree_name.get_definition().stars == 1:
return i return i

View File

@@ -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,6 +489,9 @@ 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'):
if par.type == 'funcdef':
return [context.function_context.name]
else:
return [context.name] return [context.name]
return [TreeNameDefinition(context, name)] return [TreeNameDefinition(context, name)]
elif isinstance(stmt, tree.Import): elif isinstance(stmt, tree.Import):
@@ -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:

View File

@@ -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):

View File

@@ -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(

View File

@@ -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):
if arguments is None:
return AnonymousInstanceFunctionExecution(
self._instance, self.parent_context, self)
else:
return InstanceFunctionExecution( return InstanceFunctionExecution(
self._instance, self._instance, self.parent_context, self, arguments)
self.parent_context,
self.funcdef,
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)

View File

@@ -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):

View File

@@ -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']