Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / tools / corcompare / mono-api-info.cs
index e168101a2ff0673354110656aac45b3da6609398..2dc4bcebb3d99ef9ce3a736184c98627b0dda979 100644 (file)
@@ -11,6 +11,8 @@ 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;
 using System.Text;
@@ -18,6 +20,7 @@ using System.Xml;
 
 using Mono.Cecil;
 using Mono.Cecil.Cil;
+using System.IO;
 
 namespace CorCompare
 {
@@ -28,10 +31,36 @@ namespace CorCompare
                        if (args.Length == 0)
                                return 1;
 
+                       AbiMode = false;
+
                        AssemblyCollection acoll = new AssemblyCollection ();
 
-                       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 args) {
+                               if (arg == "--abi") {
+                                       AbiMode = true;
+                               } else {
+                                       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 ();
@@ -44,6 +73,8 @@ namespace CorCompare
                        doc.WriteTo (writer);
                        return 0;
                }
+
+               internal static bool AbiMode { get; private set; }
        }
 
        public class Utils {
@@ -53,7 +84,7 @@ namespace CorCompare
                        return CleanupTypeName (type.FullName);
                }
 
-               static string CleanupTypeName (string t)
+               public static string CleanupTypeName (string t)
                {
                        return t.Replace ('<', '[').Replace ('>', ']').Replace ('/', '+');
                }
@@ -71,8 +102,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;
@@ -98,8 +131,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;
                        }
                }
@@ -126,6 +163,46 @@ namespace CorCompare
                }
        }
 
+       class TypeForwardedToData : BaseData
+       {
+               AssemblyDefinition ass;
+
+               public TypeForwardedToData (XmlDocument document, XmlNode parent, AssemblyDefinition ass)
+                       : base (document, parent)
+               {
+                       this.ass = ass;
+               }
+
+               public override void DoOutput ()
+               {
+                       XmlNode natts = parent.SelectSingleNode("attributes");
+                       if (natts == null) {
+                               natts = document.CreateElement ("attributes", null);
+                               parent.AppendChild (natts);
+                       }
+
+                       foreach (ExportedType type in ass.MainModule.ExportedTypes) {
+
+                               if (((uint)type.Attributes & 0x200000u) == 0)
+                                       continue;
+
+                               XmlNode node = document.CreateElement ("attribute");
+                               AddAttribute (node, "name", typeof (TypeForwardedToAttribute).FullName);
+                               XmlNode properties = node.AppendChild (document.CreateElement ("properties"));
+                               XmlNode property = properties.AppendChild (document.CreateElement ("property"));
+                               AddAttribute (property, "name", "Destination");
+                               AddAttribute (property, "value", Utils.CleanupTypeName (type.FullName));
+                               natts.AppendChild (node);
+                       }
+               }
+
+               public static void OutputForwarders (XmlDocument document, XmlNode parent, AssemblyDefinition ass)
+               {
+                       TypeForwardedToData tftd = new TypeForwardedToData (document, parent, ass);
+                       tftd.DoOutput ();
+               }
+       }
+
        class AssemblyData : BaseData
        {
                AssemblyDefinition ass;
@@ -146,8 +223,9 @@ 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;
+                       var typesCollection = ass.MainModule.Types;
                        if (typesCollection == null || typesCollection.Count == 0)
                                return;
                        object [] typesArray = new object [typesCollection.Count];
@@ -166,7 +244,7 @@ namespace CorCompare
                                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)
@@ -216,7 +294,7 @@ namespace CorCompare
                }
 
 
-               protected abstract CustomAttributeCollection GetCustomAttributes (MemberReference member);
+               protected abstract IList<CustomAttribute> GetCustomAttributes (MemberReference member);
 
                protected virtual void AddExtraData (XmlNode p, MemberReference memberDefenition)
                {
@@ -291,7 +369,7 @@ namespace CorCompare
                        this.type = type;
                }
 
-               protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+               protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
                        return ((TypeDefinition) member).CustomAttributes;
                }
 
@@ -324,6 +402,14 @@ 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));
@@ -364,34 +450,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, MemberReferenceComparer.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, MemberReferenceComparer.Default);
+                                       members.Add (new PropertyData (document, nclass, properties));
+                               }
 
-                       MethodDefinition [] methods = GetMethods (type);
-                       if (methods.Length > 0) {
-                               Array.Sort (methods, MemberReferenceComparer.Default);
-                               members.Add (new MethodData (document, nclass, methods));
+                               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));
+                               }
                        }
 
                        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];
@@ -492,17 +581,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);
+                                       }
                                }
                        }
 
@@ -513,7 +609,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;
@@ -535,7 +631,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;
@@ -544,8 +640,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);
                        }
@@ -571,7 +673,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))
@@ -587,7 +689,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);
 
@@ -608,7 +710,7 @@ namespace CorCompare
                {
                }
 
-               protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+               protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
                        return ((FieldDefinition) member).CustomAttributes;
                }
 
@@ -664,7 +766,7 @@ namespace CorCompare
                {
                }
 
-               protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+               protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
                        return ((PropertyDefinition) member).CustomAttributes;
                }
 
