public IEnumerable <IAttribute> GetAttributes()
        {
            var b              = new AttributeListBuilder(module);
            var metadata       = module.metadata;
            var typeDefinition = metadata.GetTypeDefinition(handle);

            // SerializableAttribute
            if ((typeDefinition.Attributes & TypeAttributes.Serializable) != 0)
            {
                b.Add(KnownAttribute.Serializable);
            }

            // ComImportAttribute
            if ((typeDefinition.Attributes & TypeAttributes.Import) != 0)
            {
                b.Add(KnownAttribute.ComImport);
            }

            #region StructLayoutAttribute
            LayoutKind layoutKind = LayoutKind.Auto;
            switch (typeDefinition.Attributes & TypeAttributes.LayoutMask)
            {
            case TypeAttributes.SequentialLayout:
                layoutKind = LayoutKind.Sequential;
                break;

            case TypeAttributes.ExplicitLayout:
                layoutKind = LayoutKind.Explicit;
                break;
            }
            CharSet charSet = CharSet.None;
            switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask)
            {
            case TypeAttributes.AnsiClass:
                charSet = CharSet.Ansi;
                break;

            case TypeAttributes.AutoClass:
                charSet = CharSet.Auto;
                break;

            case TypeAttributes.UnicodeClass:
                charSet = CharSet.Unicode;
                break;
            }
            var        layout            = typeDefinition.GetLayout();
            LayoutKind defaultLayoutKind = Kind == TypeKind.Struct ? LayoutKind.Sequential : LayoutKind.Auto;
            if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || layout.PackingSize > 0 || layout.Size > 0)
            {
                var structLayout = new AttributeBuilder(module, KnownAttribute.StructLayout);
                structLayout.AddFixedArg(
                    new TopLevelTypeName("System.Runtime.InteropServices", "LayoutKind"),
                    (int)layoutKind);
                if (charSet != CharSet.Ansi)
                {
                    var charSetType = Compilation.FindType(new TopLevelTypeName("System.Runtime.InteropServices", "CharSet"));
                    structLayout.AddNamedArg("CharSet", charSetType, (int)charSet);
                }
                if (layout.PackingSize > 0)
                {
                    structLayout.AddNamedArg("Pack", KnownTypeCode.Int32, (int)layout.PackingSize);
                }
                if (layout.Size > 0)
                {
                    structLayout.AddNamedArg("Size", KnownTypeCode.Int32, (int)layout.Size);
                }
                b.Add(structLayout.Build());
            }
            #endregion

            b.Add(typeDefinition.GetCustomAttributes(), SymbolKind.TypeDefinition);
            b.AddSecurityAttributes(typeDefinition.GetDeclarativeSecurityAttributes());

            return(b.Build());
        }
