/// <summary> /// Builds a new MethodCandidate which takes count arguments and the provided list of keyword arguments. /// /// The basic idea here is to figure out which parameters map to params or a dictionary params and /// fill in those spots w/ extra ParameterWrapper's. /// </summary> internal MethodCandidate MakeParamsExtended(ActionBinder binder, int count, SymbolId[] names) { Debug.Assert(BinderHelpers.IsParamsMethod(_target.Method)); List <ParameterWrapper> newParameters = new List <ParameterWrapper>(count); // if we don't have a param array we'll have a param dict which is type object Type elementType = null; int index = -1, kwIndex = -1; // keep track of which kw args map to a real argument, and which ones // map to the params dictionary. List <SymbolId> unusedNames = new List <SymbolId>(names); List <int> unusedNameIndexes = new List <int>(); for (int i = 0; i < unusedNames.Count; i++) { unusedNameIndexes.Add(i); } for (int i = 0; i < _parameters.Count; i++) { ParameterWrapper pw = _parameters[i]; if (_parameters[i].IsParamsDict) { kwIndex = i; } else if (_parameters[i].IsParamsArray) { elementType = pw.Type.GetElementType(); index = i; } else { for (int j = 0; j < unusedNames.Count; j++) { if (unusedNames[j] == _parameters[i].Name) { unusedNames.RemoveAt(j); unusedNameIndexes.RemoveAt(j); break; } } newParameters.Add(pw); } } if (index != -1) { while (newParameters.Count < (count - unusedNames.Count)) { ParameterWrapper param = new ParameterWrapper(binder, elementType, SymbolId.Empty, false); newParameters.Insert(System.Math.Min(index, newParameters.Count), param); } } if (kwIndex != -1) { foreach (SymbolId si in unusedNames) { newParameters.Add(new ParameterWrapper(binder, typeof(object), si, false)); } } else if (unusedNames.Count != 0) { // unbound kw args and no where to put them, can't call... // TODO: We could do better here because this results in an incorrect arg # error message. return(null); } // if we have too many or too few args we also can't call if (count != newParameters.Count) { return(null); } return(new MethodCandidate(_target.MakeParamsExtended(count, unusedNames.ToArray(), unusedNameIndexes.ToArray()), newParameters)); }