mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 14:54:47 +08:00
Also return the issues when retruning the executed params
This commit is contained in:
@@ -86,9 +86,10 @@ def add(node_context, error_name, node, message=None, typ=Error, payload=None):
|
|||||||
# TODO this path is probably not right
|
# TODO this path is probably not right
|
||||||
module_context = node_context.get_root_context()
|
module_context = node_context.get_root_context()
|
||||||
module_path = module_context.py__file__()
|
module_path = module_context.py__file__()
|
||||||
instance = typ(error_name, module_path, node.start_pos, message)
|
issue_instance = typ(error_name, module_path, node.start_pos, message)
|
||||||
debug.warning(str(instance), format=False)
|
debug.warning(str(issue_instance), format=False)
|
||||||
node_context.evaluator.analysis.append(instance)
|
node_context.evaluator.analysis.append(issue_instance)
|
||||||
|
return issue_instance
|
||||||
|
|
||||||
|
|
||||||
def _check_for_setattr(instance):
|
def _check_for_setattr(instance):
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from jedi.evaluate.lazy_context import LazyKnownContext, LazyKnownContexts, \
|
|||||||
from jedi.evaluate.filters import ParamName
|
from jedi.evaluate.filters import ParamName
|
||||||
from jedi.evaluate.base_context import NO_CONTEXTS, ContextSet
|
from jedi.evaluate.base_context import NO_CONTEXTS, ContextSet
|
||||||
from jedi.evaluate.context import iterable
|
from jedi.evaluate.context import iterable
|
||||||
from jedi.evaluate.param import get_executed_params, ExecutedParam
|
from jedi.evaluate.param import get_executed_params_and_issues, ExecutedParam
|
||||||
|
|
||||||
|
|
||||||
def try_iter_content(types, depth=0):
|
def try_iter_content(types, depth=0):
|
||||||
@@ -148,12 +148,12 @@ class AbstractArguments(object):
|
|||||||
def unpack(self, funcdef=None):
|
def unpack(self, funcdef=None):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_executed_params(self, execution_context):
|
def get_executed_params_and_issues(self, execution_context):
|
||||||
return get_executed_params(execution_context, self)
|
return get_executed_params_and_issues(execution_context, self)
|
||||||
|
|
||||||
|
|
||||||
class AnonymousArguments(AbstractArguments):
|
class AnonymousArguments(AbstractArguments):
|
||||||
def get_executed_params(self, execution_context):
|
def get_executed_params_and_issues(self, execution_context):
|
||||||
from jedi.evaluate.dynamic import search_params
|
from jedi.evaluate.dynamic import search_params
|
||||||
return search_params(
|
return search_params(
|
||||||
execution_context.evaluator,
|
execution_context.evaluator,
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class FunctionContext(use_metaclass(CachedMetaClass, AbstractFunction)):
|
|||||||
if overloaded_funcs:
|
if overloaded_funcs:
|
||||||
return OverloadedFunctionContext(
|
return OverloadedFunctionContext(
|
||||||
function,
|
function,
|
||||||
ContextSet.from_iterable(create(f) for f in overloaded_funcs)
|
[create(f) for f in overloaded_funcs]
|
||||||
)
|
)
|
||||||
return function
|
return function
|
||||||
|
|
||||||
@@ -273,12 +273,16 @@ class FunctionExecutionContext(TreeContext):
|
|||||||
origin_scope=origin_scope)
|
origin_scope=origin_scope)
|
||||||
|
|
||||||
@evaluator_method_cache()
|
@evaluator_method_cache()
|
||||||
def get_executed_params(self):
|
def get_executed_params_and_issues(self):
|
||||||
return self.var_args.get_executed_params(self)
|
return self.var_args.get_executed_params_and_issues(self)
|
||||||
|
|
||||||
def matches_signature(self):
|
def matches_signature(self):
|
||||||
|
executed_params, issues = self.get_executed_params_and_issues()
|
||||||
|
if issues:
|
||||||
|
return False
|
||||||
|
|
||||||
matches = all(executed_param.matches_signature()
|
matches = all(executed_param.matches_signature()
|
||||||
for executed_param in self.get_executed_params())
|
for executed_param in executed_params)
|
||||||
if debug.enable_notice:
|
if debug.enable_notice:
|
||||||
signature = parser_utils.get_call_signature(self.tree_node)
|
signature = parser_utils.get_call_signature(self.tree_node)
|
||||||
if matches:
|
if matches:
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ class AnonymousInstanceArguments(AnonymousArguments):
|
|||||||
def __init__(self, instance):
|
def __init__(self, instance):
|
||||||
self._instance = instance
|
self._instance = instance
|
||||||
|
|
||||||
def get_executed_params(self, execution_context):
|
def get_executed_params_and_issues(self, execution_context):
|
||||||
from jedi.evaluate.dynamic import search_params
|
from jedi.evaluate.dynamic import search_params
|
||||||
tree_params = execution_context.tree_node.get_params()
|
tree_params = execution_context.tree_node.get_params()
|
||||||
if not tree_params:
|
if not tree_params:
|
||||||
return []
|
return [], []
|
||||||
|
|
||||||
self_param = InstanceExecutedParam(self._instance, tree_params[0])
|
self_param = InstanceExecutedParam(self._instance, tree_params[0])
|
||||||
if len(tree_params) == 1:
|
if len(tree_params) == 1:
|
||||||
@@ -49,7 +49,7 @@ class AnonymousInstanceArguments(AnonymousArguments):
|
|||||||
execution_context.tree_node
|
execution_context.tree_node
|
||||||
))
|
))
|
||||||
executed_params[0] = self_param
|
executed_params[0] = self_param
|
||||||
return executed_params
|
return [], executed_params
|
||||||
|
|
||||||
|
|
||||||
class AbstractInstanceContext(Context):
|
class AbstractInstanceContext(Context):
|
||||||
@@ -273,7 +273,6 @@ class TreeInstance(AbstractInstanceContext):
|
|||||||
if not execution.matches_signature():
|
if not execution.matches_signature():
|
||||||
# First check if the signature even matches, if not we don't
|
# First check if the signature even matches, if not we don't
|
||||||
# need to infer anything.
|
# need to infer anything.
|
||||||
print('no m', bound)
|
|
||||||
continue
|
continue
|
||||||
print(bound)
|
print(bound)
|
||||||
context_set = define_type_vars_for_execution(
|
context_set = define_type_vars_for_execution(
|
||||||
@@ -541,11 +540,11 @@ class InstanceArguments(AbstractArguments):
|
|||||||
def get_calling_nodes(self):
|
def get_calling_nodes(self):
|
||||||
return self._arguments.get_calling_nodes()
|
return self._arguments.get_calling_nodes()
|
||||||
|
|
||||||
def get_executed_params(self, execution_context):
|
def get_executed_params_and_issues(self, execution_context):
|
||||||
if isinstance(self._arguments, AnonymousInstanceArguments):
|
if isinstance(self._arguments, AnonymousInstanceArguments):
|
||||||
return self._arguments.get_executed_params(execution_context)
|
return self._arguments.get_executed_params_and_issues(execution_context)
|
||||||
|
|
||||||
return super(InstanceArguments, self).get_executed_params(execution_context)
|
return super(InstanceArguments, self).get_executed_params_and_issues(execution_context)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s>' % (self.__class__.__name__, self._arguments)
|
return '<%s: %s>' % (self.__class__.__name__, self._arguments)
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ def search_params(evaluator, execution_context, funcdef):
|
|||||||
)
|
)
|
||||||
if function_executions:
|
if function_executions:
|
||||||
zipped_params = zip(*list(
|
zipped_params = zip(*list(
|
||||||
function_execution.get_executed_params()
|
function_execution.get_executed_params_and_issues()[0]
|
||||||
for function_execution in function_executions
|
for function_execution in function_executions
|
||||||
))
|
))
|
||||||
params = [DynamicExecutedParams(evaluator, executed_params) for executed_params in zipped_params]
|
params = [DynamicExecutedParams(evaluator, executed_params) for executed_params in zipped_params]
|
||||||
@@ -208,7 +208,7 @@ def _check_name_for_execution(evaluator, context, compare_node, name, trailer):
|
|||||||
# Here we're trying to find decorators by checking the first
|
# Here we're trying to find decorators by checking the first
|
||||||
# parameter. It's not very generic though. Should find a better
|
# parameter. It's not very generic though. Should find a better
|
||||||
# solution that also applies to nested decorators.
|
# solution that also applies to nested decorators.
|
||||||
params = value.parent_context.get_executed_params()
|
params, _ = value.parent_context.get_executed_params_and_issues()
|
||||||
if len(params) != 1:
|
if len(params) != 1:
|
||||||
continue
|
continue
|
||||||
values = params[0].infer()
|
values = params[0].infer()
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ class ParamName(AbstractTreeName):
|
|||||||
return self.get_param().infer()
|
return self.get_param().infer()
|
||||||
|
|
||||||
def get_param(self):
|
def get_param(self):
|
||||||
params = self.parent_context.get_executed_params()
|
params, _ = self.parent_context.get_executed_params_and_issues()
|
||||||
param_node = search_ancestor(self.tree_name, 'param')
|
param_node = search_ancestor(self.tree_name, 'param')
|
||||||
return params[param_node.position_index]
|
return params[param_node.position_index]
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ def _add_argument_issue(parent_context, error_name, lazy_context, message):
|
|||||||
node = lazy_context.data
|
node = lazy_context.data
|
||||||
if node.parent.type == 'argument':
|
if node.parent.type == 'argument':
|
||||||
node = node.parent
|
node = node.parent
|
||||||
analysis.add(parent_context, error_name, node, message)
|
return analysis.add(parent_context, error_name, node, message)
|
||||||
|
|
||||||
|
|
||||||
class ExecutedParam(object):
|
class ExecutedParam(object):
|
||||||
@@ -58,7 +58,25 @@ class ExecutedParam(object):
|
|||||||
return '<%s: %s>' % (self.__class__.__name__, self.string_name)
|
return '<%s: %s>' % (self.__class__.__name__, self.string_name)
|
||||||
|
|
||||||
|
|
||||||
def get_executed_params(execution_context, var_args):
|
def get_executed_params_and_issues(execution_context, var_args):
|
||||||
|
def too_many_args(argument):
|
||||||
|
m = _error_argument_count(funcdef, len(unpacked_va))
|
||||||
|
# Just report an error for the first param that is not needed (like
|
||||||
|
# cPython).
|
||||||
|
if var_args.get_calling_nodes():
|
||||||
|
# There might not be a valid calling node so check for that first.
|
||||||
|
issues.append(
|
||||||
|
_add_argument_issue(
|
||||||
|
default_param_context,
|
||||||
|
'type-error-too-many-arguments',
|
||||||
|
lazy_context,
|
||||||
|
message=m
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
issues.append(None)
|
||||||
|
|
||||||
|
issues = [] # List[Optional[analysis issue]]
|
||||||
result_params = []
|
result_params = []
|
||||||
param_dict = {}
|
param_dict = {}
|
||||||
funcdef = execution_context.tree_node
|
funcdef = execution_context.tree_node
|
||||||
@@ -94,8 +112,10 @@ def get_executed_params(execution_context, var_args):
|
|||||||
m = ("TypeError: %s() got multiple values for keyword argument '%s'."
|
m = ("TypeError: %s() got multiple values for keyword argument '%s'."
|
||||||
% (funcdef.name, key))
|
% (funcdef.name, key))
|
||||||
for node in var_args.get_calling_nodes():
|
for node in var_args.get_calling_nodes():
|
||||||
analysis.add(default_param_context, 'type-error-multiple-values',
|
issues.append(
|
||||||
node, message=m)
|
analysis.add(default_param_context, 'type-error-multiple-values',
|
||||||
|
node, message=m)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
keys_used[key] = ExecutedParam(execution_context, key_param, argument)
|
keys_used[key] = ExecutedParam(execution_context, key_param, argument)
|
||||||
key, argument = next(var_arg_iterator, (None, None))
|
key, argument = next(var_arg_iterator, (None, None))
|
||||||
@@ -120,6 +140,8 @@ def get_executed_params(execution_context, var_args):
|
|||||||
seq = iterable.FakeSequence(execution_context.evaluator, u'tuple', lazy_context_list)
|
seq = iterable.FakeSequence(execution_context.evaluator, u'tuple', lazy_context_list)
|
||||||
result_arg = LazyKnownContext(seq)
|
result_arg = LazyKnownContext(seq)
|
||||||
elif param.star_count == 2:
|
elif param.star_count == 2:
|
||||||
|
if argument is not None:
|
||||||
|
too_many_args(argument)
|
||||||
# **kwargs param
|
# **kwargs param
|
||||||
dct = iterable.FakeDict(execution_context.evaluator, dict(non_matching_keys))
|
dct = iterable.FakeDict(execution_context.evaluator, dict(non_matching_keys))
|
||||||
result_arg = LazyKnownContext(dct)
|
result_arg = LazyKnownContext(dct)
|
||||||
@@ -133,8 +155,14 @@ def get_executed_params(execution_context, var_args):
|
|||||||
if not keys_only:
|
if not keys_only:
|
||||||
for node in var_args.get_calling_nodes():
|
for node in var_args.get_calling_nodes():
|
||||||
m = _error_argument_count(funcdef, len(unpacked_va))
|
m = _error_argument_count(funcdef, len(unpacked_va))
|
||||||
analysis.add(default_param_context, 'type-error-too-few-arguments',
|
issues.append(
|
||||||
node, message=m)
|
analysis.add(
|
||||||
|
default_param_context,
|
||||||
|
'type-error-too-few-arguments',
|
||||||
|
node,
|
||||||
|
message=m,
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
result_arg = LazyTreeContext(default_param_context, param.default)
|
result_arg = LazyTreeContext(default_param_context, param.default)
|
||||||
else:
|
else:
|
||||||
@@ -156,34 +184,28 @@ def get_executed_params(execution_context, var_args):
|
|||||||
# add a warning only if there's not another one.
|
# add a warning only if there's not another one.
|
||||||
for node in var_args.get_calling_nodes():
|
for node in var_args.get_calling_nodes():
|
||||||
m = _error_argument_count(funcdef, len(unpacked_va))
|
m = _error_argument_count(funcdef, len(unpacked_va))
|
||||||
analysis.add(default_param_context, 'type-error-too-few-arguments',
|
issues.append(
|
||||||
node, message=m)
|
analysis.add(default_param_context, 'type-error-too-few-arguments',
|
||||||
|
node, message=m)
|
||||||
|
)
|
||||||
|
|
||||||
for key, lazy_context in non_matching_keys.items():
|
for key, lazy_context in non_matching_keys.items():
|
||||||
m = "TypeError: %s() got an unexpected keyword argument '%s'." \
|
m = "TypeError: %s() got an unexpected keyword argument '%s'." \
|
||||||
% (funcdef.name, key)
|
% (funcdef.name, key)
|
||||||
_add_argument_issue(
|
issues.append(
|
||||||
default_param_context,
|
_add_argument_issue(
|
||||||
'type-error-keyword-argument',
|
default_param_context,
|
||||||
lazy_context,
|
'type-error-keyword-argument',
|
||||||
message=m
|
lazy_context,
|
||||||
|
message=m
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
remaining_arguments = list(var_arg_iterator)
|
remaining_arguments = list(var_arg_iterator)
|
||||||
if remaining_arguments:
|
if remaining_arguments:
|
||||||
m = _error_argument_count(funcdef, len(unpacked_va))
|
|
||||||
# Just report an error for the first param that is not needed (like
|
|
||||||
# cPython).
|
|
||||||
first_key, lazy_context = remaining_arguments[0]
|
first_key, lazy_context = remaining_arguments[0]
|
||||||
if var_args.get_calling_nodes():
|
too_many_args(lazy_context)
|
||||||
# There might not be a valid calling node so check for that first.
|
return result_params, issues
|
||||||
_add_argument_issue(
|
|
||||||
default_param_context,
|
|
||||||
'type-error-too-many-arguments',
|
|
||||||
lazy_context,
|
|
||||||
message=m
|
|
||||||
)
|
|
||||||
return result_params
|
|
||||||
|
|
||||||
|
|
||||||
def _error_argument_count(funcdef, actual_count):
|
def _error_argument_count(funcdef, actual_count):
|
||||||
|
|||||||
@@ -250,7 +250,8 @@ def _infer_type_vars_for_execution(execution_context, annotation_dict):
|
|||||||
context = execution_context.function_context.get_default_param_context()
|
context = execution_context.function_context.get_default_param_context()
|
||||||
|
|
||||||
annotation_variable_results = {}
|
annotation_variable_results = {}
|
||||||
for executed_param in execution_context.get_executed_params():
|
executed_params, _ = execution_context.get_executed_params_and_issues()
|
||||||
|
for executed_param in executed_params:
|
||||||
try:
|
try:
|
||||||
annotation_node = annotation_dict[executed_param.string_name]
|
annotation_node = annotation_dict[executed_param.string_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|||||||
Reference in New Issue
Block a user