* *: begin support for 2.0
[mono.git] / mcs / tools / monop / outline.cs
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 //
10
11 //
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.
30 //
31
32 using System;
33 using System.Reflection;
34 using System.Collections;
35 using System.CodeDom.Compiler;
36 using System.IO;
37 using System.Text;
38         
39 public class Outline {
40         
41         Options options;
42         IndentedTextWriter o;
43         Type t;
44         
45         public Outline (Type t, TextWriter output, Options options)
46         {
47                 this.t = t;
48                 this.o = new IndentedTextWriter (output, "    ");
49                 this.options = options;
50         }
51
52         public void OutlineType ()
53         {
54                 bool first;
55                 
56                 OutlineAttributes ();
57                 o.Write (GetTypeVisibility (t));
58                 
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");
64                 }
65                 
66                 o.Write (" ");
67                 o.Write (GetTypeKind (t));
68                 o.Write (" ");
69                 
70                 Type [] interfaces = (Type []) Comparer.Sort (t.GetInterfaces ());
71                 Type parent = t.BaseType;
72
73                 if (t.IsSubclassOf (typeof (System.MulticastDelegate))) {
74                         MethodInfo method;
75
76                         method = t.GetMethod ("Invoke");
77
78                         o.Write (FormatType (method.ReturnType));
79                         o.Write (" ");
80                         o.Write (GetTypeName (t));
81                         o.Write (" (");
82                         OutlineParams (method.GetParameters ());
83                         o.WriteLine (");");
84
85                         return;
86                 }
87                 
88                 o.Write (GetTypeName (t));
89                 if (((parent != null && parent != typeof (object) && parent != typeof (ValueType)) || interfaces.Length != 0) && ! t.IsEnum) {
90                         first = true;
91                         o.Write (" : ");
92                         
93                         if (parent != null && parent != typeof (object) && parent != typeof (ValueType)) {
94                                 o.Write (FormatType (parent));
95                                 first = false;
96                         }
97                         
98                         foreach (Type intf in interfaces) {
99                                 if (!first) o.Write (", ");
100                                 first = false;
101                                 
102                                 o.Write (FormatType (intf));
103                         }
104                 }
105
106                 if (t.IsEnum) {
107                         Type underlyingType = Enum.GetUnderlyingType (t);
108                         if (underlyingType != typeof (int))
109                                 o.Write (" : {0}", FormatType (underlyingType));
110                 }
111                 
112                 o.WriteLine (" {");
113                 o.Indent++;
114
115                 if (t.IsEnum) {
116                         bool is_first = true;
117                         foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Static)) {
118                                 
119                                 if (! is_first)
120                                         o.WriteLine (",");
121                                 is_first = false;
122                                 o.Write (fi.Name);
123                         }
124                         o.WriteLine ();
125                         o.Indent--; o.WriteLine ("}");
126                         return;
127                 }
128                 
129                 first = true;
130                 
131                 foreach (ConstructorInfo ci in t.GetConstructors (DefaultFlags)) {
132                         
133                         if (! ShowMember (ci))
134                                 continue;
135                         
136                         if (first)
137                                 o.WriteLine ();
138                         first = false;
139                         
140                         OutlineConstructor (ci);
141                         
142                         o.WriteLine ();
143                 }
144                 
145
146                 first = true;
147                 
148                 foreach (MethodInfo m in Comparer.Sort (t.GetMethods (DefaultFlags))) {
149                         
150                         if (! ShowMember (m))
151                                 continue;               
152                         
153                         if ((m.Attributes & MethodAttributes.SpecialName) != 0)
154                                 continue;
155                         
156                         if (first)
157                                 o.WriteLine ();
158                         first = false;
159                         
160                         OutlineMethod (m);
161                         
162                         o.WriteLine ();
163                 }
164                 
165                 first = true;
166                 
167                 foreach (MethodInfo m in t.GetMethods (DefaultFlags)) {
168                         
169                         if (! ShowMember (m))
170                                 continue;
171                         
172                         if ((m.Attributes & MethodAttributes.SpecialName) == 0)
173                                 continue;
174                         if (!(m.Name.StartsWith ("op_")))
175                                 continue;
176
177                         if (first)
178                                 o.WriteLine ();
179                         first = false;
180                         
181                         OutlineOperator (m);
182                         
183                         o.WriteLine ();
184                 }
185
186                 first = true;
187                 
188                 foreach (PropertyInfo pi in Comparer.Sort (t.GetProperties (DefaultFlags))) {
189                         
190                         if (! ((pi.CanRead  && ShowMember (pi.GetGetMethod (true))) ||
191                                (pi.CanWrite && ShowMember (pi.GetSetMethod (true)))))
192                                 continue;
193                         
194                         if (first)
195                                 o.WriteLine ();
196                         first = false;
197                         
198                         OutlineProperty (pi);
199                         
200                         o.WriteLine ();
201                 }
202                 
203                 first = true;
204
205                 foreach (FieldInfo fi in t.GetFields (DefaultFlags)) {
206                         
207                         if (! ShowMember (fi))
208                                 continue;
209                         
210                         if (first)
211                                 o.WriteLine ();
212                         first = false;
213                         
214                         OutlineField (fi);
215                         
216                         o.WriteLine ();
217                 }
218
219                 first = true;
220                 
221                 foreach (EventInfo ei in Comparer.Sort (t.GetEvents (DefaultFlags))) {
222                         
223                         if (! ShowMember (ei.GetAddMethod ()))
224                                 continue;
225                         
226                         if (first)
227                                 o.WriteLine ();
228                         first = false;
229                         
230                         OutlineEvent (ei);
231                         
232                         o.WriteLine ();
233                 }
234
235                 first = true;
236
237                 foreach (Type ntype in Comparer.Sort (t.GetNestedTypes (DefaultFlags))) {
238                         
239                         if (! ShowMember (ntype))
240                                 continue;
241                         
242                         if (first)
243                                 o.WriteLine ();
244                         first = false;
245                         
246                         new Outline (ntype, o, options).OutlineType ();
247                 }
248                 
249                 o.Indent--; o.WriteLine ("}");
250         }
251         
252         BindingFlags DefaultFlags {
253                 get {
254                         BindingFlags f = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
255                         
256                         if (options.DeclaredOnly)
257                                 f |= BindingFlags.DeclaredOnly;
258                         
259                         return f;
260                 }
261         }
262
263         // FIXME: add other interesting attributes?
264         void OutlineAttributes ()
265         {
266                 if (t.IsSerializable)
267                         o.WriteLine ("[Serializable]");
268
269                 if (t.IsDefined (typeof (System.FlagsAttribute), true))
270                         o.WriteLine ("[Flags]");
271
272                 if (t.IsDefined (typeof (System.ObsoleteAttribute), true))
273                         o.WriteLine ("[Obsolete]");
274         }
275
276         void OutlineEvent (EventInfo ei)
277         {
278                 MethodBase accessor = ei.GetAddMethod ();
279                 
280                 o.Write (GetMethodVisibility (accessor));
281                 o.Write ("event ");
282                 o.Write (FormatType (ei.EventHandlerType));
283                 o.Write (" ");
284                 o.Write (ei.Name);
285                 o.Write (";");
286         }
287         
288         void OutlineConstructor (ConstructorInfo ci)
289         {
290                 o.Write (GetMethodVisibility (ci));
291                 o.Write (RemoveGenericArity (t.Name));
292                 o.Write (" (");
293                 OutlineParams (ci.GetParameters ());
294                 o.Write (");");
295         }
296         
297         
298         void OutlineProperty (PropertyInfo pi)
299         {
300                 ParameterInfo [] idxp = pi.GetIndexParameters ();
301                 MethodBase g = pi.GetGetMethod (true);
302                 MethodBase s = pi.GetSetMethod (true);
303                 MethodBase accessor = g != null ? g : s;
304                 
305                 if (pi.CanRead && pi.CanWrite) {
306
307                         
308                         // Get the more accessible accessor
309                         if ((g.Attributes & MethodAttributes.MemberAccessMask) !=
310                             (s.Attributes & MethodAttributes.MemberAccessMask)) {
311                                 
312                                 if (g.IsPublic) accessor = g;
313                                 else if (s.IsPublic) accessor = s;
314                                 else if (g.IsFamilyOrAssembly) accessor = g;
315                                 else if (s.IsFamilyOrAssembly) accessor = s;
316                                 else if (g.IsAssembly || g.IsFamily) accessor = g;
317                                 else if (s.IsAssembly || s.IsFamily) accessor = s;
318                         }
319                 }
320                 
321                 o.Write (GetMethodVisibility (accessor));
322                 o.Write (GetMethodModifiers  (accessor));
323                 o.Write (FormatType (pi.PropertyType));
324                 o.Write (" ");
325                 
326                 if (idxp.Length == 0)
327                         o.Write (pi.Name);
328                 else {
329                         o.Write ("this [");
330                         OutlineParams (idxp);
331                         o.Write ("]");
332                 }
333                 
334                 o.WriteLine (" {");
335                 o.Indent ++;
336                 
337                 if (g != null && ShowMember (g)) {
338                         if ((g.Attributes & MethodAttributes.MemberAccessMask) !=
339                             (accessor.Attributes & MethodAttributes.MemberAccessMask))
340                                 o.Write (GetMethodVisibility (g));
341                         o.WriteLine ("get;");
342                 }
343                 
344                 if (s != null && ShowMember (s)) {
345                         if ((s.Attributes & MethodAttributes.MemberAccessMask) !=
346                             (accessor.Attributes & MethodAttributes.MemberAccessMask))
347                                 o.Write (GetMethodVisibility (s));
348                         o.WriteLine ("set;");
349                 }
350                 
351                 o.Indent --;
352                 o.Write ("}");
353         }
354         
355         void OutlineMethod (MethodInfo mi)
356         {
357                 o.Write (GetMethodVisibility (mi));
358                 o.Write (GetMethodModifiers  (mi));
359                 o.Write (FormatType (mi.ReturnType));
360                 o.Write (" ");
361                 o.Write (mi.Name);
362                 o.Write (" (");
363                 OutlineParams (mi.GetParameters ());
364                 o.Write (");");
365         }
366         
367         void OutlineOperator (MethodInfo mi)
368         {
369                 o.Write (GetMethodVisibility (mi));
370                 o.Write (GetMethodModifiers  (mi));
371                 if (mi.Name == "op_Explicit" || mi.Name == "op_Implicit") {
372                         o.Write (mi.Name.Substring (3).ToLower ());
373                         o.Write (" operator ");
374                         o.Write (FormatType (mi.ReturnType));
375                 } else {
376                         o.Write (FormatType (mi.ReturnType));
377                         o.Write (" operator ");
378                         o.Write (OperatorFromName (mi.Name));
379                 }
380                 o.Write (" (");
381                 OutlineParams (mi.GetParameters ());
382                 o.Write (");");
383         }
384         
385         void OutlineParams (ParameterInfo [] pi)
386         {
387                 int i = 0;
388                 foreach (ParameterInfo p in pi) {
389                         if (p.ParameterType.IsByRef) {
390                                 o.Write (p.IsOut ? "out " : "ref ");
391                                 o.Write (FormatType (p.ParameterType.GetElementType ()));
392                         } else if (p.IsDefined (typeof (ParamArrayAttribute), false)) {
393                                 o.Write ("params ");
394                                 o.Write (FormatType (p.ParameterType));
395                         } else {
396                                 o.Write (FormatType (p.ParameterType));
397                         }
398                         
399                         o.Write (" ");
400                         o.Write (p.Name);
401                         if (i + 1 < pi.Length)
402                                 o.Write (", ");
403                         i++;
404                 }
405         }
406
407         void OutlineField (FieldInfo fi)
408         {
409                 if (fi.IsPublic)   o.Write ("public ");
410                 if (fi.IsFamily)   o.Write ("protected ");
411                 if (fi.IsPrivate)  o.Write ("private ");
412                 if (fi.IsAssembly) o.Write ("internal ");
413                 if (fi.IsLiteral)  o.Write ("const ");
414                 if (fi.IsInitOnly) o.Write ("readonly ");
415
416                 o.Write (FormatType (fi.FieldType));
417                 o.Write (" ");
418                 o.Write (fi.Name);
419                 if (fi.IsLiteral)
420                 {
421                         o.Write (" = ");
422                         o.Write (fi.GetValue (this));
423                 }
424                 o.Write (";");
425         }
426
427         static string GetMethodVisibility (MethodBase m)
428         {
429                 // itnerfaces have no modifiers here
430                 if (m.DeclaringType.IsInterface)
431                         return "";
432                 
433                 if (m.IsPublic)   return "public ";
434                 if (m.IsFamily)   return "protected ";
435                 if (m.IsPrivate)  return "private ";
436                 if (m.IsAssembly) return "internal ";
437                         
438                 return null;
439         }
440         
441         static string GetMethodModifiers (MethodBase method)
442         {
443                 if (method.IsStatic)
444                         return "static ";
445         
446                 // all interface methods are "virtual" but we don't say that in c#
447                 if (method.IsVirtual && !method.DeclaringType.IsInterface)
448                         return ((method.Attributes & MethodAttributes.NewSlot) != 0) ?
449                                 "virtual " :
450                                 "override ";
451                 
452                 return null;
453         }
454
455         static string GetTypeKind (Type t)
456         {
457                 if (t.IsEnum)
458                         return "enum";
459                 if (t.IsClass) {
460                         if (t.IsSubclassOf (typeof (System.MulticastDelegate)))
461                                 return "delegate";
462                         else
463                                 return "class";
464                 }
465                 if (t.IsInterface)
466                         return "interface";
467                 if (t.IsValueType)
468                         return "struct";
469                 return "class";
470         }
471         
472         static string GetTypeVisibility (Type t)
473         {
474                 switch (t.Attributes & TypeAttributes.VisibilityMask){
475                 case TypeAttributes.Public:
476                 case TypeAttributes.NestedPublic:
477                         return "public";
478
479                 case TypeAttributes.NestedFamily:
480                 case TypeAttributes.NestedFamANDAssem:
481                 case TypeAttributes.NestedFamORAssem:
482                         return "protected";
483
484                 default:
485                         return "internal";
486                 }
487         }
488         
489         string FormatType (Type t)
490         {
491                 string type = GetFullName (t);
492                 
493                 if (!type.StartsWith ("System.")) {
494                         if (t.Namespace == this.t.Namespace)
495                                 return t.Name;
496                         return type;
497                 }
498                 
499                 if (t.HasElementType) {
500                         Type et = t.GetElementType ();
501                         if (t.IsArray)
502                                 return FormatType (et) + " []";
503                         if (t.IsPointer)
504                                 return FormatType (et) + " *";
505                         if (t.IsByRef)
506                                 return "ref " + FormatType (et);
507                 }
508         
509                 switch (type) {
510                 case "System.Byte": return "byte";
511                 case "System.SByte": return "sbyte";
512                 case "System.Int16": return "short";
513                 case "System.Int32": return "int";
514                 case "System.Int64": return "long";
515                         
516                 case "System.UInt16": return "ushort";
517                 case "System.UInt32": return "uint";
518                 case "System.UInt64": return "ulong";
519                         
520                 case "System.Single":  return "float";
521                 case "System.Double":  return "double";
522                 case "System.Decimal": return "decimal";
523                 case "System.Boolean": return "bool";
524                 case "System.Char":    return "char";
525                 case "System.String":  return "string";
526                         
527                 case "System.Object":  return "object";
528                 case "System.Void":  return "void";
529                 }
530         
531                 if (type.LastIndexOf(".") == 6)
532                         return type.Substring(7);
533                 
534                 return type;
535         }
536
537         public static string RemoveGenericArity (string name)
538         {
539                 int start = 0;
540                 StringBuilder sb = new StringBuilder ();
541                 while (start < name.Length) {
542                         int pos = name.IndexOf ('`', start);
543                         if (pos < 0) {
544                                 sb.Append (name.Substring (start));
545                                 break;
546                         }
547                         sb.Append (name.Substring (start, pos-start));
548
549                         pos++;
550
551                         while ((pos < name.Length) && Char.IsNumber (name [pos]))
552                                 pos++;
553
554                         start = pos;
555                 }
556
557                 return sb.ToString ();
558         }
559
560         string GetTypeName (Type t)
561         {
562                 StringBuilder sb = new StringBuilder ();
563                 GetTypeName (sb, t);
564                 return sb.ToString ();
565         }
566
567         void GetTypeName (StringBuilder sb, Type t)
568         {
569                 sb.Append (RemoveGenericArity (t.Name));
570 #if NET_2_0
571                 Type[] args = t.GetGenericArguments ();
572                 if (args.Length > 0) {
573                         sb.Append ("<");
574                         for (int i = 0; i < args.Length; i++) {
575                                 if (i > 0)
576                                         sb.Append (",");
577                                 sb.Append (FormatType (args [i]));
578                         }
579                         sb.Append (">");
580                 }
581 #endif
582         }
583
584         string GetFullName (Type t)
585         {
586                 StringBuilder sb = new StringBuilder ();
587                 GetFullName_recursed (sb, t, false);
588                 return sb.ToString ();
589         }
590
591         void GetFullName_recursed (StringBuilder sb, Type t, bool recursed)
592         {
593 #if NET_2_0
594                 if (t.IsGenericParameter) {
595                         sb.Append (t.Name);
596                         return;
597                 }
598 #endif
599
600                 if (t.DeclaringType != null) {
601                         GetFullName_recursed (sb, t.DeclaringType, true);
602                         sb.Append (".");
603                 }
604
605                 if (!recursed) {
606                         string ns = t.Namespace;
607                         if ((ns != null) && (ns != "")) {
608                                 sb.Append (ns);
609                                 sb.Append (".");
610                         }
611                 }
612
613                 GetTypeName (sb, t);
614         }
615
616         string OperatorFromName (string name)
617         {
618                 switch (name) {
619                 case "op_UnaryPlus": return "+";
620                 case "op_UnaryNegation": return "-";
621                 case "op_LogicalNot": return "!";
622                 case "op_OnesComplement": return "~";
623                 case "op_Increment": return "++";
624                 case "op_Decrement": return "--";
625                 case "op_True": return "true";
626                 case "op_False": return "false";
627                 case "op_Addition": return "+";
628                 case "op_Subtraction": return "-";
629                 case "op_Multiply": return "*";
630                 case "op_Division": return "/";
631                 case "op_Modulus": return "%";
632                 case "op_BitwiseAnd": return "&";
633                 case "op_BitwiseOr": return "|";
634                 case "op_ExclusiveOr": return "^";
635                 case "op_LeftShift": return "<<";
636                 case "op_RightShift": return ">>";
637                 case "op_Equality": return "==";
638                 case "op_Inequality": return "!=";
639                 case "op_GreaterThan": return ">";
640                 case "op_LessThan": return "<";
641                 case "op_GreaterThanOrEqual": return ">=";
642                 case "op_LessThanOrEqual": return "<=";
643                 default: return name;
644                 }
645         }
646         
647         bool ShowMember (MemberInfo mi)
648         {
649                 if (mi.MemberType == MemberTypes.Constructor && ((MethodBase) mi).IsStatic)
650                         return false;
651                 
652                 if (options.ShowPrivate)
653                         return true;
654                 
655                 switch (mi.MemberType) {
656                 case MemberTypes.Constructor:
657                 case MemberTypes.Method:
658                         MethodBase mb = mi as MethodBase;
659                 
660                         if (mb.IsFamily || mb.IsPublic || mb.IsFamilyOrAssembly)
661                                 return true;
662                         
663                         return false;
664                 
665                 
666                 case MemberTypes.Field:
667                         FieldInfo fi = mi as FieldInfo;
668                 
669                         if (fi.IsFamily || fi.IsPublic || fi.IsFamilyOrAssembly)
670                                 return true;
671                         
672                         return false;
673                 
674                 
675                 case MemberTypes.NestedType:
676                 case MemberTypes.TypeInfo:
677                         Type t = mi as Type;
678                 
679                         switch (t.Attributes & TypeAttributes.VisibilityMask){
680                         case TypeAttributes.Public:
681                         case TypeAttributes.NestedPublic:
682                         case TypeAttributes.NestedFamily:
683                         case TypeAttributes.NestedFamORAssem:
684                                 return true;
685                         }
686                         
687                         return false;
688                 }
689                 
690                 // What am I !!!
691                 return true;
692         }
693 }
694
695 public class Comparer : IComparer  {
696         delegate int ComparerFunc (object a, object b);
697         
698         ComparerFunc cmp;
699         
700         Comparer (ComparerFunc f)
701         {
702                 this.cmp = f;
703         }
704         
705         public int Compare (object a, object b)
706         {
707                 return cmp (a, b);
708         }
709
710         static int CompareType (object a, object b)
711         {
712                 Type type1 = (Type) a;
713                 Type type2 = (Type) b;
714
715                 if (type1.IsSubclassOf (typeof (System.MulticastDelegate)) != type2.IsSubclassOf (typeof (System.MulticastDelegate)))
716                                 return (type1.IsSubclassOf (typeof (System.MulticastDelegate)))? -1:1;
717                 return string.Compare (type1.Name, type2.Name);
718                         
719         }
720
721         static Comparer TypeComparer = new Comparer (new ComparerFunc (CompareType));
722
723         static Type [] Sort (Type [] types)
724         {
725                 Array.Sort (types, TypeComparer);
726                 return types;
727         }
728         
729         static int CompareMemberInfo (object a, object b)
730         {
731                 return string.Compare (((MemberInfo) a).Name, ((MemberInfo) b).Name);
732         }
733         
734         static Comparer MemberInfoComparer = new Comparer (new ComparerFunc (CompareMemberInfo));
735         
736         public static MemberInfo [] Sort (MemberInfo [] inf)
737         {
738                 Array.Sort (inf, MemberInfoComparer);
739                 return inf;
740         }
741         
742         static int CompareMethodBase (object a, object b)
743         {
744                 MethodBase aa = (MethodBase) a, bb = (MethodBase) b;
745                 
746                 if (aa.IsStatic == bb.IsStatic)
747                         return CompareMemberInfo (a, b);
748                 
749                 if (aa.IsStatic)
750                         return -1;
751                 
752                 return 1;
753         }
754         
755         static Comparer MethodBaseComparer = new Comparer (new ComparerFunc (CompareMethodBase));
756         
757         public static MethodBase [] Sort (MethodBase [] inf)
758         {
759                 Array.Sort (inf, MethodBaseComparer);
760                 return inf;
761         }
762         
763         static int ComparePropertyInfo (object a, object b)
764         {
765                 PropertyInfo aa = (PropertyInfo) a, bb = (PropertyInfo) b;
766                 
767                 bool astatic = (aa.CanRead ? aa.GetGetMethod (true) : aa.GetSetMethod (true)).IsStatic;
768                 bool bstatic = (bb.CanRead ? bb.GetGetMethod (true) : bb.GetSetMethod (true)).IsStatic;
769                 
770                 if (astatic == bstatic)
771                         return CompareMemberInfo (a, b);
772                 
773                 if (astatic)
774                         return -1;
775                 
776                 return 1;
777         }
778         
779         static Comparer PropertyInfoComparer = new Comparer (new ComparerFunc (ComparePropertyInfo));
780         
781         public static PropertyInfo [] Sort (PropertyInfo [] inf)
782         {
783                 Array.Sort (inf, PropertyInfoComparer);
784                 return inf;
785         }
786         
787         static int CompareEventInfo (object a, object b)
788         {
789                 EventInfo aa = (EventInfo) a, bb = (EventInfo) b;
790                 
791                 bool astatic = aa.GetAddMethod (true).IsStatic;
792                 bool bstatic = bb.GetAddMethod (true).IsStatic;
793                 
794                 if (astatic == bstatic)
795                         return CompareMemberInfo (a, b);
796                 
797                 if (astatic)
798                         return -1;
799                 
800                 return 1;
801         }
802         
803         static Comparer EventInfoComparer = new Comparer (new ComparerFunc (CompareEventInfo));
804         
805         public static EventInfo [] Sort (EventInfo [] inf)
806         {
807                 Array.Sort (inf, EventInfoComparer);
808                 return inf;
809         }
810 }