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); }