Example #1
0
        public void MapParameter(ParameterInfo pi) {
            int indexForArgBuilder;
            int nameIndex = _argNames.IndexOf(pi.Name);
            if (nameIndex == -1) {
                // positional argument, we simply consume the next argument
                indexForArgBuilder = _argIndex++;
            } else {
                // keyword argument, we just tell the simple arg builder to consume arg 0.
                // KeywordArgBuilder will then pass in the correct single argument based 
                // upon the actual argument number provided by the user.
                indexForArgBuilder = 0;
            }

            // if the parameter is default we need to build a default arg builder and then
            // build a reduced method at the end.  
            if (!pi.IsMandatory()) {
                // We need to build the default builder even if we have a parameter for it already to
                // get good consistency of our error messages.  But consider a method like 
                // def foo(a=1, b=2) and the user calls it as foo(b=3). Then adding the default
                // value breaks an otherwise valid call.  This is because we only generate MethodCandidates
                // filling in the defaults from right to left (so the method - 1 arg requires a,
                // and the method minus 2 args requires b).  So we only add the default if it's 
                // a positional arg or we don't already have a default value.
                if (nameIndex == -1 || !_hasDefaults) {
                    _defaultArguments.Add(new DefaultArgBuilder(pi));
                    _hasDefaults = true;
                } else {
                    _defaultArguments.Add(null);
                }
            } else if (_defaultArguments.Count > 0) {
                // non-contigious default parameter
                _defaultArguments.Add(null);
            }

            ArgBuilder ab;
            if (pi.ParameterType.IsByRef) {
                _hasByRef = true;
                Type refType = typeof(StrongBox<>).MakeGenericType(pi.ParameterType.GetElementType());
                _parameters.Add(new ParameterWrapper(pi, refType, pi.Name, ParameterBindingFlags.ProhibitNull));
                ab = new ReferenceArgBuilder(pi, refType, indexForArgBuilder);
            } else if (pi.Position == 0 && _overload.IsExtension) {
                _parameters.Add(new ParameterWrapper(pi, pi.ParameterType, pi.Name, ParameterBindingFlags.IsHidden));
                ab = new SimpleArgBuilder(pi.ParameterType, indexForArgBuilder, false, false);
            } else {
                ab = AddSimpleParameterMapping(pi, indexForArgBuilder);
            }

            if (nameIndex == -1) {
                _arguments.Add(ab);
            } else {
                Debug.Assert(KeywordArgBuilder.BuilderExpectsSingleParameter(ab));
                _arguments.Add(new KeywordArgBuilder(ab, _argNames.Count, nameIndex));
            }
        }