2007-03-22 Chris Toshok <toshok@ximian.com>
[mcs.git] / tools / monop / outline.cs
blob35f1e4fb99cd3079c853e593c2ab50486c7607e3
1 //
2 // outline -- support for rendering in monop
3 // Some code stolen from updater.cs in monodoc.
4 //
5 // Authors:
6 // Ben Maurer (bmaurer@users.sourceforge.net)
7 //
8 // (C) 2004 Ben Maurer
9 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System;
33 using System.Reflection;
34 using System.Collections;
35 using System.CodeDom.Compiler;
36 using System.IO;
37 using System.Text;
39 public class Outline {
41 Options options;
42 IndentedTextWriter o;
43 Type t;
45 public Outline (Type t, TextWriter output, Options options)
47 this.t = t;
48 this.o = new IndentedTextWriter (output, "\t");
49 this.options = options;
52 public void OutlineType ()
54 bool first;
56 OutlineAttributes ();
57 o.Write (GetTypeVisibility (t));
59 if (t.IsClass && !t.IsSubclassOf (typeof (System.MulticastDelegate))) {
60 if (t.IsSealed)
61 o.Write (t.IsAbstract ? " static" : " sealed");
62 else if (t.IsAbstract)
63 o.Write (" abstract");
66 o.Write (" ");
67 o.Write (GetTypeKind (t));
68 o.Write (" ");
70 Type [] interfaces = (Type []) Comparer.Sort (TypeGetInterfaces (t, options.DeclaredOnly));
71 Type parent = t.BaseType;
73 if (t.IsSubclassOf (typeof (System.MulticastDelegate))) {
74 MethodInfo method;
76 method = t.GetMethod ("Invoke");
78 o.Write (FormatType (method.ReturnType));
79 o.Write (" ");
80 o.Write (GetTypeName (t));
81 o.Write (" (");
82 OutlineParams (method.GetParameters ());
83 o.Write (")");
85 #if NET_2_0
86 WriteGenericConstraints (t.GetGenericArguments ());
87 #endif
89 o.WriteLine (";");
90 return;
93 o.Write (GetTypeName (t));
94 if (((parent != null && parent != typeof (object) && parent != typeof (ValueType)) || interfaces.Length != 0) && ! t.IsEnum) {
95 first = true;
96 o.Write (" : ");
98 if (parent != null && parent != typeof (object) && parent != typeof (ValueType)) {
99 o.Write (FormatType (parent));
100 first = false;
103 foreach (Type intf in interfaces) {
104 if (!first) o.Write (", ");
105 first = false;
107 o.Write (FormatType (intf));
111 if (t.IsEnum) {
112 Type underlyingType = Enum.GetUnderlyingType (t);
113 if (underlyingType != typeof (int))
114 o.Write (" : {0}", FormatType (underlyingType));
116 #if NET_2_0
117 WriteGenericConstraints (t.GetGenericArguments ());
118 #endif
119 o.WriteLine (" {");
120 o.Indent++;
122 if (t.IsEnum) {
123 bool is_first = true;
124 foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Static)) {
126 if (! is_first)
127 o.WriteLine (",");
128 is_first = false;
129 o.Write (fi.Name);
131 o.WriteLine ();
132 o.Indent--; o.WriteLine ("}");
133 return;
136 first = true;
138 foreach (ConstructorInfo ci in t.GetConstructors (DefaultFlags)) {
140 if (! ShowMember (ci))
141 continue;
143 if (first)
144 o.WriteLine ();
145 first = false;
147 OutlineConstructor (ci);
149 o.WriteLine ();
153 first = true;
155 foreach (MethodInfo m in Comparer.Sort (t.GetMethods (DefaultFlags))) {
157 if (! ShowMember (m))
158 continue;
160 if ((m.Attributes & MethodAttributes.SpecialName) != 0)
161 continue;
163 if (first)
164 o.WriteLine ();
165 first = false;
167 OutlineMethod (m);
169 o.WriteLine ();
172 first = true;
174 foreach (MethodInfo m in t.GetMethods (DefaultFlags)) {
176 if (! ShowMember (m))
177 continue;
179 if ((m.Attributes & MethodAttributes.SpecialName) == 0)
180 continue;
181 if (!(m.Name.StartsWith ("op_")))
182 continue;
184 if (first)
185 o.WriteLine ();
186 first = false;
188 OutlineOperator (m);
190 o.WriteLine ();
193 first = true;
195 foreach (PropertyInfo pi in Comparer.Sort (t.GetProperties (DefaultFlags))) {
197 if (! ((pi.CanRead && ShowMember (pi.GetGetMethod (true))) ||
198 (pi.CanWrite && ShowMember (pi.GetSetMethod (true)))))
199 continue;
201 if (first)
202 o.WriteLine ();
203 first = false;
205 OutlineProperty (pi);
207 o.WriteLine ();
210 first = true;
212 foreach (FieldInfo fi in t.GetFields (DefaultFlags)) {
214 if (! ShowMember (fi))
215 continue;
217 if (first)
218 o.WriteLine ();
219 first = false;
221 OutlineField (fi);
223 o.WriteLine ();
226 first = true;
228 foreach (EventInfo ei in Comparer.Sort (t.GetEvents (DefaultFlags))) {
230 if (! ShowMember (ei.GetAddMethod (true)))
231 continue;
233 if (first)
234 o.WriteLine ();
235 first = false;
237 OutlineEvent (ei);
239 o.WriteLine ();
242 first = true;
244 foreach (Type ntype in Comparer.Sort (t.GetNestedTypes (DefaultFlags))) {
246 if (! ShowMember (ntype))
247 continue;
249 if (first)
250 o.WriteLine ();
251 first = false;
253 new Outline (ntype, o, options).OutlineType ();
256 o.Indent--; o.WriteLine ("}");
259 BindingFlags DefaultFlags {
260 get {
261 BindingFlags f = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
263 if (options.DeclaredOnly)
264 f |= BindingFlags.DeclaredOnly;
266 return f;
270 // FIXME: add other interesting attributes?
271 void OutlineAttributes ()
273 if (t.IsSerializable)
274 o.WriteLine ("[Serializable]");
276 if (t.IsDefined (typeof (System.FlagsAttribute), true))
277 o.WriteLine ("[Flags]");
279 if (t.IsDefined (typeof (System.ObsoleteAttribute), true))
280 o.WriteLine ("[Obsolete]");
283 void OutlineEvent (EventInfo ei)
285 MethodBase accessor = ei.GetAddMethod (true);
287 o.Write (GetMethodVisibility (accessor));
288 o.Write ("event ");
289 o.Write (FormatType (ei.EventHandlerType));
290 o.Write (" ");
291 o.Write (ei.Name);
292 o.Write (";");
295 void OutlineConstructor (ConstructorInfo ci)
297 o.Write (GetMethodVisibility (ci));
298 o.Write (RemoveGenericArity (t.Name));
299 o.Write (" (");
300 OutlineParams (ci.GetParameters ());
301 o.Write (");");
305 void OutlineProperty (PropertyInfo pi)
307 ParameterInfo [] idxp = pi.GetIndexParameters ();
308 MethodBase g = pi.GetGetMethod (true);
309 MethodBase s = pi.GetSetMethod (true);
310 MethodBase accessor = g != null ? g : s;
312 if (pi.CanRead && pi.CanWrite) {
315 // Get the more accessible accessor
316 if ((g.Attributes & MethodAttributes.MemberAccessMask) !=
317 (s.Attributes & MethodAttributes.MemberAccessMask)) {
319 if (g.IsPublic) accessor = g;
320 else if (s.IsPublic) accessor = s;
321 else if (g.IsFamilyOrAssembly) accessor = g;
322 else if (s.IsFamilyOrAssembly) accessor = s;
323 else if (g.IsAssembly || g.IsFamily) accessor = g;
324 else if (s.IsAssembly || s.IsFamily) accessor = s;
328 o.Write (GetMethodVisibility (accessor));
329 o.Write (GetMethodModifiers (accessor));
330 o.Write (FormatType (pi.PropertyType));
331 o.Write (" ");
333 if (idxp.Length == 0)
334 o.Write (pi.Name);
335 else {
336 o.Write ("this [");
337 OutlineParams (idxp);
338 o.Write ("]");
341 o.WriteLine (" {");
342 o.Indent ++;
344 if (g != null && ShowMember (g)) {
345 if ((g.Attributes & MethodAttributes.MemberAccessMask) !=
346 (accessor.Attributes & MethodAttributes.MemberAccessMask))
347 o.Write (GetMethodVisibility (g));
348 o.WriteLine ("get;");
351 if (s != null && ShowMember (s)) {
352 if ((s.Attributes & MethodAttributes.MemberAccessMask) !=
353 (accessor.Attributes & MethodAttributes.MemberAccessMask))
354 o.Write (GetMethodVisibility (s));
355 o.WriteLine ("set;");
358 o.Indent --;
359 o.Write ("}");
362 void OutlineMethod (MethodInfo mi)
364 if (MethodIsExplicitIfaceImpl (mi)) {
365 o.Write (FormatType (mi.ReturnType));
366 o.Write (" ");
367 // MSFT has no way to get the method that we are overriding
368 // from the interface. this would allow us to pretty print
369 // the type name (and be more correct if there compiler
370 // were to do some strange naming thing).
371 } else {
372 o.Write (GetMethodVisibility (mi));
373 o.Write (GetMethodModifiers (mi));
374 o.Write (FormatType (mi.ReturnType));
375 o.Write (" ");
378 o.Write (mi.Name);
379 #if NET_2_0
380 o.Write (FormatGenericParams (mi.GetGenericArguments ()));
381 #endif
382 o.Write (" (");
383 OutlineParams (mi.GetParameters ());
384 o.Write (")");
385 #if NET_2_0
386 WriteGenericConstraints (mi.GetGenericArguments ());
387 #endif
388 o.Write (";");
391 void OutlineOperator (MethodInfo mi)
393 o.Write (GetMethodVisibility (mi));
394 o.Write (GetMethodModifiers (mi));
395 if (mi.Name == "op_Explicit" || mi.Name == "op_Implicit") {
396 o.Write (mi.Name.Substring (3).ToLower ());
397 o.Write (" operator ");
398 o.Write (FormatType (mi.ReturnType));
399 } else {
400 o.Write (FormatType (mi.ReturnType));
401 o.Write (" operator ");
402 o.Write (OperatorFromName (mi.Name));
404 o.Write (" (");
405 OutlineParams (mi.GetParameters ());
406 o.Write (");");
409 void OutlineParams (ParameterInfo [] pi)
411 int i = 0;
412 foreach (ParameterInfo p in pi) {
413 if (p.ParameterType.IsByRef) {
414 o.Write (p.IsOut ? "out " : "ref ");
415 o.Write (FormatType (p.ParameterType.GetElementType ()));
416 } else if (p.IsDefined (typeof (ParamArrayAttribute), false)) {
417 o.Write ("params ");
418 o.Write (FormatType (p.ParameterType));
419 } else {
420 o.Write (FormatType (p.ParameterType));
423 o.Write (" ");
424 o.Write (p.Name);
425 if (i + 1 < pi.Length)
426 o.Write (", ");
427 i++;
431 void OutlineField (FieldInfo fi)
433 if (fi.IsPublic) o.Write ("public ");
434 if (fi.IsFamily) o.Write ("protected ");
435 if (fi.IsPrivate) o.Write ("private ");
436 if (fi.IsAssembly) o.Write ("internal ");
437 if (fi.IsLiteral) o.Write ("const ");
438 else if (fi.IsStatic) o.Write ("static ");
439 if (fi.IsInitOnly) o.Write ("readonly ");
441 o.Write (FormatType (fi.FieldType));
442 o.Write (" ");
443 o.Write (fi.Name);
444 if (fi.IsLiteral) {
445 object v = fi.GetValue (this);
447 // TODO: Escape values here
448 o.Write (" = ");
449 if (v is char)
450 o.Write ("'{0}'", v);
451 else if (v is string)
452 o.Write ("\"{0}\"", v);
453 else
454 o.Write (fi.GetValue (this));
456 o.Write (";");
459 static string GetMethodVisibility (MethodBase m)
461 // itnerfaces have no modifiers here
462 if (m.DeclaringType.IsInterface)
463 return "";
465 if (m.IsPublic) return "public ";
466 if (m.IsFamily) return "protected ";
467 if (m.IsPrivate) return "private ";
468 if (m.IsAssembly) return "internal ";
470 return null;
473 static string GetMethodModifiers (MethodBase method)
475 if (method.IsStatic)
476 return "static ";
478 if (method.IsFinal) {
479 // This will happen if you have
480 // class X : IA {
481 // public void A () {}
482 // static void Main () {}
483 // }
484 // interface IA {
485 // void A ();
486 // }
488 // A needs to be virtual (the CLR requires
489 // methods implementing an iface be virtual),
490 // but can not be inherited. It also can not
491 // be inherited. In C# this is represented
492 // with no special modifiers
494 if (method.IsVirtual)
495 return null;
496 return "sealed ";
499 // all interface methods are "virtual" but we don't say that in c#
500 if (method.IsVirtual && !method.DeclaringType.IsInterface) {
501 if (method.IsAbstract)
502 return "abstract ";
504 return ((method.Attributes & MethodAttributes.NewSlot) != 0) ?
505 "virtual " :
506 "override ";
509 return null;
512 static string GetTypeKind (Type t)
514 if (t.IsEnum)
515 return "enum";
516 if (t.IsClass) {
517 if (t.IsSubclassOf (typeof (System.MulticastDelegate)))
518 return "delegate";
519 else
520 return "class";
522 if (t.IsInterface)
523 return "interface";
524 if (t.IsValueType)
525 return "struct";
526 return "class";
529 static string GetTypeVisibility (Type t)
531 switch (t.Attributes & TypeAttributes.VisibilityMask){
532 case TypeAttributes.Public:
533 case TypeAttributes.NestedPublic:
534 return "public";
536 case TypeAttributes.NestedFamily:
537 case TypeAttributes.NestedFamANDAssem:
538 case TypeAttributes.NestedFamORAssem:
539 return "protected";
541 default:
542 return "internal";
546 string FormatGenericParams (Type [] args)
548 StringBuilder sb = new StringBuilder ();
549 if (args.Length == 0)
550 return "";
552 sb.Append ("<");
553 for (int i = 0; i < args.Length; i++) {
554 if (i > 0)
555 sb.Append (",");
556 sb.Append (FormatType (args [i]));
558 sb.Append (">");
559 return sb.ToString ();
562 // TODO: fine tune this so that our output is less verbose. We need to figure
563 // out a way to do this while not making things confusing.
564 string FormatType (Type t)
566 string type = GetFullName (t);
568 if (!type.StartsWith ("System.")) {
569 if (t.Namespace == this.t.Namespace)
570 return t.Name;
571 return type;
574 if (t.HasElementType) {
575 Type et = t.GetElementType ();
576 if (t.IsArray)
577 return FormatType (et) + " []";
578 if (t.IsPointer)
579 return FormatType (et) + " *";
580 if (t.IsByRef)
581 return "ref " + FormatType (et);
584 switch (type) {
585 case "System.Byte": return "byte";
586 case "System.SByte": return "sbyte";
587 case "System.Int16": return "short";
588 case "System.Int32": return "int";
589 case "System.Int64": return "long";
591 case "System.UInt16": return "ushort";
592 case "System.UInt32": return "uint";
593 case "System.UInt64": return "ulong";
595 case "System.Single": return "float";
596 case "System.Double": return "double";
597 case "System.Decimal": return "decimal";
598 case "System.Boolean": return "bool";
599 case "System.Char": return "char";
600 case "System.String": return "string";
602 case "System.Object": return "object";
603 case "System.Void": return "void";
606 if (type.LastIndexOf(".") == 6)
607 return type.Substring(7);
610 // If the namespace of the type is the namespace of what
611 // we are printing (or is a member of one if its children
612 // don't print it. This basically means that in C# we would
613 // automatically get the namespace imported by virtue of the
614 // namespace {} block.
616 if (this.t.Namespace.StartsWith (t.Namespace + ".") || t.Namespace == this.t.Namespace)
617 return type.Substring (t.Namespace.Length + 1);
619 return type;
622 public static string RemoveGenericArity (string name)
624 int start = 0;
625 StringBuilder sb = new StringBuilder ();
626 while (start < name.Length) {
627 int pos = name.IndexOf ('`', start);
628 if (pos < 0) {
629 sb.Append (name.Substring (start));
630 break;
632 sb.Append (name.Substring (start, pos-start));
634 pos++;
636 while ((pos < name.Length) && Char.IsNumber (name [pos]))
637 pos++;
639 start = pos;
642 return sb.ToString ();
645 string GetTypeName (Type t)
647 StringBuilder sb = new StringBuilder ();
648 GetTypeName (sb, t);
649 return sb.ToString ();
652 void GetTypeName (StringBuilder sb, Type t)
654 sb.Append (RemoveGenericArity (t.Name));
655 #if NET_2_0
656 sb.Append (FormatGenericParams (t.GetGenericArguments ()));
657 #endif
660 string GetFullName (Type t)
662 StringBuilder sb = new StringBuilder ();
663 GetFullName_recursed (sb, t, false);
664 return sb.ToString ();
667 void GetFullName_recursed (StringBuilder sb, Type t, bool recursed)
669 #if NET_2_0
670 if (t.IsGenericParameter) {
671 sb.Append (t.Name);
672 return;
674 #endif
676 if (t.DeclaringType != null) {
677 GetFullName_recursed (sb, t.DeclaringType, true);
678 sb.Append (".");
681 if (!recursed) {
682 string ns = t.Namespace;
683 if ((ns != null) && (ns != "")) {
684 sb.Append (ns);
685 sb.Append (".");
689 GetTypeName (sb, t);
692 #if NET_2_0
693 void WriteGenericConstraints (Type [] args)
696 foreach (Type t in args) {
697 bool first = true;
698 Type[] ifaces = TypeGetInterfaces (t, true);
700 GenericParameterAttributes attrs = t.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
701 GenericParameterAttributes [] interesting = {
702 GenericParameterAttributes.ReferenceTypeConstraint,
703 GenericParameterAttributes.NotNullableValueTypeConstraint,
704 GenericParameterAttributes.DefaultConstructorConstraint
707 if (t.BaseType != typeof (object) || ifaces.Length != 0 || attrs != 0) {
708 o.Write (" where ");
709 o.Write (FormatType (t));
710 o.Write (" : ");
713 if (t.BaseType != typeof (object)) {
714 o.Write (FormatType (t.BaseType));
715 first = false;
718 foreach (Type iface in ifaces) {
719 if (!first)
720 o.Write (", ");
721 first = false;
723 o.Write (FormatType (iface));
726 foreach (GenericParameterAttributes a in interesting) {
727 if ((attrs & a) == 0)
728 continue;
730 if (!first)
731 o.Write (", ");
732 first = false;
734 switch (a) {
735 case GenericParameterAttributes.ReferenceTypeConstraint:
736 o.Write ("class");
737 break;
738 case GenericParameterAttributes.NotNullableValueTypeConstraint:
739 o.Write ("struct");
740 break;
741 case GenericParameterAttributes.DefaultConstructorConstraint:
742 o.Write ("new ()");
743 break;
748 #endif
750 string OperatorFromName (string name)
752 switch (name) {
753 case "op_UnaryPlus": return "+";
754 case "op_UnaryNegation": return "-";
755 case "op_LogicalNot": return "!";
756 case "op_OnesComplement": return "~";
757 case "op_Increment": return "++";
758 case "op_Decrement": return "--";
759 case "op_True": return "true";
760 case "op_False": return "false";
761 case "op_Addition": return "+";
762 case "op_Subtraction": return "-";
763 case "op_Multiply": return "*";
764 case "op_Division": return "/";
765 case "op_Modulus": return "%";
766 case "op_BitwiseAnd": return "&";
767 case "op_BitwiseOr": return "|";
768 case "op_ExclusiveOr": return "^";
769 case "op_LeftShift": return "<<";
770 case "op_RightShift": return ">>";
771 case "op_Equality": return "==";
772 case "op_Inequality": return "!=";
773 case "op_GreaterThan": return ">";
774 case "op_LessThan": return "<";
775 case "op_GreaterThanOrEqual": return ">=";
776 case "op_LessThanOrEqual": return "<=";
777 default: return name;
781 bool MethodIsExplicitIfaceImpl (MethodBase mb)
783 if (!(mb.IsFinal && mb.IsVirtual && mb.IsPrivate))
784 return false;
786 // UGH msft has no way to get the info about what method is
787 // getting overriden. Another reason to use cecil :-)
789 //MethodInfo mi = mb as MethodInfo;
790 //if (mi == null)
791 // return false;
793 //Console.WriteLine (mi.GetBaseDefinition ().DeclaringType);
794 //return mi.GetBaseDefinition ().DeclaringType.IsInterface;
796 // So, we guess that virtual final private methods only come
797 // from ifaces :-)
798 return true;
801 bool ShowMember (MemberInfo mi)
803 if (mi.MemberType == MemberTypes.Constructor && ((MethodBase) mi).IsStatic)
804 return false;
806 if (options.ShowPrivate)
807 return true;
809 if (options.FilterObsolete && mi.IsDefined (typeof (ObsoleteAttribute), false))
810 return false;
812 switch (mi.MemberType) {
813 case MemberTypes.Constructor:
814 case MemberTypes.Method:
815 MethodBase mb = mi as MethodBase;
817 if (mb.IsFamily || mb.IsPublic || mb.IsFamilyOrAssembly)
818 return true;
820 if (MethodIsExplicitIfaceImpl (mb))
821 return true;
823 return false;
826 case MemberTypes.Field:
827 FieldInfo fi = mi as FieldInfo;
829 if (fi.IsFamily || fi.IsPublic || fi.IsFamilyOrAssembly)
830 return true;
832 return false;
835 case MemberTypes.NestedType:
836 case MemberTypes.TypeInfo:
837 Type t = mi as Type;
839 switch (t.Attributes & TypeAttributes.VisibilityMask){
840 case TypeAttributes.Public:
841 case TypeAttributes.NestedPublic:
842 case TypeAttributes.NestedFamily:
843 case TypeAttributes.NestedFamORAssem:
844 return true;
847 return false;
850 // What am I !!!
851 return true;
854 static Type [] TypeGetInterfaces (Type t, bool declonly)
856 Type [] ifaces = t.GetInterfaces ();
857 if (! declonly)
858 return ifaces;
860 // Handle Object. Also, optimize for no interfaces
861 if (t.BaseType == null || ifaces.Length == 0)
862 return ifaces;
864 ArrayList ar = new ArrayList ();
866 foreach (Type i in ifaces)
867 if (! i.IsAssignableFrom (t.BaseType))
868 ar.Add (i);
870 return (Type []) ar.ToArray (typeof (Type));
874 public class Comparer : IComparer {
875 delegate int ComparerFunc (object a, object b);
877 ComparerFunc cmp;
879 Comparer (ComparerFunc f)
881 this.cmp = f;
884 public int Compare (object a, object b)
886 return cmp (a, b);
889 static int CompareType (object a, object b)
891 Type type1 = (Type) a;
892 Type type2 = (Type) b;
894 if (type1.IsSubclassOf (typeof (System.MulticastDelegate)) != type2.IsSubclassOf (typeof (System.MulticastDelegate)))
895 return (type1.IsSubclassOf (typeof (System.MulticastDelegate)))? -1:1;
896 return string.Compare (type1.Name, type2.Name);
900 static Comparer TypeComparer = new Comparer (new ComparerFunc (CompareType));
902 static Type [] Sort (Type [] types)
904 Array.Sort (types, TypeComparer);
905 return types;
908 static int CompareMemberInfo (object a, object b)
910 return string.Compare (((MemberInfo) a).Name, ((MemberInfo) b).Name);
913 static Comparer MemberInfoComparer = new Comparer (new ComparerFunc (CompareMemberInfo));
915 public static MemberInfo [] Sort (MemberInfo [] inf)
917 Array.Sort (inf, MemberInfoComparer);
918 return inf;
921 static int CompareMethodBase (object a, object b)
923 MethodBase aa = (MethodBase) a, bb = (MethodBase) b;
925 if (aa.IsStatic == bb.IsStatic) {
926 int c = CompareMemberInfo (a, b);
927 if (c != 0)
928 return c;
929 ParameterInfo [] ap, bp;
932 // Sort overloads by the names of their types
933 // put methods with fewer params first.
936 ap = aa.GetParameters ();
937 bp = bb.GetParameters ();
938 int n = Math.Min (ap.Length, bp.Length);
940 for (int i = 0; i < n; i ++)
941 if ((c = CompareType (ap [i].ParameterType, bp [i].ParameterType)) != 0)
942 return c;
944 return ap.Length.CompareTo (bp.Length);
946 if (aa.IsStatic)
947 return -1;
949 return 1;
952 static Comparer MethodBaseComparer = new Comparer (new ComparerFunc (CompareMethodBase));
954 public static MethodBase [] Sort (MethodBase [] inf)
956 Array.Sort (inf, MethodBaseComparer);
957 return inf;
960 static int ComparePropertyInfo (object a, object b)
962 PropertyInfo aa = (PropertyInfo) a, bb = (PropertyInfo) b;
964 bool astatic = (aa.CanRead ? aa.GetGetMethod (true) : aa.GetSetMethod (true)).IsStatic;
965 bool bstatic = (bb.CanRead ? bb.GetGetMethod (true) : bb.GetSetMethod (true)).IsStatic;
967 if (astatic == bstatic)
968 return CompareMemberInfo (a, b);
970 if (astatic)
971 return -1;
973 return 1;
976 static Comparer PropertyInfoComparer = new Comparer (new ComparerFunc (ComparePropertyInfo));
978 public static PropertyInfo [] Sort (PropertyInfo [] inf)
980 Array.Sort (inf, PropertyInfoComparer);
981 return inf;
984 static int CompareEventInfo (object a, object b)
986 EventInfo aa = (EventInfo) a, bb = (EventInfo) b;
988 bool astatic = aa.GetAddMethod (true).IsStatic;
989 bool bstatic = bb.GetAddMethod (true).IsStatic;
991 if (astatic == bstatic)
992 return CompareMemberInfo (a, b);
994 if (astatic)
995 return -1;
997 return 1;
1000 static Comparer EventInfoComparer = new Comparer (new ComparerFunc (CompareEventInfo));
1002 public static EventInfo [] Sort (EventInfo [] inf)
1004 Array.Sort (inf, EventInfoComparer);
1005 return inf;