Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / tools / corcompare / mono-api-info.cs
index 8048ffa29d8480bec5990f4565d38d41f569d287..2dc4bcebb3d99ef9ce3a736184c98627b0dda979 100644 (file)
@@ -20,6 +20,7 @@ using System.Xml;
 
 using Mono.Cecil;
 using Mono.Cecil.Cil;
+using System.IO;
 
 namespace CorCompare
 {
@@ -34,11 +35,32 @@ namespace CorCompare
 
                        AssemblyCollection acoll = new AssemblyCollection ();
 
+                       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")
+                               if (arg == "--abi") {
                                        AbiMode = true;
-                               else
+                               } 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 ();
@@ -80,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;
@@ -107,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;
                        }
                }
@@ -374,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));
@@ -604,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);
                        }
@@ -756,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;
@@ -1004,6 +1048,7 @@ namespace CorCompare
                                                AddAttribute (n, "value", "null");
                                                continue;
                                        }
+                                       
                                        string value = o.ToString ();
                                        if (attName.EndsWith ("GuidAttribute"))
                                                value = value.ToUpper ();
@@ -1033,8 +1078,12 @@ namespace CorCompare
                {
                        foreach (var named_argument in attribute.Properties) {
                                var name = named_argument.Name;
+                               var arg = named_argument.Argument;
 
-                               mapping.Add (name, GetArgumentValue (named_argument.Argument.Type, named_argument.Argument.Value));
+                               if (arg.Value is CustomAttributeArgument)
+                                       arg = (CustomAttributeArgument) arg.Value;
+
+                               mapping.Add (name, GetArgumentValue (arg.Type, arg.Value));
                        }
                }
 
@@ -1110,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);
 
@@ -1118,7 +1190,10 @@ namespace CorCompare
                                if (!field_mapping.TryGetValue (pair.Value, out argument))
                                        continue;
 
-                               var ca_arg = attribute.ConstructorArguments [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));
                        }
                }
@@ -1156,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 ();
 
@@ -1182,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) {