public IMethodReference Map(R.IMethodSymbol methodSymbol)
        {
            Contract.Requires(methodSymbol != null);
            IMethodReference mr = null;

            if (!methodSymbolCache.TryGetValue(methodSymbol, out mr))
            {
                List <IParameterTypeInformation> ps = methodSymbol.Parameters.Count == 0 ? null : new List <IParameterTypeInformation>();
                if (methodSymbol.IsGenericMethod && methodSymbol.ConstructedFrom != methodSymbol)
                {
                    var gArgs = new List <ITypeReference>();
                    foreach (var a in methodSymbol.TypeArguments)
                    {
                        gArgs.Add(Map(a));
                    }
                    mr = new Microsoft.Cci.MutableCodeModel.GenericMethodInstanceReference()
                    {
                        CallingConvention     = methodSymbol.IsStatic ? CallingConvention.Default : CallingConvention.HasThis,
                        ContainingType        = Map(methodSymbol.ContainingType),
                        GenericArguments      = gArgs,
                        GenericMethod         = Map(methodSymbol.ConstructedFrom),
                        GenericParameterCount = (ushort)methodSymbol.TypeParameters.Count,
                        InternFactory         = this.host.InternFactory,
                        Name       = this.nameTable.GetNameFor(methodSymbol.Name),
                        Parameters = ps,
                        Type       = Map(methodSymbol.ReturnType),
                    };
                }
                else
                {
                    var m = new Microsoft.Cci.MutableCodeModel.MethodReference();
                    // IMPORTANT: Have to add it to the cache before doing anything else because it may
                    // get looked up if it is generic and a parameter's type involves the generic
                    // method parameter.
                    this.methodSymbolCache.Add(methodSymbol, m);
                    m.CallingConvention = methodSymbol.IsStatic ? CallingConvention.Default : CallingConvention.HasThis;
                    m.ContainingType    = Map(methodSymbol.ContainingType);
                    m.InternFactory     = this.host.InternFactory;
                    m.Name       = this.nameTable.GetNameFor(methodSymbol.Name);
                    m.Parameters = ps;
                    m.Type       = Map(methodSymbol.ReturnType);
                    mr           = m;
                }
                foreach (var p in methodSymbol.Parameters)
                {
                    var p_prime = new ParameterTypeInformation()
                    {
                        ContainingSignature = mr,
                        Index = (ushort)p.Ordinal,
                        Type  = Map(p.Type),
                    };
                    ps.Add(p_prime);
                }
            }
            return(mr);
        }
        /// <summary>
        /// Returns a method whose body is empty, but which can be replaced with the real body when it is
        /// available.
        /// </summary>
        /// <remarks>
        /// Public because it needs to get called when an anonymous delegate is encountered
        /// while translating a method body. Just mapping the anonymous delegate doesn't
        /// provide the information needed. The parameters of a method reference are not
        /// IParameterDefinitions.
        /// </remarks>
        public MethodDefinition TranslateMetadata(R.IMethodSymbol methodSymbol)
        {
            Contract.Requires(methodSymbol != null);
            Contract.Ensures(Contract.Result <MethodDefinition>() != null);

            var containingType = (ITypeDefinition)this.typeSymbolCache[methodSymbol.ContainingType];
            var isConstructor  = methodSymbol.MethodKind == R.CommonMethodKind.Constructor;
            List <IParameterDefinition> parameters = new List <IParameterDefinition>();

            var m = new MethodDefinition()
            {
                CallingConvention        = methodSymbol.IsStatic ? CallingConvention.Default : CallingConvention.HasThis,
                ContainingTypeDefinition = containingType,
                InternFactory            = this.host.InternFactory,
                IsHiddenBySignature      = true,               // REVIEW
                IsNewSlot        = containingType.IsInterface, // REVIEW
                IsRuntimeSpecial = isConstructor,
                IsSpecialName    = isConstructor,
                IsStatic         = methodSymbol.IsStatic,
                IsVirtual        = containingType.IsInterface, // REVIEW: Why doesn't using methodSymbol.Virtual work for interface methods?
                Locations        = Helper.WrapLocations(methodSymbol.Locations),
                Name             = this.nameTable.GetNameFor(methodSymbol.Name),
                Parameters       = parameters,
                Type             = this.Map(methodSymbol.ReturnType),
                Visibility       = this.Map(methodSymbol.DeclaredAccessibility),
            };

            // IMPORTANT: Have to add it to the cache before doing anything else because it may
            // get looked up if it is generic and a parameter's type involves the generic
            // method parameter.
            this.methodSymbolCache.Add(methodSymbol, m);

            #region Define the generic parameters
            if (methodSymbol.IsGenericMethod)
            {
                var genericParameters = new List <IGenericMethodParameter>();
                foreach (var gp in methodSymbol.TypeParameters)
                {
                    var gp2 = this.CreateTypeDefinition(gp);
                    genericParameters.Add((IGenericMethodParameter)gp2);
                }
                m.GenericParameters = genericParameters;
            }
            #endregion

            #region Define the parameters
            ushort i = 0;
            foreach (var p in methodSymbol.Parameters)
            {
                var p_prime = new ParameterDefinition()
                {
                    ContainingSignature = m,
                    IsByReference       = p.RefKind == RefKind.Ref,
                    IsIn  = p.RefKind == RefKind.None,
                    IsOut = p.RefKind == RefKind.Out,
                    Name  = nameTable.GetNameFor(p.Name),
                    Type  = this.Map(p.Type),
                    Index = i++,
                };
                parameters.Add(p_prime);
            }
            #endregion Define the parameters

            #region Define default ctor, if needed
            if (/*methodSymbol.IsSynthesized &&*/ isConstructor) // BUGBUG!!
            {
                m.IsHiddenBySignature = true;
                m.IsRuntimeSpecial    = true;
                m.IsSpecialName       = true;
                var statements = new List <IStatement>();
                var body       = new SourceMethodBody(this.host, null, null)
                {
                    LocalsAreZeroed = true,
                    Block           = new BlockStatement()
                    {
                        Statements = statements
                    },
                };
                var thisRef = new ThisReference()
                {
                    Type = containingType,
                };
                // base();
                foreach (var baseClass in containingType.BaseClasses)
                {
                    var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference()
                    {
                        CallingConvention     = CallingConvention.HasThis,
                        ContainingType        = baseClass,
                        GenericParameterCount = 0,
                        InternFactory         = this.host.InternFactory,
                        Name = nameTable.Ctor,
                        Type = this.host.PlatformType.SystemVoid,
                    };
                    statements.Add(
                        new ExpressionStatement()
                    {
                        Expression = new MethodCall()
                        {
                            MethodToCall = baseCtor,
                            IsStaticCall = false,                             // REVIEW: Is this needed in addition to setting the ThisArgument?
                            ThisArgument = thisRef,
                            Type         = this.host.PlatformType.SystemVoid, // REVIEW: Is this the right way to do this?
                            Arguments    = new List <IExpression>(),
                        }
                    }
                        );
                    break;
                }
                // return;
                statements.Add(new ReturnStatement());
                body.MethodDefinition = m;
                m.Body = body;
            }
            #endregion

            return(m);
        }