o.Write (GetTypeKind (t));
o.Write (" ");
- Type [] interfaces = (Type []) Comparer.Sort (t.GetInterfaces ());
+ Type [] interfaces = (Type []) Comparer.Sort (TypeGetInterfaces (t, options.DeclaredOnly));
Type parent = t.BaseType;
if (t.IsSubclassOf (typeof (System.MulticastDelegate))) {
o.Write (GetTypeName (t));
o.Write (" (");
OutlineParams (method.GetParameters ());
- o.WriteLine (")");
+ o.Write (")");
#if NET_2_0
WriteGenericConstraints (t.GetGenericArguments ());
#endif
-
+
+ o.WriteLine (";");
return;
}
foreach (EventInfo ei in Comparer.Sort (t.GetEvents (DefaultFlags))) {
- if (! ShowMember (ei.GetAddMethod ()))
+ if (! ShowMember (ei.GetAddMethod (true)))
continue;
if (first)
void OutlineEvent (EventInfo ei)
{
- MethodBase accessor = ei.GetAddMethod ();
+ MethodBase accessor = ei.GetAddMethod (true);
o.Write (GetMethodVisibility (accessor));
o.Write ("event ");
void OutlineMethod (MethodInfo mi)
{
- o.Write (GetMethodVisibility (mi));
- o.Write (GetMethodModifiers (mi));
- o.Write (FormatType (mi.ReturnType));
- o.Write (" ");
+ if (MethodIsExplicitIfaceImpl (mi)) {
+ o.Write (FormatType (mi.ReturnType));
+ o.Write (" ");
+ // MSFT has no way to get the method that we are overriding
+ // from the interface. this would allow us to pretty print
+ // the type name (and be more correct if there compiler
+ // were to do some strange naming thing).
+ } else {
+ o.Write (GetMethodVisibility (mi));
+ o.Write (GetMethodModifiers (mi));
+ o.Write (FormatType (mi.ReturnType));
+ o.Write (" ");
+ }
+
o.Write (mi.Name);
#if NET_2_0
o.Write (FormatGenericParams (mi.GetGenericArguments ()));
if (fi.IsPrivate) o.Write ("private ");
if (fi.IsAssembly) o.Write ("internal ");
if (fi.IsLiteral) o.Write ("const ");
+ else if (fi.IsStatic) o.Write ("static ");
if (fi.IsInitOnly) o.Write ("readonly ");
o.Write (FormatType (fi.FieldType));
o.Write (" ");
o.Write (fi.Name);
- if (fi.IsLiteral)
- {
+ if (fi.IsLiteral) {
+ object v = fi.GetValue (this);
+
+ // TODO: Escape values here
o.Write (" = ");
- o.Write (fi.GetValue (this));
+ if (v is char)
+ o.Write ("'{0}'", v);
+ else if (v is string)
+ o.Write ("\"{0}\"", v);
+ else
+ o.Write (fi.GetValue (this));
}
o.Write (";");
}
{
if (method.IsStatic)
return "static ";
-
+
+ if (method.IsFinal) {
+ // This will happen if you have
+ // class X : IA {
+ // public void A () {}
+ // static void Main () {}
+ // }
+ // interface IA {
+ // void A ();
+ // }
+ //
+ // A needs to be virtual (the CLR requires
+ // methods implementing an iface be virtual),
+ // but can not be inherited. It also can not
+ // be inherited. In C# this is represented
+ // with no special modifiers
+
+ if (method.IsVirtual)
+ return null;
+ return "sealed ";
+ }
+
// all interface methods are "virtual" but we don't say that in c#
- if (method.IsVirtual && !method.DeclaringType.IsInterface)
+ if (method.IsVirtual && !method.DeclaringType.IsInterface) {
+ if (method.IsAbstract)
+ return "abstract ";
+
return ((method.Attributes & MethodAttributes.NewSlot) != 0) ?
"virtual " :
- "override ";
-
+ "override ";
+ }
+
return null;
}
return sb.ToString ();
}
+ // TODO: fine tune this so that our output is less verbose. We need to figure
+ // out a way to do this while not making things confusing.
string FormatType (Type t)
{
string type = GetFullName (t);
if (type.LastIndexOf(".") == 6)
return type.Substring(7);
-
+
+ //
+ // If the namespace of the type is the namespace of what
+ // we are printing (or is a member of one if its children
+ // don't print it. This basically means that in C# we would
+ // automatically get the namespace imported by virtue of the
+ // namespace {} block.
+ //
+ if (this.t.Namespace.StartsWith (t.Namespace + ".") || t.Namespace == this.t.Namespace)
+ return type.Substring (t.Namespace.Length + 1);
+
return type;
}
foreach (Type t in args) {
bool first = true;
- Type[] ifaces = t.GetInterfaces();
- ifaces = Array.FindAll<Type> (ifaces, delegate (Type iface) { return !iface.IsAssignableFrom (t.BaseType); });
+ Type[] ifaces = TypeGetInterfaces (t, true);
GenericParameterAttributes attrs = t.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
GenericParameterAttributes [] interesting = {
GenericParameterAttributes.ReferenceTypeConstraint,
- GenericParameterAttributes.ValueTypeConstraint,
+ GenericParameterAttributes.NotNullableValueTypeConstraint,
GenericParameterAttributes.DefaultConstructorConstraint
};
case GenericParameterAttributes.ReferenceTypeConstraint:
o.Write ("class");
break;
- case GenericParameterAttributes.ValueTypeConstraint:
+ case GenericParameterAttributes.NotNullableValueTypeConstraint:
o.Write ("struct");
break;
case GenericParameterAttributes.DefaultConstructorConstraint:
default: return name;
}
}
+
+ bool MethodIsExplicitIfaceImpl (MethodBase mb)
+ {
+ if (!(mb.IsFinal && mb.IsVirtual && mb.IsPrivate))
+ return false;
+
+ // UGH msft has no way to get the info about what method is
+ // getting overriden. Another reason to use cecil :-)
+ //
+ //MethodInfo mi = mb as MethodInfo;
+ //if (mi == null)
+ // return false;
+ //
+ //Console.WriteLine (mi.GetBaseDefinition ().DeclaringType);
+ //return mi.GetBaseDefinition ().DeclaringType.IsInterface;
+
+ // So, we guess that virtual final private methods only come
+ // from ifaces :-)
+ return true;
+ }
bool ShowMember (MemberInfo mi)
{
if (options.ShowPrivate)
return true;
+
+ if (options.FilterObsolete && mi.IsDefined (typeof (ObsoleteAttribute), false))
+ return false;
switch (mi.MemberType) {
case MemberTypes.Constructor:
if (mb.IsFamily || mb.IsPublic || mb.IsFamilyOrAssembly)
return true;
+ if (MethodIsExplicitIfaceImpl (mb))
+ return true;
+
return false;
// What am I !!!
return true;
}
+
+ static Type [] TypeGetInterfaces (Type t, bool declonly)
+ {
+ Type [] ifaces = t.GetInterfaces ();
+ if (! declonly)
+ return ifaces;
+
+ // Handle Object. Also, optimize for no interfaces
+ if (t.BaseType == null || ifaces.Length == 0)
+ return ifaces;
+
+ ArrayList ar = new ArrayList ();
+
+ foreach (Type i in ifaces)
+ if (! i.IsAssignableFrom (t.BaseType))
+ ar.Add (i);
+
+ return (Type []) ar.ToArray (typeof (Type));
+ }
}
public class Comparer : IComparer {
{
MethodBase aa = (MethodBase) a, bb = (MethodBase) b;
- if (aa.IsStatic == bb.IsStatic)
- return CompareMemberInfo (a, b);
-
+ if (aa.IsStatic == bb.IsStatic) {
+ int c = CompareMemberInfo (a, b);
+ if (c != 0)
+ return c;
+ ParameterInfo [] ap, bp;
+
+ //
+ // Sort overloads by the names of their types
+ // put methods with fewer params first.
+ //
+
+ ap = aa.GetParameters ();
+ bp = bb.GetParameters ();
+ int n = Math.Min (ap.Length, bp.Length);
+
+ for (int i = 0; i < n; i ++)
+ if ((c = CompareType (ap [i].ParameterType, bp [i].ParameterType)) != 0)
+ return c;
+
+ return ap.Length.CompareTo (bp.Length);
+ }
if (aa.IsStatic)
return -1;