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
;
15 using System
.Runtime
.CompilerServices
;
16 using System
.Runtime
.InteropServices
;
17 using System
.Security
.Permissions
;
25 namespace Mono
.ApiTools
{
30 public static int Main (string [] args
)
32 bool showHelp
= false;
34 List
<string> asms
= null;
35 ApiInfoConfig config
= new ApiInfoConfig ();
37 var options
= new Mono
.Options
.OptionSet
{
39 "Generate ABI, not API; contains only classes with instance fields which are not [NonSerialized].",
40 v
=> config
.AbiMode
= v
!= null },
41 { "f|follow-forwarders",
42 "Follow type forwarders.",
43 v
=> config
.FollowForwarders
= v
!= null },
44 { "ignore-inherited-interfaces",
45 "Ignore interfaces on the base type.",
46 v
=> config
.IgnoreInheritedInterfaces
= v
!= null },
47 { "ignore-resolution-errors",
48 "Ignore any assemblies that cannot be found.",
49 v
=> config
.IgnoreResolutionErrors
= v
!= null },
50 { "d|L|lib|search-directory=",
51 "Check for assembly references in {DIRECTORY}.",
52 v
=> config
.SearchDirectories
.Add (v
) },
54 "Read and register the file {ASSEMBLY}, and add the directory containing ASSEMBLY to the search path.",
55 v
=> config
.ResolveFiles
.Add (v
) },
57 "The output file. If not specified the output will be written to stdout.",
60 "Show this message and exit.",
61 v
=> showHelp
= v
!= null },
63 "Produces contract API with all members at each level of inheritance hierarchy",
64 v
=> config
.FullApiSet
= v
!= null },
68 asms
= options
.Parse (args
);
69 } catch (Mono
.Options
.OptionException e
) {
70 Console
.WriteLine ("Option error: {0}", e
.Message
);
74 if (showHelp
|| asms
== null || asms
.Count
== 0) {
75 Console
.WriteLine ("usage: mono-api-info [OPTIONS+] ASSEMBLY+");
77 Console
.WriteLine ("Expose IL structure of CLR assemblies as XML.");
79 Console
.WriteLine ("Available Options:");
81 options
.WriteOptionDescriptions (Console
.Out
);
83 return showHelp
? 0 : 1;
86 TextWriter outputStream
= null;
88 if (!string.IsNullOrEmpty (output
))
89 outputStream
= new StreamWriter (output
);
91 ApiInfo
.Generate (asms
, null, outputStream
?? Console
.Out
, config
);
92 } catch (Exception e
) {
93 Console
.Error
.WriteLine (e
);
96 outputStream
?.Dispose ();
105 public bool AbiMode { get; set; }
= false;
107 public bool FollowForwarders { get; set; }
= false;
109 public bool FullApiSet { get; set; }
= false;
111 public bool IgnoreResolutionErrors { get; set; }
= false;
113 public bool IgnoreInheritedInterfaces { get; set; }
= false;
115 public List
<string> SearchDirectories { get; }
= new List
<string> ();
117 public List
<string> ResolveFiles { get; }
= new List
<string> ();
119 public List
<Stream
> ResolveStreams { get; }
= new List
<Stream
> ();
121 public TypeHelper TypeHelper { get; private set; }
123 public void ResolveTypes ()
125 TypeHelper
= new TypeHelper (IgnoreResolutionErrors
, IgnoreInheritedInterfaces
);
127 if (SearchDirectories
!= null) {
128 foreach (var v
in SearchDirectories
)
129 TypeHelper
.Resolver
.AddSearchDirectory (v
);
131 if (ResolveFiles
!= null) {
132 foreach (var v
in ResolveFiles
)
133 TypeHelper
.Resolver
.ResolveFile (v
);
135 if (ResolveStreams
!= null) {
136 foreach (var v
in ResolveStreams
)
137 TypeHelper
.Resolver
.ResolveStream (v
);
142 public class ApiInfoConfig
144 public bool AbiMode { get; set; }
= false;
146 public bool FollowForwarders { get; set; }
= false;
148 public bool FullApiSet { get; set; }
= false;
150 public bool IgnoreResolutionErrors { get; set; }
= false;
152 public bool IgnoreInheritedInterfaces { get; set; }
= false;
154 public List
<string> SearchDirectories { get; set; }
= new List
<string> ();
156 public List
<string> ResolveFiles { get; set; }
= new List
<string> ();
158 public List
<Stream
> ResolveStreams { get; set; }
= new List
<Stream
> ();
161 public static class ApiInfo
163 public static void Generate (string assemblyPath
, TextWriter outStream
, ApiInfoConfig config
= null)
165 if (assemblyPath
== null)
166 throw new ArgumentNullException (nameof (assemblyPath
));
168 Generate (new [] { assemblyPath }
, null, outStream
, config
);
171 public static void Generate (Stream assemblyStream
, TextWriter outStream
, ApiInfoConfig config
= null)
173 if (assemblyStream
== null)
174 throw new ArgumentNullException (nameof (assemblyStream
));
176 Generate (null, new [] { assemblyStream }
, outStream
, config
);
179 public static void Generate (IEnumerable
<string> assemblyPaths
, TextWriter outStream
, ApiInfoConfig config
= null)
181 Generate (assemblyPaths
, null, outStream
, config
);
184 public static void Generate (IEnumerable
<Stream
> assemblyStreams
, TextWriter outStream
, ApiInfoConfig config
= null)
186 Generate (null, assemblyStreams
, outStream
, config
);
189 public static void Generate (IEnumerable
<string> assemblyPaths
, IEnumerable
<Stream
> assemblyStreams
, TextWriter outStream
, ApiInfoConfig config
= null)
191 if (outStream
== null)
192 throw new ArgumentNullException (nameof (outStream
));
195 config
= new ApiInfoConfig ();
197 var state
= new State
{
198 AbiMode
= config
.AbiMode
,
199 FollowForwarders
= config
.FollowForwarders
,
200 FullApiSet
= config
.FullApiSet
,
201 IgnoreResolutionErrors
= config
.IgnoreResolutionErrors
,
202 IgnoreInheritedInterfaces
= config
.IgnoreInheritedInterfaces
,
204 state
.SearchDirectories
.AddRange (config
.SearchDirectories
);
205 state
.ResolveFiles
.AddRange (config
.ResolveFiles
);
206 state
.ResolveStreams
.AddRange (config
.ResolveStreams
);
208 Generate (assemblyPaths
, assemblyStreams
, outStream
, state
);
211 internal static void Generate (IEnumerable
<string> assemblyFiles
, IEnumerable
<Stream
> assemblyStreams
, TextWriter outStream
, State state
= null)
213 if (outStream
== null)
214 throw new ArgumentNullException (nameof (outStream
));
217 state
= new State ();
219 state
.ResolveTypes ();
221 string windir
= Environment
.GetFolderPath (Environment
.SpecialFolder
.Windows
);
222 string pf
= Environment
.GetFolderPath (Environment
.SpecialFolder
.ProgramFiles
);
223 state
.TypeHelper
.Resolver
.AddSearchDirectory (Path
.Combine (windir
, @"assembly\GAC\MSDATASRC\7.0.3300.0__b03f5f7f11d50a3a"));
225 var acoll
= new AssemblyCollection (state
);
226 if (assemblyFiles
!= null) {
227 foreach (string arg
in assemblyFiles
) {
230 if (arg
.Contains ("v3.0")) {
231 state
.TypeHelper
.Resolver
.AddSearchDirectory (Path
.Combine (windir
, @"Microsoft.NET\Framework\v2.0.50727"));
232 } else if (arg
.Contains ("v3.5")) {
233 state
.TypeHelper
.Resolver
.AddSearchDirectory (Path
.Combine (windir
, @"Microsoft.NET\Framework\v2.0.50727"));
234 state
.TypeHelper
.Resolver
.AddSearchDirectory (Path
.Combine (windir
, @"Microsoft.NET\Framework\v3.0\Windows Communication Foundation"));
235 } else if (arg
.Contains ("v4.0")) {
236 if (arg
.Contains ("Silverlight")) {
237 state
.TypeHelper
.Resolver
.AddSearchDirectory (Path
.Combine (pf
, @"Microsoft Silverlight\4.0.51204.0"));
239 state
.TypeHelper
.Resolver
.AddSearchDirectory (Path
.Combine (windir
, @"Microsoft.NET\Framework\v4.0.30319"));
240 state
.TypeHelper
.Resolver
.AddSearchDirectory (Path
.Combine (windir
, @"Microsoft.NET\Framework\v4.0.30319\WPF"));
243 state
.TypeHelper
.Resolver
.AddSearchDirectory (Path
.GetDirectoryName (arg
));
247 if (assemblyStreams
!= null) {
248 foreach (var arg
in assemblyStreams
) {
253 var settings
= new XmlWriterSettings
{
256 using (var textWriter
= XmlWriter
.Create (outStream
, settings
)) {
257 var writer
= new WellFormedXmlWriter (textWriter
);
258 writer
.WriteStartDocument ();
259 acoll
.Writer
= writer
;
261 writer
.WriteEndDocument ();
268 static char[] CharsToCleanup
= new char[] { '<', '>', '/' }
;
270 public static string CleanupTypeName (TypeReference type
)
272 return CleanupTypeName (type
.FullName
);
275 public static string CleanupTypeName (string t
)
277 if (t
.IndexOfAny (CharsToCleanup
) == -1)
279 var sb
= new StringBuilder (t
.Length
);
280 for (int i
= 0; i
< t
.Length
; i
++) {
297 return sb
.ToString ();
301 class AssemblyCollection
304 List
<AssemblyDefinition
> assemblies
= new List
<AssemblyDefinition
> ();
307 public AssemblyCollection (State state
)
312 public bool Add (string name
)
314 AssemblyDefinition ass
= LoadAssembly (name
);
315 assemblies
.Add (ass
);
319 public bool Add (Stream stream
)
321 AssemblyDefinition ass
= LoadAssembly (stream
);
322 assemblies
.Add (ass
);
326 public void DoOutput ()
329 throw new InvalidOperationException ("Document not set");
331 writer
.WriteStartElement ("assemblies");
332 foreach (AssemblyDefinition a
in assemblies
) {
333 AssemblyData data
= new AssemblyData (writer
, a
, state
);
336 writer
.WriteEndElement ();
339 public XmlWriter Writer
{
340 set { writer = value; }
343 AssemblyDefinition
LoadAssembly (string assembly
)
345 if (File
.Exists (assembly
))
346 return state
.TypeHelper
.Resolver
.ResolveFile (assembly
);
348 return state
.TypeHelper
.Resolver
.Resolve (AssemblyNameReference
.Parse (assembly
), new ReaderParameters ());
351 AssemblyDefinition
LoadAssembly (Stream assembly
)
353 return state
.TypeHelper
.Resolver
.ResolveStream (assembly
);
357 abstract class BaseData
359 protected XmlWriter writer
;
360 protected State state
;
362 protected BaseData (XmlWriter writer
, State state
)
364 this.writer
= writer
;
368 public abstract void DoOutput ();
370 protected void AddAttribute (string name
, string value)
372 writer
.WriteAttributeString (name
, value);
376 class TypeForwardedToData
: BaseData
378 AssemblyDefinition ass
;
380 public TypeForwardedToData (XmlWriter writer
, AssemblyDefinition ass
, State state
)
381 : base (writer
, state
)
386 public override void DoOutput ()
388 foreach (ExportedType type
in ass
.MainModule
.ExportedTypes
) {
390 if (((uint)type
.Attributes
& 0x200000u
) == 0)
393 writer
.WriteStartElement ("attribute");
394 AddAttribute ("name", typeof (TypeForwardedToAttribute
).FullName
);
395 writer
.WriteStartElement ("properties");
396 writer
.WriteStartElement ("property");
397 AddAttribute ("name", "Destination");
398 AddAttribute ("value", Utils
.CleanupTypeName (type
.FullName
));
399 writer
.WriteEndElement (); // properties
400 writer
.WriteEndElement (); // properties
401 writer
.WriteEndElement (); // attribute
405 public static void OutputForwarders (XmlWriter writer
, AssemblyDefinition ass
, State state
)
407 TypeForwardedToData tftd
= new TypeForwardedToData (writer
, ass
, state
);
412 class AssemblyData
: BaseData
414 AssemblyDefinition ass
;
416 public AssemblyData (XmlWriter writer
, AssemblyDefinition ass
, State state
)
417 : base (writer
, state
)
422 public override void DoOutput ()
425 throw new InvalidOperationException ("Document not set");
427 writer
.WriteStartElement ("assembly");
428 AssemblyNameDefinition aname
= ass
.Name
;
429 AddAttribute ("name", aname
.Name
);
430 AddAttribute ("version", aname
.Version
.ToString ());
432 AttributeData
.OutputAttributes (writer
, state
, ass
);
434 var types
= new List
<TypeDefinition
> ();
435 if (ass
.MainModule
.Types
!= null) {
436 types
.AddRange (ass
.MainModule
.Types
);
439 if (state
.FollowForwarders
&& ass
.MainModule
.ExportedTypes
!= null) {
440 foreach (var t
in ass
.MainModule
.ExportedTypes
) {
441 var forwarded
= t
.Resolve ();
442 if (forwarded
== null) {
443 throw new Exception ("Could not resolve forwarded type " + t
.FullName
+ " in " + ass
.Name
);
445 types
.Add (forwarded
);
449 if (types
.Count
== 0) {
450 writer
.WriteEndElement (); // assembly
454 types
.Sort (TypeReferenceComparer
.Default
);
456 writer
.WriteStartElement ("namespaces");
458 string current_namespace
= "$%&$&";
459 bool in_namespace
= false;
460 foreach (TypeDefinition t
in types
) {
461 if (string.IsNullOrEmpty (t
.Namespace
))
464 if (!state
.AbiMode
&& ((t
.Attributes
& TypeAttributes
.VisibilityMask
) != TypeAttributes
.Public
))
467 if (t
.DeclaringType
!= null)
468 continue; // enforce !nested
470 if (t
.Namespace
!= current_namespace
) {
471 current_namespace
= t
.Namespace
;
473 writer
.WriteEndElement (); // classes
474 writer
.WriteEndElement (); // namespace
478 writer
.WriteStartElement ("namespace");
479 AddAttribute ("name", current_namespace
);
480 writer
.WriteStartElement ("classes");
483 TypeData bd
= new TypeData (writer
, t
, state
);
489 writer
.WriteEndElement (); // classes
490 writer
.WriteEndElement (); // namespace
493 writer
.WriteEndElement (); // namespaces
495 writer
.WriteEndElement (); // assembly
499 abstract class MemberData
: BaseData
501 MemberReference
[] members
;
503 public MemberData (XmlWriter writer
, MemberReference
[] members
, State state
)
504 : base (writer
, state
)
506 this.members
= members
;
509 protected virtual ICustomAttributeProvider
GetAdditionalCustomAttributeProvider (MemberReference member
)
514 public override void DoOutput ()
516 writer
.WriteStartElement (ParentTag
);
518 foreach (MemberReference member
in members
) {
519 writer
.WriteStartElement (Tag
);
520 AddAttribute ("name", GetName (member
));
521 if (!NoMemberAttributes
)
522 AddAttribute ("attrib", GetMemberAttributes (member
));
523 AddExtraAttributes (member
);
525 AttributeData
.OutputAttributes (writer
, state
, (ICustomAttributeProvider
) member
, GetAdditionalCustomAttributeProvider (member
));
527 AddExtraData (member
);
528 writer
.WriteEndElement (); // Tag
531 writer
.WriteEndElement (); // ParentTag
534 protected virtual void AddExtraData (MemberReference memberDefenition
)
538 protected virtual void AddExtraAttributes (MemberReference memberDefinition
)
542 protected virtual string GetName (MemberReference memberDefenition
)
547 protected virtual string GetMemberAttributes (MemberReference memberDefenition
)
552 public virtual bool NoMemberAttributes
{
553 get { return false; }
557 public virtual string ParentTag
{
558 get { return "NoPARENTTAG"; }
561 public virtual string Tag
{
562 get { return "NoTAG"; }
565 public static void OutputGenericParameters (XmlWriter writer
, IGenericParameterProvider provider
, State state
)
567 if (provider
.GenericParameters
.Count
== 0)
570 var gparameters
= provider
.GenericParameters
;
572 writer
.WriteStartElement ("generic-parameters");
574 foreach (GenericParameter gp
in gparameters
) {
575 writer
.WriteStartElement ("generic-parameter");
576 writer
.WriteAttributeString ("name", gp
.Name
);
577 writer
.WriteAttributeString ("attributes", ((int) gp
.Attributes
).ToString ());
579 AttributeData
.OutputAttributes (writer
, state
, gp
);
581 var constraints
= gp
.Constraints
;
582 if (constraints
.Count
== 0) {
583 writer
.WriteEndElement (); // generic-parameter
587 writer
.WriteStartElement ("generic-parameter-constraints");
589 foreach (GenericParameterConstraint constraint
in constraints
) {
590 writer
.WriteStartElement ("generic-parameter-constraint");
591 writer
.WriteAttributeString ("name", Utils
.CleanupTypeName (constraint
.ConstraintType
));
592 writer
.WriteEndElement (); // generic-parameter-constraint
595 writer
.WriteEndElement (); // generic-parameter-constraints
597 writer
.WriteEndElement (); // generic-parameter
600 writer
.WriteEndElement (); // generic-parameters
604 class TypeData
: MemberData
608 public TypeData (XmlWriter writer
, TypeDefinition type
, State state
)
609 : base (writer
, null, state
)
613 public override void DoOutput ()
616 throw new InvalidOperationException ("Document not set");
618 writer
.WriteStartElement ("class");
619 AddAttribute ("name", type
.Name
);
620 string classType
= GetClassType (type
);
621 AddAttribute ("type", classType
);
623 if (type
.BaseType
!= null)
624 AddAttribute ("base", Utils
.CleanupTypeName (type
.BaseType
));
627 AddAttribute ("sealed", "true");
630 AddAttribute ("abstract", "true");
632 if ( (type
.Attributes
& TypeAttributes
.Serializable
) != 0 || type
.IsEnum
)
633 AddAttribute ("serializable", "true");
635 string charSet
= GetCharSet (type
);
636 AddAttribute ("charset", charSet
);
638 string layout
= GetLayout (type
);
640 AddAttribute ("layout", layout
);
642 if (type
.PackingSize
>= 0) {
643 AddAttribute ("pack", type
.PackingSize
.ToString ());
646 if (type
.ClassSize
>= 0) {
647 AddAttribute ("size", type
.ClassSize
.ToString ());
651 var value_type
= GetEnumValueField (type
);
652 if (value_type
== null)
653 throw new NotSupportedException ();
655 AddAttribute ("enumtype", Utils
.CleanupTypeName (value_type
.FieldType
));
658 AttributeData
.OutputAttributes (writer
, state
, type
);
660 var ifaces
= state
.TypeHelper
.GetInterfaces (type
).
661 Where ((iface
) => state
.TypeHelper
.IsPublic (iface
)). // we're only interested in public interfaces
662 OrderBy (s
=> s
.FullName
, StringComparer
.Ordinal
);
665 writer
.WriteStartElement ("interfaces");
666 foreach (TypeReference iface
in ifaces
) {
667 writer
.WriteStartElement ("interface");
668 AddAttribute ("name", Utils
.CleanupTypeName (iface
));
669 writer
.WriteEndElement (); // interface
671 writer
.WriteEndElement (); // interfaces
674 MemberData
.OutputGenericParameters (writer
, type
, state
);
676 ArrayList members
= new ArrayList ();
678 FieldDefinition
[] fields
= GetFields (type
);
679 if (fields
.Length
> 0) {
680 Array
.Sort (fields
, MemberReferenceComparer
.Default
);
681 FieldData fd
= new FieldData (writer
, fields
, state
);
685 if (!state
.AbiMode
) {
687 MethodDefinition
[] ctors
= GetConstructors (type
);
688 if (ctors
.Length
> 0) {
689 Array
.Sort (ctors
, MethodDefinitionComparer
.Default
);
690 members
.Add (new ConstructorData (writer
, ctors
, state
));
693 PropertyDefinition
[] properties
= GetProperties (type
, state
.FullApiSet
);
694 if (properties
.Length
> 0) {
695 Array
.Sort (properties
, PropertyDefinitionComparer
.Default
);
696 members
.Add (new PropertyData (writer
, properties
, state
));
699 EventDefinition
[] events
= GetEvents (type
);
700 if (events
.Length
> 0) {
701 Array
.Sort (events
, MemberReferenceComparer
.Default
);
702 members
.Add (new EventData (writer
, events
, state
));
705 MethodDefinition
[] methods
= GetMethods (type
, state
.FullApiSet
);
706 if (methods
.Length
> 0) {
707 Array
.Sort (methods
, MethodDefinitionComparer
.Default
);
708 members
.Add (new MethodData (writer
, methods
, state
));
712 foreach (MemberData md
in members
)
715 var nested
= type
.NestedTypes
;
716 //remove non public(familiy) and nested in second degree
717 for (int i
= nested
.Count
- 1; i
>= 0; i
--) {
718 TypeDefinition t
= nested
[i
];
719 if ((t
.Attributes
& TypeAttributes
.VisibilityMask
) == TypeAttributes
.NestedPublic
||
720 (t
.Attributes
& TypeAttributes
.VisibilityMask
) == TypeAttributes
.NestedFamily
||
721 (t
.Attributes
& TypeAttributes
.VisibilityMask
) == TypeAttributes
.NestedFamORAssem
) {
723 if (t
.DeclaringType
== type
)
724 continue; // not nested of nested
730 if (nested
.Count
> 0) {
731 var nestedArray
= nested
.ToArray ();
732 Array
.Sort (nestedArray
, TypeReferenceComparer
.Default
);
734 writer
.WriteStartElement ("classes");
735 foreach (TypeDefinition t
in nestedArray
) {
736 TypeData td
= new TypeData (writer
, t
, state
);
739 writer
.WriteEndElement (); // classes
742 writer
.WriteEndElement (); // class
745 static FieldReference
GetEnumValueField (TypeDefinition type
)
747 foreach (FieldDefinition field
in type
.Fields
)
748 if (field
.IsSpecialName
&& field
.Name
== "value__")
754 protected override string GetMemberAttributes (MemberReference member
)
757 throw new InvalidOperationException ("odd");
759 return ((int) type
.Attributes
).ToString (CultureInfo
.InvariantCulture
);
762 public static bool MustDocumentMethod (MethodDefinition method
) {
764 MethodAttributes maskedAccess
= method
.Attributes
& MethodAttributes
.MemberAccessMask
;
765 return maskedAccess
== MethodAttributes
.Public
766 || maskedAccess
== MethodAttributes
.Family
767 || maskedAccess
== MethodAttributes
.FamORAssem
;
770 string GetClassType (TypeDefinition t
)
781 if (state
.TypeHelper
.IsDelegate(t
))
790 static string GetCharSet (TypeDefinition type
)
792 TypeAttributes maskedStringFormat
= type
.Attributes
& TypeAttributes
.StringFormatMask
;
793 if (maskedStringFormat
== TypeAttributes
.AnsiClass
)
794 return CharSet
.Ansi
.ToString ();
796 if (maskedStringFormat
== TypeAttributes
.AutoClass
)
797 return CharSet
.Auto
.ToString ();
799 if (maskedStringFormat
== TypeAttributes
.UnicodeClass
)
800 return CharSet
.Unicode
.ToString ();
802 return CharSet
.None
.ToString ();
805 static string GetLayout (TypeDefinition type
)
807 TypeAttributes maskedLayout
= type
.Attributes
& TypeAttributes
.LayoutMask
;
808 if (maskedLayout
== TypeAttributes
.AutoLayout
)
809 return LayoutKind
.Auto
.ToString ();
811 if (maskedLayout
== TypeAttributes
.ExplicitLayout
)
812 return LayoutKind
.Explicit
.ToString ();
814 if (maskedLayout
== TypeAttributes
.SequentialLayout
)
815 return LayoutKind
.Sequential
.ToString ();
820 FieldDefinition
[] GetFields (TypeDefinition type
) {
821 ArrayList list
= new ArrayList ();
823 var fields
= type
.Fields
;
824 foreach (FieldDefinition field
in fields
) {
825 if (field
.IsSpecialName
)
828 if (state
.AbiMode
&& field
.IsStatic
)
831 // we're only interested in public or protected members
832 FieldAttributes maskedVisibility
= (field
.Attributes
& FieldAttributes
.FieldAccessMask
);
833 if (state
.AbiMode
&& !field
.IsNotSerialized
) {
836 if (maskedVisibility
== FieldAttributes
.Public
837 || maskedVisibility
== FieldAttributes
.Family
838 || maskedVisibility
== FieldAttributes
.FamORAssem
) {
844 return (FieldDefinition
[]) list
.ToArray (typeof (FieldDefinition
));
848 internal PropertyDefinition
[] GetProperties (TypeDefinition type
, bool fullAPI
) {
849 var list
= new List
<PropertyDefinition
> ();
853 var properties
= t
.Properties
;//type.GetProperties (flags);
854 foreach (PropertyDefinition property
in properties
) {
855 MethodDefinition getMethod
= property
.GetMethod
;
856 MethodDefinition setMethod
= property
.SetMethod
;
858 bool hasGetter
= (getMethod
!= null) && MustDocumentMethod (getMethod
);
859 bool hasSetter
= (setMethod
!= null) && MustDocumentMethod (setMethod
);
861 // if neither the getter or setter should be documented, then
863 if (hasGetter
|| hasSetter
) {
865 if (t
!= type
&& list
.Any (l
=> l
.Name
== property
.Name
))
875 if (t
.IsInterface
|| t
.IsEnum
)
878 if (t
.BaseType
== null || t
.BaseType
.FullName
== "System.Object")
881 t
= state
.TypeHelper
.GetBaseType (t
);
885 return list
.ToArray ();
888 private MethodDefinition
[] GetMethods (TypeDefinition type
, bool fullAPI
)
890 var list
= new List
<MethodDefinition
> ();
894 var methods
= t
.Methods
;//type.GetMethods (flags);
895 foreach (MethodDefinition method
in methods
) {
896 if (method
.IsSpecialName
&& !method
.Name
.StartsWith ("op_", StringComparison
.Ordinal
))
899 // we're only interested in public or protected members
900 if (!MustDocumentMethod (method
))
903 if (t
== type
&& IsFinalizer (method
)) {
904 string name
= method
.DeclaringType
.Name
;
905 int arity
= name
.IndexOf ('`');
907 name
= name
.Substring (0, arity
);
909 method
.Name
= "~" + name
;
912 if (t
!= type
&& list
.Any (l
=> l
.DeclaringType
!= method
.DeclaringType
&& l
.Name
== method
.Name
&& l
.Parameters
.Count
== method
.Parameters
.Count
&&
913 l
.Parameters
.SequenceEqual (method
.Parameters
, new ParameterComparer ())))
922 if (t
.IsInterface
|| t
.IsEnum
)
925 if (t
.BaseType
== null || t
.BaseType
.FullName
== "System.Object")
928 t
= state
.TypeHelper
.GetBaseType (t
);
932 return list
.ToArray ();
935 sealed class ParameterComparer
: IEqualityComparer
<ParameterDefinition
>
937 public bool Equals (ParameterDefinition x
, ParameterDefinition y
)
939 return x
.ParameterType
.Name
== y
.ParameterType
.Name
;
942 public int GetHashCode (ParameterDefinition obj
)
944 return obj
.ParameterType
.Name
.GetHashCode ();
948 static bool IsFinalizer (MethodDefinition method
)
950 if (method
.Name
!= "Finalize")
953 if (!method
.IsVirtual
)
956 if (method
.Parameters
.Count
!= 0)
962 private MethodDefinition
[] GetConstructors (TypeDefinition type
)
964 ArrayList list
= new ArrayList ();
966 var ctors
= type
.Methods
.Where (m
=> m
.IsConstructor
);//type.GetConstructors (flags);
967 foreach (MethodDefinition constructor
in ctors
) {
968 // we're only interested in public or protected members
969 if (!MustDocumentMethod(constructor
))
972 list
.Add (constructor
);
975 return (MethodDefinition
[]) list
.ToArray (typeof (MethodDefinition
));
978 private EventDefinition
[] GetEvents (TypeDefinition type
)
980 ArrayList list
= new ArrayList ();
982 var events
= type
.Events
;//type.GetEvents (flags);
983 foreach (EventDefinition eventDef
in events
) {
984 MethodDefinition addMethod
= eventDef
.AddMethod
;//eventInfo.GetAddMethod (true);
986 if (addMethod
== null || !MustDocumentMethod (addMethod
))
992 return (EventDefinition
[]) list
.ToArray (typeof (EventDefinition
));
996 class FieldData
: MemberData
998 public FieldData (XmlWriter writer
, FieldDefinition
[] members
, State state
)
999 : base (writer
, members
, state
)
1003 protected override string GetName (MemberReference memberDefenition
)
1005 FieldDefinition field
= (FieldDefinition
) memberDefenition
;
1009 protected override string GetMemberAttributes (MemberReference memberDefenition
)
1011 FieldDefinition field
= (FieldDefinition
) memberDefenition
;
1012 return ((int) field
.Attributes
).ToString (CultureInfo
.InvariantCulture
);
1015 protected override void AddExtraAttributes (MemberReference memberDefinition
)
1017 base.AddExtraAttributes (memberDefinition
);
1019 FieldDefinition field
= (FieldDefinition
) memberDefinition
;
1020 AddAttribute ("fieldtype", Utils
.CleanupTypeName (field
.FieldType
));
1022 if (field
.IsLiteral
) {
1023 object value = field
.Constant
;//object value = field.GetValue (null);
1024 string stringValue
= null;
1025 //if (value is Enum) {
1026 // // FIXME: when Mono bug #60090 has been
1027 // // fixed, we should just be able to use
1028 // // Convert.ToString
1029 // stringValue = ((Enum) value).ToString ("D", CultureInfo.InvariantCulture);
1032 stringValue
= Convert
.ToString (value, CultureInfo
.InvariantCulture
);
1035 if (stringValue
!= null)
1036 AddAttribute ("value", stringValue
);
1040 public override string ParentTag
{
1041 get { return "fields"; }
1044 public override string Tag
{
1045 get { return "field"; }
1049 class PropertyData
: MemberData
1051 public PropertyData (XmlWriter writer
, PropertyDefinition
[] members
, State state
)
1052 : base (writer
, members
, state
)
1056 protected override string GetName (MemberReference memberDefenition
)
1058 PropertyDefinition prop
= (PropertyDefinition
) memberDefenition
;
1062 MethodDefinition
[] GetMethods (PropertyDefinition prop
, out bool haveParameters
)
1064 MethodDefinition _get
= prop
.GetMethod
;
1065 MethodDefinition _set
= prop
.SetMethod
;
1066 bool haveGet
= (_get
!= null && TypeData
.MustDocumentMethod(_get
));
1067 bool haveSet
= (_set
!= null && TypeData
.MustDocumentMethod(_set
));
1068 haveParameters
= haveGet
|| (haveSet
&& _set
.Parameters
.Count
> 1);
1069 MethodDefinition
[] methods
;
1071 if (haveGet
&& haveSet
) {
1072 methods
= new MethodDefinition
[] { _get, _set }
;
1073 } else if (haveGet
) {
1074 methods
= new MethodDefinition
[] { _get }
;
1075 } else if (haveSet
) {
1076 methods
= new MethodDefinition
[] { _set }
;
1085 protected override void AddExtraAttributes (MemberReference memberDefinition
)
1087 base.AddExtraAttributes (memberDefinition
);
1089 PropertyDefinition prop
= (PropertyDefinition
) memberDefinition
;
1090 AddAttribute ("ptype", Utils
.CleanupTypeName (prop
.PropertyType
));
1092 bool haveParameters
;
1093 MethodDefinition
[] methods
= GetMethods ((PropertyDefinition
) memberDefinition
, out haveParameters
);
1095 if (methods
!= null && haveParameters
) {
1096 string parms
= Parameters
.GetSignature (methods
[0].Parameters
);
1097 if (!string.IsNullOrEmpty (parms
))
1098 AddAttribute ("params", parms
);
1103 protected override void AddExtraData (MemberReference memberDefenition
)
1105 base.AddExtraData (memberDefenition
);
1107 bool haveParameters
;
1108 MethodDefinition
[] methods
= GetMethods ((PropertyDefinition
) memberDefenition
, out haveParameters
);
1110 if (methods
== null)
1113 MethodData data
= new MethodData (writer
, methods
, state
);
1114 //data.NoMemberAttributes = true;
1118 protected override string GetMemberAttributes (MemberReference memberDefenition
)
1120 PropertyDefinition prop
= (PropertyDefinition
) memberDefenition
;
1121 return ((int) prop
.Attributes
).ToString (CultureInfo
.InvariantCulture
);
1124 public override string ParentTag
{
1125 get { return "properties"; }
1128 public override string Tag
{
1129 get { return "property"; }
1133 class EventData
: MemberData
1135 public EventData (XmlWriter writer
, EventDefinition
[] members
, State state
)
1136 : base (writer
, members
, state
)
1140 protected override string GetName (MemberReference memberDefenition
)
1142 EventDefinition evt
= (EventDefinition
) memberDefenition
;
1146 protected override string GetMemberAttributes (MemberReference memberDefenition
)
1148 EventDefinition evt
= (EventDefinition
) memberDefenition
;
1149 return ((int) evt
.Attributes
).ToString (CultureInfo
.InvariantCulture
);
1152 protected override void AddExtraAttributes (MemberReference memberDefinition
)
1154 base.AddExtraAttributes (memberDefinition
);
1156 EventDefinition evt
= (EventDefinition
) memberDefinition
;
1157 AddAttribute ("eventtype", Utils
.CleanupTypeName (evt
.EventType
));
1160 public override string ParentTag
{
1161 get { return "events"; }
1164 public override string Tag
{
1165 get { return "event"; }
1169 class MethodData
: MemberData
1173 public MethodData (XmlWriter writer
, MethodDefinition
[] members
, State state
)
1174 : base (writer
, members
, state
)
1178 protected override string GetName (MemberReference memberDefenition
)
1180 MethodDefinition method
= (MethodDefinition
) memberDefenition
;
1181 string name
= method
.Name
;
1182 string parms
= Parameters
.GetSignature (method
.Parameters
);
1184 return string.Format ("{0}({1})", name
, parms
);
1187 protected override string GetMemberAttributes (MemberReference memberDefenition
)
1189 MethodDefinition method
= (MethodDefinition
) memberDefenition
;
1190 return ((int)( method
.Attributes
)).ToString (CultureInfo
.InvariantCulture
);
1193 protected override ICustomAttributeProvider
GetAdditionalCustomAttributeProvider (MemberReference member
)
1195 var mbase
= (MethodDefinition
) member
;
1196 return mbase
.MethodReturnType
;
1199 protected override void AddExtraAttributes (MemberReference memberDefinition
)
1201 base.AddExtraAttributes (memberDefinition
);
1203 if (!(memberDefinition
is MethodDefinition
))
1206 MethodDefinition mbase
= (MethodDefinition
) memberDefinition
;
1208 if (mbase
.IsAbstract
)
1209 AddAttribute ("abstract", "true");
1210 if (mbase
.IsVirtual
)
1211 AddAttribute ("virtual", "true");
1212 if (mbase
.IsFinal
&& mbase
.IsVirtual
&& mbase
.IsReuseSlot
)
1213 AddAttribute ("sealed", "true");
1215 AddAttribute ("static", "true");
1216 var baseMethod
= state
.TypeHelper
.GetBaseMethodInTypeHierarchy (mbase
);
1217 if (baseMethod
!= null && baseMethod
!= mbase
) {
1218 // This indicates whether this method is an override of another method.
1219 // This information is not necessarily available in the api info for any
1220 // particular assembly, because a method is only overriding another if
1221 // there is a base virtual function with the same signature, and that
1222 // base method can come from another assembly.
1223 AddAttribute ("is-override", "true");
1225 string rettype
= Utils
.CleanupTypeName (mbase
.MethodReturnType
.ReturnType
);
1226 if (rettype
!= "System.Void" || !mbase
.IsConstructor
)
1227 AddAttribute ("returntype", (rettype
));
1229 // if (mbase.MethodReturnType.HasCustomAttributes)
1230 // AttributeData.OutputAttributes (writer, mbase.MethodReturnType);
1233 protected override void AddExtraData (MemberReference memberDefenition
)
1235 base.AddExtraData (memberDefenition
);
1237 if (!(memberDefenition
is MethodDefinition
))
1240 MethodDefinition mbase
= (MethodDefinition
)memberDefenition
;
1242 ParameterData parms
= new ParameterData (writer
, mbase
.Parameters
, state
) {
1243 HasExtensionParameter
= mbase
.CustomAttributes
.Any (l
=> l
.AttributeType
.FullName
== "System.Runtime.CompilerServices.ExtensionAttribute")
1248 MemberData
.OutputGenericParameters (writer
, mbase
, state
);
1251 public override bool NoMemberAttributes
{
1252 get { return noAtts; }
1253 set { noAtts = value; }
1256 public override string ParentTag
{
1257 get { return "methods"; }
1260 public override string Tag
{
1261 get { return "method"; }
1265 class ConstructorData
: MethodData
1267 public ConstructorData (XmlWriter writer
, MethodDefinition
[] members
, State state
)
1268 : base (writer
, members
, state
)
1272 public override string ParentTag
{
1273 get { return "constructors"; }
1276 public override string Tag
{
1277 get { return "constructor"; }
1281 class ParameterData
: BaseData
1283 private IList
<ParameterDefinition
> parameters
;
1285 public ParameterData (XmlWriter writer
, IList
<ParameterDefinition
> parameters
, State state
)
1286 : base (writer
, state
)
1288 this.parameters
= parameters
;
1291 public bool HasExtensionParameter { get; set; }
1293 public override void DoOutput ()
1296 writer
.WriteStartElement ("parameters");
1297 foreach (ParameterDefinition parameter
in parameters
) {
1298 writer
.WriteStartElement ("parameter");
1299 AddAttribute ("name", parameter
.Name
);
1300 AddAttribute ("position", parameter
.Method
.Parameters
.IndexOf(parameter
).ToString(CultureInfo
.InvariantCulture
));
1301 AddAttribute ("attrib", ((int) parameter
.Attributes
).ToString());
1303 string direction
= first
&& HasExtensionParameter
? "this" : "in";
1306 var pt
= parameter
.ParameterType
;
1307 var brt
= pt
as ByReferenceType
;
1309 direction
= parameter
.IsOut
? "out" : "ref";
1310 pt
= brt
.ElementType
;
1313 AddAttribute ("type", Utils
.CleanupTypeName (pt
));
1315 if (parameter
.IsOptional
) {
1316 AddAttribute ("optional", "true");
1317 if (parameter
.HasConstant
)
1318 AddAttribute ("defaultValue", parameter
.Constant
== null ? "NULL" : parameter
.Constant
.ToString ());
1321 if (direction
!= "in")
1322 AddAttribute ("direction", direction
);
1324 AttributeData
.OutputAttributes (writer
, state
, parameter
);
1325 writer
.WriteEndElement (); // parameter
1327 writer
.WriteEndElement (); // parameters
1335 public AttributeData (State state
)
1340 public void DoOutput (XmlWriter writer
, IList
<ICustomAttributeProvider
> providers
)
1343 throw new InvalidOperationException ("Document not set");
1345 if (providers
== null || providers
.Count
== 0)
1348 if (!providers
.Any ((provider
) => provider
!= null && provider
.HasCustomAttributes
))
1351 writer
.WriteStartElement ("attributes");
1353 foreach (var provider
in providers
) {
1354 if (provider
== null)
1357 if (!provider
.HasCustomAttributes
)
1361 var ass
= provider
as AssemblyDefinition
;
1362 if (ass
!= null && !state
.FollowForwarders
)
1363 TypeForwardedToData
.OutputForwarders (writer
, ass
, state
);
1365 var attributes
= provider
.CustomAttributes
.
1366 Where ((att
) => !SkipAttribute (att
)).
1367 OrderBy ((a
) => a
.Constructor
.DeclaringType
.FullName
, StringComparer
.Ordinal
);
1369 foreach (var att
in attributes
) {
1370 string attName
= Utils
.CleanupTypeName (att
.Constructor
.DeclaringType
);
1372 writer
.WriteStartElement ("attribute");
1373 writer
.WriteAttributeString ("name", attName
);
1375 var attribute_mapping
= CreateAttributeMapping (att
);
1377 if (attribute_mapping
!= null) {
1378 var mapping
= attribute_mapping
.Where ((attr
) => attr
.Key
!= "TypeId");
1379 if (mapping
.Any ()) {
1380 writer
.WriteStartElement ("properties");
1381 foreach (var kvp
in mapping
) {
1382 string name
= kvp
.Key
;
1383 object o
= kvp
.Value
;
1385 writer
.WriteStartElement ("property");
1386 writer
.WriteAttributeString ("name", name
);
1389 writer
.WriteAttributeString ("value", "null");
1391 string value = o
.ToString ();
1392 if (attName
.EndsWith ("GuidAttribute", StringComparison
.Ordinal
))
1393 value = value.ToUpper ();
1394 writer
.WriteAttributeString ("value", value);
1397 writer
.WriteEndElement (); // property
1399 writer
.WriteEndElement (); // properties
1402 writer
.WriteEndElement (); // attribute
1406 writer
.WriteEndElement (); // attributes
1409 Dictionary
<string, object> CreateAttributeMapping (CustomAttribute attribute
)
1411 Dictionary
<string, object> mapping
= null;
1413 if (!state
.TypeHelper
.TryResolve (attribute
))
1416 PopulateMapping (ref mapping
, attribute
);
1418 var constructor
= state
.TypeHelper
.GetMethod (attribute
.Constructor
);
1419 if (constructor
== null || !constructor
.HasParameters
)
1422 PopulateMapping (ref mapping
, constructor
, attribute
);
1427 static void PopulateMapping (ref Dictionary
<string, object> mapping
, CustomAttribute attribute
)
1429 if (!attribute
.HasProperties
)
1432 foreach (var named_argument
in attribute
.Properties
) {
1433 var name
= named_argument
.Name
;
1434 var arg
= named_argument
.Argument
;
1436 if (arg
.Value
is CustomAttributeArgument
)
1437 arg
= (CustomAttributeArgument
) arg
.Value
;
1439 if (mapping
== null)
1440 mapping
= new Dictionary
<string, object> (StringComparer
.Ordinal
);
1441 mapping
.Add (name
, GetArgumentValue (arg
.Type
, arg
.Value
));
1445 static Dictionary
<FieldReference
, int> CreateArgumentFieldMapping (MethodDefinition constructor
)
1447 Dictionary
<FieldReference
, int> field_mapping
= null;
1449 int? argument
= null;
1451 foreach (Instruction instruction
in constructor
.Body
.Instructions
) {
1452 switch (instruction
.OpCode
.Code
) {
1464 argument
= ((ParameterDefinition
) instruction
.Operand
).Index
+ 1;
1468 FieldReference field
= (FieldReference
) instruction
.Operand
;
1469 if (field
.DeclaringType
.FullName
!= constructor
.DeclaringType
.FullName
)
1472 if (!argument
.HasValue
)
1475 if (field_mapping
== null)
1476 field_mapping
= new Dictionary
<FieldReference
, int> ();
1478 if (!field_mapping
.ContainsKey (field
))
1479 field_mapping
.Add (field
, (int) argument
- 1);
1486 return field_mapping
;
1489 static Dictionary
<PropertyDefinition
, FieldReference
> CreatePropertyFieldMapping (TypeDefinition type
)
1491 Dictionary
<PropertyDefinition
, FieldReference
> property_mapping
= null;
1493 foreach (PropertyDefinition property
in type
.Properties
) {
1494 if (property
.GetMethod
== null)
1496 if (!property
.GetMethod
.HasBody
)
1499 foreach (Instruction instruction
in property
.GetMethod
.Body
.Instructions
) {
1500 if (instruction
.OpCode
.Code
!= Code
.Ldfld
)
1503 FieldReference field
= (FieldReference
) instruction
.Operand
;
1504 if (field
.DeclaringType
.FullName
!= type
.FullName
)
1507 if (property_mapping
== null)
1508 property_mapping
= new Dictionary
<PropertyDefinition
, FieldReference
> ();
1509 property_mapping
.Add (property
, field
);
1514 return property_mapping
;
1517 static void PopulateMapping (ref Dictionary
<string, object> mapping
, MethodDefinition constructor
, CustomAttribute attribute
)
1519 if (!constructor
.HasBody
)
1522 // Custom handling for attributes with arguments which cannot be easily extracted
1523 var ca
= attribute
.ConstructorArguments
;
1524 switch (constructor
.DeclaringType
.FullName
) {
1525 case "System.Runtime.CompilerServices.DecimalConstantAttribute":
1526 var dca
= constructor
.Parameters
[2].ParameterType
== constructor
.Module
.TypeSystem
.Int32
?
1527 new DecimalConstantAttribute ((byte) ca
[0].Value
, (byte) ca
[1].Value
, (int) ca
[2].Value
, (int) ca
[3].Value
, (int) ca
[4].Value
) :
1528 new DecimalConstantAttribute ((byte) ca
[0].Value
, (byte) ca
[1].Value
, (uint) ca
[2].Value
, (uint) ca
[3].Value
, (uint) ca
[4].Value
);
1530 if (mapping
== null)
1531 mapping
= new Dictionary
<string, object> (StringComparer
.Ordinal
);
1532 mapping
.Add ("Value", dca
.Value
);
1534 case "System.ComponentModel.BindableAttribute":
1538 if (mapping
== null)
1539 mapping
= new Dictionary
<string, object> (StringComparer
.Ordinal
);
1541 if (constructor
.Parameters
[0].ParameterType
== constructor
.Module
.TypeSystem
.Boolean
) {
1542 mapping
.Add ("Bindable", ca
[0].Value
);
1543 } else if (constructor
.Parameters
[0].ParameterType
.FullName
== "System.ComponentModel.BindableSupport") {
1544 if ((int)ca
[0].Value
== 0)
1545 mapping
.Add ("Bindable", false);
1546 else if ((int)ca
[0].Value
== 1)
1547 mapping
.Add ("Bindable", true);
1549 throw new NotImplementedException ();
1551 throw new NotImplementedException ();
1557 var field_mapping
= CreateArgumentFieldMapping (constructor
);
1558 if (field_mapping
!= null) {
1559 var property_mapping
= CreatePropertyFieldMapping ((TypeDefinition
) constructor
.DeclaringType
);
1561 if (property_mapping
!= null) {
1562 foreach (var pair
in property_mapping
) {
1564 if (!field_mapping
.TryGetValue (pair
.Value
, out argument
))
1567 var ca_arg
= ca
[argument
];
1568 if (ca_arg
.Value
is CustomAttributeArgument
)
1569 ca_arg
= (CustomAttributeArgument
)ca_arg
.Value
;
1571 if (mapping
== null)
1572 mapping
= new Dictionary
<string, object> (StringComparer
.Ordinal
);
1573 mapping
.Add (pair
.Key
.Name
, GetArgumentValue (ca_arg
.Type
, ca_arg
.Value
));
1579 static object GetArgumentValue (TypeReference reference
, object value)
1581 var type
= reference
.Resolve ();
1586 if (IsFlaggedEnum (type
))
1587 return GetFlaggedEnumValue (type
, value);
1589 return GetEnumValue (type
, value);
1595 static bool IsFlaggedEnum (TypeDefinition type
)
1600 if (!type
.HasCustomAttributes
)
1603 foreach (CustomAttribute attribute
in type
.CustomAttributes
)
1604 if (attribute
.Constructor
.DeclaringType
.FullName
== "System.FlagsAttribute")
1610 static object GetFlaggedEnumValue (TypeDefinition type
, object value)
1613 return GetFlaggedEnumValue (type
, (ulong)value);
1615 long flags
= Convert
.ToInt64 (value);
1616 var signature
= new StringBuilder ();
1618 for (int i
= type
.Fields
.Count
- 1; i
>= 0; i
--) {
1619 FieldDefinition field
= type
.Fields
[i
];
1621 if (!field
.HasConstant
)
1624 long flag
= Convert
.ToInt64 (field
.Constant
);
1629 if ((flags
& flag
) == flag
) {
1630 if (signature
.Length
!= 0)
1631 signature
.Append (", ");
1633 signature
.Append (field
.Name
);
1638 return signature
.ToString ();
1641 static object GetFlaggedEnumValue (TypeDefinition type
, ulong flags
)
1643 var signature
= new StringBuilder ();
1645 for (int i
= type
.Fields
.Count
- 1; i
>= 0; i
--) {
1646 FieldDefinition field
= type
.Fields
[i
];
1648 if (!field
.HasConstant
)
1651 ulong flag
= Convert
.ToUInt64 (field
.Constant
);
1656 if ((flags
& flag
) == flag
) {
1657 if (signature
.Length
!= 0)
1658 signature
.Append (", ");
1660 signature
.Append (field
.Name
);
1665 return signature
.ToString ();
1668 static object GetEnumValue (TypeDefinition type
, object value)
1670 foreach (FieldDefinition field
in type
.Fields
) {
1671 if (!field
.HasConstant
)
1674 if (Comparer
.Default
.Compare (field
.Constant
, value) == 0)
1681 bool SkipAttribute (CustomAttribute attribute
)
1683 if (!state
.TypeHelper
.IsPublic (attribute
))
1686 return attribute
.Constructor
.DeclaringType
.Name
.EndsWith ("TODOAttribute", StringComparison
.Ordinal
);
1689 public static void OutputAttributes (XmlWriter writer
, State state
, params ICustomAttributeProvider
[] providers
)
1691 var data
= new AttributeData (state
);
1692 data
.DoOutput (writer
, providers
);
1696 static class Parameters
{
1698 public static string GetSignature (IList
<ParameterDefinition
> infos
)
1700 if (infos
== null || infos
.Count
== 0)
1701 return string.Empty
;
1703 var signature
= new StringBuilder ();
1704 for (int i
= 0; i
< infos
.Count
; i
++) {
1707 signature
.Append (", ");
1709 ParameterDefinition info
= infos
[i
];
1711 string modifier
= string.Empty
;
1712 if (info
.ParameterType
.IsByReference
) {
1713 if ((info
.Attributes
& ParameterAttributes
.In
) != 0)
1715 else if ((info
.Attributes
& ParameterAttributes
.Out
) != 0)
1719 if (modifier
.Length
> 0) {
1720 signature
.Append (modifier
);
1721 signature
.Append (" ");
1724 signature
.Append (Utils
.CleanupTypeName (info
.ParameterType
));
1727 return signature
.ToString ();
1732 class TypeReferenceComparer
: IComparer
<TypeReference
>
1734 public static TypeReferenceComparer Default
= new TypeReferenceComparer ();
1736 public int Compare (TypeReference a
, TypeReference b
)
1738 int result
= String
.Compare (a
.Namespace
, b
.Namespace
, StringComparison
.Ordinal
);
1742 return String
.Compare (a
.Name
, b
.Name
, StringComparison
.Ordinal
);
1746 class MemberReferenceComparer
: IComparer
1748 public static MemberReferenceComparer Default
= new MemberReferenceComparer ();
1750 public int Compare (object a
, object b
)
1752 MemberReference ma
= (MemberReference
) a
;
1753 MemberReference mb
= (MemberReference
) b
;
1754 return String
.Compare (ma
.Name
, mb
.Name
, StringComparison
.Ordinal
);
1758 class PropertyDefinitionComparer
: IComparer
<PropertyDefinition
>
1760 public static PropertyDefinitionComparer Default
= new PropertyDefinitionComparer ();
1762 public int Compare (PropertyDefinition ma
, PropertyDefinition mb
)
1764 int res
= String
.Compare (ma
.Name
, mb
.Name
, StringComparison
.Ordinal
);
1768 if (!ma
.HasParameters
&& !mb
.HasParameters
)
1771 if (!ma
.HasParameters
)
1774 if (!mb
.HasParameters
)
1777 return MethodDefinitionComparer
.Compare (ma
.Parameters
, mb
.Parameters
);
1781 class MethodDefinitionComparer
: IComparer
1783 public static MethodDefinitionComparer Default
= new MethodDefinitionComparer ();
1785 public int Compare (object a
, object b
)
1787 MethodDefinition ma
= (MethodDefinition
) a
;
1788 MethodDefinition mb
= (MethodDefinition
) b
;
1789 int res
= String
.Compare (ma
.Name
, mb
.Name
, StringComparison
.Ordinal
);
1793 if (!ma
.HasParameters
&& !mb
.HasParameters
)
1796 if (!ma
.HasParameters
)
1799 if (!mb
.HasParameters
)
1802 res
= Compare (ma
.Parameters
, mb
.Parameters
);
1806 if (ma
.HasGenericParameters
!= mb
.HasGenericParameters
)
1807 return ma
.HasGenericParameters
? -1 : 1;
1809 if (ma
.HasGenericParameters
&& mb
.HasGenericParameters
) {
1810 res
= ma
.GenericParameters
.Count
- mb
.GenericParameters
.Count
;
1815 // operators can differ by only return type
1816 return string.CompareOrdinal (ma
.ReturnType
.FullName
, mb
.ReturnType
.FullName
);
1819 public static int Compare (IList
<ParameterDefinition
> pia
, IList
<ParameterDefinition
> pib
)
1821 var res
= pia
.Count
- pib
.Count
;
1825 string siga
= Parameters
.GetSignature (pia
);
1826 string sigb
= Parameters
.GetSignature (pib
);
1827 return String
.Compare (siga
, sigb
, StringComparison
.Ordinal
);