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