mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Extracted getParameters(Callable, TypeEvalContext)
This commit is contained in:
@@ -1238,5 +1238,32 @@ public class PyUtil {
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PyParameter> getParameters(@NotNull Callable callable, @NotNull TypeEvalContext context) {
|
||||
PyType type = context.getType(callable);
|
||||
if (type instanceof PyUnionType) {
|
||||
type = ((PyUnionType)type).excludeNull();
|
||||
}
|
||||
if (type instanceof PyCallableType) {
|
||||
final PyCallableType callableType = (PyCallableType)type;
|
||||
final List<PyCallableParameter> callableTypeParameters = callableType.getParameters(context);
|
||||
if (callableTypeParameters != null) {
|
||||
boolean allParametersDefined = true;
|
||||
final List<PyParameter> parameters = new ArrayList<PyParameter>();
|
||||
for (PyCallableParameter callableParameter : callableTypeParameters) {
|
||||
final PyParameter parameter = callableParameter.getParameter();
|
||||
if (parameter == null) {
|
||||
allParametersDefined = false;
|
||||
break;
|
||||
}
|
||||
parameters.add(parameter);
|
||||
}
|
||||
if (allParametersDefined) {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Arrays.asList(callable.getParameterList().getParameters());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,280 +73,263 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
|
||||
}
|
||||
}
|
||||
}
|
||||
PyType type = context.getType(myMarkedCallee.getCallable());
|
||||
if (type instanceof PyUnionType) {
|
||||
type = ((PyUnionType)type).excludeNull();
|
||||
}
|
||||
if (type instanceof PyCallableType) {
|
||||
final PyCallableType callableType = (PyCallableType)type;
|
||||
final List<PyCallableParameter> callableTypeParameters = callableType.getParameters(context);
|
||||
if (callableTypeParameters != null) {
|
||||
final List<PyParameter> parameters = new ArrayList<PyParameter>();
|
||||
for (PyCallableParameter callableParameter : callableTypeParameters) {
|
||||
final PyParameter parameter = callableParameter.getParameter();
|
||||
if (parameter == null) {
|
||||
return;
|
||||
final List<PyParameter> parameters = PyUtil.getParameters(myMarkedCallee.getCallable(), context);
|
||||
// prepare parameter slots
|
||||
Map<PyNamedParameter, PyExpression> slots = new LinkedHashMap<PyNamedParameter, PyExpression>();
|
||||
PyNamedParameter kwd_par = null; // **param
|
||||
PyNamedParameter tuple_par = null; // *param
|
||||
Set<PyExpression> mapped_args = new HashSet<PyExpression>();
|
||||
final int implicit_offset = resolved_callee.getImplicitOffset();
|
||||
int positional_index = 0; // up to this index parameters are positional
|
||||
// check positional arguments, fill slots
|
||||
int i = 0;
|
||||
for (PyParameter par : parameters) {
|
||||
if (tuple_par == null && kwd_par == null && positional_index < implicit_offset) {
|
||||
positional_index += 1;
|
||||
continue;
|
||||
}
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (n_par != null) {
|
||||
if (n_par.isPositionalContainer()) tuple_par = n_par;
|
||||
else if (n_par.isKeywordContainer()) kwd_par = n_par;
|
||||
else {
|
||||
slots.put(n_par, null); // regular parameter that may serve as positional/named
|
||||
if (tuple_par == null && kwd_par == null) {
|
||||
positional_index += 1; // only if we're not past *param / **param
|
||||
}
|
||||
parameters.add(parameter);
|
||||
}
|
||||
// prepare parameter slots
|
||||
Map<PyNamedParameter, PyExpression> slots = new LinkedHashMap<PyNamedParameter, PyExpression>();
|
||||
PyNamedParameter kwd_par = null; // **param
|
||||
PyNamedParameter tuple_par = null; // *param
|
||||
Set<PyExpression> mapped_args = new HashSet<PyExpression>();
|
||||
final int implicit_offset = resolved_callee.getImplicitOffset();
|
||||
int positional_index = 0; // up to this index parameters are positional
|
||||
// check positional arguments, fill slots
|
||||
int i = 0;
|
||||
for (PyParameter par : parameters) {
|
||||
if (tuple_par == null && kwd_par == null && positional_index < implicit_offset) {
|
||||
positional_index += 1;
|
||||
continue;
|
||||
}
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (n_par != null) {
|
||||
if (n_par.isPositionalContainer()) tuple_par = n_par;
|
||||
else if (n_par.isKeywordContainer()) kwd_par = n_par;
|
||||
}
|
||||
else {
|
||||
PyTupleParameter t_par = par.getAsTuple();
|
||||
if (t_par != null) positional_index += 1; // tuple can only be positional
|
||||
// else lone star, skip
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
// rule out 'self' or other implicit params
|
||||
for (i=0; i < implicit_offset && i < parameters.size(); i+=1) {
|
||||
slots.remove(parameters.get(i).getAsNamed());
|
||||
positional_index += 1;
|
||||
}
|
||||
// now params to the left of positional_index are positional.
|
||||
// map positional args to positional params.
|
||||
// we assume that implicitly skipped parameters are never nested tuples. no idea when they could ever be.
|
||||
int cnt = implicit_offset;
|
||||
int positional_bound = arguments.length; // to the right of this pos args are verboten
|
||||
ListIterator<PyExpression> unmatched_arg_iter = unmatched_args.listIterator();
|
||||
while (unmatched_arg_iter.hasNext()) {
|
||||
PyExpression arg = unmatched_arg_iter.next();
|
||||
if (arg instanceof PyStarArgument || arg instanceof PyKeywordArgument) {
|
||||
positional_bound = cnt;
|
||||
break;
|
||||
}
|
||||
if (cnt < parameters.size() && cnt < positional_index) {
|
||||
final PyParameter par = parameters.get(cnt);
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (n_par != null) {
|
||||
cnt += 1;
|
||||
slots.put(n_par, PyUtil.peelArgument(arg));
|
||||
mapped_args.add(arg);
|
||||
}
|
||||
else {
|
||||
PyTupleParameter t_par = par.getAsTuple();
|
||||
if (t_par != null) {
|
||||
if (arg instanceof PyParenthesizedExpression) {
|
||||
mapped_args.add(arg); // tuple itself is always mapped; its insides can fail
|
||||
}
|
||||
else {
|
||||
slots.put(n_par, null); // regular parameter that may serve as positional/named
|
||||
if (tuple_par == null && kwd_par == null) {
|
||||
positional_index += 1; // only if we're not past *param / **param
|
||||
PyType arg_type = context.getType(arg);
|
||||
if (arg_type != null && arg_type.isBuiltin(context) && "list".equals(arg_type.getName())) {
|
||||
mapped_args.add(arg); // we can't really analyze arbitrary lists statically yet
|
||||
// but ListLiteralExpressions are handled by visitor
|
||||
}
|
||||
}
|
||||
unmatched_arg_iter.previous();
|
||||
MyParamVisitor visitor = new MyParamVisitor(unmatched_arg_iter, this);
|
||||
visitor.enterTuple(t_par.getAsTuple()); // will recur as needed
|
||||
unmatched_subargs.addAll(visitor.getUnmatchedSubargs()); // what didn't match inside
|
||||
cnt += 1;
|
||||
}
|
||||
else {
|
||||
PyTupleParameter t_par = par.getAsTuple();
|
||||
if (t_par != null) positional_index += 1; // tuple can only be positional
|
||||
// else lone star, skip
|
||||
// else: goes to *param
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
// anything left after mapping of nested-tuple params?
|
||||
for (Map.Entry<PyExpression, List<PyNamedParameter>> pair : myNestedMappedParams.entrySet()) {
|
||||
PyExpression arg = pair.getKey();
|
||||
List<PyNamedParameter> params = pair.getValue();
|
||||
mapped_args.add(arg);
|
||||
for (PyNamedParameter n_par : params) slots.remove(n_par);
|
||||
}
|
||||
for (PyExpression arg : unmatched_subargs) {
|
||||
markArgument(arg, ArgFlag.IS_UNMAPPED);
|
||||
}
|
||||
// mark past-bound positional args
|
||||
i = positional_bound;
|
||||
while (i<arguments.length) {
|
||||
PyExpression arg = arguments[i];
|
||||
if (!(arg instanceof PyStarArgument) && !(arg instanceof PyKeywordArgument)) {
|
||||
markArgument(arg, ArgFlag.IS_POS_PAST_KWD);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
boolean seen_named_args = false;
|
||||
// map named args to named params if possible
|
||||
Map<String, PyNamedParameter> parameter_by_name = new LinkedHashMap<String, PyNamedParameter>();
|
||||
for (PyParameter par : parameters) {
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (n_par != null) parameter_by_name.put(n_par.getName(), n_par);
|
||||
}
|
||||
for (PyExpression arg : arguments) {
|
||||
if (arg instanceof PyKeywordArgument) { // to explicitly named param?
|
||||
String arg_name = ((PyKeywordArgument)arg).getKeyword();
|
||||
PyNamedParameter respective_par = parameter_by_name.get(arg_name);
|
||||
if (respective_par != null && !respective_par.isKeywordContainer() && !respective_par.isPositionalContainer()) {
|
||||
if (slots.get(respective_par) != null) markArgument(arg, ArgFlag.IS_DUP);
|
||||
else slots.put(respective_par, arg);
|
||||
}
|
||||
else { // to **param?
|
||||
if (kwd_par != null) {
|
||||
myPlainMappedParams.put(arg, kwd_par);
|
||||
mapped_args.add(arg);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
// rule out 'self' or other implicit params
|
||||
for (i=0; i < implicit_offset && i < parameters.size(); i+=1) {
|
||||
slots.remove(parameters.get(i).getAsNamed());
|
||||
positional_index += 1;
|
||||
}
|
||||
// now params to the left of positional_index are positional.
|
||||
// map positional args to positional params.
|
||||
// we assume that implicitly skipped parameters are never nested tuples. no idea when they could ever be.
|
||||
int cnt = implicit_offset;
|
||||
int positional_bound = arguments.length; // to the right of this pos args are verboten
|
||||
ListIterator<PyExpression> unmatched_arg_iter = unmatched_args.listIterator();
|
||||
while (unmatched_arg_iter.hasNext()) {
|
||||
PyExpression arg = unmatched_arg_iter.next();
|
||||
if (arg instanceof PyStarArgument || arg instanceof PyKeywordArgument) {
|
||||
positional_bound = cnt;
|
||||
seen_named_args = true;
|
||||
}
|
||||
}
|
||||
// map *arg to positional params if possible
|
||||
boolean tuple_arg_not_exhausted = false;
|
||||
boolean tuple_dup_found = false;
|
||||
if (cnt < parameters.size() && cnt < positional_index && myTupleArg != null) {
|
||||
// check length of myTupleArg
|
||||
PyType tuple_arg_type = null;
|
||||
final PyExpression expression = PsiTreeUtil.getChildOfType(myTupleArg, PyExpression.class);
|
||||
if (expression != null) {
|
||||
tuple_arg_type = context.getType(expression);
|
||||
}
|
||||
int tuple_length;
|
||||
boolean tuple_length_known;
|
||||
if (tuple_arg_type instanceof PyTupleType) {
|
||||
tuple_length = ((PyTupleType)tuple_arg_type).getElementCount();
|
||||
tuple_length_known = true;
|
||||
}
|
||||
else {
|
||||
tuple_length = 2000000; // no practical function will have so many positional params
|
||||
tuple_length_known = false;
|
||||
}
|
||||
int mapped_params_count = 0;
|
||||
while (cnt < parameters.size() && cnt < positional_index && mapped_params_count < tuple_length) {
|
||||
PyParameter par = parameters.get(cnt);
|
||||
if (par instanceof PySingleStarParameter) break;
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (slots.containsKey(n_par)) {
|
||||
final PyExpression arg_here = slots.get(n_par);
|
||||
if (arg_here != null) {
|
||||
if (tuple_length_known) {
|
||||
final EnumSet<ArgFlag> flags = myArgFlags.get(arg_here);
|
||||
if (flags == null || flags.isEmpty()) {
|
||||
markArgument(arg_here, ArgFlag.IS_DUP);
|
||||
tuple_dup_found = true;
|
||||
}
|
||||
}
|
||||
// else: unknown tuple length is just enough
|
||||
// the spree is over
|
||||
break;
|
||||
}
|
||||
if (cnt < parameters.size() && cnt < positional_index) {
|
||||
final PyParameter par = parameters.get(cnt);
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (n_par != null) {
|
||||
cnt += 1;
|
||||
slots.put(n_par, PyUtil.peelArgument(arg));
|
||||
mapped_args.add(arg);
|
||||
}
|
||||
else {
|
||||
PyTupleParameter t_par = par.getAsTuple();
|
||||
if (t_par != null) {
|
||||
if (arg instanceof PyParenthesizedExpression) {
|
||||
mapped_args.add(arg); // tuple itself is always mapped; its insides can fail
|
||||
}
|
||||
else {
|
||||
PyType arg_type = context.getType(arg);
|
||||
if (arg_type != null && arg_type.isBuiltin(context) && "list".equals(arg_type.getName())) {
|
||||
mapped_args.add(arg); // we can't really analyze arbitrary lists statically yet
|
||||
// but ListLiteralExpressions are handled by visitor
|
||||
}
|
||||
}
|
||||
unmatched_arg_iter.previous();
|
||||
MyParamVisitor visitor = new MyParamVisitor(unmatched_arg_iter, this);
|
||||
visitor.enterTuple(t_par.getAsTuple()); // will recur as needed
|
||||
unmatched_subargs.addAll(visitor.getUnmatchedSubargs()); // what didn't match inside
|
||||
cnt += 1;
|
||||
}
|
||||
// else: goes to *param
|
||||
}
|
||||
else if (n_par != null) { // normally always true
|
||||
myTupleMappedParams.add(n_par);
|
||||
mapped_args.add(myTupleArg);
|
||||
slots.remove(n_par);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
// anything left after mapping of nested-tuple params?
|
||||
for (Map.Entry<PyExpression, List<PyNamedParameter>> pair : myNestedMappedParams.entrySet()) {
|
||||
PyExpression arg = pair.getKey();
|
||||
List<PyNamedParameter> params = pair.getValue();
|
||||
mapped_args.add(arg);
|
||||
for (PyNamedParameter n_par : params) slots.remove(n_par);
|
||||
else if (n_par == tuple_par) {
|
||||
mapped_params_count = tuple_length; // we found *param for our *arg, consider it fully mapped
|
||||
break;
|
||||
}
|
||||
for (PyExpression arg : unmatched_subargs) {
|
||||
markArgument(arg, ArgFlag.IS_UNMAPPED);
|
||||
}
|
||||
// mark past-bound positional args
|
||||
i = positional_bound;
|
||||
while (i<arguments.length) {
|
||||
PyExpression arg = arguments[i];
|
||||
if (!(arg instanceof PyStarArgument) && !(arg instanceof PyKeywordArgument)) {
|
||||
markArgument(arg, ArgFlag.IS_POS_PAST_KWD);
|
||||
}
|
||||
cnt += 1;
|
||||
mapped_params_count += 1;
|
||||
}
|
||||
if (
|
||||
tuple_length_known && (mapped_params_count < tuple_length) || // not exhausted
|
||||
mapped_params_count == 0 // unknown length must consume at least first param
|
||||
) {
|
||||
tuple_arg_not_exhausted = true;
|
||||
}
|
||||
}
|
||||
// map *param to the leftmost chunk of unmapped positional args
|
||||
// NOTE: ignores the structure of nested-tuple params!
|
||||
if (tuple_par != null) {
|
||||
i = 0;
|
||||
while (i < arguments.length && mapped_args.contains(arguments[i]) && isPositionalArg(arguments[i])) {
|
||||
i += 1; // skip first mapped args
|
||||
}
|
||||
if (i < arguments.length && isPositionalArg(arguments[i])) {
|
||||
while (i < arguments.length && !mapped_args.contains(arguments[i]) && isPositionalArg(arguments[i])) {
|
||||
myPlainMappedParams.put(arguments[i], tuple_par);
|
||||
mapped_args.add(arguments[i]);
|
||||
i += 1;
|
||||
}
|
||||
boolean seen_named_args = false;
|
||||
// map named args to named params if possible
|
||||
Map<String, PyNamedParameter> parameter_by_name = new LinkedHashMap<String, PyNamedParameter>();
|
||||
for (PyParameter par : parameters) {
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (n_par != null) parameter_by_name.put(n_par.getName(), n_par);
|
||||
}
|
||||
}
|
||||
// map unmapped *arg to *param
|
||||
if (myTupleArg != null && tuple_par != null) {
|
||||
if (!mapped_args.contains(myTupleArg)) {
|
||||
myTupleMappedParams.add(tuple_par);
|
||||
mapped_args.add(myTupleArg);
|
||||
}
|
||||
else if (! seen_named_args && tuple_arg_not_exhausted) {
|
||||
// case of (*(1, 2, 3)) -> (a, *b); map the rest of *arg to *param
|
||||
myTupleMappedParams.add(tuple_par);
|
||||
mapped_args.add(myTupleArg);
|
||||
tuple_arg_not_exhausted = false;
|
||||
}
|
||||
}
|
||||
if (tuple_arg_not_exhausted && ! tuple_dup_found) {
|
||||
markArgument(myTupleArg, ArgFlag.IS_TOO_LONG);
|
||||
}
|
||||
// map unmapped named params to **kwarg
|
||||
if (myKwdArg != null) {
|
||||
for (PyParameter par : parameters) {
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (n_par != null && !n_par.isKeywordContainer() && !n_par.isPositionalContainer() && slots.get(n_par) == null) {
|
||||
slots.put(n_par, myKwdArg);
|
||||
}
|
||||
for (PyExpression arg : arguments) {
|
||||
if (arg instanceof PyKeywordArgument) { // to explicitly named param?
|
||||
String arg_name = ((PyKeywordArgument)arg).getKeyword();
|
||||
PyNamedParameter respective_par = parameter_by_name.get(arg_name);
|
||||
if (respective_par != null && !respective_par.isKeywordContainer() && !respective_par.isPositionalContainer()) {
|
||||
if (slots.get(respective_par) != null) markArgument(arg, ArgFlag.IS_DUP);
|
||||
else slots.put(respective_par, arg);
|
||||
}
|
||||
else { // to **param?
|
||||
if (kwd_par != null) {
|
||||
myPlainMappedParams.put(arg, kwd_par);
|
||||
mapped_args.add(arg);
|
||||
}
|
||||
}
|
||||
seen_named_args = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// map unmapped **kwarg to **param
|
||||
if (myKwdArg != null && kwd_par != null && !mapped_args.contains(myKwdArg)) {
|
||||
myKwdMappedParams.add(kwd_par);
|
||||
mapped_args.add(myKwdArg);
|
||||
}
|
||||
// fill in ret, mark unmapped named params
|
||||
for (Map.Entry<PyNamedParameter, PyExpression> pair : slots.entrySet()) {
|
||||
PyNamedParameter n_par = pair.getKey();
|
||||
PyExpression arg = pair.getValue();
|
||||
if (arg == null) {
|
||||
if (!n_par.hasDefaultValue()) myUnmappedParams.add(n_par);
|
||||
}
|
||||
else {
|
||||
if (arg == myTupleArg) {
|
||||
myTupleMappedParams.add(n_par);
|
||||
}
|
||||
// map *arg to positional params if possible
|
||||
boolean tuple_arg_not_exhausted = false;
|
||||
boolean tuple_dup_found = false;
|
||||
if (cnt < parameters.size() && cnt < positional_index && myTupleArg != null) {
|
||||
// check length of myTupleArg
|
||||
PyType tuple_arg_type = null;
|
||||
final PyExpression expression = PsiTreeUtil.getChildOfType(myTupleArg, PyExpression.class);
|
||||
if (expression != null) {
|
||||
tuple_arg_type = context.getType(expression);
|
||||
}
|
||||
int tuple_length;
|
||||
boolean tuple_length_known;
|
||||
if (tuple_arg_type instanceof PyTupleType) {
|
||||
tuple_length = ((PyTupleType)tuple_arg_type).getElementCount();
|
||||
tuple_length_known = true;
|
||||
}
|
||||
else {
|
||||
tuple_length = 2000000; // no practical function will have so many positional params
|
||||
tuple_length_known = false;
|
||||
}
|
||||
int mapped_params_count = 0;
|
||||
while (cnt < parameters.size() && cnt < positional_index && mapped_params_count < tuple_length) {
|
||||
PyParameter par = parameters.get(cnt);
|
||||
if (par instanceof PySingleStarParameter) break;
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (slots.containsKey(n_par)) {
|
||||
final PyExpression arg_here = slots.get(n_par);
|
||||
if (arg_here != null) {
|
||||
if (tuple_length_known) {
|
||||
final EnumSet<ArgFlag> flags = myArgFlags.get(arg_here);
|
||||
if (flags == null || flags.isEmpty()) {
|
||||
markArgument(arg_here, ArgFlag.IS_DUP);
|
||||
tuple_dup_found = true;
|
||||
}
|
||||
}
|
||||
// else: unknown tuple length is just enough
|
||||
// the spree is over
|
||||
break;
|
||||
}
|
||||
else if (n_par != null) { // normally always true
|
||||
myTupleMappedParams.add(n_par);
|
||||
mapped_args.add(myTupleArg);
|
||||
slots.remove(n_par);
|
||||
}
|
||||
}
|
||||
else if (n_par == tuple_par) {
|
||||
mapped_params_count = tuple_length; // we found *param for our *arg, consider it fully mapped
|
||||
break;
|
||||
}
|
||||
cnt += 1;
|
||||
mapped_params_count += 1;
|
||||
}
|
||||
if (
|
||||
tuple_length_known && (mapped_params_count < tuple_length) || // not exhausted
|
||||
mapped_params_count == 0 // unknown length must consume at least first param
|
||||
) {
|
||||
tuple_arg_not_exhausted = true;
|
||||
}
|
||||
else if (arg == myKwdArg) {
|
||||
myKwdMappedParams.add(n_par);
|
||||
}
|
||||
// map *param to the leftmost chunk of unmapped positional args
|
||||
// NOTE: ignores the structure of nested-tuple params!
|
||||
if (tuple_par != null) {
|
||||
i = 0;
|
||||
while (i < arguments.length && mapped_args.contains(arguments[i]) && isPositionalArg(arguments[i])) {
|
||||
i += 1; // skip first mapped args
|
||||
}
|
||||
if (i < arguments.length && isPositionalArg(arguments[i])) {
|
||||
while (i < arguments.length && !mapped_args.contains(arguments[i]) && isPositionalArg(arguments[i])) {
|
||||
myPlainMappedParams.put(arguments[i], tuple_par);
|
||||
mapped_args.add(arguments[i]);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
myPlainMappedParams.put(arg, n_par);
|
||||
}
|
||||
// map unmapped *arg to *param
|
||||
if (myTupleArg != null && tuple_par != null) {
|
||||
if (!mapped_args.contains(myTupleArg)) {
|
||||
myTupleMappedParams.add(tuple_par);
|
||||
mapped_args.add(myTupleArg);
|
||||
}
|
||||
else if (! seen_named_args && tuple_arg_not_exhausted) {
|
||||
// case of (*(1, 2, 3)) -> (a, *b); map the rest of *arg to *param
|
||||
myTupleMappedParams.add(tuple_par);
|
||||
mapped_args.add(myTupleArg);
|
||||
tuple_arg_not_exhausted = false;
|
||||
}
|
||||
}
|
||||
if (tuple_arg_not_exhausted && ! tuple_dup_found) {
|
||||
markArgument(myTupleArg, ArgFlag.IS_TOO_LONG);
|
||||
}
|
||||
// map unmapped named params to **kwarg
|
||||
if (myKwdArg != null) {
|
||||
for (PyParameter par : parameters) {
|
||||
PyNamedParameter n_par = par.getAsNamed();
|
||||
if (n_par != null && !n_par.isKeywordContainer() && !n_par.isPositionalContainer() && slots.get(n_par) == null) {
|
||||
slots.put(n_par, myKwdArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// map unmapped **kwarg to **param
|
||||
if (myKwdArg != null && kwd_par != null && !mapped_args.contains(myKwdArg)) {
|
||||
myKwdMappedParams.add(kwd_par);
|
||||
mapped_args.add(myKwdArg);
|
||||
}
|
||||
// fill in ret, mark unmapped named params
|
||||
for (Map.Entry<PyNamedParameter, PyExpression> pair : slots.entrySet()) {
|
||||
PyNamedParameter n_par = pair.getKey();
|
||||
PyExpression arg = pair.getValue();
|
||||
if (arg == null) {
|
||||
if (!n_par.hasDefaultValue()) myUnmappedParams.add(n_par);
|
||||
}
|
||||
else {
|
||||
if (arg == myTupleArg) {
|
||||
myTupleMappedParams.add(n_par);
|
||||
}
|
||||
else if (arg == myKwdArg) {
|
||||
myKwdMappedParams.add(n_par);
|
||||
}
|
||||
else {
|
||||
myPlainMappedParams.put(arg, n_par);
|
||||
}
|
||||
}
|
||||
}
|
||||
// mark unmapped args
|
||||
for (PyExpression arg : slots.values()) {
|
||||
if (arg != null) mapped_args.add(arg);
|
||||
}
|
||||
for (PyExpression arg : arguments) {
|
||||
if (!mapped_args.contains(arg)) {
|
||||
final EnumSet<ArgFlag> flags = myArgFlags.get(arg);
|
||||
if (flags == null || flags.isEmpty()) {
|
||||
markArgument(arg, ArgFlag.IS_UNMAPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// mark unmapped args
|
||||
for (PyExpression arg : slots.values()) {
|
||||
if (arg != null) mapped_args.add(arg);
|
||||
}
|
||||
for (PyExpression arg : arguments) {
|
||||
if (!mapped_args.contains(arg)) {
|
||||
final EnumSet<ArgFlag> flags = myArgFlags.get(arg);
|
||||
if (flags == null || flags.isEmpty()) {
|
||||
markArgument(arg, ArgFlag.IS_UNMAPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user