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