X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Ftools%2Fcorcompare%2Fmono-api-info.cs;h=c43437fe40d869165c5b7d20f02eaa036c58a85f;hb=266345ec8f312b59cbd0bd1026d7304e30a91a2a;hp=203875b15ccf4701050a53f44fd36d1bffcf94f3;hpb=8ef4e4703172fd32ada3f74b22df5203b4683493;p=mono.git diff --git a/mcs/tools/corcompare/mono-api-info.cs b/mcs/tools/corcompare/mono-api-info.cs index 203875b15cc..c43437fe40d 100644 --- a/mcs/tools/corcompare/mono-api-info.cs +++ b/mcs/tools/corcompare/mono-api-info.cs @@ -11,6 +11,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Permissions; @@ -19,6 +20,7 @@ using System.Xml; using Mono.Cecil; using Mono.Cecil.Cil; +using System.IO; namespace CorCompare { @@ -26,13 +28,65 @@ namespace CorCompare { public static int Main (string [] args) { - if (args.Length == 0) - return 1; - - AssemblyCollection acoll = new AssemblyCollection (); + bool showHelp = false; + AbiMode = false; + FollowForwarders = false; + + var acoll = new AssemblyCollection (); + + var options = new Mono.Options.OptionSet { + "usage: mono-api-info [OPTIONS+] ASSEMBLY+", + "", + "Expose IL structure of CLR assemblies as XML.", + "", + "Available Options:", + { "abi", + "Generate ABI, not API; contains only classes with instance fields which are not [NonSerialized].", + v => AbiMode = v != null }, + { "f|follow-forwarders", + "Follow type forwarders.", + v => FollowForwarders = v != null }, + { "d|L|lib|search-directory=", + "Check for assembly references in {DIRECTORY}.", + v => TypeHelper.Resolver.AddSearchDirectory (v) }, + { "r=", + "Read and register the file {ASSEMBLY}, and add the directory containing ASSEMBLY to the search path.", + v => TypeHelper.Resolver.ResolveFile (v) }, + { "h|?|help", + "Show this message and exit.", + v => showHelp = v != null }, + }; + + var asms = options.Parse (args); + + if (showHelp || asms.Count == 0) { + options.WriteOptionDescriptions (Console.Out); + Console.WriteLine (); + return showHelp? 0 :1; + } - foreach (string fullName in args) { - acoll.Add (fullName); + string windir = Environment.GetFolderPath(Environment.SpecialFolder.Windows); + string pf = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + TypeHelper.Resolver.AddSearchDirectory (Path.Combine (windir, @"assembly\GAC\MSDATASRC\7.0.3300.0__b03f5f7f11d50a3a")); + + foreach (string arg in asms) { + acoll.Add (arg); + + if (arg.Contains ("v3.0")) { + TypeHelper.Resolver.AddSearchDirectory (Path.Combine (windir, @"Microsoft.NET\Framework\v2.0.50727")); + } else if (arg.Contains ("v3.5")) { + TypeHelper.Resolver.AddSearchDirectory (Path.Combine (windir, @"Microsoft.NET\Framework\v2.0.50727")); + TypeHelper.Resolver.AddSearchDirectory (Path.Combine (windir, @"Microsoft.NET\Framework\v3.0\Windows Communication Foundation")); + } else if (arg.Contains ("v4.0")) { + if (arg.Contains ("Silverlight")) { + TypeHelper.Resolver.AddSearchDirectory (Path.Combine (pf, @"Microsoft Silverlight\4.0.51204.0")); + } else { + TypeHelper.Resolver.AddSearchDirectory (Path.Combine (windir, @"Microsoft.NET\Framework\v4.0.30319")); + TypeHelper.Resolver.AddSearchDirectory (Path.Combine (windir, @"Microsoft.NET\Framework\v4.0.30319\WPF")); + } + } else { + TypeHelper.Resolver.AddSearchDirectory (Path.GetDirectoryName (arg)); + } } XmlDocument doc = new XmlDocument (); @@ -45,6 +99,9 @@ namespace CorCompare doc.WriteTo (writer); return 0; } + + internal static bool AbiMode { get; private set; } + internal static bool FollowForwarders { get; private set; } } public class Utils { @@ -54,7 +111,7 @@ namespace CorCompare return CleanupTypeName (type.FullName); } - static string CleanupTypeName (string t) + public static string CleanupTypeName (string t) { return t.Replace ('<', '[').Replace ('>', ']').Replace ('/', '+'); } @@ -72,8 +129,10 @@ namespace CorCompare public bool Add (string name) { AssemblyDefinition ass = LoadAssembly (name); - if (ass == null) + if (ass == null) { + Console.Error.WriteLine ("Cannot load assembly file " + name); return false; + } assemblies.Add (ass); return true; @@ -99,8 +158,12 @@ namespace CorCompare AssemblyDefinition LoadAssembly (string assembly) { try { + if (File.Exists (assembly)) + return TypeHelper.Resolver.ResolveFile (assembly); + return TypeHelper.Resolver.Resolve (assembly); - } catch { + } catch (Exception e) { + Console.WriteLine (e); return null; } } @@ -144,13 +207,10 @@ namespace CorCompare natts = document.CreateElement ("attributes", null); parent.AppendChild (natts); } - - foreach (TypeReference tref in ass.MainModule.ExternTypes) { - TypeDefinition def = tref.Resolve (); - if (def == null) - continue; - if (((uint)def.Attributes & 0x200000u) == 0) + foreach (ExportedType type in ass.MainModule.ExportedTypes) { + + if (((uint)type.Attributes & 0x200000u) == 0) continue; XmlNode node = document.CreateElement ("attribute"); @@ -158,7 +218,7 @@ namespace CorCompare XmlNode properties = node.AppendChild (document.CreateElement ("properties")); XmlNode property = properties.AppendChild (document.CreateElement ("property")); AddAttribute (property, "name", "Destination"); - AddAttribute (property, "value", Utils.CleanupTypeName (tref)); + AddAttribute (property, "value", Utils.CleanupTypeName (type.FullName)); natts.AppendChild (node); } } @@ -169,7 +229,7 @@ namespace CorCompare tftd.DoOutput (); } } - + class AssemblyData : BaseData { AssemblyDefinition ass; @@ -190,16 +250,33 @@ namespace CorCompare AddAttribute (nassembly, "name", aname.Name); AddAttribute (nassembly, "version", aname.Version.ToString ()); parent.AppendChild (nassembly); - TypeForwardedToData.OutputForwarders (document, nassembly, ass); - AttributeData.OutputAttributes (document, nassembly, ass.CustomAttributes); - TypeDefinitionCollection typesCollection = ass.MainModule.Types; - if (typesCollection == null || typesCollection.Count == 0) + + if (!Driver.FollowForwarders) { + TypeForwardedToData.OutputForwarders (document, nassembly, ass); + } + + AttributeData.OutputAttributes (document, nassembly, ass); + + var types = new List (); + if (ass.MainModule.Types != null) { + types.AddRange (ass.MainModule.Types); + } + + if (Driver.FollowForwarders && ass.MainModule.ExportedTypes != null) { + foreach (var t in ass.MainModule.ExportedTypes) { + var forwarded = t.Resolve (); + if (forwarded == null) { + throw new Exception ("Could not resolve forwarded type " + t.FullName + " in " + ass.Name); + } + types.Add (forwarded); + } + } + + if (types.Count == 0) { return; - object [] typesArray = new object [typesCollection.Count]; - for (int i = 0; i < typesCollection.Count; i++) { - typesArray [i] = typesCollection [i]; } - Array.Sort (typesArray, TypeReferenceComparer.Default); + + types.Sort (TypeReferenceComparer.Default); XmlNode nss = document.CreateElement ("namespaces", null); nassembly.AppendChild (nss); @@ -207,11 +284,11 @@ namespace CorCompare string current_namespace = "$%&$&"; XmlNode ns = null; XmlNode classes = null; - foreach (TypeDefinition t in typesArray) { + foreach (TypeDefinition t in types) { if (string.IsNullOrEmpty (t.Namespace)) continue; - if ((t.Attributes & TypeAttributes.VisibilityMask) != TypeAttributes.Public) + if (!Driver.AbiMode && ((t.Attributes & TypeAttributes.VisibilityMask) != TypeAttributes.Public)) continue; if (t.DeclaringType != null) @@ -254,15 +331,12 @@ namespace CorCompare if (!NoMemberAttributes) AddAttribute (mnode, "attrib", GetMemberAttributes (member)); - AttributeData.OutputAttributes (document, mnode, GetCustomAttributes (member)); + AttributeData.OutputAttributes (document, mnode, (ICustomAttributeProvider) member); AddExtraData (mnode, member); } } - - protected abstract CustomAttributeCollection GetCustomAttributes (MemberReference member); - protected virtual void AddExtraData (XmlNode p, MemberReference memberDefenition) { } @@ -297,15 +371,15 @@ namespace CorCompare var gparameters = provider.GenericParameters; - XmlElement ngeneric = document.CreateElement (string.Format ("generic-parameters")); + XmlElement ngeneric = document.CreateElement ("generic-parameters"); nclass.AppendChild (ngeneric); foreach (GenericParameter gp in gparameters) { - XmlElement nparam = document.CreateElement (string.Format ("generic-parameter")); + XmlElement nparam = document.CreateElement ("generic-parameter"); nparam.SetAttribute ("name", gp.Name); nparam.SetAttribute ("attributes", ((int) gp.Attributes).ToString ()); - AttributeData.OutputAttributes (document, nparam, gp.CustomAttributes); + AttributeData.OutputAttributes (document, nparam, gp); ngeneric.AppendChild (nparam); @@ -335,11 +409,6 @@ namespace CorCompare { this.type = type; } - - protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) { - return ((TypeDefinition) member).CustomAttributes; - } - public override void DoOutput () { if (document == null) @@ -369,13 +438,21 @@ namespace CorCompare if (layout != null) AddAttribute (nclass, "layout", layout); + if (type.PackingSize >= 0) { + AddAttribute (nclass, "pack", type.PackingSize.ToString ()); + } + + if (type.ClassSize >= 0) { + AddAttribute (nclass, "size", type.ClassSize.ToString ()); + } + parent.AppendChild (nclass); - AttributeData.OutputAttributes (document, nclass, GetCustomAttributes(type)); + AttributeData.OutputAttributes (document, nclass, type); XmlNode ifaces = null; - foreach (TypeReference iface in TypeHelper.GetInterfaces (type)) { + foreach (TypeReference iface in TypeHelper.GetInterfaces (type).OrderBy (s => s.FullName)) { if (!TypeHelper.IsPublic (iface)) // we're only interested in public interfaces continue; @@ -409,34 +486,37 @@ namespace CorCompare AddAttribute (nclass, "enumtype", Utils.CleanupTypeName (value_type.FieldType)); } - MethodDefinition [] ctors = GetConstructors (type); - if (ctors.Length > 0) { - Array.Sort (ctors, MemberReferenceComparer.Default); - members.Add (new ConstructorData (document, nclass, ctors)); - } + if (!Driver.AbiMode) { - PropertyDefinition[] properties = GetProperties (type); - if (properties.Length > 0) { - Array.Sort (properties, MemberReferenceComparer.Default); - members.Add (new PropertyData (document, nclass, properties)); - } + MethodDefinition [] ctors = GetConstructors (type); + if (ctors.Length > 0) { + Array.Sort (ctors, MethodDefinitionComparer.Default); + members.Add (new ConstructorData (document, nclass, ctors)); + } - EventDefinition [] events = GetEvents (type); - if (events.Length > 0) { - Array.Sort (events, MemberReferenceComparer.Default); - members.Add (new EventData (document, nclass, events)); - } + PropertyDefinition[] properties = GetProperties (type); + if (properties.Length > 0) { + Array.Sort (properties, PropertyDefinitionComparer.Default); + members.Add (new PropertyData (document, nclass, properties)); + } + + EventDefinition [] events = GetEvents (type); + if (events.Length > 0) { + Array.Sort (events, MemberReferenceComparer.Default); + members.Add (new EventData (document, nclass, events)); + } - MethodDefinition [] methods = GetMethods (type); - if (methods.Length > 0) { - Array.Sort (methods, MemberReferenceComparer.Default); - members.Add (new MethodData (document, nclass, methods)); + MethodDefinition [] methods = GetMethods (type); + if (methods.Length > 0) { + Array.Sort (methods, MethodDefinitionComparer.Default); + members.Add (new MethodData (document, nclass, methods)); + } } foreach (MemberData md in members) md.DoOutput (); - NestedTypeCollection nested = type.NestedTypes; + var nested = type.NestedTypes; //remove non public(familiy) and nested in second degree for (int i = nested.Count - 1; i >= 0; i--) { TypeDefinition t = nested [i]; @@ -451,11 +531,13 @@ namespace CorCompare nested.RemoveAt (i); } - if (nested.Count > 0) { + var nestedArray = nested.ToArray (); + Array.Sort (nestedArray, TypeReferenceComparer.Default); + XmlNode classes = document.CreateElement ("classes", null); nclass.AppendChild (classes); - foreach (TypeDefinition t in nested) { + foreach (TypeDefinition t in nestedArray) { TypeData td = new TypeData (document, classes, t); td.DoOutput (); } @@ -501,6 +583,9 @@ namespace CorCompare if (TypeHelper.IsDelegate(t)) return "delegate"; + if (t.IsPointer) + return "pointer"; + return "class"; } @@ -537,17 +622,24 @@ namespace CorCompare FieldDefinition [] GetFields (TypeDefinition type) { ArrayList list = new ArrayList (); - FieldDefinitionCollection fields = type.Fields; + var fields = type.Fields; foreach (FieldDefinition field in fields) { if (field.IsSpecialName) continue; + if (Driver.AbiMode && field.IsStatic) + continue; + // we're only interested in public or protected members FieldAttributes maskedVisibility = (field.Attributes & FieldAttributes.FieldAccessMask); - if (maskedVisibility == FieldAttributes.Public - || maskedVisibility == FieldAttributes.Family - || maskedVisibility == FieldAttributes.FamORAssem) { + if (Driver.AbiMode && !field.IsNotSerialized) { list.Add (field); + } else { + if (maskedVisibility == FieldAttributes.Public + || maskedVisibility == FieldAttributes.Family + || maskedVisibility == FieldAttributes.FamORAssem) { + list.Add (field); + } } } @@ -558,7 +650,7 @@ namespace CorCompare internal static PropertyDefinition [] GetProperties (TypeDefinition type) { ArrayList list = new ArrayList (); - PropertyDefinitionCollection properties = type.Properties;//type.GetProperties (flags); + var properties = type.Properties;//type.GetProperties (flags); foreach (PropertyDefinition property in properties) { MethodDefinition getMethod = property.GetMethod; MethodDefinition setMethod = property.SetMethod; @@ -580,7 +672,7 @@ namespace CorCompare { ArrayList list = new ArrayList (); - MethodDefinitionCollection methods = type.Methods;//type.GetMethods (flags); + var methods = type.Methods;//type.GetMethods (flags); foreach (MethodDefinition method in methods) { if (method.IsSpecialName && !method.Name.StartsWith ("op_")) continue; @@ -589,8 +681,14 @@ namespace CorCompare if (!MustDocumentMethod(method)) continue; - if (IsFinalizer (method)) - continue; + if (IsFinalizer (method)) { + string name = method.DeclaringType.Name; + int arity = name.IndexOf ('`'); + if (arity > 0) + name = name.Substring (0, arity); + + method.Name = "~" + name; + } list.Add (method); } @@ -616,7 +714,7 @@ namespace CorCompare { ArrayList list = new ArrayList (); - ConstructorCollection ctors = type.Constructors;//type.GetConstructors (flags); + var ctors = type.Methods.Where (m => m.IsConstructor);//type.GetConstructors (flags); foreach (MethodDefinition constructor in ctors) { // we're only interested in public or protected members if (!MustDocumentMethod(constructor)) @@ -632,7 +730,7 @@ namespace CorCompare { ArrayList list = new ArrayList (); - EventDefinitionCollection events = type.Events;//type.GetEvents (flags); + var events = type.Events;//type.GetEvents (flags); foreach (EventDefinition eventDef in events) { MethodDefinition addMethod = eventDef.AddMethod;//eventInfo.GetAddMethod (true); @@ -653,10 +751,6 @@ namespace CorCompare { } - protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) { - return ((FieldDefinition) member).CustomAttributes; - } - protected override string GetName (MemberReference memberDefenition) { FieldDefinition field = (FieldDefinition) memberDefenition; @@ -709,10 +803,6 @@ namespace CorCompare { } - protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) { - return ((PropertyDefinition) member).CustomAttributes; - } - protected override string GetName (MemberReference memberDefenition) { PropertyDefinition prop = (PropertyDefinition) memberDefenition; @@ -741,9 +831,11 @@ namespace CorCompare return; } - string parms = Parameters.GetSignature (methods [0].Parameters); - if (!string.IsNullOrEmpty (parms)) - AddAttribute (p, "params", parms); + if (haveGet || _set.Parameters.Count > 1) { + string parms = Parameters.GetSignature (methods [0].Parameters); + if (!string.IsNullOrEmpty (parms)) + AddAttribute (p, "params", parms); + } MethodData data = new MethodData (document, p, methods); //data.NoMemberAttributes = true; @@ -772,10 +864,6 @@ namespace CorCompare { } - protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) { - return ((EventDefinition) member).CustomAttributes; - } - protected override string GetName (MemberReference memberDefenition) { EventDefinition evt = (EventDefinition) memberDefenition; @@ -813,10 +901,6 @@ namespace CorCompare { } - protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) { - return ((MethodDefinition) member).CustomAttributes; - } - protected override string GetName (MemberReference memberDefenition) { MethodDefinition method = (MethodDefinition) memberDefenition; @@ -848,14 +932,16 @@ namespace CorCompare AddAttribute (p, "abstract", "true"); if (mbase.IsVirtual) AddAttribute (p, "virtual", "true"); + if (mbase.IsFinal && mbase.IsVirtual && mbase.IsReuseSlot) + AddAttribute (p, "sealed", "true"); if (mbase.IsStatic) AddAttribute (p, "static", "true"); - string rettype = Utils.CleanupTypeName (mbase.ReturnType.ReturnType); + string rettype = Utils.CleanupTypeName (mbase.MethodReturnType.ReturnType); if (rettype != "System.Void" || !mbase.IsConstructor) AddAttribute (p, "returntype", (rettype)); - AttributeData.OutputAttributes (document, p, mbase.ReturnType.CustomAttributes); + AttributeData.OutputAttributes (document, p, mbase.MethodReturnType); MemberData.OutputGenericParameters (document, p, mbase); } @@ -892,9 +978,9 @@ namespace CorCompare class ParameterData : BaseData { - private ParameterDefinitionCollection parameters; + private IList parameters; - public ParameterData (XmlDocument document, XmlNode parent, ParameterDefinitionCollection parameters) + public ParameterData (XmlDocument document, XmlNode parent, IList parameters) : base (document, parent) { this.parameters = parameters; @@ -914,7 +1000,7 @@ namespace CorCompare string direction = "in"; - if (parameter.ParameterType is ReferenceType) + if (parameter.ParameterType is ByReferenceType) direction = parameter.IsOut ? "out" : "ref"; TypeReference t = parameter.ParameterType; @@ -929,16 +1015,16 @@ namespace CorCompare if (direction != "in") AddAttribute (paramNode, "direction", direction); - AttributeData.OutputAttributes (document, paramNode, parameter.CustomAttributes); + AttributeData.OutputAttributes (document, paramNode, parameter); } } } class AttributeData : BaseData { - CustomAttributeCollection atts; + IList atts; - AttributeData (XmlDocument doc, XmlNode parent, CustomAttributeCollection attributes) + AttributeData (XmlDocument doc, XmlNode parent, IList attributes) : base (doc, parent) { atts = attributes; @@ -958,15 +1044,7 @@ namespace CorCompare parent.AppendChild (natts); } - for (int i = 0; i < atts.Count; ++i) { - CustomAttribute att = atts [i]; - try { - att.Resolve (); - } catch {} - - if (!att.Resolved) - continue; - + foreach (var att in atts.OrderBy ((a) => a.Constructor.DeclaringType.FullName)) { string attName = Utils.CleanupTypeName (att.Constructor.DeclaringType); if (SkipAttribute (att)) continue; @@ -995,6 +1073,7 @@ namespace CorCompare AddAttribute (n, "value", "null"); continue; } + string value = o.ToString (); if (attName.EndsWith ("GuidAttribute")) value = value.ToUpper (); @@ -1012,7 +1091,7 @@ namespace CorCompare PopulateMapping (mapping, attribute); var constructor = attribute.Constructor.Resolve (); - if (constructor == null || constructor.Parameters.Count == 0) + if (constructor == null || !constructor.HasParameters) return mapping; PopulateMapping (mapping, constructor, attribute); @@ -1022,10 +1101,17 @@ namespace CorCompare static void PopulateMapping (Dictionary mapping, CustomAttribute attribute) { - foreach (DictionaryEntry entry in attribute.Properties) { - var name = (string) entry.Key; + if (!attribute.HasProperties) + return; + + foreach (var named_argument in attribute.Properties) { + var name = named_argument.Name; + var arg = named_argument.Argument; + + if (arg.Value is CustomAttributeArgument) + arg = (CustomAttributeArgument) arg.Value; - mapping.Add (name, GetArgumentValue (attribute.GetPropertyType (name), entry.Value)); + mapping.Add (name, GetArgumentValue (arg.Type, arg.Value)); } } @@ -1048,7 +1134,7 @@ namespace CorCompare break; case Code.Ldarg: case Code.Ldarg_S: - argument = ((ParameterDefinition) instruction.Operand).Sequence; + argument = ((ParameterDefinition) instruction.Operand).Index + 1; break; case Code.Stfld: @@ -1101,6 +1187,29 @@ namespace CorCompare if (!constructor.HasBody) return; + // Custom handling for attributes with arguments which cannot be easily extracted + var ca = attribute.ConstructorArguments; + switch (constructor.DeclaringType.FullName) { + case "System.Runtime.CompilerServices.DecimalConstantAttribute": + var dca = constructor.Parameters[2].ParameterType == constructor.Module.TypeSystem.Int32 ? + new DecimalConstantAttribute ((byte) ca[0].Value, (byte) ca[1].Value, (int) ca[2].Value, (int) ca[3].Value, (int) ca[4].Value) : + new DecimalConstantAttribute ((byte) ca[0].Value, (byte) ca[1].Value, (uint) ca[2].Value, (uint) ca[3].Value, (uint) ca[4].Value); + + mapping.Add ("Value", dca.Value); + return; + case "System.ComponentModel.BindableAttribute": + if (ca.Count != 1) + break; + + if (constructor.Parameters[0].ParameterType == constructor.Module.TypeSystem.Boolean) { + mapping.Add ("Bindable", ca[0].Value); + } else { + throw new NotImplementedException (); + } + + return; + } + var field_mapping = CreateArgumentFieldMapping (constructor); var property_mapping = CreatePropertyFieldMapping ((TypeDefinition) constructor.DeclaringType); @@ -1109,7 +1218,11 @@ namespace CorCompare if (!field_mapping.TryGetValue (pair.Value, out argument)) continue; - mapping.Add (pair.Key.Name, GetArgumentValue (constructor.Parameters [argument].ParameterType, attribute.ConstructorParameters [argument])); + var ca_arg = ca [argument]; + if (ca_arg.Value is CustomAttributeArgument) + ca_arg = (CustomAttributeArgument) ca_arg.Value; + + mapping.Add (pair.Key.Name, GetArgumentValue (ca_arg.Type, ca_arg.Value)); } } @@ -1134,7 +1247,7 @@ namespace CorCompare if (!type.IsEnum) return false; - if (type.CustomAttributes.Count == 0) + if (!type.HasCustomAttributes) return false; foreach (CustomAttribute attribute in type.CustomAttributes) @@ -1146,6 +1259,9 @@ namespace CorCompare static object GetFlaggedEnumValue (TypeDefinition type, object value) { + if (value is ulong) + return GetFlaggedEnumValue (type, (ulong)value); + long flags = Convert.ToInt64 (value); var signature = new StringBuilder (); @@ -1172,6 +1288,33 @@ namespace CorCompare return signature.ToString (); } + static object GetFlaggedEnumValue (TypeDefinition type, ulong flags) + { + var signature = new StringBuilder (); + + for (int i = type.Fields.Count - 1; i >= 0; i--) { + FieldDefinition field = type.Fields [i]; + + if (!field.HasConstant) + continue; + + ulong flag = Convert.ToUInt64 (field.Constant); + + if (flag == 0) + continue; + + if ((flags & flag) == flag) { + if (signature.Length != 0) + signature.Append (", "); + + signature.Append (field.Name); + flags -= flag; + } + } + + return signature.ToString (); + } + static object GetEnumValue (TypeDefinition type, object value) { foreach (FieldDefinition field in type.Fields) { @@ -1193,19 +1336,22 @@ namespace CorCompare || type_name.EndsWith ("TODOAttribute"); } - public static void OutputAttributes (XmlDocument doc, XmlNode parent, CustomAttributeCollection attributes) + public static void OutputAttributes (XmlDocument doc, XmlNode parent, ICustomAttributeProvider provider) { - AttributeData ad = new AttributeData (doc, parent, attributes); + if (!provider.HasCustomAttributes) + return; + + AttributeData ad = new AttributeData (doc, parent, provider.CustomAttributes); ad.DoOutput (); } } static class Parameters { - public static string GetSignature (ParameterDefinitionCollection infos) + public static string GetSignature (IList infos) { if (infos == null || infos.Count == 0) - return ""; + return string.Empty; var signature = new StringBuilder (); for (int i = 0; i < infos.Count; i++) { @@ -1218,15 +1364,15 @@ namespace CorCompare string modifier; if ((info.Attributes & ParameterAttributes.In) != 0) modifier = "in"; - else if ((info.Attributes & ParameterAttributes.Retval) != 0) - modifier = "ref"; else if ((info.Attributes & ParameterAttributes.Out) != 0) modifier = "out"; else modifier = string.Empty; - if (modifier.Length > 0) - signature.AppendFormat ("{0} ", modifier); + if (modifier.Length > 0) { + signature.Append (modifier); + signature.Append (" "); + } signature.Append (Utils.CleanupTypeName (info.ParameterType)); } @@ -1236,19 +1382,17 @@ namespace CorCompare } - class TypeReferenceComparer : IComparer + class TypeReferenceComparer : IComparer { public static TypeReferenceComparer Default = new TypeReferenceComparer (); - public int Compare (object a, object b) + public int Compare (TypeReference a, TypeReference b) { - TypeReference ta = (TypeReference) a; - TypeReference tb = (TypeReference) b; - int result = String.Compare (ta.Namespace, tb.Namespace); + int result = String.Compare (a.Namespace, b.Namespace, StringComparison.Ordinal); if (result != 0) return result; - return String.Compare (ta.Name, tb.Name); + return String.Compare (a.Name, b.Name, StringComparison.Ordinal); } } @@ -1260,7 +1404,30 @@ namespace CorCompare { MemberReference ma = (MemberReference) a; MemberReference mb = (MemberReference) b; - return String.Compare (ma.Name, mb.Name); + return String.Compare (ma.Name, mb.Name, StringComparison.Ordinal); + } + } + + class PropertyDefinitionComparer : IComparer + { + public static PropertyDefinitionComparer Default = new PropertyDefinitionComparer (); + + public int Compare (PropertyDefinition ma, PropertyDefinition mb) + { + int res = String.Compare (ma.Name, mb.Name); + if (res != 0) + return res; + + if (!ma.HasParameters && !mb.HasParameters) + return 0; + + if (!ma.HasParameters) + return -1; + + if (!mb.HasParameters) + return 1; + + return MethodDefinitionComparer.Compare (ma.Parameters, mb.Parameters); } } @@ -1276,9 +1443,26 @@ namespace CorCompare if (res != 0) return res; - ParameterDefinitionCollection pia = ma.Parameters ; - ParameterDefinitionCollection pib = mb.Parameters; - res = pia.Count - pib.Count; + if (!ma.HasParameters && !mb.HasParameters) + return 0; + + if (!ma.HasParameters) + return -1; + + if (!mb.HasParameters) + return 1; + + res = Compare (ma.Parameters, mb.Parameters); + if (res != 0) + return res; + + // operators can differ by only return type + return string.CompareOrdinal (ma.ReturnType.FullName, mb.ReturnType.FullName); + } + + public static int Compare (IList pia, IList pib) + { + var res = pia.Count - pib.Count; if (res != 0) return res;