PageRenderTime 57ms CodeModel.GetById 16ms app.highlight 32ms RepoModel.GetById 2ms app.codeStats 0ms

/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/outline.cs

http://github.com/icsharpcode/ILSpy
C# | 1038 lines | 748 code | 206 blank | 84 comment | 214 complexity | c52c7deb826d99ed8cc3cacda975c2ed MD5 | raw file
   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
  32using System;
  33using System.Reflection;
  34using System.Collections;
  35using System.CodeDom.Compiler;
  36using System.IO;
  37using System.Text;
  38
  39namespace Mono.CSharp {
  40public 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
 904public 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}