Example #2
0
        public IEnumerable <IAttribute> GetAttributes()
        {
            var b = new AttributeListBuilder(module);

            var metadata = module.metadata;
            var def      = metadata.GetMethodDefinition(handle);
            MethodImplAttributes implAttributes = def.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;

            #region DllImportAttribute
            var info = def.GetImport();
            if ((attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl && !info.Module.IsNil)
            {
                var dllImport = new AttributeBuilder(module, KnownAttribute.DllImport);
                dllImport.AddFixedArg(KnownTypeCode.String,
                                      metadata.GetString(metadata.GetModuleReference(info.Module).Name));

                var importAttrs = info.Attributes;
                if ((importAttrs & MethodImportAttributes.BestFitMappingDisable) == MethodImportAttributes.BestFitMappingDisable)
                {
                    dllImport.AddNamedArg("BestFitMapping", KnownTypeCode.Boolean, false);
                }
                if ((importAttrs & MethodImportAttributes.BestFitMappingEnable) == MethodImportAttributes.BestFitMappingEnable)
                {
                    dllImport.AddNamedArg("BestFitMapping", KnownTypeCode.Boolean, true);
                }

                CallingConvention callingConvention;
                switch (info.Attributes & MethodImportAttributes.CallingConventionMask)
                {
                case 0:
                    Debug.WriteLine($"P/Invoke calling convention not set on: {this}");
                    callingConvention = 0;
                    break;

                case MethodImportAttributes.CallingConventionCDecl:
                    callingConvention = CallingConvention.Cdecl;
                    break;

                case MethodImportAttributes.CallingConventionFastCall:
                    callingConvention = CallingConvention.FastCall;
                    break;

                case MethodImportAttributes.CallingConventionStdCall:
                    callingConvention = CallingConvention.StdCall;
                    break;

                case MethodImportAttributes.CallingConventionThisCall:
                    callingConvention = CallingConvention.ThisCall;
                    break;

                case MethodImportAttributes.CallingConventionWinApi:
                    callingConvention = CallingConvention.Winapi;
                    break;

                default:
                    throw new NotSupportedException("unknown calling convention");
                }
                if (callingConvention != CallingConvention.Winapi)
                {
                    var callingConventionType = FindInteropType(nameof(CallingConvention));
                    dllImport.AddNamedArg("CallingConvention", callingConventionType, (int)callingConvention);
                }

                CharSet charSet = CharSet.None;
                switch (info.Attributes & MethodImportAttributes.CharSetMask)
                {
                case MethodImportAttributes.CharSetAnsi:
                    charSet = CharSet.Ansi;
                    break;

                case MethodImportAttributes.CharSetAuto:
                    charSet = CharSet.Auto;
                    break;

                case MethodImportAttributes.CharSetUnicode:
                    charSet = CharSet.Unicode;
                    break;
                }
                if (charSet != CharSet.None)
                {
                    var charSetType = FindInteropType(nameof(CharSet));
                    dllImport.AddNamedArg("CharSet", charSetType, (int)charSet);
                }

                if (!info.Name.IsNil && info.Name != def.Name)
                {
                    dllImport.AddNamedArg("EntryPoint", KnownTypeCode.String, metadata.GetString(info.Name));
                }

                if ((info.Attributes & MethodImportAttributes.ExactSpelling) == MethodImportAttributes.ExactSpelling)
                {
                    dllImport.AddNamedArg("ExactSpelling", KnownTypeCode.Boolean, true);
                }

                if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig)
                {
                    implAttributes &= ~MethodImplAttributes.PreserveSig;
                }
                else
                {
                    dllImport.AddNamedArg("PreserveSig", KnownTypeCode.Boolean, false);
                }

                if ((info.Attributes & MethodImportAttributes.SetLastError) == MethodImportAttributes.SetLastError)
                {
                    dllImport.AddNamedArg("SetLastError", KnownTypeCode.Boolean, true);
                }

                if ((info.Attributes & MethodImportAttributes.ThrowOnUnmappableCharDisable) == MethodImportAttributes.ThrowOnUnmappableCharDisable)
                {
                    dllImport.AddNamedArg("ThrowOnUnmappableChar", KnownTypeCode.Boolean, false);
                }
                if ((info.Attributes & MethodImportAttributes.ThrowOnUnmappableCharEnable) == MethodImportAttributes.ThrowOnUnmappableCharEnable)
                {
                    dllImport.AddNamedArg("ThrowOnUnmappableChar", KnownTypeCode.Boolean, true);
                }

                b.Add(dllImport.Build());
            }
            #endregion

            #region PreserveSigAttribute
            if (implAttributes == MethodImplAttributes.PreserveSig)
            {
                b.Add(KnownAttribute.PreserveSig);
                implAttributes = 0;
            }
            #endregion

            #region MethodImplAttribute
            if (implAttributes != 0)
            {
                b.Add(KnownAttribute.MethodImpl,
                      new TopLevelTypeName("System.Runtime.CompilerServices", nameof(MethodImplOptions)),
                      (int)implAttributes
                      );
            }
            #endregion

            b.Add(def.GetCustomAttributes(), symbolKind);
            b.AddSecurityAttributes(def.GetDeclarativeSecurityAttributes());

            return(b.Build());
        }