From 0475bb5fd07e48ca7defb81da3c634f18fa78c64 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sun, 23 Oct 2016 03:02:57 +0200 Subject: [PATCH] First function execution that is working. --- jedi/evaluate/__init__.py | 11 ++++++----- jedi/evaluate/filters.py | 9 ++++++--- jedi/evaluate/param.py | 34 +++++++++++++++------------------ jedi/evaluate/representation.py | 6 +----- 4 files changed, 28 insertions(+), 32 deletions(-) diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index b332fa8d..25ead36e 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -303,7 +303,7 @@ class Evaluator(object): right = self.eval_element(context, element.children[2]) types = set(precedence.calculate(self, types, trailer, right)) break - types = self.eval_trailer(types, trailer) + types = self.eval_trailer(context, types, trailer) elif element.type in ('testlist_star_expr', 'testlist',): # The implicit tuple in statements. types = set([iterable.ImplicitTuple(self, element)]) @@ -388,7 +388,7 @@ class Evaluator(object): return set([iterable.Comprehension.from_atom(self, atom)]) return set([iterable.Array(self, atom)]) - def eval_trailer(self, types, trailer): + def eval_trailer(self, context, types, trailer): trailer_op, node = trailer.children[:2] if node == ')': # `arglist` is optional. node = () @@ -402,7 +402,8 @@ class Evaluator(object): if trailer_op == '.': new_types |= self.find_types(typ, node) elif trailer_op == '(': - new_types |= self.execute(typ, node, trailer) + arguments = param.Arguments(self, context, node, trailer) + new_types |= self.execute(typ, arguments) return new_types def execute_evaluated(self, obj, *args): @@ -413,9 +414,9 @@ class Evaluator(object): return self.execute(obj, args) @debug.increase_indent - def execute(self, obj, arguments=(), trailer=None): + def execute(self, obj, arguments=None): if not isinstance(arguments, param.Arguments): - arguments = param.Arguments(self, arguments, trailer) + arguments = param.Arguments(self, arguments) if self.is_analysis: arguments.eval_all() diff --git a/jedi/evaluate/filters.py b/jedi/evaluate/filters.py index f0b8d6a8..156e8d7c 100644 --- a/jedi/evaluate/filters.py +++ b/jedi/evaluate/filters.py @@ -62,7 +62,11 @@ class ParamName(ContextName): self.name = name def infer(self): - return set() + return self._get_param().infer(self.parent_context._evaluator) + + def _get_param(self): + params = self.parent_context.get_params() + return [p for p in params if p.string_name == self.string_name][0] class AbstractFilter(object): @@ -136,7 +140,7 @@ class ParserTreeFilter(AbstractUsedNamesFilter): class FunctionExecutionFilter(ParserTreeFilter): - def __init__(self, evaluator, context, parser_scope, param_by_name, + def __init__(self, evaluator, context, parser_scope, until_position=None, origin_scope=None): super(FunctionExecutionFilter, self).__init__( evaluator, @@ -150,7 +154,6 @@ class FunctionExecutionFilter(ParserTreeFilter): for name in names: param = search_ancestor(name, 'param') if param: - #yield self.context._param_by_name(str(name)) yield ParamName(self._context, name) else: yield TreeNameDefinition(self._context, name) diff --git a/jedi/evaluate/param.py b/jedi/evaluate/param.py index 66fbd507..9654e418 100644 --- a/jedi/evaluate/param.py +++ b/jedi/evaluate/param.py @@ -8,8 +8,6 @@ from jedi.parser import tree from jedi.evaluate import iterable from jedi.evaluate import analysis from jedi.evaluate import precedence -from jedi.evaluate.helpers import FakeName -from jedi.cache import underscore_memoization def try_iter_content(types, depth=0): @@ -30,7 +28,7 @@ def try_iter_content(types, depth=0): class Arguments(tree.Base): - def __init__(self, evaluator, context, argument_node, trailer=None): + def __init__(self, evaluator, context, argument_node, trailer): """ The argument_node is either a parser node or a list of evaluated objects. Those evaluated objects may be lists of evaluated objects @@ -202,11 +200,14 @@ class ExecutedParam(tree.Param): self._original_param = original_param self.var_args = var_args self._values = values + self.string_name = self._original_param.name.value - def eval(self, evaluator): + def infer(self, evaluator): types = set() for v in self._values: - types |= evaluator.eval_element(v) + # TODO this context selection seems wrong. Fix it once we change + # the way executed params work. + types |= evaluator.eval_element(self.var_args._context, v) return types @property @@ -214,11 +215,6 @@ class ExecutedParam(tree.Param): # Need to use the original logic here, because it uses the parent. return self._original_param.position_nr - @property - @underscore_memoization - def name(self): - return FakeName(str(self._original_param.name), self, self.start_pos) - def __getattr__(self, name): return getattr(self._original_param, name) @@ -249,7 +245,7 @@ def _get_calling_var_args(evaluator, var_args): def get_params(evaluator, func, var_args): - param_names = [] + result_params = [] param_dict = {} for param in func.params: param_dict[str(param.name)] = param @@ -279,7 +275,7 @@ def get_params(evaluator, func, var_args): except KeyError: non_matching_keys[key] = va_values else: - param_names.append(ExecutedParam(key_param, var_args, va_values).name) + result_params.append(ExecutedParam(key_param, var_args, va_values)) if k in keys_used: had_multiple_value_error = True @@ -291,7 +287,7 @@ def get_params(evaluator, func, var_args): calling_va, message=m) else: try: - keys_used[k] = param_names[-1] + keys_used[k] = result_params[-1] except IndexError: # TODO this is wrong stupid and whatever. pass @@ -331,8 +327,8 @@ def get_params(evaluator, func, var_args): # Now add to result if it's not one of the previously covered cases. if (not keys_only or param.stars == 2): - param_names.append(ExecutedParam(param, var_args, values).name) - keys_used[unicode(param.name)] = param_names[-1] + result_params.append(ExecutedParam(param, var_args, values)) + keys_used[unicode(param.name)] = result_params[-1] if keys_only: # All arguments should be handed over to the next function. It's not @@ -341,10 +337,10 @@ def get_params(evaluator, func, var_args): for k in set(param_dict) - set(keys_used): param = param_dict[k] values = [] if param.default is None else [param.default] - param_names.append(ExecutedParam(param, var_args, values).name) + result_params.append(ExecutedParam(param, var_args, values)) - if not (non_matching_keys or had_multiple_value_error - or param.stars or param.default): + if not (non_matching_keys or had_multiple_value_error or + param.stars or param.default): # add a warning only if there's not another one. calling_va = _get_calling_var_args(evaluator, var_args) if calling_va is not None: @@ -382,7 +378,7 @@ def get_params(evaluator, func, var_args): continue analysis.add(evaluator, 'type-error-too-many-arguments', v, message=m) - return param_names + return result_params def _iterate_star_args(evaluator, array, input_node, func=None): diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index a5bb156f..fac7c1fa 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -835,17 +835,13 @@ class FunctionExecutionContext(Executed): def get_filters(self, search_global, until_position=None, origin_scope=None): yield FunctionExecutionFilter(self._evaluator, self, self._funcdef, - self.param_by_name, until_position, origin_scope=origin_scope) @memoize_default(default=NO_DEFAULT) - def _get_params(self): + def get_params(self): return param.get_params(self._evaluator, self._funcdef, self.var_args) - def param_by_name(self, name): - return [n for n in self._get_params() if str(n) == name][0] - def __repr__(self): return "<%s of %s>" % (type(self).__name__, self._funcdef)