merge
[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 using System;
12 using System.Reflection;
13 using System.Collections;
14 using System.CodeDom.Compiler;
15 using System.IO;
16         
17 public class Outline {
18         
19         IndentedTextWriter o;
20         Type t;
21         
22         public Outline (Type t, TextWriter output)
23         {
24                 this.t = t;
25                 this.o = new IndentedTextWriter (output, "    ");
26         }
27
28         public void OutlineType (BindingFlags flags)
29         {
30                 bool first;
31                 
32                 OutlineAttributes ();
33                 o.Write (GetTypeVisibility (t));
34                 
35                 if (t.IsClass && !t.IsSubclassOf (typeof (System.MulticastDelegate))) {
36                         if (t.IsSealed)
37                                 o.Write (t.IsAbstract ? " static" : " sealed");
38                         else if (t.IsAbstract)
39                                 o.Write (" abstract");
40                 }
41                 
42                 o.Write (" ");
43                 o.Write (GetTypeKind (t));
44                 o.Write (" ");
45                 
46                 Type [] interfaces = (Type []) Comparer.Sort (t.GetInterfaces ());
47                 Type parent = t.BaseType;
48
49                 if (t.IsSubclassOf (typeof (System.MulticastDelegate))) {
50                         MethodInfo method;
51
52                         method = t.GetMethod ("Invoke");
53
54                         o.Write (FormatType (method.ReturnType));
55                         o.Write (" ");
56                         o.Write (t.Name);
57                         o.Write (" (");
58                         OutlineParams (method.GetParameters ());
59                         o.WriteLine (");");
60
61                         return;
62                 }
63                 
64                 o.Write (t.Name);
65                 if (((parent != null && parent != typeof (object) && parent != typeof (ValueType)) || interfaces.Length != 0) && ! t.IsEnum) {
66                         first = true;
67                         o.Write (" : ");
68                         
69                         if (parent != null && parent != typeof (object) && parent != typeof (ValueType)) {
70                                 o.Write (FormatType (parent));
71                                 first = false;
72                         }
73                         
74                         foreach (Type intf in interfaces) {
75                                 if (!first) o.Write (", ");
76                                 first = false;
77                                 
78                                 o.Write (FormatType (intf));
79                         }
80                 }
81                 
82                 o.WriteLine (" {");
83                 o.Indent++;
84
85                 if (t.IsEnum) {
86                         bool is_first = true;
87                         foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Static)) {
88                                 
89                                 if (! is_first)
90                                         o.WriteLine (",");
91                                 is_first = false;
92                                 o.Write (fi.Name);
93                         }
94                         o.WriteLine ();
95                         o.Indent--; o.WriteLine ("}");
96                         return;
97                 }
98                 
99                 first = true;
100                 
101                 foreach (ConstructorInfo ci in t.GetConstructors (flags)) {
102                         if (first)
103                                 o.WriteLine ();
104                         first = false;
105                         
106                         OutlineConstructor (ci);
107                         
108                         o.WriteLine ();
109                 }
110                 
111
112                 first = true;
113                 
114                 foreach (MethodInfo m in Comparer.Sort (t.GetMethods (flags))) {
115                         if ((m.Attributes & MethodAttributes.SpecialName) != 0)
116                                 continue;
117                         
118                         if (first)
119                                 o.WriteLine ();
120                         first = false;
121                         
122                         OutlineMethod (m);
123                         
124                         o.WriteLine ();
125                 }
126                 
127                 first = true;
128                 
129                 foreach (PropertyInfo pi in Comparer.Sort (t.GetProperties (flags))) {
130                         
131                         if (first)
132                                 o.WriteLine ();
133                         first = false;
134                         
135                         OutlineProperty (pi);
136                         
137                         o.WriteLine ();
138                 }
139                 
140                 first = true;
141
142                 foreach (FieldInfo fi in t.GetFields (flags)) {
143                         
144                         if (first)
145                                 o.WriteLine ();
146                         first = false;
147                         
148                         OutlineField (fi);
149                         
150                         o.WriteLine ();
151                 }
152
153                 first = true;
154                 
155                 foreach (EventInfo ei in Comparer.Sort (t.GetEvents (flags))) {
156                         
157                         if (first)
158                                 o.WriteLine ();
159                         first = false;
160                         
161                         OutlineEvent (ei);
162                         
163                         o.WriteLine ();
164                 }
165
166                 first = true;
167
168                 foreach (Type ntype in Comparer.Sort (t.GetNestedTypes (flags))) {
169                         
170                         if (first)
171                                 o.WriteLine ();
172                         first = false;
173                         
174                         new Outline (ntype, o).OutlineType (flags);
175                 }
176                 
177                 o.Indent--; o.WriteLine ("}");
178         }
179
180         // FIXME: add other interesting attributes?
181         void OutlineAttributes ()
182         {
183                 if (t.IsSerializable)
184                         o.WriteLine ("[Serializable]");
185
186                 if (t.IsDefined (typeof (System.FlagsAttribute), true))
187                         o.WriteLine ("[Flags]");
188
189                 if (t.IsDefined (typeof (System.ObsoleteAttribute), true))
190                         o.WriteLine ("[Obsolete]");
191         }
192
193         void OutlineEvent (EventInfo ei)
194         {
195                 MethodBase accessor = ei.GetAddMethod ();
196                 
197                 o.Write (GetMethodVisibility (accessor));
198                 o.Write ("event ");
199                 o.Write (FormatType (ei.EventHandlerType));
200                 o.Write (" ");
201                 o.Write (ei.Name);
202                 o.Write (";");
203         }
204         
205         void OutlineConstructor (ConstructorInfo ci)
206         {
207                 o.Write (GetMethodVisibility (ci));
208                 o.Write (t.Name);
209                 o.Write (" (");
210                 OutlineParams (ci.GetParameters ());
211                 o.Write (");");
212         }
213         
214         
215         void OutlineProperty (PropertyInfo pi)
216         {
217                 ParameterInfo [] idxp = pi.GetIndexParameters ();
218                 MethodBase accessor = pi.CanRead ? pi.GetGetMethod (true) : pi.GetSetMethod (true);
219                 
220                 o.Write (GetMethodVisibility (accessor));
221                 o.Write (GetMethodModifiers  (accessor));
222                 o.Write (FormatType (pi.PropertyType));
223                 o.Write (" ");
224                 
225                 if (idxp.Length == 0)
226                         o.Write (pi.Name);
227                 else {
228                         o.Write ("this [");
229                         OutlineParams (idxp);
230                         o.Write ("]");
231                 }
232                 
233                 o.WriteLine (" {");
234                 o.Indent ++;
235                 
236                 if (pi.CanRead)  o.WriteLine ("get;");
237                 if (pi.CanWrite) o.WriteLine ("set;");
238                 
239                 o.Indent --;
240                 o.Write ("}");
241         }
242         
243         void OutlineMethod (MethodInfo mi)
244         {
245                 o.Write (GetMethodVisibility (mi));
246                 o.Write (GetMethodModifiers  (mi));
247                 o.Write (FormatType (mi.ReturnType));
248                 o.Write (" ");
249                 o.Write (mi.Name);
250                 o.Write (" (");
251                 OutlineParams (mi.GetParameters ());
252                 o.Write (");");
253         }
254         
255         void OutlineParams (ParameterInfo [] pi)
256         {
257                 int i = 0;
258                 foreach (ParameterInfo p in pi) {
259                         if (p.ParameterType.IsByRef) {
260                                 o.Write (p.IsOut ? "out " : "ref ");
261                                 o.Write (FormatType (p.ParameterType.GetElementType ()));
262                         } else if (p.IsDefined (typeof (ParamArrayAttribute), false)) {
263                                 o.Write ("params ");
264                                 o.Write (FormatType (p.ParameterType));
265                         } else {
266                                 o.Write (FormatType (p.ParameterType));
267                         }
268                         
269                         o.Write (" ");
270                         o.Write (p.Name);
271                         if (i + 1 < pi.Length)
272                                 o.Write (", ");
273                         i++;
274                 }
275         }
276
277         void OutlineField (FieldInfo fi)
278         {
279                 if (fi.IsPublic)   o.Write ("public ");
280                 if (fi.IsFamily)   o.Write ("protected ");
281                 if (fi.IsPrivate)  o.Write ("private ");
282                 if (fi.IsAssembly) o.Write ("internal ");
283                 if (fi.IsLiteral) o.Write ("const ");
284                 o.Write (FormatType (fi.FieldType));
285                 o.Write (" ");
286                 o.Write (fi.Name);
287                 if (fi.IsLiteral)
288                 {
289                         o.Write (" = ");
290                         o.Write (fi.GetValue (this));
291                 }
292                 o.Write (";");
293         }
294
295         static string GetMethodVisibility (MethodBase m)
296         {
297                 if (m.IsPublic)   return "public ";
298                 if (m.IsFamily)   return "protected ";
299                 if (m.IsPrivate)  return "private ";
300                 if (m.IsAssembly) return "internal ";
301                         
302                 return null;
303         }
304         
305         static string GetMethodModifiers (MethodBase method)
306         {
307                 if (method.IsStatic)
308                         return "static ";
309         
310                 if (method.IsVirtual)
311                         return ((method.Attributes & MethodAttributes.NewSlot) != 0) ?
312                                 "virtual " :
313                                 "override ";
314                 
315                 return null;
316         }
317
318         static string GetTypeKind (Type t)
319         {
320                 if (t.IsEnum)
321                         return "enum";
322                 if (t.IsClass) {
323                         if (t.IsSubclassOf (typeof (System.MulticastDelegate)))
324                                 return "delegate";
325                         else
326                                 return "class";
327                 }
328                 if (t.IsInterface)
329                         return "interface";
330                 if (t.IsValueType)
331                         return "struct";
332                 return "class";
333         }
334         
335         static string GetTypeVisibility (Type t)
336         {
337                 switch (t.Attributes & TypeAttributes.VisibilityMask){
338                 case TypeAttributes.Public:
339                 case TypeAttributes.NestedPublic:
340                         return "public";
341
342                 case TypeAttributes.NestedFamily:
343                 case TypeAttributes.NestedFamANDAssem:
344                 case TypeAttributes.NestedFamORAssem:
345                         return "protected";
346
347                 default:
348                         return "internal";
349                 }
350         }
351         
352         static string FormatType (Type t)
353         {
354                 string type = t.FullName;
355                 if (!type.StartsWith ("System."))
356                         return type;
357                 
358                 if (t.HasElementType) {
359                         Type et = t.GetElementType ();
360                         if (t.IsArray)
361                                 return FormatType (et) + " []";
362                         if (t.IsPointer)
363                                 return FormatType (et) + " *";
364                         if (t.IsByRef)
365                                 return "ref " + FormatType (et);
366                 }
367         
368                 switch (type) {
369                 case "System.Byte": return "byte";
370                 case "System.SByte": return "sbyte";
371                 case "System.Int16": return "short";
372                 case "System.Int32": return "int";
373                 case "System.Int64": return "long";
374                         
375                 case "System.UInt16": return "ushort";
376                 case "System.UInt32": return "uint";
377                 case "System.UInt64": return "ulong";
378                         
379                 case "System.Single":  return "float";
380                 case "System.Double":  return "double";
381                 case "System.Decimal": return "decimal";
382                 case "System.Boolean": return "bool";
383                 case "System.Char":    return "char";
384                 case "System.String":  return "string";
385                         
386                 case "System.Object":  return "object";
387                 case "System.Void":  return "void";
388                 }
389         
390                 if (type.LastIndexOf(".") == 6)
391                         return type.Substring(7);
392                 
393                 return type;
394         }
395 }
396
397 public class Comparer : IComparer  {
398         delegate int ComparerFunc (object a, object b);
399         
400         ComparerFunc cmp;
401         
402         Comparer (ComparerFunc f)
403         {
404                 this.cmp = f;
405         }
406         
407         public int Compare (object a, object b)
408         {
409                 return cmp (a, b);
410         }
411
412         static int CompareType (object a, object b)
413         {
414                 Type type1 = (Type) a;
415                 Type type2 = (Type) b;
416
417                 if (type1.IsSubclassOf (typeof (System.MulticastDelegate)) != type2.IsSubclassOf (typeof (System.MulticastDelegate)))
418                                 return (type1.IsSubclassOf (typeof (System.MulticastDelegate)))? -1:1;
419                 return string.Compare (type1.Name, type2.Name);
420                         
421         }
422
423         static Comparer TypeComparer = new Comparer (new ComparerFunc (CompareType));
424
425         static Type [] Sort (Type [] types)
426         {
427                 Array.Sort (types, TypeComparer);
428                 return types;
429         }
430         
431         static int CompareMemberInfo (object a, object b)
432         {
433                 return string.Compare (((MemberInfo) a).Name, ((MemberInfo) b).Name);
434         }
435         
436         static Comparer MemberInfoComparer = new Comparer (new ComparerFunc (CompareMemberInfo));
437         
438         public static MemberInfo [] Sort (MemberInfo [] inf)
439         {
440                 Array.Sort (inf, MemberInfoComparer);
441                 return inf;
442         }
443         
444         static int CompareMethodBase (object a, object b)
445         {
446                 MethodBase aa = (MethodBase) a, bb = (MethodBase) b;
447                 
448                 if (aa.IsStatic == bb.IsStatic)
449                         return CompareMemberInfo (a, b);
450                 
451                 if (aa.IsStatic)
452                         return -1;
453                 
454                 return 1;
455         }
456         
457         static Comparer MethodBaseComparer = new Comparer (new ComparerFunc (CompareMethodBase));
458         
459         public static MethodBase [] Sort (MethodBase [] inf)
460         {
461                 Array.Sort (inf, MethodBaseComparer);
462                 return inf;
463         }
464         
465         static int ComparePropertyInfo (object a, object b)
466         {
467                 PropertyInfo aa = (PropertyInfo) a, bb = (PropertyInfo) b;
468                 
469                 bool astatic = (aa.CanRead ? aa.GetGetMethod (true) : aa.GetSetMethod (true)).IsStatic;
470                 bool bstatic = (bb.CanRead ? bb.GetGetMethod (true) : bb.GetSetMethod (true)).IsStatic;
471                 
472                 if (astatic == bstatic)
473                         return CompareMemberInfo (a, b);
474                 
475                 if (astatic)
476                         return -1;
477                 
478                 return 1;
479         }
480         
481         static Comparer PropertyInfoComparer = new Comparer (new ComparerFunc (ComparePropertyInfo));
482         
483         public static PropertyInfo [] Sort (PropertyInfo [] inf)
484         {
485                 Array.Sort (inf, PropertyInfoComparer);
486                 return inf;
487         }
488         
489         static int CompareEventInfo (object a, object b)
490         {
491                 EventInfo aa = (EventInfo) a, bb = (EventInfo) b;
492                 
493                 bool astatic = aa.GetAddMethod (true).IsStatic;
494                 bool bstatic = bb.GetAddMethod (true).IsStatic;
495                 
496                 if (astatic == bstatic)
497                         return CompareMemberInfo (a, b);
498                 
499                 if (astatic)
500                         return -1;
501                 
502                 return 1;
503         }
504         
505         static Comparer EventInfoComparer = new Comparer (new ComparerFunc (CompareEventInfo));
506         
507         public static EventInfo [] Sort (EventInfo [] inf)
508         {
509                 Array.Sort (inf, EventInfoComparer);
510                 return inf;
511         }
512 }