2010-06-03 Jb Evain <jbevain@novell.com>
[mcs.git] / tools / monop / outline.cs
blob784cece95b2cbd41f030192bbaecacd71d740879
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 namespace Mono.CSharp {
40 public class Outline {
42 bool declared_only;
43 bool show_private;
44 bool filter_obsolete;
46 IndentedTextWriter o;
47 Type t;
49 public Outline (Type t, TextWriter output, bool declared_only, bool show_private, bool filter_obsolete)
51 this.t = t;
52 this.o = new IndentedTextWriter (output, "\t");
53 this.declared_only = declared_only;
54 this.show_private = show_private;
55 this.filter_obsolete = filter_obsolete;
58 public void OutlineType ()
60 bool first;
62 OutlineAttributes ();
63 o.Write (GetTypeVisibility (t));
65 if (t.IsClass && !t.IsSubclassOf (typeof (System.MulticastDelegate))) {
66 if (t.IsSealed)
67 o.Write (t.IsAbstract ? " static" : " sealed");
68 else if (t.IsAbstract)
69 o.Write (" abstract");
72 o.Write (" ");
73 o.Write (GetTypeKind (t));
74 o.Write (" ");
76 Type [] interfaces = (Type []) Comparer.Sort (TypeGetInterfaces (t, declared_only));
77 Type parent = t.BaseType;
79 if (t.IsSubclassOf (typeof (System.MulticastDelegate))) {
80 MethodInfo method;
82 method = t.GetMethod ("Invoke");
84 o.Write (FormatType (method.ReturnType));
85 o.Write (" ");
86 o.Write (GetTypeName (t));
87 o.Write (" (");
88 OutlineParams (method.GetParameters ());
89 o.Write (")");
91 #if NET_2_0
92 WriteGenericConstraints (t.GetGenericArguments ());
93 #endif
95 o.WriteLine (";");
96 return;
99 o.Write (GetTypeName (t));
100 if (((parent != null && parent != typeof (object) && parent != typeof (ValueType)) || interfaces.Length != 0) && ! t.IsEnum) {
101 first = true;
102 o.Write (" : ");
104 if (parent != null && parent != typeof (object) && parent != typeof (ValueType)) {
105 o.Write (FormatType (parent));
106 first = false;
109 foreach (Type intf in interfaces) {
110 if (!first) o.Write (", ");
111 first = false;
113 o.Write (FormatType (intf));
117 if (t.IsEnum) {
118 Type underlyingType = System.Enum.GetUnderlyingType (t);
119 if (underlyingType != typeof (int))
120 o.Write (" : {0}", FormatType (underlyingType));
122 #if NET_2_0
123 WriteGenericConstraints (t.GetGenericArguments ());
124 #endif
125 o.WriteLine (" {");
126 o.Indent++;
128 if (t.IsEnum) {
129 bool is_first = true;
130 foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Static)) {
132 if (! is_first)
133 o.WriteLine (",");
134 is_first = false;
135 o.Write (fi.Name);
137 o.WriteLine ();
138 o.Indent--; o.WriteLine ("}");
139 return;
142 first = true;
144 foreach (ConstructorInfo ci in t.GetConstructors (DefaultFlags)) {
146 if (! ShowMember (ci))
147 continue;
149 if (first)
150 o.WriteLine ();
151 first = false;
153 OutlineConstructor (ci);
155 o.WriteLine ();
159 first = true;
161 foreach (MethodInfo m in Comparer.Sort (t.GetMethods (DefaultFlags))) {
163 if (! ShowMember (m))
164 continue;
166 if ((m.Attributes & MethodAttributes.SpecialName) != 0)
167 continue;
169 if (first)
170 o.WriteLine ();
171 first = false;
173 OutlineMethod (m);
175 o.WriteLine ();
178 first = true;
180 foreach (MethodInfo m in t.GetMethods (DefaultFlags)) {
182 if (! ShowMember (m))
183 continue;
185 if ((m.Attributes & MethodAttributes.SpecialName) == 0)
186 continue;
187 if (!(m.Name.StartsWith ("op_")))
188 continue;
190 if (first)
191 o.WriteLine ();
192 first = false;
194 OutlineOperator (m);
196 o.WriteLine ();
199 first = true;
201 foreach (PropertyInfo pi in Comparer.Sort (t.GetProperties (DefaultFlags))) {
203 if (! ((pi.CanRead && ShowMember (pi.GetGetMethod (true))) ||
204 (pi.CanWrite && ShowMember (pi.GetSetMethod (true)))))
205 continue;
207 if (first)
208 o.WriteLine ();
209 first = false;
211 OutlineProperty (pi);
213 o.WriteLine ();
216 first = true;
218 foreach (FieldInfo fi in t.GetFields (DefaultFlags)) {
220 if (! ShowMember (fi))
221 continue;
223 if (first)
224 o.WriteLine ();
225 first = false;
227 OutlineField (fi);
229 o.WriteLine ();
232 first = true;
234 foreach (EventInfo ei in Comparer.Sort (t.GetEvents (DefaultFlags))) {
236 if (! ShowMember (ei.GetAddMethod (true)))
237 continue;
239 if (first)
240 o.WriteLine ();
241 first = false;
243 OutlineEvent (ei);
245 o.WriteLine ();
248 first = true;
250 foreach (Type ntype in Comparer.Sort (t.GetNestedTypes (DefaultFlags))) {
252 if (! ShowMember (ntype))
253 continue;
255 if (first)
256 o.WriteLine ();
257 first = false;
259 new Outline (ntype, o, declared_only, show_private, filter_obsolete).OutlineType ();
262 o.Indent--; o.WriteLine ("}");
265 BindingFlags DefaultFlags {
266 get {
267 BindingFlags f = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
269 if (declared_only)
270 f |= BindingFlags.DeclaredOnly;
272 return f;
276 // FIXME: add other interesting attributes?
277 void OutlineAttributes ()
279 if (t.IsSerializable)
280 o.WriteLine ("[Serializable]");
282 if (t.IsDefined (typeof (System.FlagsAttribute), true))
283 o.WriteLine ("[Flags]");
285 if (t.IsDefined (typeof (System.ObsoleteAttribute), true))
286 o.WriteLine ("[Obsolete]");
289 void OutlineEvent (EventInfo ei)
291 MethodBase accessor = ei.GetAddMethod (true);
293 o.Write (GetMethodVisibility (accessor));
294 o.Write ("event ");
295 o.Write (FormatType (ei.EventHandlerType));
296 o.Write (" ");
297 o.Write (ei.Name);
298 o.Write (";");
301 void OutlineConstructor (ConstructorInfo ci)
303 o.Write (GetMethodVisibility (ci));
304 o.Write (RemoveGenericArity (t.Name));
305 o.Write (" (");
306 OutlineParams (ci.GetParameters ());
307 o.Write (");");
311 void OutlineProperty (PropertyInfo pi)
313 ParameterInfo [] idxp = pi.GetIndexParameters ();
314 MethodBase g = pi.GetGetMethod (true);
315 MethodBase s = pi.GetSetMethod (true);
316 MethodBase accessor = g != null ? g : s;
318 if (pi.CanRead && pi.CanWrite) {
321 // Get the more accessible accessor
322 if ((g.Attributes & MethodAttributes.MemberAccessMask) !=
323 (s.Attributes & MethodAttributes.MemberAccessMask)) {
325 if (g.IsPublic) accessor = g;
326 else if (s.IsPublic) accessor = s;
327 else if (g.IsFamilyOrAssembly) accessor = g;
328 else if (s.IsFamilyOrAssembly) accessor = s;
329 else if (g.IsAssembly || g.IsFamily) accessor = g;
330 else if (s.IsAssembly || s.IsFamily) accessor = s;
334 o.Write (GetMethodVisibility (accessor));
335 o.Write (GetMethodModifiers (accessor));
336 o.Write (FormatType (pi.PropertyType));
337 o.Write (" ");
339 if (idxp.Length == 0)
340 o.Write (pi.Name);
341 else {
342 o.Write ("this [");
343 OutlineParams (idxp);
344 o.Write ("]");
347 o.WriteLine (" {");
348 o.Indent ++;
350 if (g != null && ShowMember (g)) {
351 if ((g.Attributes & MethodAttributes.MemberAccessMask) !=
352 (accessor.Attributes & MethodAttributes.MemberAccessMask))
353 o.Write (GetMethodVisibility (g));
354 o.WriteLine ("get;");
357 if (s != null && ShowMember (s)) {
358 if ((s.Attributes & MethodAttributes.MemberAccessMask) !=
359 (accessor.Attributes & MethodAttributes.MemberAccessMask))
360 o.Write (GetMethodVisibility (s));
361 o.WriteLine ("set;");
364 o.Indent --;
365 o.Write ("}");
368 void OutlineMethod (MethodInfo mi)
370 if (MethodIsExplicitIfaceImpl (mi)) {
371 o.Write (FormatType (mi.ReturnType));
372 o.Write (" ");
373 // MSFT has no way to get the method that we are overriding
374 // from the interface. this would allow us to pretty print
375 // the type name (and be more correct if there compiler
376 // were to do some strange naming thing).
377 } else {
378 o.Write (GetMethodVisibility (mi));
379 o.Write (GetMethodModifiers (mi));
380 o.Write (FormatType (mi.ReturnType));
381 o.Write (" ");
384 o.Write (mi.Name);
385 #if NET_2_0
386 o.Write (FormatGenericParams (mi.GetGenericArguments ()));
387 #endif
388 o.Write (" (");
389 OutlineParams (mi.GetParameters ());
390 o.Write (")");
391 #if NET_2_0
392 WriteGenericConstraints (mi.GetGenericArguments ());
393 #endif
394 o.Write (";");
397 void OutlineOperator (MethodInfo mi)
399 o.Write (GetMethodVisibility (mi));
400 o.Write (GetMethodModifiers (mi));
401 if (mi.Name == "op_Explicit" || mi.Name == "op_Implicit") {
402 o.Write (mi.Name.Substring (3).ToLower ());
403 o.Write (" operator ");
404 o.Write (FormatType (mi.ReturnType));
405 } else {
406 o.Write (FormatType (mi.ReturnType));
407 o.Write (" operator ");
408 o.Write (OperatorFromName (mi.Name));
410 o.Write (" (");
411 OutlineParams (mi.GetParameters ());
412 o.Write (");");
415 void OutlineParams (ParameterInfo [] pi)
417 int i = 0;
418 foreach (ParameterInfo p in pi) {
419 if (p.ParameterType.IsByRef) {
420 o.Write (p.IsOut ? "out " : "ref ");
421 o.Write (FormatType (p.ParameterType.GetElementType ()));
422 } else if (p.IsDefined (typeof (ParamArrayAttribute), false)) {
423 o.Write ("params ");
424 o.Write (FormatType (p.ParameterType));
425 } else {
426 o.Write (FormatType (p.ParameterType));
429 o.Write (" ");
430 o.Write (p.Name);
431 if (i + 1 < pi.Length)
432 o.Write (", ");
433 i++;
437 void OutlineField (FieldInfo fi)
439 if (fi.IsPublic) o.Write ("public ");
440 if (fi.IsFamily) o.Write ("protected ");
441 if (fi.IsPrivate) o.Write ("private ");
442 if (fi.IsAssembly) o.Write ("internal ");
443 if (fi.IsLiteral) o.Write ("const ");
444 else if (fi.IsStatic) o.Write ("static ");
445 if (fi.IsInitOnly) o.Write ("readonly ");
447 o.Write (FormatType (fi.FieldType));
448 o.Write (" ");
449 o.Write (fi.Name);
450 if (fi.IsLiteral) {
451 object v = fi.GetValue (this);
453 // TODO: Escape values here
454 o.Write (" = ");
455 if (v is char)
456 o.Write ("'{0}'", v);
457 else if (v is string)
458 o.Write ("\"{0}\"", v);
459 else
460 o.Write (fi.GetValue (this));
462 o.Write (";");
465 static string GetMethodVisibility (MethodBase m)
467 // itnerfaces have no modifiers here
468 if (m.DeclaringType.IsInterface)
469 return "";
471 if (m.IsPublic) return "public ";
472 if (m.IsFamily) return "protected ";
473 if (m.IsPrivate) return "private ";
474 if (m.IsAssembly) return "internal ";
476 return null;
479 static string GetMethodModifiers (MethodBase method)
481 if (method.IsStatic)
482 return "static ";
484 if (method.IsFinal) {
485 // This will happen if you have
486 // class X : IA {
487 // public void A () {}
488 // static void Main () {}
489 // }
490 // interface IA {
491 // void A ();
492 // }
494 // A needs to be virtual (the CLR requires
495 // methods implementing an iface be virtual),
496 // but can not be inherited. It also can not
497 // be inherited. In C# this is represented
498 // with no special modifiers
500 if (method.IsVirtual)
501 return null;
502 return "sealed ";
505 // all interface methods are "virtual" but we don't say that in c#
506 if (method.IsVirtual && !method.DeclaringType.IsInterface) {
507 if (method.IsAbstract)
508 return "abstract ";
510 return ((method.Attributes & MethodAttributes.NewSlot) != 0) ?
511 "virtual " :
512 "override ";
515 return null;
518 static string GetTypeKind (Type t)
520 if (t.IsEnum)
521 return "enum";
522 if (t.IsClass) {
523 if (t.IsSubclassOf (typeof (System.MulticastDelegate)))
524 return "delegate";
525 else
526 return "class";
528 if (t.IsInterface)
529 return "interface";
530 if (t.IsValueType)
531 return "struct";
532 return "class";
535 static string GetTypeVisibility (Type t)
537 switch (t.Attributes & TypeAttributes.VisibilityMask){
538 case TypeAttributes.Public:
539 case TypeAttributes.NestedPublic:
540 return "public";
542 case TypeAttributes.NestedFamily:
543 case TypeAttributes.NestedFamANDAssem:
544 case TypeAttributes.NestedFamORAssem:
545 return "protected";
547 default:
548 return "internal";
552 #if NET_2_0
553 string FormatGenericParams (Type [] args)
555 StringBuilder sb = new StringBuilder ();
556 if (args.Length == 0)
557 return "";
559 sb.Append ("<");
560 for (int i = 0; i < args.Length; i++) {
561 if (i > 0)
562 sb.Append (",");
563 sb.Append (FormatType (args [i]));
565 sb.Append (">");
566 return sb.ToString ();
568 #endif
570 // TODO: fine tune this so that our output is less verbose. We need to figure
571 // out a way to do this while not making things confusing.
572 string FormatType (Type t)
574 if (t == null)
575 return "";
577 string type = GetFullName (t);
578 if (type == null)
579 return t.ToString ();
581 if (!type.StartsWith ("System.")) {
582 if (t.Namespace == this.t.Namespace)
583 return t.Name;
584 return type;
587 if (t.HasElementType) {
588 Type et = t.GetElementType ();
589 if (t.IsArray)
590 return FormatType (et) + " []";
591 if (t.IsPointer)
592 return FormatType (et) + " *";
593 if (t.IsByRef)
594 return "ref " + FormatType (et);
597 switch (type) {
598 case "System.Byte": return "byte";
599 case "System.SByte": return "sbyte";
600 case "System.Int16": return "short";
601 case "System.Int32": return "int";
602 case "System.Int64": return "long";
604 case "System.UInt16": return "ushort";
605 case "System.UInt32": return "uint";
606 case "System.UInt64": return "ulong";
608 case "System.Single": return "float";
609 case "System.Double": return "double";
610 case "System.Decimal": return "decimal";
611 case "System.Boolean": return "bool";
612 case "System.Char": return "char";
613 case "System.String": return "string";
615 case "System.Object": return "object";
616 case "System.Void": return "void";
619 if (type.LastIndexOf(".") == 6)
620 return type.Substring(7);
623 // If the namespace of the type is the namespace of what
624 // we are printing (or is a member of one if its children
625 // don't print it. This basically means that in C# we would
626 // automatically get the namespace imported by virtue of the
627 // namespace {} block.
629 if (this.t.Namespace.StartsWith (t.Namespace + ".") || t.Namespace == this.t.Namespace)
630 return type.Substring (t.Namespace.Length + 1);
632 return type;
635 public static string RemoveGenericArity (string name)
637 int start = 0;
638 StringBuilder sb = new StringBuilder ();
639 while (start < name.Length) {
640 int pos = name.IndexOf ('`', start);
641 if (pos < 0) {
642 sb.Append (name.Substring (start));
643 break;
645 sb.Append (name.Substring (start, pos-start));
647 pos++;
649 while ((pos < name.Length) && Char.IsNumber (name [pos]))
650 pos++;
652 start = pos;
655 return sb.ToString ();
658 string GetTypeName (Type t)
660 StringBuilder sb = new StringBuilder ();
661 GetTypeName (sb, t);
662 return sb.ToString ();
665 void GetTypeName (StringBuilder sb, Type t)
667 sb.Append (RemoveGenericArity (t.Name));
668 #if NET_2_0
669 sb.Append (FormatGenericParams (t.GetGenericArguments ()));
670 #endif
673 string GetFullName (Type t)
675 StringBuilder sb = new StringBuilder ();
676 GetFullName_recursed (sb, t, false);
677 return sb.ToString ();
680 void GetFullName_recursed (StringBuilder sb, Type t, bool recursed)
682 #if NET_2_0
683 if (t.IsGenericParameter) {
684 sb.Append (t.Name);
685 return;
687 #endif
689 if (t.DeclaringType != null) {
690 GetFullName_recursed (sb, t.DeclaringType, true);
691 sb.Append (".");
694 if (!recursed) {
695 string ns = t.Namespace;
696 if ((ns != null) && (ns != "")) {
697 sb.Append (ns);
698 sb.Append (".");
702 GetTypeName (sb, t);
705 #if NET_2_0
706 void WriteGenericConstraints (Type [] args)
709 foreach (Type t in args) {
710 bool first = true;
711 Type[] ifaces = TypeGetInterfaces (t, true);
713 GenericParameterAttributes attrs = t.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
714 GenericParameterAttributes [] interesting = {
715 GenericParameterAttributes.ReferenceTypeConstraint,
716 GenericParameterAttributes.NotNullableValueTypeConstraint,
717 GenericParameterAttributes.DefaultConstructorConstraint
720 if (t.BaseType != typeof (object) || ifaces.Length != 0 || attrs != 0) {
721 o.Write (" where ");
722 o.Write (FormatType (t));
723 o.Write (" : ");
726 if (t.BaseType != typeof (object)) {
727 o.Write (FormatType (t.BaseType));
728 first = false;
731 foreach (Type iface in ifaces) {
732 if (!first)
733 o.Write (", ");
734 first = false;
736 o.Write (FormatType (iface));
739 foreach (GenericParameterAttributes a in interesting) {
740 if ((attrs & a) == 0)
741 continue;
743 if (!first)
744 o.Write (", ");
745 first = false;
747 switch (a) {
748 case GenericParameterAttributes.ReferenceTypeConstraint:
749 o.Write ("class");
750 break;
751 case GenericParameterAttributes.NotNullableValueTypeConstraint:
752 o.Write ("struct");
753 break;
754 case GenericParameterAttributes.DefaultConstructorConstraint:
755 o.Write ("new ()");
756 break;
761 #endif
763 string OperatorFromName (string name)
765 switch (name) {
766 case "op_UnaryPlus": return "+";
767 case "op_UnaryNegation": return "-";
768 case "op_LogicalNot": return "!";
769 case "op_OnesComplement": return "~";
770 case "op_Increment": return "++";
771 case "op_Decrement": return "--";
772 case "op_True": return "true";
773 case "op_False": return "false";
774 case "op_Addition": return "+";
775 case "op_Subtraction": return "-";
776 case "op_Multiply": return "*";
777 case "op_Division": return "/";
778 case "op_Modulus": return "%";
779 case "op_BitwiseAnd": return "&";
780 case "op_BitwiseOr": return "|";
781 case "op_ExclusiveOr": return "^";
782 case "op_LeftShift": return "<<";
783 case "op_RightShift": return ">>";
784 case "op_Equality": return "==";
785 case "op_Inequality": return "!=";
786 case "op_GreaterThan": return ">";
787 case "op_LessThan": return "<";
788 case "op_GreaterThanOrEqual": return ">=";
789 case "op_LessThanOrEqual": return "<=";
790 default: return name;
794 bool MethodIsExplicitIfaceImpl (MethodBase mb)
796 if (!(mb.IsFinal && mb.IsVirtual && mb.IsPrivate))
797 return false;
799 // UGH msft has no way to get the info about what method is
800 // getting overriden. Another reason to use cecil :-)
802 //MethodInfo mi = mb as MethodInfo;
803 //if (mi == null)
804 // return false;
806 //Console.WriteLine (mi.GetBaseDefinition ().DeclaringType);
807 //return mi.GetBaseDefinition ().DeclaringType.IsInterface;
809 // So, we guess that virtual final private methods only come
810 // from ifaces :-)
811 return true;
814 bool ShowMember (MemberInfo mi)
816 if (mi.MemberType == MemberTypes.Constructor && ((MethodBase) mi).IsStatic)
817 return false;
819 if (show_private)
820 return true;
822 if (filter_obsolete && mi.IsDefined (typeof (ObsoleteAttribute), false))
823 return false;
825 switch (mi.MemberType) {
826 case MemberTypes.Constructor:
827 case MemberTypes.Method:
828 MethodBase mb = mi as MethodBase;
830 if (mb.IsFamily || mb.IsPublic || mb.IsFamilyOrAssembly)
831 return true;
833 if (MethodIsExplicitIfaceImpl (mb))
834 return true;
836 return false;
839 case MemberTypes.Field:
840 FieldInfo fi = mi as FieldInfo;
842 if (fi.IsFamily || fi.IsPublic || fi.IsFamilyOrAssembly)
843 return true;
845 return false;
848 case MemberTypes.NestedType:
849 case MemberTypes.TypeInfo:
850 Type t = mi as Type;
852 switch (t.Attributes & TypeAttributes.VisibilityMask){
853 case TypeAttributes.Public:
854 case TypeAttributes.NestedPublic:
855 case TypeAttributes.NestedFamily:
856 case TypeAttributes.NestedFamORAssem:
857 return true;
860 return false;
863 // What am I !!!
864 return true;
867 static Type [] TypeGetInterfaces (Type t, bool declonly)
869 if (t.IsGenericParameter)
870 return new Type [0];
872 Type [] ifaces = t.GetInterfaces ();
873 if (! declonly)
874 return ifaces;
876 // Handle Object. Also, optimize for no interfaces
877 if (t.BaseType == null || ifaces.Length == 0)
878 return ifaces;
880 ArrayList ar = new ArrayList ();
882 foreach (Type i in ifaces)
883 if (! i.IsAssignableFrom (t.BaseType))
884 ar.Add (i);
886 return (Type []) ar.ToArray (typeof (Type));
890 public class Comparer : IComparer {
891 delegate int ComparerFunc (object a, object b);
893 ComparerFunc cmp;
895 Comparer (ComparerFunc f)
897 this.cmp = f;
900 public int Compare (object a, object b)
902 return cmp (a, b);
905 static int CompareType (object a, object b)
907 Type type1 = (Type) a;
908 Type type2 = (Type) b;
910 if (type1.IsSubclassOf (typeof (System.MulticastDelegate)) != type2.IsSubclassOf (typeof (System.MulticastDelegate)))
911 return (type1.IsSubclassOf (typeof (System.MulticastDelegate)))? -1:1;
912 return string.Compare (type1.Name, type2.Name);
916 // static Comparer TypeComparer = new Comparer (new ComparerFunc (CompareType));
918 // static Type [] Sort (Type [] types)
919 // {
920 // Array.Sort (types, TypeComparer);
921 // return types;
922 // }
924 static int CompareMemberInfo (object a, object b)
926 return string.Compare (((MemberInfo) a).Name, ((MemberInfo) b).Name);
929 static Comparer MemberInfoComparer = new Comparer (new ComparerFunc (CompareMemberInfo));
931 public static MemberInfo [] Sort (MemberInfo [] inf)
933 Array.Sort (inf, MemberInfoComparer);
934 return inf;
937 static int CompareMethodBase (object a, object b)
939 MethodBase aa = (MethodBase) a, bb = (MethodBase) b;
941 if (aa.IsStatic == bb.IsStatic) {
942 int c = CompareMemberInfo (a, b);
943 if (c != 0)
944 return c;
945 ParameterInfo [] ap, bp;
948 // Sort overloads by the names of their types
949 // put methods with fewer params first.
952 ap = aa.GetParameters ();
953 bp = bb.GetParameters ();
954 int n = System.Math.Min (ap.Length, bp.Length);
956 for (int i = 0; i < n; i ++)
957 if ((c = CompareType (ap [i].ParameterType, bp [i].ParameterType)) != 0)
958 return c;
960 return ap.Length.CompareTo (bp.Length);
962 if (aa.IsStatic)
963 return -1;
965 return 1;
968 static Comparer MethodBaseComparer = new Comparer (new ComparerFunc (CompareMethodBase));
970 public static MethodBase [] Sort (MethodBase [] inf)
972 Array.Sort (inf, MethodBaseComparer);
973 return inf;
976 static int ComparePropertyInfo (object a, object b)
978 PropertyInfo aa = (PropertyInfo) a, bb = (PropertyInfo) b;
980 bool astatic = (aa.CanRead ? aa.GetGetMethod (true) : aa.GetSetMethod (true)).IsStatic;
981 bool bstatic = (bb.CanRead ? bb.GetGetMethod (true) : bb.GetSetMethod (true)).IsStatic;
983 if (astatic == bstatic)
984 return CompareMemberInfo (a, b);
986 if (astatic)
987 return -1;
989 return 1;
992 static Comparer PropertyInfoComparer = new Comparer (new ComparerFunc (ComparePropertyInfo));
994 public static PropertyInfo [] Sort (PropertyInfo [] inf)
996 Array.Sort (inf, PropertyInfoComparer);
997 return inf;
1000 static int CompareEventInfo (object a, object b)
1002 EventInfo aa = (EventInfo) a, bb = (EventInfo) b;
1004 bool astatic = aa.GetAddMethod (true).IsStatic;
1005 bool bstatic = bb.GetAddMethod (true).IsStatic;
1007 if (astatic == bstatic)
1008 return CompareMemberInfo (a, b);
1010 if (astatic)
1011 return -1;
1013 return 1;
1016 static Comparer EventInfoComparer = new Comparer (new ComparerFunc (CompareEventInfo));
1018 public static EventInfo [] Sort (EventInfo [] inf)
1020 Array.Sort (inf, EventInfoComparer);
1021 return inf;