importing messaging-2008 branch to trunk, going on.
[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 namespace Mono.CSharp {
40 public class Outline {
41
42         bool declared_only;
43         bool show_private;
44         bool filter_obsolete;
45         
46         IndentedTextWriter o;
47         Type t;
48         
49         public Outline (Type t, TextWriter output, bool declared_only, bool show_private, bool filter_obsolete)
50         {
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;
56         }
57
58         public void OutlineType ()
59         {
60                 bool first;
61                 
62                 OutlineAttributes ();
63                 o.Write (GetTypeVisibility (t));
64                 
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");
70                 }
71                 
72                 o.Write (" ");
73                 o.Write (GetTypeKind (t));
74                 o.Write (" ");
75                 
76                 Type [] interfaces = (Type []) Comparer.Sort (TypeGetInterfaces (t, declared_only));
77                 Type parent = t.BaseType;
78
79                 if (t.IsSubclassOf (typeof (System.MulticastDelegate))) {
80                         MethodInfo method;
81
82                         method = t.GetMethod ("Invoke");
83
84                         o.Write (FormatType (method.ReturnType));
85                         o.Write (" ");
86                         o.Write (GetTypeName (t));
87                         o.Write (" (");
88                         OutlineParams (method.GetParameters ());
89                         o.Write (")");
90
91 #if NET_2_0
92                         WriteGenericConstraints (t.GetGenericArguments ());
93 #endif                  
94         
95                         o.WriteLine (";"); 
96                         return;
97                 }
98                 
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 (" : ");
103                         
104                         if (parent != null && parent != typeof (object) && parent != typeof (ValueType)) {
105                                 o.Write (FormatType (parent));
106                                 first = false;
107                         }
108                         
109                         foreach (Type intf in interfaces) {
110                                 if (!first) o.Write (", ");
111                                 first = false;
112                                 
113                                 o.Write (FormatType (intf));
114                         }
115                 }
116
117                 if (t.IsEnum) {
118                         Type underlyingType = System.Enum.GetUnderlyingType (t);
119                         if (underlyingType != typeof (int))
120                                 o.Write (" : {0}", FormatType (underlyingType));
121                 }
122 #if NET_2_0
123                 WriteGenericConstraints (t.GetGenericArguments ());
124 #endif          
125                 o.WriteLine (" {");
126                 o.Indent++;
127
128                 if (t.IsEnum) {
129                         bool is_first = true;
130                         foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Static)) {
131                                 
132                                 if (! is_first)
133                                         o.WriteLine (",");
134                                 is_first = false;
135                                 o.Write (fi.Name);
136                         }
137                         o.WriteLine ();
138                         o.Indent--; o.WriteLine ("}");
139                         return;
140                 }
141                 
142                 first = true;
143                 
144                 foreach (ConstructorInfo ci in t.GetConstructors (DefaultFlags)) {
145                         
146                         if (! ShowMember (ci))
147                                 continue;
148                         
149                         if (first)
150                                 o.WriteLine ();
151                         first = false;
152                         
153                         OutlineConstructor (ci);
154                         
155                         o.WriteLine ();
156                 }
157                 
158
159                 first = true;
160                 
161                 foreach (MethodInfo m in Comparer.Sort (t.GetMethods (DefaultFlags))) {
162                         
163                         if (! ShowMember (m))
164                                 continue;               
165                         
166                         if ((m.Attributes & MethodAttributes.SpecialName) != 0)
167                                 continue;
168                         
169                         if (first)
170                                 o.WriteLine ();
171                         first = false;
172                         
173                         OutlineMethod (m);
174                         
175                         o.WriteLine ();
176                 }
177                 
178                 first = true;
179                 
180                 foreach (MethodInfo m in t.GetMethods (DefaultFlags)) {
181                         
182                         if (! ShowMember (m))
183                                 continue;
184                         
185                         if ((m.Attributes & MethodAttributes.SpecialName) == 0)
186                                 continue;
187                         if (!(m.Name.StartsWith ("op_")))
188                                 continue;
189
190                         if (first)
191                                 o.WriteLine ();
192                         first = false;
193                         
194                         OutlineOperator (m);
195                         
196                         o.WriteLine ();
197                 }
198
199                 first = true;
200                 
201                 foreach (PropertyInfo pi in Comparer.Sort (t.GetProperties (DefaultFlags))) {
202                         
203                         if (! ((pi.CanRead  && ShowMember (pi.GetGetMethod (true))) ||
204                                (pi.CanWrite && ShowMember (pi.GetSetMethod (true)))))
205                                 continue;
206                         
207                         if (first)
208                                 o.WriteLine ();
209                         first = false;
210                         
211                         OutlineProperty (pi);
212                         
213                         o.WriteLine ();
214                 }
215                 
216                 first = true;
217
218                 foreach (FieldInfo fi in t.GetFields (DefaultFlags)) {
219                         
220                         if (! ShowMember (fi))
221                                 continue;
222                         
223                         if (first)
224                                 o.WriteLine ();
225                         first = false;
226                         
227                         OutlineField (fi);
228                         
229                         o.WriteLine ();
230                 }
231
232                 first = true;
233                 
234                 foreach (EventInfo ei in Comparer.Sort (t.GetEvents (DefaultFlags))) {
235                         
236                         if (! ShowMember (ei.GetAddMethod (true)))
237                                 continue;
238                         
239                         if (first)
240                                 o.WriteLine ();
241                         first = false;
242                         
243                         OutlineEvent (ei);
244                         
245                         o.WriteLine ();
246                 }
247
248                 first = true;
249
250                 foreach (Type ntype in Comparer.Sort (t.GetNestedTypes (DefaultFlags))) {
251                         
252                         if (! ShowMember (ntype))
253                                 continue;
254                         
255                         if (first)
256                                 o.WriteLine ();
257                         first = false;
258                         
259                         new Outline (ntype, o, declared_only, show_private, filter_obsolete).OutlineType ();
260                 }
261                 
262                 o.Indent--; o.WriteLine ("}");
263         }
264         
265         BindingFlags DefaultFlags {
266                 get {
267                         BindingFlags f = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
268                         
269                         if (declared_only)
270                                 f |= BindingFlags.DeclaredOnly;
271                         
272                         return f;
273                 }
274         }
275
276         // FIXME: add other interesting attributes?
277         void OutlineAttributes ()
278         {
279                 if (t.IsSerializable)
280                         o.WriteLine ("[Serializable]");
281
282                 if (t.IsDefined (typeof (System.FlagsAttribute), true))
283                         o.WriteLine ("[Flags]");
284
285                 if (t.IsDefined (typeof (System.ObsoleteAttribute), true))
286                         o.WriteLine ("[Obsolete]");
287         }
288
289         void OutlineEvent (EventInfo ei)
290         {
291                 MethodBase accessor = ei.GetAddMethod (true);
292                 
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 (";");
299         }
300         
301         void OutlineConstructor (ConstructorInfo ci)
302         {
303                 o.Write (GetMethodVisibility (ci));
304                 o.Write (RemoveGenericArity (t.Name));
305                 o.Write (" (");
306                 OutlineParams (ci.GetParameters ());
307                 o.Write (");");
308         }
309         
310         
311         void OutlineProperty (PropertyInfo pi)
312         {
313                 ParameterInfo [] idxp = pi.GetIndexParameters ();
314                 MethodBase g = pi.GetGetMethod (true);
315                 MethodBase s = pi.GetSetMethod (true);
316                 MethodBase accessor = g != null ? g : s;
317                 
318                 if (pi.CanRead && pi.CanWrite) {
319
320                         
321                         // Get the more accessible accessor
322                         if ((g.Attributes & MethodAttributes.MemberAccessMask) !=
323                             (s.Attributes & MethodAttributes.MemberAccessMask)) {
324                                 
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;
331                         }
332                 }
333                 
334                 o.Write (GetMethodVisibility (accessor));
335                 o.Write (GetMethodModifiers  (accessor));
336                 o.Write (FormatType (pi.PropertyType));
337                 o.Write (" ");
338                 
339                 if (idxp.Length == 0)
340                         o.Write (pi.Name);
341                 else {
342                         o.Write ("this [");
343                         OutlineParams (idxp);
344                         o.Write ("]");
345                 }
346                 
347                 o.WriteLine (" {");
348                 o.Indent ++;
349                 
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;");
355                 }
356                 
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;");
362                 }
363                 
364                 o.Indent --;
365                 o.Write ("}");
366         }
367         
368         void OutlineMethod (MethodInfo mi)
369         {
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 (" ");
382                 }
383
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 (";");
395         }
396         
397         void OutlineOperator (MethodInfo mi)
398         {
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));
409                 }
410                 o.Write (" (");
411                 OutlineParams (mi.GetParameters ());
412                 o.Write (");");
413         }
414         
415         void OutlineParams (ParameterInfo [] pi)
416         {
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));
427                         }
428                         
429                         o.Write (" ");
430                         o.Write (p.Name);
431                         if (i + 1 < pi.Length)
432                                 o.Write (", ");
433                         i++;
434                 }
435         }
436
437         void OutlineField (FieldInfo fi)
438         {
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 ");
446
447                 o.Write (FormatType (fi.FieldType));
448                 o.Write (" ");
449                 o.Write (fi.Name);
450                 if (fi.IsLiteral) { 
451                         object v = fi.GetValue (this);
452
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));
461                 }
462                 o.Write (";");
463         }
464
465         static string GetMethodVisibility (MethodBase m)
466         {
467                 // itnerfaces have no modifiers here
468                 if (m.DeclaringType.IsInterface)
469                         return "";
470                 
471                 if (m.IsPublic)   return "public ";
472                 if (m.IsFamily)   return "protected ";
473                 if (m.IsPrivate)  return "private ";
474                 if (m.IsAssembly) return "internal ";
475                         
476                 return null;
477         }
478         
479         static string GetMethodModifiers (MethodBase method)
480         {
481                 if (method.IsStatic)
482                         return "static ";
483
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                         // }
493                         //
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
499
500                         if (method.IsVirtual)
501                                 return null;
502                         return "sealed ";
503                 }
504                 
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 ";
509
510                         return ((method.Attributes & MethodAttributes.NewSlot) != 0) ?
511                                 "virtual " :
512                                 "override ";    
513                 }
514                                 
515                 return null;
516         }
517
518         static string GetTypeKind (Type t)
519         {
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";
527                 }
528                 if (t.IsInterface)
529                         return "interface";
530                 if (t.IsValueType)
531                         return "struct";
532                 return "class";
533         }
534         
535         static string GetTypeVisibility (Type t)
536         {
537                 switch (t.Attributes & TypeAttributes.VisibilityMask){
538                 case TypeAttributes.Public:
539                 case TypeAttributes.NestedPublic:
540                         return "public";
541
542                 case TypeAttributes.NestedFamily:
543                 case TypeAttributes.NestedFamANDAssem:
544                 case TypeAttributes.NestedFamORAssem:
545                         return "protected";
546
547                 default:
548                         return "internal";
549                 }
550         }
551
552 #if NET_2_0
553         string FormatGenericParams (Type [] args)
554         {
555                 StringBuilder sb = new StringBuilder ();
556                 if (args.Length == 0)
557                         return "";
558                 
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]));
564                 }
565                 sb.Append (">");
566                 return sb.ToString ();
567         }
568 #endif
569
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)
573         {
574                 string type = GetFullName (t);
575                 
576                 if (!type.StartsWith ("System.")) {
577                         if (t.Namespace == this.t.Namespace)
578                                 return t.Name;
579                         return type;
580                 }
581                 
582                 if (t.HasElementType) {
583                         Type et = t.GetElementType ();
584                         if (t.IsArray)
585                                 return FormatType (et) + " []";
586                         if (t.IsPointer)
587                                 return FormatType (et) + " *";
588                         if (t.IsByRef)
589                                 return "ref " + FormatType (et);
590                 }
591         
592                 switch (type) {
593                 case "System.Byte": return "byte";
594                 case "System.SByte": return "sbyte";
595                 case "System.Int16": return "short";
596                 case "System.Int32": return "int";
597                 case "System.Int64": return "long";
598                         
599                 case "System.UInt16": return "ushort";
600                 case "System.UInt32": return "uint";
601                 case "System.UInt64": return "ulong";
602                         
603                 case "System.Single":  return "float";
604                 case "System.Double":  return "double";
605                 case "System.Decimal": return "decimal";
606                 case "System.Boolean": return "bool";
607                 case "System.Char":    return "char";
608                 case "System.String":  return "string";
609                         
610                 case "System.Object":  return "object";
611                 case "System.Void":  return "void";
612                 }
613         
614                 if (type.LastIndexOf(".") == 6)
615                         return type.Substring(7);
616
617                 //
618                 // If the namespace of the type is the namespace of what
619                 // we are printing (or is a member of one if its children
620                 // don't print it. This basically means that in C# we would
621                 // automatically get the namespace imported by virtue of the
622                 // namespace {} block.
623                 //      
624                 if (this.t.Namespace.StartsWith (t.Namespace + ".") || t.Namespace == this.t.Namespace)
625                         return type.Substring (t.Namespace.Length + 1);
626         
627                 return type;
628         }
629
630         public static string RemoveGenericArity (string name)
631         {
632                 int start = 0;
633                 StringBuilder sb = new StringBuilder ();
634                 while (start < name.Length) {
635                         int pos = name.IndexOf ('`', start);
636                         if (pos < 0) {
637                                 sb.Append (name.Substring (start));
638                                 break;
639                         }
640                         sb.Append (name.Substring (start, pos-start));
641
642                         pos++;
643
644                         while ((pos < name.Length) && Char.IsNumber (name [pos]))
645                                 pos++;
646
647                         start = pos;
648                 }
649
650                 return sb.ToString ();
651         }
652
653         string GetTypeName (Type t)
654         {
655                 StringBuilder sb = new StringBuilder ();
656                 GetTypeName (sb, t);
657                 return sb.ToString ();
658         }
659
660         void GetTypeName (StringBuilder sb, Type t)
661         {
662                 sb.Append (RemoveGenericArity (t.Name));
663 #if NET_2_0
664                 sb.Append (FormatGenericParams (t.GetGenericArguments ()));
665 #endif
666         }
667
668         string GetFullName (Type t)
669         {
670                 StringBuilder sb = new StringBuilder ();
671                 GetFullName_recursed (sb, t, false);
672                 return sb.ToString ();
673         }
674
675         void GetFullName_recursed (StringBuilder sb, Type t, bool recursed)
676         {
677 #if NET_2_0
678                 if (t.IsGenericParameter) {
679                         sb.Append (t.Name);
680                         return;
681                 }
682 #endif
683
684                 if (t.DeclaringType != null) {
685                         GetFullName_recursed (sb, t.DeclaringType, true);
686                         sb.Append (".");
687                 }
688
689                 if (!recursed) {
690                         string ns = t.Namespace;
691                         if ((ns != null) && (ns != "")) {
692                                 sb.Append (ns);
693                                 sb.Append (".");
694                         }
695                 }
696
697                 GetTypeName (sb, t);
698         }
699
700 #if NET_2_0
701         void WriteGenericConstraints (Type [] args)
702         {
703
704                 foreach (Type t in args) {
705                         bool first = true;
706                         Type[] ifaces = TypeGetInterfaces (t, true);
707                         
708                         GenericParameterAttributes attrs = t.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
709                         GenericParameterAttributes [] interesting = {
710                                 GenericParameterAttributes.ReferenceTypeConstraint,
711                                 GenericParameterAttributes.NotNullableValueTypeConstraint,
712                                 GenericParameterAttributes.DefaultConstructorConstraint
713                         };
714                         
715                         if (t.BaseType != typeof (object) || ifaces.Length != 0 || attrs != 0) {
716                                 o.Write (" where ");
717                                 o.Write (FormatType (t));
718                                 o.Write (" : ");
719                         }
720
721                         if (t.BaseType != typeof (object)) {
722                                 o.Write (FormatType (t.BaseType));
723                                 first = false;
724                         }
725
726                         foreach (Type iface in ifaces) {
727                                 if (!first)
728                                         o.Write (", ");
729                                 first = false;
730                                 
731                                 o.Write (FormatType (iface));
732                         }
733
734                         foreach (GenericParameterAttributes a in interesting) {
735                                 if ((attrs & a) == 0)
736                                         continue;
737                                 
738                                 if (!first)
739                                         o.Write (", ");
740                                 first = false;
741                                 
742                                 switch (a) {
743                                 case GenericParameterAttributes.ReferenceTypeConstraint:
744                                         o.Write ("class");
745                                         break;
746                                 case GenericParameterAttributes.NotNullableValueTypeConstraint:
747                                         o.Write ("struct");
748                                         break;
749                                 case GenericParameterAttributes.DefaultConstructorConstraint:
750                                         o.Write ("new ()");
751                                         break;
752                                 }
753                         }
754                 }
755         }
756 #endif
757  
758         string OperatorFromName (string name)
759         {
760                 switch (name) {
761                 case "op_UnaryPlus": return "+";
762                 case "op_UnaryNegation": return "-";
763                 case "op_LogicalNot": return "!";
764                 case "op_OnesComplement": return "~";
765                 case "op_Increment": return "++";
766                 case "op_Decrement": return "--";
767                 case "op_True": return "true";
768                 case "op_False": return "false";
769                 case "op_Addition": return "+";
770                 case "op_Subtraction": return "-";
771                 case "op_Multiply": return "*";
772                 case "op_Division": return "/";
773                 case "op_Modulus": return "%";
774                 case "op_BitwiseAnd": return "&";
775                 case "op_BitwiseOr": return "|";
776                 case "op_ExclusiveOr": return "^";
777                 case "op_LeftShift": return "<<";
778                 case "op_RightShift": return ">>";
779                 case "op_Equality": return "==";
780                 case "op_Inequality": return "!=";
781                 case "op_GreaterThan": return ">";
782                 case "op_LessThan": return "<";
783                 case "op_GreaterThanOrEqual": return ">=";
784                 case "op_LessThanOrEqual": return "<=";
785                 default: return name;
786                 }
787         }
788
789         bool MethodIsExplicitIfaceImpl (MethodBase mb)
790         {
791                 if (!(mb.IsFinal && mb.IsVirtual && mb.IsPrivate))
792                         return false;
793                 
794                 // UGH msft has no way to get the info about what method is
795                 // getting overriden. Another reason to use cecil :-)
796                 //
797                 //MethodInfo mi = mb as MethodInfo;
798                 //if (mi == null)
799                 //      return false;
800                 //
801                 //Console.WriteLine (mi.GetBaseDefinition ().DeclaringType);
802                 //return mi.GetBaseDefinition ().DeclaringType.IsInterface;
803                 
804                 // So, we guess that virtual final private methods only come
805                 // from ifaces :-)
806                 return true;
807         }
808         
809         bool ShowMember (MemberInfo mi)
810         {
811                 if (mi.MemberType == MemberTypes.Constructor && ((MethodBase) mi).IsStatic)
812                         return false;
813                 
814                 if (show_private)
815                         return true;
816
817                 if (filter_obsolete && mi.IsDefined (typeof (ObsoleteAttribute), false))
818                         return false;
819                 
820                 switch (mi.MemberType) {
821                 case MemberTypes.Constructor:
822                 case MemberTypes.Method:
823                         MethodBase mb = mi as MethodBase;
824                 
825                         if (mb.IsFamily || mb.IsPublic || mb.IsFamilyOrAssembly)
826                                 return true;
827                         
828                         if (MethodIsExplicitIfaceImpl (mb))
829                                 return true;
830                                         
831                         return false;
832                 
833                 
834                 case MemberTypes.Field:
835                         FieldInfo fi = mi as FieldInfo;
836                 
837                         if (fi.IsFamily || fi.IsPublic || fi.IsFamilyOrAssembly)
838                                 return true;
839                         
840                         return false;
841                 
842                 
843                 case MemberTypes.NestedType:
844                 case MemberTypes.TypeInfo:
845                         Type t = mi as Type;
846                 
847                         switch (t.Attributes & TypeAttributes.VisibilityMask){
848                         case TypeAttributes.Public:
849                         case TypeAttributes.NestedPublic:
850                         case TypeAttributes.NestedFamily:
851                         case TypeAttributes.NestedFamORAssem:
852                                 return true;
853                         }
854                         
855                         return false;
856                 }
857                 
858                 // What am I !!!
859                 return true;
860         }
861
862         static Type [] TypeGetInterfaces (Type t, bool declonly)
863         {
864                 Type [] ifaces = t.GetInterfaces ();
865                 if (! declonly)
866                         return ifaces;
867
868                 // Handle Object. Also, optimize for no interfaces
869                 if (t.BaseType == null || ifaces.Length == 0)
870                         return ifaces;
871
872                 ArrayList ar = new ArrayList ();
873
874                 foreach (Type i in ifaces)
875                         if (! i.IsAssignableFrom (t.BaseType))
876                                 ar.Add (i);
877
878                 return (Type []) ar.ToArray (typeof (Type));
879         }
880 }
881
882 public class Comparer : IComparer  {
883         delegate int ComparerFunc (object a, object b);
884         
885         ComparerFunc cmp;
886         
887         Comparer (ComparerFunc f)
888         {
889                 this.cmp = f;
890         }
891         
892         public int Compare (object a, object b)
893         {
894                 return cmp (a, b);
895         }
896
897         static int CompareType (object a, object b)
898         {
899                 Type type1 = (Type) a;
900                 Type type2 = (Type) b;
901
902                 if (type1.IsSubclassOf (typeof (System.MulticastDelegate)) != type2.IsSubclassOf (typeof (System.MulticastDelegate)))
903                                 return (type1.IsSubclassOf (typeof (System.MulticastDelegate)))? -1:1;
904                 return string.Compare (type1.Name, type2.Name);
905                         
906         }
907
908 //      static Comparer TypeComparer = new Comparer (new ComparerFunc (CompareType));
909
910 //      static Type [] Sort (Type [] types)
911 //      {
912 //              Array.Sort (types, TypeComparer);
913 //              return types;
914 //      }
915         
916         static int CompareMemberInfo (object a, object b)
917         {
918                 return string.Compare (((MemberInfo) a).Name, ((MemberInfo) b).Name);
919         }
920         
921         static Comparer MemberInfoComparer = new Comparer (new ComparerFunc (CompareMemberInfo));
922         
923         public static MemberInfo [] Sort (MemberInfo [] inf)
924         {
925                 Array.Sort (inf, MemberInfoComparer);
926                 return inf;
927         }
928         
929         static int CompareMethodBase (object a, object b)
930         {
931                 MethodBase aa = (MethodBase) a, bb = (MethodBase) b;
932                 
933                 if (aa.IsStatic == bb.IsStatic) {
934                         int c = CompareMemberInfo (a, b);
935                         if (c != 0)
936                                 return c;
937                         ParameterInfo [] ap, bp;
938
939                         //
940                         // Sort overloads by the names of their types
941                         // put methods with fewer params first.
942                         //
943                         
944                         ap = aa.GetParameters ();
945                         bp = bb.GetParameters ();
946                         int n = System.Math.Min (ap.Length, bp.Length);
947
948                         for (int i = 0; i < n; i ++)
949                                 if ((c = CompareType (ap [i].ParameterType, bp [i].ParameterType)) != 0)
950                                         return c;
951
952                         return ap.Length.CompareTo (bp.Length);
953                 }
954                 if (aa.IsStatic)
955                         return -1;
956                 
957                 return 1;
958         }
959         
960         static Comparer MethodBaseComparer = new Comparer (new ComparerFunc (CompareMethodBase));
961         
962         public static MethodBase [] Sort (MethodBase [] inf)
963         {
964                 Array.Sort (inf, MethodBaseComparer);
965                 return inf;
966         }
967         
968         static int ComparePropertyInfo (object a, object b)
969         {
970                 PropertyInfo aa = (PropertyInfo) a, bb = (PropertyInfo) b;
971                 
972                 bool astatic = (aa.CanRead ? aa.GetGetMethod (true) : aa.GetSetMethod (true)).IsStatic;
973                 bool bstatic = (bb.CanRead ? bb.GetGetMethod (true) : bb.GetSetMethod (true)).IsStatic;
974                 
975                 if (astatic == bstatic)
976                         return CompareMemberInfo (a, b);
977                 
978                 if (astatic)
979                         return -1;
980                 
981                 return 1;
982         }
983         
984         static Comparer PropertyInfoComparer = new Comparer (new ComparerFunc (ComparePropertyInfo));
985         
986         public static PropertyInfo [] Sort (PropertyInfo [] inf)
987         {
988                 Array.Sort (inf, PropertyInfoComparer);
989                 return inf;
990         }
991         
992         static int CompareEventInfo (object a, object b)
993         {
994                 EventInfo aa = (EventInfo) a, bb = (EventInfo) b;
995                 
996                 bool astatic = aa.GetAddMethod (true).IsStatic;
997                 bool bstatic = bb.GetAddMethod (true).IsStatic;
998                 
999                 if (astatic == bstatic)
1000                         return CompareMemberInfo (a, b);
1001                 
1002                 if (astatic)
1003                         return -1;
1004                 
1005                 return 1;
1006         }
1007         
1008         static Comparer EventInfoComparer = new Comparer (new ComparerFunc (CompareEventInfo));
1009         
1010         public static EventInfo [] Sort (EventInfo [] inf)
1011         {
1012                 Array.Sort (inf, EventInfoComparer);
1013                 return inf;
1014         }
1015 }
1016 }