2 // mono-api-info.cs - Dumps public assembly information to an xml file.
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Copyright (C) 2003-2008 Novell, Inc (http://www.novell.com)
11 using System
.Collections
;
12 using System
.Collections
.Generic
;
13 using System
.Globalization
;
14 using System
.Runtime
.CompilerServices
;
15 using System
.Runtime
.InteropServices
;
16 using System
.Security
.Permissions
;
27 public static int Main (string [] args
)
32 AssemblyCollection acoll
= new AssemblyCollection ();
34 foreach (string fullName
in args
) {
38 XmlDocument doc
= new XmlDocument ();
42 var writer
= new WellFormedXmlWriter (new XmlTextWriter (Console
.Out
) { Formatting = Formatting.Indented }
);
43 XmlNode decl
= doc
.CreateXmlDeclaration ("1.0", "utf-8", null);
44 doc
.InsertBefore (decl
, doc
.DocumentElement
);
52 public static string CleanupTypeName (TypeReference type
)
54 return CleanupTypeName (type
.FullName
);
57 static string CleanupTypeName (string t
)
59 return t
.Replace ('<', '[').Replace ('>', ']').Replace ('/', '+');
63 class AssemblyCollection
66 List
<AssemblyDefinition
> assemblies
= new List
<AssemblyDefinition
> ();
68 public AssemblyCollection ()
72 public bool Add (string name
)
74 AssemblyDefinition ass
= LoadAssembly (name
);
82 public void DoOutput ()
85 throw new InvalidOperationException ("Document not set");
87 XmlNode nassemblies
= document
.CreateElement ("assemblies", null);
88 document
.AppendChild (nassemblies
);
89 foreach (AssemblyDefinition a
in assemblies
) {
90 AssemblyData data
= new AssemblyData (document
, nassemblies
, a
);
95 public XmlDocument Document
{
96 set { document = value; }
99 AssemblyDefinition
LoadAssembly (string assembly
)
102 return TypeHelper
.Resolver
.Resolve (assembly
);
109 abstract class BaseData
111 protected XmlDocument document
;
112 protected XmlNode parent
;
114 protected BaseData (XmlDocument doc
, XmlNode parent
)
117 this.parent
= parent
;
120 public abstract void DoOutput ();
122 protected void AddAttribute (XmlNode node
, string name
, string value)
124 XmlAttribute attr
= document
.CreateAttribute (name
);
126 node
.Attributes
.Append (attr
);
130 class TypeForwardedToData
: BaseData
132 AssemblyDefinition ass
;
134 public TypeForwardedToData (XmlDocument document
, XmlNode parent
, AssemblyDefinition ass
)
135 : base (document
, parent
)
140 public override void DoOutput ()
142 XmlNode natts
= parent
.SelectSingleNode("attributes");
144 natts
= document
.CreateElement ("attributes", null);
145 parent
.AppendChild (natts
);
148 foreach (TypeReference tref
in ass
.MainModule
.ExternTypes
) {
149 TypeDefinition def
= tref
.Resolve ();
153 if (((uint)def
.Attributes
& 0x200000u
) == 0)
156 XmlNode node
= document
.CreateElement ("attribute");
157 AddAttribute (node
, "name", typeof (TypeForwardedToAttribute
).FullName
);
158 XmlNode properties
= node
.AppendChild (document
.CreateElement ("properties"));
159 XmlNode property
= properties
.AppendChild (document
.CreateElement ("property"));
160 AddAttribute (property
, "name", "Destination");
161 AddAttribute (property
, "value", Utils
.CleanupTypeName (tref
));
162 natts
.AppendChild (node
);
166 public static void OutputForwarders (XmlDocument document
, XmlNode parent
, AssemblyDefinition ass
)
168 TypeForwardedToData tftd
= new TypeForwardedToData (document
, parent
, ass
);
173 class AssemblyData
: BaseData
175 AssemblyDefinition ass
;
177 public AssemblyData (XmlDocument document
, XmlNode parent
, AssemblyDefinition ass
)
178 : base (document
, parent
)
183 public override void DoOutput ()
185 if (document
== null)
186 throw new InvalidOperationException ("Document not set");
188 XmlNode nassembly
= document
.CreateElement ("assembly", null);
189 AssemblyNameDefinition aname
= ass
.Name
;
190 AddAttribute (nassembly
, "name", aname
.Name
);
191 AddAttribute (nassembly
, "version", aname
.Version
.ToString ());
192 parent
.AppendChild (nassembly
);
193 TypeForwardedToData
.OutputForwarders (document
, nassembly
, ass
);
194 AttributeData
.OutputAttributes (document
, nassembly
, ass
.CustomAttributes
);
195 TypeDefinitionCollection typesCollection
= ass
.MainModule
.Types
;
196 if (typesCollection
== null || typesCollection
.Count
== 0)
198 object [] typesArray
= new object [typesCollection
.Count
];
199 for (int i
= 0; i
< typesCollection
.Count
; i
++) {
200 typesArray
[i
] = typesCollection
[i
];
202 Array
.Sort (typesArray
, TypeReferenceComparer
.Default
);
204 XmlNode nss
= document
.CreateElement ("namespaces", null);
205 nassembly
.AppendChild (nss
);
207 string current_namespace
= "$%&$&";
209 XmlNode classes
= null;
210 foreach (TypeDefinition t
in typesArray
) {
211 if (string.IsNullOrEmpty (t
.Namespace
))
214 if ((t
.Attributes
& TypeAttributes
.VisibilityMask
) != TypeAttributes
.Public
)
217 if (t
.DeclaringType
!= null)
218 continue; // enforce !nested
220 if (t
.Namespace
!= current_namespace
) {
221 current_namespace
= t
.Namespace
;
222 ns
= document
.CreateElement ("namespace", null);
223 AddAttribute (ns
, "name", current_namespace
);
224 nss
.AppendChild (ns
);
225 classes
= document
.CreateElement ("classes", null);
226 ns
.AppendChild (classes
);
229 TypeData bd
= new TypeData (document
, classes
, t
);
235 abstract class MemberData
: BaseData
237 MemberReference
[] members
;
239 public MemberData (XmlDocument document
, XmlNode parent
, MemberReference
[] members
)
240 : base (document
, parent
)
242 this.members
= members
;
245 public override void DoOutput ()
247 XmlNode mclass
= document
.CreateElement (ParentTag
, null);
248 parent
.AppendChild (mclass
);
250 foreach (MemberReference member
in members
) {
251 XmlNode mnode
= document
.CreateElement (Tag
, null);
252 mclass
.AppendChild (mnode
);
253 AddAttribute (mnode
, "name", GetName (member
));
254 if (!NoMemberAttributes
)
255 AddAttribute (mnode
, "attrib", GetMemberAttributes (member
));
257 AttributeData
.OutputAttributes (document
, mnode
, GetCustomAttributes (member
));
259 AddExtraData (mnode
, member
);
264 protected abstract CustomAttributeCollection
GetCustomAttributes (MemberReference member
);
266 protected virtual void AddExtraData (XmlNode p
, MemberReference memberDefenition
)
270 protected virtual string GetName (MemberReference memberDefenition
)
275 protected virtual string GetMemberAttributes (MemberReference memberDefenition
)
280 public virtual bool NoMemberAttributes
{
281 get { return false; }
285 public virtual string ParentTag
{
286 get { return "NoPARENTTAG"; }
289 public virtual string Tag
{
290 get { return "NoTAG"; }
293 public static void OutputGenericParameters (XmlDocument document
, XmlNode nclass
, IGenericParameterProvider provider
)
295 if (provider
.GenericParameters
.Count
== 0)
298 var gparameters
= provider
.GenericParameters
;
300 XmlElement ngeneric
= document
.CreateElement (string.Format ("generic-parameters"));
301 nclass
.AppendChild (ngeneric
);
303 foreach (GenericParameter gp
in gparameters
) {
304 XmlElement nparam
= document
.CreateElement (string.Format ("generic-parameter"));
305 nparam
.SetAttribute ("name", gp
.Name
);
306 nparam
.SetAttribute ("attributes", ((int) gp
.Attributes
).ToString ());
308 AttributeData
.OutputAttributes (document
, nparam
, gp
.CustomAttributes
);
310 ngeneric
.AppendChild (nparam
);
312 var constraints
= gp
.Constraints
;
313 if (constraints
.Count
== 0)
316 XmlElement nconstraint
= document
.CreateElement ("generic-parameter-constraints");
318 foreach (TypeReference constraint
in constraints
) {
319 XmlElement ncons
= document
.CreateElement ("generic-parameter-constraint");
320 ncons
.SetAttribute ("name", Utils
.CleanupTypeName (constraint
));
321 nconstraint
.AppendChild (ncons
);
324 nparam
.AppendChild (nconstraint
);
329 class TypeData
: MemberData
333 public TypeData (XmlDocument document
, XmlNode parent
, TypeDefinition type
)
334 : base (document
, parent
, null)
339 protected override CustomAttributeCollection
GetCustomAttributes (MemberReference member
) {
340 return ((TypeDefinition
) member
).CustomAttributes
;
343 public override void DoOutput ()
345 if (document
== null)
346 throw new InvalidOperationException ("Document not set");
348 XmlNode nclass
= document
.CreateElement ("class", null);
349 AddAttribute (nclass
, "name", type
.Name
);
350 string classType
= GetClassType (type
);
351 AddAttribute (nclass
, "type", classType
);
353 if (type
.BaseType
!= null)
354 AddAttribute (nclass
, "base", Utils
.CleanupTypeName (type
.BaseType
));
357 AddAttribute (nclass
, "sealed", "true");
360 AddAttribute (nclass
, "abstract", "true");
362 if ( (type
.Attributes
& TypeAttributes
.Serializable
) != 0 || type
.IsEnum
)
363 AddAttribute (nclass
, "serializable", "true");
365 string charSet
= GetCharSet (type
);
366 AddAttribute (nclass
, "charset", charSet
);
368 string layout
= GetLayout (type
);
370 AddAttribute (nclass
, "layout", layout
);
372 parent
.AppendChild (nclass
);
374 AttributeData
.OutputAttributes (document
, nclass
, GetCustomAttributes(type
));
376 XmlNode ifaces
= null;
378 foreach (TypeReference iface
in TypeHelper
.GetInterfaces (type
)) {
379 if (!TypeHelper
.IsPublic (iface
))
380 // we're only interested in public interfaces
383 if (ifaces
== null) {
384 ifaces
= document
.CreateElement ("interfaces", null);
385 nclass
.AppendChild (ifaces
);
388 XmlNode iface_node
= document
.CreateElement ("interface", null);
389 AddAttribute (iface_node
, "name", Utils
.CleanupTypeName (iface
));
390 ifaces
.AppendChild (iface_node
);
393 MemberData
.OutputGenericParameters (document
, nclass
, type
);
395 ArrayList members
= new ArrayList ();
397 FieldDefinition
[] fields
= GetFields (type
);
398 if (fields
.Length
> 0) {
399 Array
.Sort (fields
, MemberReferenceComparer
.Default
);
400 FieldData fd
= new FieldData (document
, nclass
, fields
);
405 var value_type
= GetEnumValueField (type
);
406 if (value_type
== null)
407 throw new NotSupportedException ();
409 AddAttribute (nclass
, "enumtype", Utils
.CleanupTypeName (value_type
.FieldType
));
412 MethodDefinition
[] ctors
= GetConstructors (type
);
413 if (ctors
.Length
> 0) {
414 Array
.Sort (ctors
, MemberReferenceComparer
.Default
);
415 members
.Add (new ConstructorData (document
, nclass
, ctors
));
418 PropertyDefinition
[] properties
= GetProperties (type
);
419 if (properties
.Length
> 0) {
420 Array
.Sort (properties
, MemberReferenceComparer
.Default
);
421 members
.Add (new PropertyData (document
, nclass
, properties
));
424 EventDefinition
[] events
= GetEvents (type
);
425 if (events
.Length
> 0) {
426 Array
.Sort (events
, MemberReferenceComparer
.Default
);
427 members
.Add (new EventData (document
, nclass
, events
));
430 MethodDefinition
[] methods
= GetMethods (type
);
431 if (methods
.Length
> 0) {
432 Array
.Sort (methods
, MemberReferenceComparer
.Default
);
433 members
.Add (new MethodData (document
, nclass
, methods
));
436 foreach (MemberData md
in members
)
439 NestedTypeCollection nested
= type
.NestedTypes
;
440 //remove non public(familiy) and nested in second degree
441 for (int i
= nested
.Count
- 1; i
>= 0; i
--) {
442 TypeDefinition t
= nested
[i
];
443 if ((t
.Attributes
& TypeAttributes
.VisibilityMask
) == TypeAttributes
.NestedPublic
||
444 (t
.Attributes
& TypeAttributes
.VisibilityMask
) == TypeAttributes
.NestedFamily
||
445 (t
.Attributes
& TypeAttributes
.VisibilityMask
) == TypeAttributes
.NestedFamORAssem
) {
447 if (t
.DeclaringType
== type
)
448 continue; // not nested of nested
455 if (nested
.Count
> 0) {
456 XmlNode classes
= document
.CreateElement ("classes", null);
457 nclass
.AppendChild (classes
);
458 foreach (TypeDefinition t
in nested
) {
459 TypeData td
= new TypeData (document
, classes
, t
);
465 static FieldReference
GetEnumValueField (TypeDefinition type
)
467 foreach (FieldDefinition field
in type
.Fields
)
468 if (field
.IsSpecialName
&& field
.Name
== "value__")
474 protected override string GetMemberAttributes (MemberReference member
)
477 throw new InvalidOperationException ("odd");
479 return ((int) type
.Attributes
).ToString (CultureInfo
.InvariantCulture
);
482 public static bool MustDocumentMethod (MethodDefinition method
) {
484 MethodAttributes maskedAccess
= method
.Attributes
& MethodAttributes
.MemberAccessMask
;
485 return maskedAccess
== MethodAttributes
.Public
486 || maskedAccess
== MethodAttributes
.Family
487 || maskedAccess
== MethodAttributes
.FamORAssem
;
490 static string GetClassType (TypeDefinition t
)
501 if (TypeHelper
.IsDelegate(t
))
507 static string GetCharSet (TypeDefinition type
)
509 TypeAttributes maskedStringFormat
= type
.Attributes
& TypeAttributes
.StringFormatMask
;
510 if (maskedStringFormat
== TypeAttributes
.AnsiClass
)
511 return CharSet
.Ansi
.ToString ();
513 if (maskedStringFormat
== TypeAttributes
.AutoClass
)
514 return CharSet
.Auto
.ToString ();
516 if (maskedStringFormat
== TypeAttributes
.UnicodeClass
)
517 return CharSet
.Unicode
.ToString ();
519 return CharSet
.None
.ToString ();
522 static string GetLayout (TypeDefinition type
)
524 TypeAttributes maskedLayout
= type
.Attributes
& TypeAttributes
.LayoutMask
;
525 if (maskedLayout
== TypeAttributes
.AutoLayout
)
526 return LayoutKind
.Auto
.ToString ();
528 if (maskedLayout
== TypeAttributes
.ExplicitLayout
)
529 return LayoutKind
.Explicit
.ToString ();
531 if (maskedLayout
== TypeAttributes
.SequentialLayout
)
532 return LayoutKind
.Sequential
.ToString ();
537 FieldDefinition
[] GetFields (TypeDefinition type
) {
538 ArrayList list
= new ArrayList ();
540 FieldDefinitionCollection fields
= type
.Fields
;
541 foreach (FieldDefinition field
in fields
) {
542 if (field
.IsSpecialName
)
545 // we're only interested in public or protected members
546 FieldAttributes maskedVisibility
= (field
.Attributes
& FieldAttributes
.FieldAccessMask
);
547 if (maskedVisibility
== FieldAttributes
.Public
548 || maskedVisibility
== FieldAttributes
.Family
549 || maskedVisibility
== FieldAttributes
.FamORAssem
) {
554 return (FieldDefinition
[]) list
.ToArray (typeof (FieldDefinition
));
558 internal static PropertyDefinition
[] GetProperties (TypeDefinition type
) {
559 ArrayList list
= new ArrayList ();
561 PropertyDefinitionCollection properties
= type
.Properties
;//type.GetProperties (flags);
562 foreach (PropertyDefinition property
in properties
) {
563 MethodDefinition getMethod
= property
.GetMethod
;
564 MethodDefinition setMethod
= property
.SetMethod
;
566 bool hasGetter
= (getMethod
!= null) && MustDocumentMethod (getMethod
);
567 bool hasSetter
= (setMethod
!= null) && MustDocumentMethod (setMethod
);
569 // if neither the getter or setter should be documented, then
571 if (hasGetter
|| hasSetter
) {
576 return (PropertyDefinition
[]) list
.ToArray (typeof (PropertyDefinition
));
579 private MethodDefinition
[] GetMethods (TypeDefinition type
)
581 ArrayList list
= new ArrayList ();
583 MethodDefinitionCollection methods
= type
.Methods
;//type.GetMethods (flags);
584 foreach (MethodDefinition method
in methods
) {
585 if (method
.IsSpecialName
&& !method
.Name
.StartsWith ("op_"))
588 // we're only interested in public or protected members
589 if (!MustDocumentMethod(method
))
592 if (IsFinalizer (method
))
598 return (MethodDefinition
[]) list
.ToArray (typeof (MethodDefinition
));
601 static bool IsFinalizer (MethodDefinition method
)
603 if (method
.Name
!= "Finalize")
606 if (!method
.IsVirtual
)
609 if (method
.Parameters
.Count
!= 0)
615 private MethodDefinition
[] GetConstructors (TypeDefinition type
)
617 ArrayList list
= new ArrayList ();
619 ConstructorCollection ctors
= type
.Constructors
;//type.GetConstructors (flags);
620 foreach (MethodDefinition constructor
in ctors
) {
621 // we're only interested in public or protected members
622 if (!MustDocumentMethod(constructor
))
625 list
.Add (constructor
);
628 return (MethodDefinition
[]) list
.ToArray (typeof (MethodDefinition
));
631 private EventDefinition
[] GetEvents (TypeDefinition type
)
633 ArrayList list
= new ArrayList ();
635 EventDefinitionCollection events
= type
.Events
;//type.GetEvents (flags);
636 foreach (EventDefinition eventDef
in events
) {
637 MethodDefinition addMethod
= eventDef
.AddMethod
;//eventInfo.GetAddMethod (true);
639 if (addMethod
== null || !MustDocumentMethod (addMethod
))
645 return (EventDefinition
[]) list
.ToArray (typeof (EventDefinition
));
649 class FieldData
: MemberData
651 public FieldData (XmlDocument document
, XmlNode parent
, FieldDefinition
[] members
)
652 : base (document
, parent
, members
)
656 protected override CustomAttributeCollection
GetCustomAttributes (MemberReference member
) {
657 return ((FieldDefinition
) member
).CustomAttributes
;
660 protected override string GetName (MemberReference memberDefenition
)
662 FieldDefinition field
= (FieldDefinition
) memberDefenition
;
666 protected override string GetMemberAttributes (MemberReference memberDefenition
)
668 FieldDefinition field
= (FieldDefinition
) memberDefenition
;
669 return ((int) field
.Attributes
).ToString (CultureInfo
.InvariantCulture
);
672 protected override void AddExtraData (XmlNode p
, MemberReference memberDefenition
)
674 base.AddExtraData (p
, memberDefenition
);
675 FieldDefinition field
= (FieldDefinition
) memberDefenition
;
676 AddAttribute (p
, "fieldtype", Utils
.CleanupTypeName (field
.FieldType
));
678 if (field
.IsLiteral
) {
679 object value = field
.Constant
;//object value = field.GetValue (null);
680 string stringValue
= null;
681 //if (value is Enum) {
682 // // FIXME: when Mono bug #60090 has been
683 // // fixed, we should just be able to use
684 // // Convert.ToString
685 // stringValue = ((Enum) value).ToString ("D", CultureInfo.InvariantCulture);
688 stringValue
= Convert
.ToString (value, CultureInfo
.InvariantCulture
);
691 if (stringValue
!= null)
692 AddAttribute (p
, "value", stringValue
);
696 public override string ParentTag
{
697 get { return "fields"; }
700 public override string Tag
{
701 get { return "field"; }
705 class PropertyData
: MemberData
707 public PropertyData (XmlDocument document
, XmlNode parent
, PropertyDefinition
[] members
)
708 : base (document
, parent
, members
)
712 protected override CustomAttributeCollection
GetCustomAttributes (MemberReference member
) {
713 return ((PropertyDefinition
) member
).CustomAttributes
;
716 protected override string GetName (MemberReference memberDefenition
)
718 PropertyDefinition prop
= (PropertyDefinition
) memberDefenition
;
722 protected override void AddExtraData (XmlNode p
, MemberReference memberDefenition
)
724 base.AddExtraData (p
, memberDefenition
);
725 PropertyDefinition prop
= (PropertyDefinition
) memberDefenition
;
726 AddAttribute (p
, "ptype", Utils
.CleanupTypeName (prop
.PropertyType
));
727 MethodDefinition _get
= prop
.GetMethod
;
728 MethodDefinition _set
= prop
.SetMethod
;
729 bool haveGet
= (_get
!= null && TypeData
.MustDocumentMethod(_get
));
730 bool haveSet
= (_set
!= null && TypeData
.MustDocumentMethod(_set
));
731 MethodDefinition
[] methods
;
733 if (haveGet
&& haveSet
) {
734 methods
= new MethodDefinition
[] { _get, _set }
;
735 } else if (haveGet
) {
736 methods
= new MethodDefinition
[] { _get }
;
737 } else if (haveSet
) {
738 methods
= new MethodDefinition
[] { _set }
;
744 string parms
= Parameters
.GetSignature (methods
[0].Parameters
);
745 if (!string.IsNullOrEmpty (parms
))
746 AddAttribute (p
, "params", parms
);
748 MethodData data
= new MethodData (document
, p
, methods
);
749 //data.NoMemberAttributes = true;
753 protected override string GetMemberAttributes (MemberReference memberDefenition
)
755 PropertyDefinition prop
= (PropertyDefinition
) memberDefenition
;
756 return ((int) prop
.Attributes
).ToString (CultureInfo
.InvariantCulture
);
759 public override string ParentTag
{
760 get { return "properties"; }
763 public override string Tag
{
764 get { return "property"; }
768 class EventData
: MemberData
770 public EventData (XmlDocument document
, XmlNode parent
, EventDefinition
[] members
)
771 : base (document
, parent
, members
)
775 protected override CustomAttributeCollection
GetCustomAttributes (MemberReference member
) {
776 return ((EventDefinition
) member
).CustomAttributes
;
779 protected override string GetName (MemberReference memberDefenition
)
781 EventDefinition evt
= (EventDefinition
) memberDefenition
;
785 protected override string GetMemberAttributes (MemberReference memberDefenition
)
787 EventDefinition evt
= (EventDefinition
) memberDefenition
;
788 return ((int) evt
.Attributes
).ToString (CultureInfo
.InvariantCulture
);
791 protected override void AddExtraData (XmlNode p
, MemberReference memberDefenition
)
793 base.AddExtraData (p
, memberDefenition
);
794 EventDefinition evt
= (EventDefinition
) memberDefenition
;
795 AddAttribute (p
, "eventtype", Utils
.CleanupTypeName (evt
.EventType
));
798 public override string ParentTag
{
799 get { return "events"; }
802 public override string Tag
{
803 get { return "event"; }
807 class MethodData
: MemberData
811 public MethodData (XmlDocument document
, XmlNode parent
, MethodDefinition
[] members
)
812 : base (document
, parent
, members
)
816 protected override CustomAttributeCollection
GetCustomAttributes (MemberReference member
) {
817 return ((MethodDefinition
) member
).CustomAttributes
;
820 protected override string GetName (MemberReference memberDefenition
)
822 MethodDefinition method
= (MethodDefinition
) memberDefenition
;
823 string name
= method
.Name
;
824 string parms
= Parameters
.GetSignature (method
.Parameters
);
826 return string.Format ("{0}({1})", name
, parms
);
829 protected override string GetMemberAttributes (MemberReference memberDefenition
)
831 MethodDefinition method
= (MethodDefinition
) memberDefenition
;
832 return ((int)( method
.Attributes
)).ToString (CultureInfo
.InvariantCulture
);
835 protected override void AddExtraData (XmlNode p
, MemberReference memberDefenition
)
837 base.AddExtraData (p
, memberDefenition
);
839 if (!(memberDefenition
is MethodDefinition
))
842 MethodDefinition mbase
= (MethodDefinition
) memberDefenition
;
844 ParameterData parms
= new ParameterData (document
, p
, mbase
.Parameters
);
847 if (mbase
.IsAbstract
)
848 AddAttribute (p
, "abstract", "true");
850 AddAttribute (p
, "virtual", "true");
852 AddAttribute (p
, "static", "true");
854 string rettype
= Utils
.CleanupTypeName (mbase
.ReturnType
.ReturnType
);
855 if (rettype
!= "System.Void" || !mbase
.IsConstructor
)
856 AddAttribute (p
, "returntype", (rettype
));
858 AttributeData
.OutputAttributes (document
, p
, mbase
.ReturnType
.CustomAttributes
);
860 MemberData
.OutputGenericParameters (document
, p
, mbase
);
863 public override bool NoMemberAttributes
{
864 get { return noAtts; }
865 set { noAtts = value; }
868 public override string ParentTag
{
869 get { return "methods"; }
872 public override string Tag
{
873 get { return "method"; }
877 class ConstructorData
: MethodData
879 public ConstructorData (XmlDocument document
, XmlNode parent
, MethodDefinition
[] members
)
880 : base (document
, parent
, members
)
884 public override string ParentTag
{
885 get { return "constructors"; }
888 public override string Tag
{
889 get { return "constructor"; }
893 class ParameterData
: BaseData
895 private ParameterDefinitionCollection parameters
;
897 public ParameterData (XmlDocument document
, XmlNode parent
, ParameterDefinitionCollection parameters
)
898 : base (document
, parent
)
900 this.parameters
= parameters
;
903 public override void DoOutput ()
905 XmlNode parametersNode
= document
.CreateElement ("parameters");
906 parent
.AppendChild (parametersNode
);
908 foreach (ParameterDefinition parameter
in parameters
) {
909 XmlNode paramNode
= document
.CreateElement ("parameter");
910 parametersNode
.AppendChild (paramNode
);
911 AddAttribute (paramNode
, "name", parameter
.Name
);
912 AddAttribute (paramNode
, "position", parameter
.Method
.Parameters
.IndexOf(parameter
).ToString(CultureInfo
.InvariantCulture
));
913 AddAttribute (paramNode
, "attrib", ((int) parameter
.Attributes
).ToString());
915 string direction
= "in";
917 if (parameter
.ParameterType
is ReferenceType
)
918 direction
= parameter
.IsOut
? "out" : "ref";
920 TypeReference t
= parameter
.ParameterType
;
921 AddAttribute (paramNode
, "type", Utils
.CleanupTypeName (t
));
923 if (parameter
.IsOptional
) {
924 AddAttribute (paramNode
, "optional", "true");
925 if (parameter
.HasConstant
)
926 AddAttribute (paramNode
, "defaultValue", parameter
.Constant
== null ? "NULL" : parameter
.Constant
.ToString ());
929 if (direction
!= "in")
930 AddAttribute (paramNode
, "direction", direction
);
932 AttributeData
.OutputAttributes (document
, paramNode
, parameter
.CustomAttributes
);
937 class AttributeData
: BaseData
939 CustomAttributeCollection atts
;
941 AttributeData (XmlDocument doc
, XmlNode parent
, CustomAttributeCollection attributes
)
947 public override void DoOutput ()
949 if (document
== null)
950 throw new InvalidOperationException ("Document not set");
952 if (atts
== null || atts
.Count
== 0)
955 XmlNode natts
= parent
.SelectSingleNode("attributes");
957 natts
= document
.CreateElement ("attributes", null);
958 parent
.AppendChild (natts
);
961 for (int i
= 0; i
< atts
.Count
; ++i
) {
962 CustomAttribute att
= atts
[i
];
970 string attName
= Utils
.CleanupTypeName (att
.Constructor
.DeclaringType
);
971 if (SkipAttribute (att
))
974 XmlNode node
= document
.CreateElement ("attribute");
975 AddAttribute (node
, "name", attName
);
977 XmlNode properties
= null;
979 Dictionary
<string, object> attribute_mapping
= CreateAttributeMapping (att
);
981 foreach (string name
in attribute_mapping
.Keys
) {
982 if (name
== "TypeId")
985 if (properties
== null) {
986 properties
= node
.AppendChild (document
.CreateElement ("properties"));
989 object o
= attribute_mapping
[name
];
991 XmlNode n
= properties
.AppendChild (document
.CreateElement ("property"));
992 AddAttribute (n
, "name", name
);
995 AddAttribute (n
, "value", "null");
998 string value = o
.ToString ();
999 if (attName
.EndsWith ("GuidAttribute"))
1000 value = value.ToUpper ();
1001 AddAttribute (n
, "value", value);
1004 natts
.AppendChild (node
);
1008 static Dictionary
<string, object> CreateAttributeMapping (CustomAttribute attribute
)
1010 var mapping
= new Dictionary
<string, object> ();
1012 PopulateMapping (mapping
, attribute
);
1014 var constructor
= attribute
.Constructor
.Resolve ();
1015 if (constructor
== null || constructor
.Parameters
.Count
== 0)
1018 PopulateMapping (mapping
, constructor
, attribute
);
1023 static void PopulateMapping (Dictionary
<string, object> mapping
, CustomAttribute attribute
)
1025 foreach (DictionaryEntry entry
in attribute
.Properties
) {
1026 var name
= (string) entry
.Key
;
1028 mapping
.Add (name
, GetArgumentValue (attribute
.GetPropertyType (name
), entry
.Value
));
1032 static Dictionary
<FieldReference
, int> CreateArgumentFieldMapping (MethodDefinition constructor
)
1034 Dictionary
<FieldReference
, int> field_mapping
= new Dictionary
<FieldReference
, int> ();
1036 int? argument
= null;
1038 foreach (Instruction instruction
in constructor
.Body
.Instructions
) {
1039 switch (instruction
.OpCode
.Code
) {
1051 argument
= ((ParameterDefinition
) instruction
.Operand
).Sequence
;
1055 FieldReference field
= (FieldReference
) instruction
.Operand
;
1056 if (field
.DeclaringType
.FullName
!= constructor
.DeclaringType
.FullName
)
1059 if (!argument
.HasValue
)
1062 if (!field_mapping
.ContainsKey (field
))
1063 field_mapping
.Add (field
, (int) argument
- 1);
1070 return field_mapping
;
1073 static Dictionary
<PropertyDefinition
, FieldReference
> CreatePropertyFieldMapping (TypeDefinition type
)
1075 Dictionary
<PropertyDefinition
, FieldReference
> property_mapping
= new Dictionary
<PropertyDefinition
, FieldReference
> ();
1077 foreach (PropertyDefinition property
in type
.Properties
) {
1078 if (property
.GetMethod
== null)
1080 if (!property
.GetMethod
.HasBody
)
1083 foreach (Instruction instruction
in property
.GetMethod
.Body
.Instructions
) {
1084 if (instruction
.OpCode
.Code
!= Code
.Ldfld
)
1087 FieldReference field
= (FieldReference
) instruction
.Operand
;
1088 if (field
.DeclaringType
.FullName
!= type
.FullName
)
1091 property_mapping
.Add (property
, field
);
1096 return property_mapping
;
1099 static void PopulateMapping (Dictionary
<string, object> mapping
, MethodDefinition constructor
, CustomAttribute attribute
)
1101 if (!constructor
.HasBody
)
1104 var field_mapping
= CreateArgumentFieldMapping (constructor
);
1105 var property_mapping
= CreatePropertyFieldMapping ((TypeDefinition
) constructor
.DeclaringType
);
1107 foreach (var pair
in property_mapping
) {
1109 if (!field_mapping
.TryGetValue (pair
.Value
, out argument
))
1112 mapping
.Add (pair
.Key
.Name
, GetArgumentValue (constructor
.Parameters
[argument
].ParameterType
, attribute
.ConstructorParameters
[argument
]));
1116 static object GetArgumentValue (TypeReference reference
, object value)
1118 var type
= reference
.Resolve ();
1123 if (IsFlaggedEnum (type
))
1124 return GetFlaggedEnumValue (type
, value);
1126 return GetEnumValue (type
, value);
1132 static bool IsFlaggedEnum (TypeDefinition type
)
1137 if (type
.CustomAttributes
.Count
== 0)
1140 foreach (CustomAttribute attribute
in type
.CustomAttributes
)
1141 if (attribute
.Constructor
.DeclaringType
.FullName
== "System.FlagsAttribute")
1147 static object GetFlaggedEnumValue (TypeDefinition type
, object value)
1149 long flags
= Convert
.ToInt64 (value);
1150 var signature
= new StringBuilder ();
1152 for (int i
= type
.Fields
.Count
- 1; i
>= 0; i
--) {
1153 FieldDefinition field
= type
.Fields
[i
];
1155 if (!field
.HasConstant
)
1158 long flag
= Convert
.ToInt64 (field
.Constant
);
1163 if ((flags
& flag
) == flag
) {
1164 if (signature
.Length
!= 0)
1165 signature
.Append (", ");
1167 signature
.Append (field
.Name
);
1172 return signature
.ToString ();
1175 static object GetEnumValue (TypeDefinition type
, object value)
1177 foreach (FieldDefinition field
in type
.Fields
) {
1178 if (!field
.HasConstant
)
1181 if (Comparer
.Default
.Compare (field
.Constant
, value) == 0)
1188 static bool SkipAttribute (CustomAttribute attribute
)
1190 var type_name
= Utils
.CleanupTypeName (attribute
.Constructor
.DeclaringType
);
1192 return !TypeHelper
.IsPublic (attribute
)
1193 || type_name
.EndsWith ("TODOAttribute");
1196 public static void OutputAttributes (XmlDocument doc
, XmlNode parent
, CustomAttributeCollection attributes
)
1198 AttributeData ad
= new AttributeData (doc
, parent
, attributes
);
1203 static class Parameters
{
1205 public static string GetSignature (ParameterDefinitionCollection infos
)
1207 if (infos
== null || infos
.Count
== 0)
1210 var signature
= new StringBuilder ();
1211 for (int i
= 0; i
< infos
.Count
; i
++) {
1214 signature
.Append (", ");
1216 ParameterDefinition info
= infos
[i
];
1219 if ((info
.Attributes
& ParameterAttributes
.In
) != 0)
1221 else if ((info
.Attributes
& ParameterAttributes
.Retval
) != 0)
1223 else if ((info
.Attributes
& ParameterAttributes
.Out
) != 0)
1226 modifier
= string.Empty
;
1228 if (modifier
.Length
> 0)
1229 signature
.AppendFormat ("{0} ", modifier
);
1231 signature
.Append (Utils
.CleanupTypeName (info
.ParameterType
));
1234 return signature
.ToString ();
1239 class TypeReferenceComparer
: IComparer
1241 public static TypeReferenceComparer Default
= new TypeReferenceComparer ();
1243 public int Compare (object a
, object b
)
1245 TypeReference ta
= (TypeReference
) a
;
1246 TypeReference tb
= (TypeReference
) b
;
1247 int result
= String
.Compare (ta
.Namespace
, tb
.Namespace
);
1251 return String
.Compare (ta
.Name
, tb
.Name
);
1255 class MemberReferenceComparer
: IComparer
1257 public static MemberReferenceComparer Default
= new MemberReferenceComparer ();
1259 public int Compare (object a
, object b
)
1261 MemberReference ma
= (MemberReference
) a
;
1262 MemberReference mb
= (MemberReference
) b
;
1263 return String
.Compare (ma
.Name
, mb
.Name
);
1267 class MethodDefinitionComparer
: IComparer
1269 public static MethodDefinitionComparer Default
= new MethodDefinitionComparer ();
1271 public int Compare (object a
, object b
)
1273 MethodDefinition ma
= (MethodDefinition
) a
;
1274 MethodDefinition mb
= (MethodDefinition
) b
;
1275 int res
= String
.Compare (ma
.Name
, mb
.Name
);
1279 ParameterDefinitionCollection pia
= ma
.Parameters
;
1280 ParameterDefinitionCollection pib
= mb
.Parameters
;
1281 res
= pia
.Count
- pib
.Count
;
1285 string siga
= Parameters
.GetSignature (pia
);
1286 string sigb
= Parameters
.GetSignature (pib
);
1287 return String
.Compare (siga
, sigb
);