mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
Use ContextualizedNode instead of Node in get_calling_nodes
This improves working with these nodes by a lot.
This commit is contained in:
@@ -9,7 +9,7 @@ from jedi.evaluate import analysis
|
|||||||
from jedi.evaluate.lazy_context import LazyKnownContext, LazyKnownContexts, \
|
from jedi.evaluate.lazy_context import LazyKnownContext, LazyKnownContexts, \
|
||||||
LazyTreeContext, get_merged_lazy_context
|
LazyTreeContext, get_merged_lazy_context
|
||||||
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, ContextualizedNode
|
||||||
from jedi.evaluate.context import iterable
|
from jedi.evaluate.context import iterable
|
||||||
from jedi.evaluate.param import get_executed_params_and_issues, ExecutedParam
|
from jedi.evaluate.param import get_executed_params_and_issues, ExecutedParam
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ class TreeArguments(AbstractArguments):
|
|||||||
else:
|
else:
|
||||||
yield None, LazyTreeContext(self.context, el)
|
yield None, LazyTreeContext(self.context, el)
|
||||||
|
|
||||||
# Reordering var_args is necessary, because star args sometimes appear
|
# Reordering arguments is necessary, because star args sometimes appear
|
||||||
# after named argument, but in the actual order it's prepended.
|
# after named argument, but in the actual order it's prepended.
|
||||||
for named_arg in named_args:
|
for named_arg in named_args:
|
||||||
yield named_arg
|
yield named_arg
|
||||||
@@ -286,9 +286,9 @@ class TreeArguments(AbstractArguments):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if arguments.argument_node is not None:
|
if arguments.argument_node is not None:
|
||||||
return [arguments.argument_node]
|
return [ContextualizedNode(arguments.context, arguments.argument_node)]
|
||||||
if arguments.trailer is not None:
|
if arguments.trailer is not None:
|
||||||
return [arguments.trailer]
|
return [ContextualizedNode(arguments.context, arguments.trailer)]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ class LazyUnknownContext(AbstractLazyContext):
|
|||||||
class LazyTreeContext(AbstractLazyContext):
|
class LazyTreeContext(AbstractLazyContext):
|
||||||
def __init__(self, context, node):
|
def __init__(self, context, node):
|
||||||
super(LazyTreeContext, self).__init__(node)
|
super(LazyTreeContext, self).__init__(node)
|
||||||
self._context = context
|
self.context = context
|
||||||
# We need to save the predefined names. It's an unfortunate side effect
|
# We need to save the predefined names. It's an unfortunate side effect
|
||||||
# that needs to be tracked otherwise results will be wrong.
|
# that needs to be tracked otherwise results will be wrong.
|
||||||
self._predefined_names = dict(context.predefined_names)
|
self._predefined_names = dict(context.predefined_names)
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
with monkeypatch(self._context, 'predefined_names', self._predefined_names):
|
with monkeypatch(self.context, 'predefined_names', self._predefined_names):
|
||||||
return self._context.eval_node(self.data)
|
return self.context.eval_node(self.data)
|
||||||
|
|
||||||
|
|
||||||
def get_merged_lazy_context(lazy_contexts):
|
def get_merged_lazy_context(lazy_contexts):
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ from jedi.evaluate import docstrings
|
|||||||
from jedi.evaluate.context import iterable
|
from jedi.evaluate.context import iterable
|
||||||
|
|
||||||
|
|
||||||
def _add_argument_issue(parent_context, error_name, lazy_context, message):
|
def _add_argument_issue(error_name, lazy_context, message):
|
||||||
if isinstance(lazy_context, LazyTreeContext):
|
if isinstance(lazy_context, LazyTreeContext):
|
||||||
node = lazy_context.data
|
node = lazy_context.data
|
||||||
if node.parent.type == 'argument':
|
if node.parent.type == 'argument':
|
||||||
node = node.parent
|
node = node.parent
|
||||||
return analysis.add(parent_context, error_name, node, message)
|
return analysis.add(lazy_context.context, error_name, node, message)
|
||||||
|
|
||||||
|
|
||||||
class ExecutedParam(object):
|
class ExecutedParam(object):
|
||||||
@@ -65,16 +65,15 @@ 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_and_issues(execution_context, var_args):
|
def get_executed_params_and_issues(execution_context, arguments):
|
||||||
def too_many_args(argument):
|
def too_many_args(argument):
|
||||||
m = _error_argument_count(funcdef, len(unpacked_va))
|
m = _error_argument_count(funcdef, len(unpacked_va))
|
||||||
# Just report an error for the first param that is not needed (like
|
# Just report an error for the first param that is not needed (like
|
||||||
# cPython).
|
# cPython).
|
||||||
if var_args.get_calling_nodes():
|
if arguments.get_calling_nodes():
|
||||||
# There might not be a valid calling node so check for that first.
|
# There might not be a valid calling node so check for that first.
|
||||||
issues.append(
|
issues.append(
|
||||||
_add_argument_issue(
|
_add_argument_issue(
|
||||||
default_param_context,
|
|
||||||
'type-error-too-many-arguments',
|
'type-error-too-many-arguments',
|
||||||
argument,
|
argument,
|
||||||
message=m
|
message=m
|
||||||
@@ -94,7 +93,7 @@ def get_executed_params_and_issues(execution_context, var_args):
|
|||||||
|
|
||||||
for param in funcdef.get_params():
|
for param in funcdef.get_params():
|
||||||
param_dict[param.name.value] = param
|
param_dict[param.name.value] = param
|
||||||
unpacked_va = list(var_args.unpack(funcdef))
|
unpacked_va = list(arguments.unpack(funcdef))
|
||||||
var_arg_iterator = PushBackIterator(iter(unpacked_va))
|
var_arg_iterator = PushBackIterator(iter(unpacked_va))
|
||||||
|
|
||||||
non_matching_keys = defaultdict(lambda: [])
|
non_matching_keys = defaultdict(lambda: [])
|
||||||
@@ -119,10 +118,11 @@ def get_executed_params_and_issues(execution_context, var_args):
|
|||||||
had_multiple_value_error = True
|
had_multiple_value_error = True
|
||||||
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 contextualized_node in arguments.get_calling_nodes():
|
||||||
issues.append(
|
issues.append(
|
||||||
analysis.add(default_param_context, 'type-error-multiple-values',
|
analysis.add(contextualized_node.context,
|
||||||
node, message=m)
|
'type-error-multiple-values',
|
||||||
|
contextualized_node.node, message=m)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
keys_used[key] = ExecutedParam(execution_context, key_param, argument)
|
keys_used[key] = ExecutedParam(execution_context, key_param, argument)
|
||||||
@@ -161,13 +161,13 @@ def get_executed_params_and_issues(execution_context, var_args):
|
|||||||
if param.default is None:
|
if param.default is None:
|
||||||
result_arg = LazyUnknownContext()
|
result_arg = LazyUnknownContext()
|
||||||
if not keys_only:
|
if not keys_only:
|
||||||
for node in var_args.get_calling_nodes():
|
for contextualized_node in arguments.get_calling_nodes():
|
||||||
m = _error_argument_count(funcdef, len(unpacked_va))
|
m = _error_argument_count(funcdef, len(unpacked_va))
|
||||||
issues.append(
|
issues.append(
|
||||||
analysis.add(
|
analysis.add(
|
||||||
default_param_context,
|
contextualized_node.context,
|
||||||
'type-error-too-few-arguments',
|
'type-error-too-few-arguments',
|
||||||
node,
|
contextualized_node.node,
|
||||||
message=m,
|
message=m,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -194,11 +194,12 @@ def get_executed_params_and_issues(execution_context, var_args):
|
|||||||
if not (non_matching_keys or had_multiple_value_error or
|
if not (non_matching_keys or had_multiple_value_error or
|
||||||
param.star_count or param.default):
|
param.star_count or param.default):
|
||||||
# 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 contextualized_node in arguments.get_calling_nodes():
|
||||||
m = _error_argument_count(funcdef, len(unpacked_va))
|
m = _error_argument_count(funcdef, len(unpacked_va))
|
||||||
issues.append(
|
issues.append(
|
||||||
analysis.add(default_param_context, 'type-error-too-few-arguments',
|
analysis.add(contextualized_node.context,
|
||||||
node, message=m)
|
'type-error-too-few-arguments',
|
||||||
|
contextualized_node.node, message=m)
|
||||||
)
|
)
|
||||||
|
|
||||||
for key, lazy_context in non_matching_keys.items():
|
for key, lazy_context in non_matching_keys.items():
|
||||||
@@ -206,7 +207,6 @@ def get_executed_params_and_issues(execution_context, var_args):
|
|||||||
% (funcdef.name, key)
|
% (funcdef.name, key)
|
||||||
issues.append(
|
issues.append(
|
||||||
_add_argument_issue(
|
_add_argument_issue(
|
||||||
default_param_context,
|
|
||||||
'type-error-keyword-argument',
|
'type-error-keyword-argument',
|
||||||
lazy_context,
|
lazy_context,
|
||||||
message=m
|
message=m
|
||||||
|
|||||||
@@ -87,3 +87,21 @@ else:
|
|||||||
str.upper
|
str.upper
|
||||||
#! 4 attribute-error
|
#! 4 attribute-error
|
||||||
str.undefined
|
str.undefined
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
# arguments
|
||||||
|
# -----------------
|
||||||
|
|
||||||
|
def i_see(r):
|
||||||
|
return r
|
||||||
|
|
||||||
|
def lala():
|
||||||
|
# This weird structure checks if the error is actually resolved in the
|
||||||
|
# right place.
|
||||||
|
a = TypeError
|
||||||
|
try:
|
||||||
|
i_see()
|
||||||
|
except a:
|
||||||
|
pass
|
||||||
|
#! 5 type-error-too-few-arguments
|
||||||
|
i_see()
|
||||||
|
|||||||
Reference in New Issue
Block a user