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;
using Mono.Cecil;
using Mono.Cecil.Cil;
+using System.IO;
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 ();
doc.WriteTo (writer);
return 0;
}
+
+ internal static bool AbiMode { get; private set; }
}
public class Utils {
return CleanupTypeName (type.FullName);
}
- static string CleanupTypeName (string t)
+ public static string CleanupTypeName (string t)
{
return t.Replace ('<', '[').Replace ('>', ']').Replace ('/', '+');
}
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;
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;
}
}
}
}
+ 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;
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];
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)
}
- protected abstract CustomAttributeCollection GetCustomAttributes (MemberReference member);
+ protected abstract IList<CustomAttribute> GetCustomAttributes (MemberReference member);
protected virtual void AddExtraData (XmlNode p, MemberReference memberDefenition)
{
this.type = type;
}
- protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+ protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
return ((TypeDefinition) member).CustomAttributes;
}
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));
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];
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);
+ }
}
}
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;
{
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;
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);
}
{
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))
{
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);
{
}
- protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+ protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
return ((FieldDefinition) member).CustomAttributes;
}
{
}
- protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+ protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
return ((PropertyDefinition) member).CustomAttributes;
}
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;
{
}
- protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+ protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
return ((EventDefinition) member).CustomAttributes;
}
{
}
- protected override CustomAttributeCollection GetCustomAttributes (MemberReference member) {
+ protected override IList<CustomAttribute> GetCustomAttributes (MemberReference member) {
return ((MethodDefinition) member).CustomAttributes;
}
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);
}
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;
string direction = "in";
- if (parameter.ParameterType is ReferenceType)
+ if (parameter.ParameterType is ByReferenceType)
direction = parameter.IsOut ? "out" : "ref";
TypeReference t = parameter.ParameterType;
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;
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))
AddAttribute (n, "value", "null");
continue;
}
+
string value = o.ToString ();
if (attName.EndsWith ("GuidAttribute"))
value = value.ToUpper ();
PopulateMapping (mapping, attribute);
- var constructor = TypeHelper.Resolver.Resolve (attribute.Constructor);
+ var constructor = attribute.Constructor.Resolve ();
if (constructor == null || constructor.Parameters.Count == 0)
return mapping;
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));
}
}
break;
case Code.Ldarg:
case Code.Ldarg_S:
- argument = ((ParameterDefinition) instruction.Operand).Sequence;
+ argument = ((ParameterDefinition) instruction.Operand).Index + 1;
break;
case Code.Stfld:
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);
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;
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 ();
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) {
|| 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 ();
static class Parameters {
- public static string GetSignature (ParameterDefinitionCollection infos)
+ public static string GetSignature (IList<ParameterDefinition> infos)
{
if (infos == null || infos.Count == 0)
return "";
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
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;