1048 строки
24 KiB
C#
1048 строки
24 KiB
C#
//
|
|
// outline -- support for rendering in monop
|
|
// Some code stolen from updater.cs in monodoc.
|
|
//
|
|
// Authors:
|
|
// Ben Maurer (bmaurer@users.sourceforge.net)
|
|
//
|
|
// (C) 2004 Ben Maurer
|
|
//
|
|
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
using System;
|
|
using System.Reflection;
|
|
using System.Collections;
|
|
using System.CodeDom.Compiler;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace Mono.CSharp {
|
|
public class Outline {
|
|
|
|
bool declared_only;
|
|
bool show_private;
|
|
bool filter_obsolete;
|
|
|
|
IndentedTextWriter o;
|
|
Type t;
|
|
|
|
public delegate void NotificationEvent (int kind, object value);
|
|
|
|
public event NotificationEvent OutlineNotificationEvent;
|
|
|
|
public Outline (Type t, TextWriter output, bool declared_only, bool show_private, bool filter_obsolete)
|
|
{
|
|
this.t = t;
|
|
this.o = new IndentedTextWriter (output, "\t");
|
|
this.declared_only = declared_only;
|
|
this.show_private = show_private;
|
|
this.filter_obsolete = filter_obsolete;
|
|
}
|
|
|
|
public void OutlineType ()
|
|
{
|
|
bool first, ns = !String.IsNullOrEmpty (t.Namespace);
|
|
|
|
if (ns){
|
|
o.WriteLine ("namespace " + t.Namespace + " {");
|
|
o.Indent++;
|
|
ns = true;
|
|
}
|
|
|
|
OutlineAttributes ();
|
|
o.Write (GetTypeVisibility (t));
|
|
|
|
if (t.IsClass && !t.IsSubclassOf (typeof (System.MulticastDelegate))) {
|
|
if (t.IsSealed)
|
|
o.Write (t.IsAbstract ? " static" : " sealed");
|
|
else if (t.IsAbstract)
|
|
o.Write (" abstract");
|
|
}
|
|
|
|
o.Write (" ");
|
|
o.Write (GetTypeKind (t));
|
|
o.Write (" ");
|
|
|
|
Type [] interfaces = (Type []) Comparer.Sort (TypeGetInterfaces (t, declared_only));
|
|
Type parent = t.BaseType;
|
|
|
|
if (t.IsSubclassOf (typeof (System.MulticastDelegate))) {
|
|
MethodInfo method;
|
|
|
|
method = t.GetMethod ("Invoke");
|
|
|
|
RenderType (method.ReturnType);
|
|
o.Write (" ");
|
|
o.Write (GetTypeName (t));
|
|
o.Write (" (");
|
|
OutlineParams (method.GetParameters ());
|
|
o.Write (")");
|
|
|
|
#if NET_2_0
|
|
WriteGenericConstraints (t.GetGenericArguments ());
|
|
#endif
|
|
|
|
o.WriteLine (";");
|
|
return;
|
|
}
|
|
|
|
o.Write (GetTypeName (t));
|
|
if (((parent != null && parent != typeof (object) && parent != typeof (ValueType)) || interfaces.Length != 0) && ! t.IsEnum) {
|
|
first = true;
|
|
o.Write (" : ");
|
|
|
|
if (parent != null && parent != typeof (object) && parent != typeof (ValueType)) {
|
|
RenderType (parent);
|
|
first = false;
|
|
}
|
|
|
|
foreach (Type intf in interfaces) {
|
|
if (!first) o.Write (", ");
|
|
first = false;
|
|
|
|
RenderType (intf);
|
|
}
|
|
}
|
|
|
|
if (t.IsEnum) {
|
|
Type underlyingType = System.Enum.GetUnderlyingType (t);
|
|
if (underlyingType != typeof (int)){
|
|
o.Write (" : ");
|
|
RenderType (underlyingType);
|
|
}
|
|
}
|
|
#if NET_2_0
|
|
WriteGenericConstraints (t.GetGenericArguments ());
|
|
#endif
|
|
o.WriteLine (" {");
|
|
o.Indent++;
|
|
|
|
if (t.IsEnum) {
|
|
bool is_first = true;
|
|
foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Static)) {
|
|
|
|
if (! is_first)
|
|
o.WriteLine (",");
|
|
is_first = false;
|
|
o.Write (fi.Name);
|
|
}
|
|
o.WriteLine ();
|
|
o.Indent--; o.WriteLine ("}");
|
|
return;
|
|
}
|
|
|
|
first = true;
|
|
|
|
foreach (ConstructorInfo ci in t.GetConstructors (DefaultFlags)) {
|
|
|
|
if (! ShowMember (ci))
|
|
continue;
|
|
|
|
if (first)
|
|
o.WriteLine ();
|
|
first = false;
|
|
|
|
OutlineConstructor (ci);
|
|
|
|
o.WriteLine ();
|
|
}
|
|
|
|
|
|
first = true;
|
|
|
|
foreach (MethodInfo m in Comparer.Sort (t.GetMethods (DefaultFlags))) {
|
|
|
|
if (! ShowMember (m))
|
|
continue;
|
|
|
|
if ((m.Attributes & MethodAttributes.SpecialName) != 0)
|
|
continue;
|
|
|
|
if (first)
|
|
o.WriteLine ();
|
|
first = false;
|
|
|
|
OutlineMethod (m);
|
|
|
|
o.WriteLine ();
|
|
}
|
|
|
|
first = true;
|
|
|
|
foreach (MethodInfo m in t.GetMethods (DefaultFlags)) {
|
|
|
|
if (! ShowMember (m))
|
|
continue;
|
|
|
|
if ((m.Attributes & MethodAttributes.SpecialName) == 0)
|
|
continue;
|
|
if (!(m.Name.StartsWith ("op_")))
|
|
continue;
|
|
|
|
if (first)
|
|
o.WriteLine ();
|
|
first = false;
|
|
|
|
OutlineOperator (m);
|
|
|
|
o.WriteLine ();
|
|
}
|
|
|
|
first = true;
|
|
|
|
foreach (PropertyInfo pi in Comparer.Sort (t.GetProperties (DefaultFlags))) {
|
|
|
|
if (! ((pi.CanRead && ShowMember (pi.GetGetMethod (true))) ||
|
|
(pi.CanWrite && ShowMember (pi.GetSetMethod (true)))))
|
|
continue;
|
|
|
|
if (first)
|
|
o.WriteLine ();
|
|
first = false;
|
|
|
|
OutlineProperty (pi);
|
|
|
|
o.WriteLine ();
|
|
}
|
|
|
|
first = true;
|
|
|
|
foreach (FieldInfo fi in t.GetFields (DefaultFlags)) {
|
|
|
|
if (! ShowMember (fi))
|
|
continue;
|
|
|
|
if (first)
|
|
o.WriteLine ();
|
|
first = false;
|
|
|
|
OutlineField (fi);
|
|
|
|
o.WriteLine ();
|
|
}
|
|
|
|
first = true;
|
|
|
|
foreach (EventInfo ei in Comparer.Sort (t.GetEvents (DefaultFlags))) {
|
|
|
|
if (! ShowMember (ei.GetAddMethod (true)))
|
|
continue;
|
|
|
|
if (first)
|
|
o.WriteLine ();
|
|
first = false;
|
|
|
|
OutlineEvent (ei);
|
|
|
|
o.WriteLine ();
|
|
}
|
|
|
|
first = true;
|
|
|
|
foreach (Type ntype in Comparer.Sort (t.GetNestedTypes (DefaultFlags))) {
|
|
|
|
if (! ShowMember (ntype))
|
|
continue;
|
|
|
|
if (first)
|
|
o.WriteLine ();
|
|
first = false;
|
|
|
|
new Outline (ntype, o, declared_only, show_private, filter_obsolete).OutlineType ();
|
|
}
|
|
|
|
o.Indent--; o.WriteLine ("}");
|
|
if (ns){
|
|
o.Indent--;
|
|
o.WriteLine ("}");
|
|
}
|
|
}
|
|
|
|
BindingFlags DefaultFlags {
|
|
get {
|
|
BindingFlags f = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
|
|
|
|
if (declared_only)
|
|
f |= BindingFlags.DeclaredOnly;
|
|
|
|
return f;
|
|
}
|
|
}
|
|
|
|
// FIXME: add other interesting attributes?
|
|
void OutlineAttributes ()
|
|
{
|
|
if (t.IsSerializable)
|
|
o.WriteLine ("[Serializable]");
|
|
|
|
if (t.IsDefined (typeof (System.FlagsAttribute), true))
|
|
o.WriteLine ("[Flags]");
|
|
|
|
if (t.IsDefined (typeof (System.ObsoleteAttribute), true))
|
|
o.WriteLine ("[Obsolete]");
|
|
}
|
|
|
|
void OutlineEvent (EventInfo ei)
|
|
{
|
|
MethodBase accessor = ei.GetAddMethod (true);
|
|
|
|
o.Write (GetMethodVisibility (accessor));
|
|
o.Write ("event ");
|
|
RenderType (ei.EventHandlerType);
|
|
o.Write (" ");
|
|
o.Write (ei.Name);
|
|
o.Write (";");
|
|
}
|
|
|
|
void OutlineConstructor (ConstructorInfo ci)
|
|
{
|
|
o.Write (GetMethodVisibility (ci));
|
|
o.Write (RemoveGenericArity (t.Name));
|
|
o.Write (" (");
|
|
OutlineParams (ci.GetParameters ());
|
|
o.Write (");");
|
|
}
|
|
|
|
|
|
void OutlineProperty (PropertyInfo pi)
|
|
{
|
|
ParameterInfo [] idxp = pi.GetIndexParameters ();
|
|
MethodBase g = pi.GetGetMethod (true);
|
|
MethodBase s = pi.GetSetMethod (true);
|
|
MethodBase accessor = g != null ? g : s;
|
|
|
|
if (pi.CanRead && pi.CanWrite) {
|
|
|
|
|
|
// Get the more accessible accessor
|
|
if ((g.Attributes & MethodAttributes.MemberAccessMask) !=
|
|
(s.Attributes & MethodAttributes.MemberAccessMask)) {
|
|
|
|
if (g.IsPublic) accessor = g;
|
|
else if (s.IsPublic) accessor = s;
|
|
else if (g.IsFamilyOrAssembly) accessor = g;
|
|
else if (s.IsFamilyOrAssembly) accessor = s;
|
|
else if (g.IsAssembly || g.IsFamily) accessor = g;
|
|
else if (s.IsAssembly || s.IsFamily) accessor = s;
|
|
}
|
|
}
|
|
|
|
o.Write (GetMethodVisibility (accessor));
|
|
o.Write (GetMethodModifiers (accessor));
|
|
RenderType (pi.PropertyType);
|
|
o.Write (" ");
|
|
|
|
if (idxp.Length == 0)
|
|
o.Write (pi.Name);
|
|
else {
|
|
o.Write ("this [");
|
|
OutlineParams (idxp);
|
|
o.Write ("]");
|
|
}
|
|
|
|
o.WriteLine (" {");
|
|
o.Indent ++;
|
|
|
|
if (g != null && ShowMember (g)) {
|
|
if ((g.Attributes & MethodAttributes.MemberAccessMask) !=
|
|
(accessor.Attributes & MethodAttributes.MemberAccessMask))
|
|
o.Write (GetMethodVisibility (g));
|
|
o.WriteLine ("get;");
|
|
}
|
|
|
|
if (s != null && ShowMember (s)) {
|
|
if ((s.Attributes & MethodAttributes.MemberAccessMask) !=
|
|
(accessor.Attributes & MethodAttributes.MemberAccessMask))
|
|
o.Write (GetMethodVisibility (s));
|
|
o.WriteLine ("set;");
|
|
}
|
|
|
|
o.Indent --;
|
|
o.Write ("}");
|
|
}
|
|
|
|
void OutlineMethod (MethodInfo mi)
|
|
{
|
|
if (MethodIsExplicitIfaceImpl (mi)) {
|
|
RenderType (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));
|
|
RenderType (mi.ReturnType);
|
|
o.Write (" ");
|
|
}
|
|
|
|
o.Write (mi.Name);
|
|
#if NET_2_0
|
|
o.Write (FormatGenericParams (mi.GetGenericArguments ()));
|
|
#endif
|
|
o.Write (" (");
|
|
OutlineParams (mi.GetParameters ());
|
|
o.Write (")");
|
|
#if NET_2_0
|
|
WriteGenericConstraints (mi.GetGenericArguments ());
|
|
#endif
|
|
o.Write (";");
|
|
}
|
|
|
|
void OutlineOperator (MethodInfo mi)
|
|
{
|
|
o.Write (GetMethodVisibility (mi));
|
|
o.Write (GetMethodModifiers (mi));
|
|
if (mi.Name == "op_Explicit" || mi.Name == "op_Implicit") {
|
|
o.Write (mi.Name.Substring (3).ToLower ());
|
|
o.Write (" operator ");
|
|
RenderType (mi.ReturnType);
|
|
} else {
|
|
RenderType (mi.ReturnType);
|
|
o.Write (" operator ");
|
|
o.Write (OperatorFromName (mi.Name));
|
|
}
|
|
o.Write (" (");
|
|
OutlineParams (mi.GetParameters ());
|
|
o.Write (");");
|
|
}
|
|
|
|
void OutlineParams (ParameterInfo [] pi)
|
|
{
|
|
int i = 0;
|
|
foreach (ParameterInfo p in pi) {
|
|
if (p.ParameterType.IsByRef) {
|
|
o.Write (p.IsOut ? "out " : "ref ");
|
|
RenderType (p.ParameterType.GetElementType ());
|
|
} else if (p.IsDefined (typeof (ParamArrayAttribute), false)) {
|
|
o.Write ("params ");
|
|
RenderType (p.ParameterType);
|
|
} else {
|
|
RenderType (p.ParameterType);
|
|
}
|
|
|
|
o.Write (" ");
|
|
o.Write (p.Name);
|
|
if (i + 1 < pi.Length)
|
|
o.Write (", ");
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void OutlineField (FieldInfo fi)
|
|
{
|
|
if (fi.IsPublic) o.Write ("public ");
|
|
if (fi.IsFamily) o.Write ("protected ");
|
|
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 ");
|
|
|
|
RenderType (fi.FieldType);
|
|
o.Write (" ");
|
|
o.Write (fi.Name);
|
|
if (fi.IsLiteral) {
|
|
object v = fi.GetValue (this);
|
|
|
|
// TODO: Escape values here
|
|
o.Write (" = ");
|
|
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 (";");
|
|
}
|
|
|
|
static string GetMethodVisibility (MethodBase m)
|
|
{
|
|
// itnerfaces have no modifiers here
|
|
if (m.DeclaringType.IsInterface)
|
|
return "";
|
|
|
|
if (m.IsPublic) return "public ";
|
|
if (m.IsFamily) return "protected ";
|
|
if (m.IsPrivate) return "private ";
|
|
if (m.IsAssembly) return "internal ";
|
|
|
|
return null;
|
|
}
|
|
|
|
static string GetMethodModifiers (MethodBase method)
|
|
{
|
|
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.IsAbstract)
|
|
return "abstract ";
|
|
|
|
return ((method.Attributes & MethodAttributes.NewSlot) != 0) ?
|
|
"virtual " :
|
|
"override ";
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static string GetTypeKind (Type t)
|
|
{
|
|
if (t.IsEnum)
|
|
return "enum";
|
|
if (t.IsClass) {
|
|
if (t.IsSubclassOf (typeof (System.MulticastDelegate)))
|
|
return "delegate";
|
|
else
|
|
return "class";
|
|
}
|
|
if (t.IsInterface)
|
|
return "interface";
|
|
if (t.IsValueType)
|
|
return "struct";
|
|
return "class";
|
|
}
|
|
|
|
static string GetTypeVisibility (Type t)
|
|
{
|
|
switch (t.Attributes & TypeAttributes.VisibilityMask){
|
|
case TypeAttributes.Public:
|
|
case TypeAttributes.NestedPublic:
|
|
return "public";
|
|
|
|
case TypeAttributes.NestedFamily:
|
|
case TypeAttributes.NestedFamANDAssem:
|
|
case TypeAttributes.NestedFamORAssem:
|
|
return "protected";
|
|
|
|
default:
|
|
return "internal";
|
|
}
|
|
}
|
|
|
|
#if NET_2_0
|
|
string FormatGenericParams (Type [] args)
|
|
{
|
|
StringBuilder sb = new StringBuilder ();
|
|
if (args.Length == 0)
|
|
return "";
|
|
|
|
sb.Append ("<");
|
|
for (int i = 0; i < args.Length; i++) {
|
|
if (i > 0)
|
|
sb.Append (",");
|
|
RenderType (args [i]);
|
|
}
|
|
sb.Append (">");
|
|
return sb.ToString ();
|
|
}
|
|
#endif
|
|
|
|
void RenderType (Type t)
|
|
{
|
|
|
|
if (OutlineNotificationEvent != null){
|
|
o.Flush ();
|
|
OutlineNotificationEvent (1, t);
|
|
|
|
o.Write (FormatType (t));
|
|
o.Flush ();
|
|
|
|
OutlineNotificationEvent (0, null);
|
|
} else {
|
|
o.Write (FormatType (t));
|
|
}
|
|
}
|
|
|
|
// 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.StartsWith ("System.")) {
|
|
if (t.Namespace == this.t.Namespace)
|
|
return t.Name;
|
|
return type;
|
|
}
|
|
|
|
if (t.HasElementType) {
|
|
Type et = t.GetElementType ();
|
|
if (t.IsArray)
|
|
return FormatType (et) + " []";
|
|
if (t.IsPointer)
|
|
return FormatType (et) + " *";
|
|
if (t.IsByRef)
|
|
return "ref " + FormatType (et);
|
|
}
|
|
|
|
switch (type) {
|
|
case "System.Byte": return "byte";
|
|
case "System.SByte": return "sbyte";
|
|
case "System.Int16": return "short";
|
|
case "System.Int32": return "int";
|
|
case "System.Int64": return "long";
|
|
|
|
case "System.UInt16": return "ushort";
|
|
case "System.UInt32": return "uint";
|
|
case "System.UInt64": return "ulong";
|
|
|
|
case "System.Single": return "float";
|
|
case "System.Double": return "double";
|
|
case "System.Decimal": return "decimal";
|
|
case "System.Boolean": return "bool";
|
|
case "System.Char": return "char";
|
|
case "System.String": return "string";
|
|
|
|
case "System.Object": return "object";
|
|
case "System.Void": return "void";
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
public static string RemoveGenericArity (string name)
|
|
{
|
|
int start = 0;
|
|
StringBuilder sb = new StringBuilder ();
|
|
while (start < name.Length) {
|
|
int pos = name.IndexOf ('`', start);
|
|
if (pos < 0) {
|
|
sb.Append (name.Substring (start));
|
|
break;
|
|
}
|
|
sb.Append (name.Substring (start, pos-start));
|
|
|
|
pos++;
|
|
|
|
while ((pos < name.Length) && Char.IsNumber (name [pos]))
|
|
pos++;
|
|
|
|
start = pos;
|
|
}
|
|
|
|
return sb.ToString ();
|
|
}
|
|
|
|
string GetTypeName (Type t)
|
|
{
|
|
StringBuilder sb = new StringBuilder ();
|
|
GetTypeName (sb, t);
|
|
return sb.ToString ();
|
|
}
|
|
|
|
void GetTypeName (StringBuilder sb, Type t)
|
|
{
|
|
sb.Append (RemoveGenericArity (t.Name));
|
|
#if NET_2_0
|
|
sb.Append (FormatGenericParams (t.GetGenericArguments ()));
|
|
#endif
|
|
}
|
|
|
|
string GetFullName (Type t)
|
|
{
|
|
StringBuilder sb = new StringBuilder ();
|
|
GetFullName_recursed (sb, t, false);
|
|
return sb.ToString ();
|
|
}
|
|
|
|
void GetFullName_recursed (StringBuilder sb, Type t, bool recursed)
|
|
{
|
|
#if NET_2_0
|
|
if (t.IsGenericParameter) {
|
|
sb.Append (t.Name);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (t.DeclaringType != null) {
|
|
GetFullName_recursed (sb, t.DeclaringType, true);
|
|
sb.Append (".");
|
|
}
|
|
|
|
if (!recursed) {
|
|
string ns = t.Namespace;
|
|
if ((ns != null) && (ns != "")) {
|
|
sb.Append (ns);
|
|
sb.Append (".");
|
|
}
|
|
}
|
|
|
|
GetTypeName (sb, t);
|
|
}
|
|
|
|
#if NET_2_0
|
|
void WriteGenericConstraints (Type [] args)
|
|
{
|
|
|
|
foreach (Type t in args) {
|
|
bool first = true;
|
|
Type[] ifaces = TypeGetInterfaces (t, true);
|
|
|
|
GenericParameterAttributes attrs = t.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
|
|
GenericParameterAttributes [] interesting = {
|
|
GenericParameterAttributes.ReferenceTypeConstraint,
|
|
GenericParameterAttributes.NotNullableValueTypeConstraint,
|
|
GenericParameterAttributes.DefaultConstructorConstraint
|
|
};
|
|
|
|
if (t.BaseType != typeof (object) || ifaces.Length != 0 || attrs != 0) {
|
|
o.Write (" where ");
|
|
RenderType (t);
|
|
o.Write (" : ");
|
|
}
|
|
|
|
if (t.BaseType != typeof (object)) {
|
|
RenderType (t.BaseType);
|
|
first = false;
|
|
}
|
|
|
|
foreach (Type iface in ifaces) {
|
|
if (!first)
|
|
o.Write (", ");
|
|
first = false;
|
|
|
|
RenderType (iface);
|
|
}
|
|
|
|
foreach (GenericParameterAttributes a in interesting) {
|
|
if ((attrs & a) == 0)
|
|
continue;
|
|
|
|
if (!first)
|
|
o.Write (", ");
|
|
first = false;
|
|
|
|
switch (a) {
|
|
case GenericParameterAttributes.ReferenceTypeConstraint:
|
|
o.Write ("class");
|
|
break;
|
|
case GenericParameterAttributes.NotNullableValueTypeConstraint:
|
|
o.Write ("struct");
|
|
break;
|
|
case GenericParameterAttributes.DefaultConstructorConstraint:
|
|
o.Write ("new ()");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
string OperatorFromName (string name)
|
|
{
|
|
switch (name) {
|
|
case "op_UnaryPlus": return "+";
|
|
case "op_UnaryNegation": return "-";
|
|
case "op_LogicalNot": return "!";
|
|
case "op_OnesComplement": return "~";
|
|
case "op_Increment": return "++";
|
|
case "op_Decrement": return "--";
|
|
case "op_True": return "true";
|
|
case "op_False": return "false";
|
|
case "op_Addition": return "+";
|
|
case "op_Subtraction": return "-";
|
|
case "op_Multiply": return "*";
|
|
case "op_Division": return "/";
|
|
case "op_Modulus": return "%";
|
|
case "op_BitwiseAnd": return "&";
|
|
case "op_BitwiseOr": return "|";
|
|
case "op_ExclusiveOr": return "^";
|
|
case "op_LeftShift": return "<<";
|
|
case "op_RightShift": return ">>";
|
|
case "op_Equality": return "==";
|
|
case "op_Inequality": return "!=";
|
|
case "op_GreaterThan": return ">";
|
|
case "op_LessThan": return "<";
|
|
case "op_GreaterThanOrEqual": return ">=";
|
|
case "op_LessThanOrEqual": return "<=";
|
|
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 (mi.MemberType == MemberTypes.Constructor && ((MethodBase) mi).IsStatic)
|
|
return false;
|
|
|
|
if (show_private)
|
|
return true;
|
|
|
|
if (filter_obsolete && mi.IsDefined (typeof (ObsoleteAttribute), false))
|
|
return false;
|
|
|
|
switch (mi.MemberType) {
|
|
case MemberTypes.Constructor:
|
|
case MemberTypes.Method:
|
|
MethodBase mb = mi as MethodBase;
|
|
|
|
if (mb.IsFamily || mb.IsPublic || mb.IsFamilyOrAssembly)
|
|
return true;
|
|
|
|
if (MethodIsExplicitIfaceImpl (mb))
|
|
return true;
|
|
|
|
return false;
|
|
|
|
|
|
case MemberTypes.Field:
|
|
FieldInfo fi = mi as FieldInfo;
|
|
|
|
if (fi.IsFamily || fi.IsPublic || fi.IsFamilyOrAssembly)
|
|
return true;
|
|
|
|
return false;
|
|
|
|
|
|
case MemberTypes.NestedType:
|
|
case MemberTypes.TypeInfo:
|
|
Type t = mi as Type;
|
|
|
|
switch (t.Attributes & TypeAttributes.VisibilityMask){
|
|
case TypeAttributes.Public:
|
|
case TypeAttributes.NestedPublic:
|
|
case TypeAttributes.NestedFamily:
|
|
case TypeAttributes.NestedFamORAssem:
|
|
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 {
|
|
delegate int ComparerFunc (object a, object b);
|
|
|
|
ComparerFunc cmp;
|
|
|
|
Comparer (ComparerFunc f)
|
|
{
|
|
this.cmp = f;
|
|
}
|
|
|
|
public int Compare (object a, object b)
|
|
{
|
|
return cmp (a, b);
|
|
}
|
|
|
|
static int CompareType (object a, object b)
|
|
{
|
|
Type type1 = (Type) a;
|
|
Type type2 = (Type) b;
|
|
|
|
if (type1.IsSubclassOf (typeof (System.MulticastDelegate)) != type2.IsSubclassOf (typeof (System.MulticastDelegate)))
|
|
return (type1.IsSubclassOf (typeof (System.MulticastDelegate)))? -1:1;
|
|
return string.Compare (type1.Name, type2.Name);
|
|
|
|
}
|
|
|
|
// static Comparer TypeComparer = new Comparer (new ComparerFunc (CompareType));
|
|
|
|
// static Type [] Sort (Type [] types)
|
|
// {
|
|
// Array.Sort (types, TypeComparer);
|
|
// return types;
|
|
// }
|
|
|
|
static int CompareMemberInfo (object a, object b)
|
|
{
|
|
return string.Compare (((MemberInfo) a).Name, ((MemberInfo) b).Name);
|
|
}
|
|
|
|
static Comparer MemberInfoComparer = new Comparer (new ComparerFunc (CompareMemberInfo));
|
|
|
|
public static MemberInfo [] Sort (MemberInfo [] inf)
|
|
{
|
|
Array.Sort (inf, MemberInfoComparer);
|
|
return inf;
|
|
}
|
|
|
|
static int CompareMethodBase (object a, object b)
|
|
{
|
|
MethodBase aa = (MethodBase) a, bb = (MethodBase) 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 = System.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;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static Comparer MethodBaseComparer = new Comparer (new ComparerFunc (CompareMethodBase));
|
|
|
|
public static MethodBase [] Sort (MethodBase [] inf)
|
|
{
|
|
Array.Sort (inf, MethodBaseComparer);
|
|
return inf;
|
|
}
|
|
|
|
static int ComparePropertyInfo (object a, object b)
|
|
{
|
|
PropertyInfo aa = (PropertyInfo) a, bb = (PropertyInfo) b;
|
|
|
|
bool astatic = (aa.CanRead ? aa.GetGetMethod (true) : aa.GetSetMethod (true)).IsStatic;
|
|
bool bstatic = (bb.CanRead ? bb.GetGetMethod (true) : bb.GetSetMethod (true)).IsStatic;
|
|
|
|
if (astatic == bstatic)
|
|
return CompareMemberInfo (a, b);
|
|
|
|
if (astatic)
|
|
return -1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static Comparer PropertyInfoComparer = new Comparer (new ComparerFunc (ComparePropertyInfo));
|
|
|
|
public static PropertyInfo [] Sort (PropertyInfo [] inf)
|
|
{
|
|
Array.Sort (inf, PropertyInfoComparer);
|
|
return inf;
|
|
}
|
|
|
|
static int CompareEventInfo (object a, object b)
|
|
{
|
|
EventInfo aa = (EventInfo) a, bb = (EventInfo) b;
|
|
|
|
bool astatic = aa.GetAddMethod (true).IsStatic;
|
|
bool bstatic = bb.GetAddMethod (true).IsStatic;
|
|
|
|
if (astatic == bstatic)
|
|
return CompareMemberInfo (a, b);
|
|
|
|
if (astatic)
|
|
return -1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static Comparer EventInfoComparer = new Comparer (new ComparerFunc (CompareEventInfo));
|
|
|
|
public static EventInfo [] Sort (EventInfo [] inf)
|
|
{
|
|
Array.Sort (inf, EventInfoComparer);
|
|
return inf;
|
|
}
|
|
}
|
|
} |