@@ -696,9 +798,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;
@@ -727,7 +831,7 @@ namespace CorCompare
                {
                }
 
-               protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+               protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
                        return ((EventDefinition) member).CustomAttributes;
                }
 
@@ -768,7 +872,7 @@ namespace CorCompare
                {
                }
 
-               protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+               protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
                        return ((MethodDefinition) member).CustomAttributes;
                }
 
@@ -806,11 +910,11 @@ namespace CorCompare
                        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.CustomAttributes);
 
                        MemberData.OutputGenericParameters (document, p, mbase);
                }
@@ -847,9 +951,9 @@ namespace CorCompare
 
        class ParameterData : BaseData
        {
-               private ParameterDefinitionCollection parameters;
+               private IList<ParameterDefinition> parameters;
 
-               public ParameterData (XmlDocument document, XmlNode parent, ParameterDefinitionCollection parameters)
+               public ParameterData (XmlDocument document, XmlNode parent, IList<ParameterDefinition> parameters)
                        : base (document, parent)
                {
                        this.parameters = parameters;
@@ -869,7 +973,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;
@@ -891,9 +995,9 @@ namespace CorCompare
 
        class AttributeData : BaseData
        {
-               CustomAttributeCollection atts;
+               IList<CustomAttribute> atts;
 
-               AttributeData (XmlDocument doc, XmlNode parent, CustomAttributeCollection attributes)
+               AttributeData (XmlDocument doc, XmlNode parent, IList<CustomAttribute> attributes)
                        : base (doc, parent)
                {
                        atts = attributes;
@@ -915,12 +1019,6 @@ namespace CorCompare
 
                        for (int i = 0; i < atts.Count; ++i) {
                                CustomAttribute att = atts [i];
-                               try {
-                                       att.Resolve ();
-                               } catch {}
-
-                               if (!att.Resolved)
-                                       continue;
 
                                string attName = Utils.CleanupTypeName (att.Constructor.DeclaringType);
                                if (SkipAttribute (att))
@@ -950,6 +1048,7 @@ namespace CorCompare
                                                AddAttribute (n, "value", "null");
                                                continue;
                                        }
+                                       
                                        string value = o.ToString ();
                                        if (attName.EndsWith ("GuidAttribute"))
                                                value = value.ToUpper ();
@@ -966,7 +1065,7 @@ namespace CorCompare
 
                        PopulateMapping (mapping, attribute);
 
-                       var constructor = TypeHelper.Resolver.Resolve (attribute.Constructor);
+                       var constructor = attribute.Constructor.Resolve ();
                        if (constructor == null || constructor.Parameters.Count == 0)
                                return mapping;
 
@@ -977,10 +1076,14 @@ namespace CorCompare
 
                static void PopulateMapping (Dictionary<string, object> mapping, CustomAttribute attribute)
                {
-                       foreach (DictionaryEntry entry in attribute.Properties) {
-                               var name = (string) entry.Key;
+                       foreach (var named_argument in attribute.Properties) {
+                               var name = named_argument.Name;
+                               var arg = named_argument.Argument;
 
-                               mapping.Add (name, GetArgumentValue (attribute.GetPropertyType (name), entry.Value));
+                               if (arg.Value is CustomAttributeArgument)
+                                       arg = (CustomAttributeArgument) arg.Value;
+
+                               mapping.Add (name, GetArgumentValue (arg.Type, arg.Value));
                        }
                }
 
@@ -1003,7 +1106,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:
@@ -1056,6 +1159,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);
 
@@ -1064,13 +1190,17 @@ 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));
                        }
                }
 
                static object GetArgumentValue (TypeReference reference, object value)
                {
-                       var type = TypeHelper.Resolver.Resolve (reference);
+                       var type = reference.Resolve ();
                        if (type == null)
                                return value;
 
@@ -1101,6 +1231,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 ();
 
@@ -1127,6 +1260,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) {
@@ -1148,7 +1308,7 @@ namespace CorCompare
                                || type_name.EndsWith ("TODOAttribute");
                }
 
-               public static void OutputAttributes (XmlDocument doc, XmlNode parent, CustomAttributeCollection attributes)
+               public static void OutputAttributes (XmlDocument doc, XmlNode parent, IList<CustomAttribute> attributes)
                {
                        AttributeData ad = new AttributeData (doc, parent, attributes);
                        ad.DoOutput ();
@@ -1157,7 +1317,7 @@ namespace CorCompare
 
        static class Parameters {
 
-               public static string GetSignature (ParameterDefinitionCollection infos)
+               public static string GetSignature (IList<ParameterDefinition> infos)
                {
                        if (infos == null || infos.Count == 0)
                                return "";
@@ -1173,8 +1333,6 @@ 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
@@ -1231,8 +1389,8 @@ namespace CorCompare
                        if (res != 0)
                                return res;
 
-                       ParameterDefinitionCollection pia = ma.Parameters ;
-                       ParameterDefinitionCollection pib = mb.Parameters;
+                       IList<ParameterDefinition> pia = ma.Parameters ;
+                       IList<ParameterDefinition> pib = mb.Parameters;
                        res = pia.Count - pib.Count;
                        if (res != 0)
                                return res;