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