1007 lines
30 KiB
C#
1007 lines
30 KiB
C#
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
using System;
|
||
|
using System.IO;
|
||
|
using System.Reflection;
|
||
|
using System.Collections;
|
||
|
using System.Text;
|
||
|
|
||
|
public class TypeWriter
|
||
|
{
|
||
|
static Hashtable typeNames;
|
||
|
static Hashtable opNames;
|
||
|
static Hashtable opSortKeys;
|
||
|
|
||
|
public static int memberCt;
|
||
|
|
||
|
TextWriter writer;
|
||
|
int indent;
|
||
|
bool startOfLine;
|
||
|
bool includeMemberKeys = false;
|
||
|
bool fullTypeNames;
|
||
|
|
||
|
public TypeWriter(TextWriter writer)
|
||
|
{
|
||
|
this.writer = writer;
|
||
|
}
|
||
|
|
||
|
static TypeWriter()
|
||
|
{
|
||
|
typeNames = new Hashtable();
|
||
|
typeNames.Add(typeof(void), "void");
|
||
|
typeNames.Add(typeof(System.Object), "object");
|
||
|
typeNames.Add(typeof(System.String), "string");
|
||
|
typeNames.Add(typeof(System.SByte), "sbyte");
|
||
|
typeNames.Add(typeof(System.Byte), "byte");
|
||
|
typeNames.Add(typeof(System.Int16), "short");
|
||
|
typeNames.Add(typeof(System.UInt16), "ushort");
|
||
|
typeNames.Add(typeof(System.Int32), "int");
|
||
|
typeNames.Add(typeof(System.UInt32), "uint");
|
||
|
typeNames.Add(typeof(System.Int64), "long");
|
||
|
typeNames.Add(typeof(System.UInt64), "ulong");
|
||
|
typeNames.Add(typeof(System.Char), "char");
|
||
|
typeNames.Add(typeof(System.Boolean), "bool");
|
||
|
typeNames.Add(typeof(System.Single), "float");
|
||
|
typeNames.Add(typeof(System.Double), "double");
|
||
|
typeNames.Add(typeof(System.Decimal), "decimal");
|
||
|
opNames = new Hashtable();
|
||
|
opNames.Add("op_UnaryPlus", "+");
|
||
|
opNames.Add("op_Addition", "+");
|
||
|
opNames.Add("op_Increment", "++");
|
||
|
opNames.Add("op_UnaryNegation", "-");
|
||
|
opNames.Add("op_Subtraction", "-");
|
||
|
opNames.Add("op_Decrement", "--");
|
||
|
opNames.Add("op_Multiply", "*");
|
||
|
opNames.Add("op_Division", "/");
|
||
|
opNames.Add("op_Modulus", "%");
|
||
|
opNames.Add("op_BitwiseAnd", "&");
|
||
|
opNames.Add("op_BitwiseOr", "|");
|
||
|
opNames.Add("op_ExclusiveOr", "^");
|
||
|
opNames.Add("op_Negation", "!");
|
||
|
opNames.Add("op_OnesComplement", "~");
|
||
|
opNames.Add("op_LeftShift", "<<");
|
||
|
opNames.Add("op_RightShift", ">>");
|
||
|
opNames.Add("op_Equality", "==");
|
||
|
opNames.Add("op_Inequality", "!=");
|
||
|
opNames.Add("op_GreaterThanOrEqual", ">=");
|
||
|
opNames.Add("op_LessThanOrEqual", "<=");
|
||
|
opNames.Add("op_GreaterThan", ">");
|
||
|
opNames.Add("op_LessThan", "<");
|
||
|
opNames.Add("op_True", "true");
|
||
|
opNames.Add("op_False", "false");
|
||
|
opNames.Add("op_Implicit", "implicit");
|
||
|
opNames.Add("op_Explicit", "explicit");
|
||
|
opSortKeys = new Hashtable();
|
||
|
opSortKeys.Add("op_UnaryPlus", "A");
|
||
|
opSortKeys.Add("op_Addition", "B");
|
||
|
opSortKeys.Add("op_Increment", "C");
|
||
|
opSortKeys.Add("op_UnaryNegation", "D");
|
||
|
opSortKeys.Add("op_Subtraction", "E");
|
||
|
opSortKeys.Add("op_Decrement", "F");
|
||
|
opSortKeys.Add("op_Multiply", "G");
|
||
|
opSortKeys.Add("op_Division", "H");
|
||
|
opSortKeys.Add("op_Modulus", "I");
|
||
|
opSortKeys.Add("op_BitwiseAnd", "J");
|
||
|
opSortKeys.Add("op_BitwiseOr", "K");
|
||
|
opSortKeys.Add("op_ExclusiveOr", "L");
|
||
|
opSortKeys.Add("op_Negation", "M");
|
||
|
opSortKeys.Add("op_OnesComplement", "N");
|
||
|
opSortKeys.Add("op_LeftShift", "O");
|
||
|
opSortKeys.Add("op_RightShift", "P");
|
||
|
opSortKeys.Add("op_Equality", "Q");
|
||
|
opSortKeys.Add("op_Inequality", "R");
|
||
|
opSortKeys.Add("op_GreaterThanOrEqual", "S");
|
||
|
opSortKeys.Add("op_LessThanOrEqual", "T");
|
||
|
opSortKeys.Add("op_GreaterThan", "U");
|
||
|
opSortKeys.Add("op_LessThan", "V");
|
||
|
opSortKeys.Add("op_True", "W");
|
||
|
opSortKeys.Add("op_False", "X");
|
||
|
opSortKeys.Add("op_Implicit", "Y");
|
||
|
opSortKeys.Add("op_Explicit", "Z");
|
||
|
}
|
||
|
|
||
|
public bool FullTypeNames
|
||
|
{
|
||
|
get { return fullTypeNames; }
|
||
|
set { fullTypeNames = value; }
|
||
|
}
|
||
|
|
||
|
void AddMemberEntries(ArrayList list, Type type, bool inherited)
|
||
|
{
|
||
|
foreach (MemberInfo member in type.GetMembers(
|
||
|
//| BindingFlags.DeclaredOnly
|
||
|
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))
|
||
|
{
|
||
|
if (member.DeclaringType != member.ReflectedType)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
// if (!inherited || member.MemberType != MemberTypes.Constructor) {
|
||
|
list.Add(new MemberEntry(member));
|
||
|
//}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static void AppendParams(StringBuilder sb, ParameterInfo[] parameters)
|
||
|
{
|
||
|
sb.Append('(');
|
||
|
for (int i = 0; i < parameters.Length; i++)
|
||
|
{
|
||
|
if (i != 0) sb.Append(',');
|
||
|
AppendType(sb, parameters[i].ParameterType);
|
||
|
}
|
||
|
sb.Append(')');
|
||
|
}
|
||
|
|
||
|
static void AppendType(StringBuilder sb, Type type)
|
||
|
{
|
||
|
if (IsArray(type))
|
||
|
{
|
||
|
AppendType(sb, type.GetElementType());
|
||
|
sb.Append("[]");
|
||
|
}
|
||
|
else if (type.IsByRef)
|
||
|
{
|
||
|
AppendType(sb, type.GetElementType());
|
||
|
sb.Append("@");
|
||
|
}
|
||
|
else if (type.IsPointer)
|
||
|
{
|
||
|
AppendType(sb, type.GetElementType());
|
||
|
sb.Append("*");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sb.Append(type.FullName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static bool ContainsInterface(Type[] types, Type type)
|
||
|
{
|
||
|
foreach (Type t in types)
|
||
|
{
|
||
|
if (ContainsType(t.GetInterfaces(), type)) return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static bool ContainsType(Type[] types, Type type)
|
||
|
{
|
||
|
if (types != null)
|
||
|
{
|
||
|
foreach (Type t in types)
|
||
|
{
|
||
|
if (t == type) return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
static MethodInfo GetAccessor(EventInfo evnt)
|
||
|
{
|
||
|
return evnt.GetAddMethod();
|
||
|
}
|
||
|
|
||
|
static MethodInfo GetAccessor(PropertyInfo property)
|
||
|
{
|
||
|
MethodInfo result = property.GetGetMethod();
|
||
|
if (result == null) result = property.GetSetMethod();
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static string GetMemberKey(MemberInfo member)
|
||
|
{
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
switch (member.MemberType)
|
||
|
{
|
||
|
case MemberTypes.Constructor:
|
||
|
sb.Append("M:");
|
||
|
sb.Append(member.DeclaringType.FullName);
|
||
|
sb.Append(".#ctor");
|
||
|
AppendParams(sb, ((ConstructorInfo)member).GetParameters());
|
||
|
break;
|
||
|
case MemberTypes.Field:
|
||
|
sb.Append("F:");
|
||
|
sb.Append(member.DeclaringType.FullName);
|
||
|
sb.Append('.');
|
||
|
sb.Append(((FieldInfo)member).Name);
|
||
|
break;
|
||
|
case MemberTypes.Property:
|
||
|
sb.Append("P:");
|
||
|
sb.Append(member.DeclaringType.FullName);
|
||
|
sb.Append('.');
|
||
|
sb.Append(((PropertyInfo)member).Name);
|
||
|
ParameterInfo[] pi = ((PropertyInfo)member).GetIndexParameters();
|
||
|
if (pi.Length != 0) AppendParams(sb, pi);
|
||
|
break;
|
||
|
case MemberTypes.Method:
|
||
|
sb.Append("M:");
|
||
|
sb.Append(member.DeclaringType.FullName);
|
||
|
sb.Append('.');
|
||
|
sb.Append(((MethodInfo)member).Name);
|
||
|
AppendParams(sb, ((MethodInfo)member).GetParameters());
|
||
|
break;
|
||
|
case MemberTypes.Event:
|
||
|
sb.Append("E:");
|
||
|
sb.Append(member.DeclaringType.FullName);
|
||
|
sb.Append('.');
|
||
|
sb.Append(((EventInfo)member).Name);
|
||
|
break;
|
||
|
}
|
||
|
return sb.ToString().Trim();
|
||
|
}
|
||
|
|
||
|
string[] GetInterfaceNames(Type type)
|
||
|
{
|
||
|
Type[] typeIntfs = type.GetInterfaces();
|
||
|
if (typeIntfs.Length == 0) return new string[0];
|
||
|
Type[] baseIntfs = type.BaseType == null ? null : type.BaseType.GetInterfaces();
|
||
|
ArrayList list = new ArrayList();
|
||
|
foreach (Type intf in typeIntfs)
|
||
|
{
|
||
|
if (!ContainsInterface(typeIntfs, intf))
|
||
|
{
|
||
|
string s = intf.Name;
|
||
|
#if GENERICS
|
||
|
if (intf.HasGenericArguments)
|
||
|
{
|
||
|
s+="<";
|
||
|
Type[] types = intf.GetGenericArguments();
|
||
|
for (int i = 0; i < types.Length; i++)
|
||
|
{
|
||
|
if (i != 0) s+=", ";
|
||
|
s+=types[i].Name;
|
||
|
}
|
||
|
s+=">";
|
||
|
}
|
||
|
#endif
|
||
|
list.Add(s);
|
||
|
s = "";
|
||
|
}
|
||
|
}
|
||
|
list.Sort();
|
||
|
return (string[])list.ToArray(typeof(string));
|
||
|
}
|
||
|
|
||
|
static bool IsVarArgs(MethodBase m)
|
||
|
{
|
||
|
return (m.CallingConvention == CallingConventions.VarArgs);
|
||
|
}
|
||
|
static bool IsArray(Type type)
|
||
|
{
|
||
|
return type.IsArray && type != typeof(Array);
|
||
|
}
|
||
|
|
||
|
static bool IsDelegate(Type type)
|
||
|
{
|
||
|
return type.IsSubclassOf(typeof(Delegate)) && type != typeof(MulticastDelegate);
|
||
|
}
|
||
|
|
||
|
static bool IsOverride(MethodInfo method)
|
||
|
{
|
||
|
return (method.Attributes & (MethodAttributes.Virtual |
|
||
|
MethodAttributes.NewSlot)) == MethodAttributes.Virtual;
|
||
|
}
|
||
|
|
||
|
void Write(string s)
|
||
|
{
|
||
|
WriteIndent();
|
||
|
writer.Write(s);
|
||
|
}
|
||
|
|
||
|
void Write(char ch)
|
||
|
{
|
||
|
WriteIndent();
|
||
|
writer.Write(ch);
|
||
|
}
|
||
|
public void WriteNamespace(string namespaceName, Type[] types)
|
||
|
{
|
||
|
Write("namespace ");
|
||
|
Write(namespaceName);
|
||
|
WriteLine();
|
||
|
Write("{");
|
||
|
WriteLine();
|
||
|
indent++;
|
||
|
foreach (Type t in types)
|
||
|
{
|
||
|
if (t.IsPublic && t.Namespace == namespaceName)
|
||
|
{
|
||
|
WriteTypeDecl(t);
|
||
|
}
|
||
|
}
|
||
|
indent--;
|
||
|
Write("} ");
|
||
|
WriteLine();
|
||
|
}
|
||
|
|
||
|
void WriteConstructor(ConstructorInfo ctor)
|
||
|
{
|
||
|
if (!(ctor.IsPublic || ctor.IsFamily || ctor.IsFamilyOrAssembly)) return;
|
||
|
if (ctor.IsStatic) return;
|
||
|
Write(ctor.IsPublic ? "public " : "protected ");
|
||
|
Write(ctor.DeclaringType.Name);
|
||
|
Write('(');
|
||
|
WriteParamList(ctor.GetParameters());
|
||
|
if (IsVarArgs(ctor))
|
||
|
{
|
||
|
Write(", __arglist");
|
||
|
}
|
||
|
Write(");");
|
||
|
WriteMemberEnd(ctor);
|
||
|
}
|
||
|
|
||
|
void WriteEvent(EventInfo evnt)
|
||
|
{
|
||
|
if (evnt.GetAddMethod() == null)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (!(evnt.GetAddMethod().IsPublic || evnt.GetAddMethod().IsFamily || evnt.GetAddMethod().IsFamilyOrAssembly)) return;
|
||
|
memberCt++;
|
||
|
Write(evnt.GetAddMethod().IsPublic ? "public " : "protected ");
|
||
|
Write("event ");
|
||
|
Write(evnt.EventHandlerType.Name);
|
||
|
Write(" ");
|
||
|
Write(evnt.Name);
|
||
|
Write(";");
|
||
|
WriteMemberEnd(evnt);
|
||
|
}
|
||
|
|
||
|
void WriteField(FieldInfo field)
|
||
|
{
|
||
|
if (!(field.IsPublic || field.IsFamily || field.IsFamilyOrAssembly)) return;
|
||
|
if (field.DeclaringType.IsEnum)
|
||
|
{
|
||
|
if (!field.IsLiteral) return;
|
||
|
Write(field.Name);
|
||
|
Write(',');
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Write(field.IsPublic ? "public " : "protected ");
|
||
|
if (field.IsStatic && field.IsLiteral)
|
||
|
{
|
||
|
Write("const ");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (field.IsStatic) Write("static ");
|
||
|
if (field.IsInitOnly) Write("readonly ");
|
||
|
}
|
||
|
WriteType(field.FieldType);
|
||
|
Write(' ');
|
||
|
Write(field.Name);
|
||
|
Write(';');
|
||
|
}
|
||
|
WriteMemberEnd(field);
|
||
|
}
|
||
|
|
||
|
void WriteIndent()
|
||
|
{
|
||
|
if (startOfLine)
|
||
|
{
|
||
|
for (int i = 0; i < indent; i++) writer.Write(" ");
|
||
|
startOfLine = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void WriteLine()
|
||
|
{
|
||
|
writer.WriteLine();
|
||
|
startOfLine = true;
|
||
|
}
|
||
|
|
||
|
public void WriteMember(MemberInfo member)
|
||
|
{
|
||
|
switch (member.MemberType)
|
||
|
{
|
||
|
case MemberTypes.Constructor:
|
||
|
WriteConstructor((ConstructorInfo)member);
|
||
|
break;
|
||
|
case MemberTypes.Field:
|
||
|
WriteField((FieldInfo)member);
|
||
|
break;
|
||
|
case MemberTypes.Property:
|
||
|
WriteProperty((PropertyInfo)member);
|
||
|
break;
|
||
|
case MemberTypes.Method:
|
||
|
WriteMethod((MethodInfo)member);
|
||
|
break;
|
||
|
case MemberTypes.Event:
|
||
|
WriteEvent((EventInfo)member);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void WriteMemberEnd(MemberInfo member)
|
||
|
{
|
||
|
if (includeMemberKeys)
|
||
|
{
|
||
|
Write(" // ");
|
||
|
Write(GetMemberKey(member));
|
||
|
}
|
||
|
WriteLine();
|
||
|
}
|
||
|
|
||
|
void WriteMethod(MethodInfo method)
|
||
|
{
|
||
|
if (!(method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly)) return;
|
||
|
if (method.IsSpecialName && !opNames.Contains(method.Name)) return;
|
||
|
if (IsOverride(method)) Write(""); //return;
|
||
|
memberCt++;
|
||
|
Write(method.IsPublic ? "public " : "protected ");
|
||
|
if (method.IsStatic) Write("static ");
|
||
|
WriteMethodModifiers(method);
|
||
|
if (method.IsSpecialName)
|
||
|
{
|
||
|
string op = (string)opNames[method.Name];
|
||
|
if (op == "explicit" || op == "implicit")
|
||
|
{
|
||
|
Write(op);
|
||
|
Write(" operator ");
|
||
|
WriteType(method.ReturnType);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WriteType(method.ReturnType);
|
||
|
Write(" operator ");
|
||
|
Write(op);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WriteType(method.ReturnType);
|
||
|
Write(' ');
|
||
|
Write(method.Name);
|
||
|
}
|
||
|
#if GENERICS
|
||
|
if (method.IsGenericMethodDefinition)
|
||
|
{
|
||
|
Write("<");
|
||
|
WriteTypeList(method.GetGenericArguments());
|
||
|
Write(">");
|
||
|
}
|
||
|
#endif
|
||
|
Write('(');
|
||
|
WriteParamList(method.GetParameters());
|
||
|
if (IsVarArgs(method))
|
||
|
{
|
||
|
Write(", __arglist");
|
||
|
}
|
||
|
Write(");");
|
||
|
WriteMemberEnd(method);
|
||
|
}
|
||
|
|
||
|
void WriteMethodModifiers(MethodInfo method)
|
||
|
{
|
||
|
if (method.DeclaringType.IsInterface)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
MethodAttributes attrs = method.Attributes;
|
||
|
if ((attrs & MethodAttributes.Final) != 0 &&
|
||
|
(attrs & MethodAttributes.Virtual) != 0 &&
|
||
|
(attrs & MethodAttributes.NewSlot) != 0)
|
||
|
{
|
||
|
attrs = 0;
|
||
|
}
|
||
|
if ((attrs & MethodAttributes.Final) != 0) Write("sealed ");
|
||
|
if ((attrs & MethodAttributes.Virtual) != 0)
|
||
|
{
|
||
|
switch (attrs & (MethodAttributes.NewSlot | MethodAttributes.Abstract))
|
||
|
{
|
||
|
case 0:
|
||
|
Write("override ");
|
||
|
break;
|
||
|
case MethodAttributes.NewSlot:
|
||
|
Write("virtual ");
|
||
|
break;
|
||
|
case MethodAttributes.Abstract:
|
||
|
Write("abstract override ");
|
||
|
break;
|
||
|
case MethodAttributes.NewSlot | MethodAttributes.Abstract:
|
||
|
Write("abstract ");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void WriteParamList(ParameterInfo[] parameters)
|
||
|
{
|
||
|
for (int i = 0; i < parameters.Length; i++)
|
||
|
{
|
||
|
ParameterInfo param = parameters[i];
|
||
|
if (i != 0) Write(", ");
|
||
|
Type type = param.ParameterType;
|
||
|
if (IsArray(type) && Attribute.IsDefined(param, typeof(ParamArrayAttribute), true))
|
||
|
{
|
||
|
Write("params ");
|
||
|
}
|
||
|
WriteType(type);
|
||
|
Write(' ');
|
||
|
Write(param.Name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void WriteProperty(PropertyInfo property)
|
||
|
{
|
||
|
MethodInfo accessor = GetAccessor(property);
|
||
|
if (accessor == null) return;
|
||
|
if (!(accessor.IsPublic || accessor.IsFamily || accessor.IsFamilyOrAssembly)) return;
|
||
|
if (IsOverride(accessor)) return;
|
||
|
ParameterInfo[] parameters = property.GetIndexParameters();
|
||
|
memberCt++;
|
||
|
Write(accessor.IsPublic ? "public " : "protected ");
|
||
|
if (accessor.IsStatic) Write("static ");
|
||
|
WriteMethodModifiers(accessor);
|
||
|
WriteType(property.PropertyType);
|
||
|
Write(' ');
|
||
|
if (parameters.Length == 0)
|
||
|
{
|
||
|
Write(property.Name);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Write("this[");
|
||
|
WriteParamList(accessor.GetParameters());
|
||
|
Write("]");
|
||
|
}
|
||
|
Write(" { ");
|
||
|
if (property.CanRead) Write("get; ");
|
||
|
if (property.CanWrite) Write("set; ");
|
||
|
Write("}");
|
||
|
WriteMemberEnd(property);
|
||
|
}
|
||
|
|
||
|
void WriteType(Type type)
|
||
|
{
|
||
|
|
||
|
if (IsArray(type))
|
||
|
{
|
||
|
WriteType(type.GetElementType());
|
||
|
Write('[');
|
||
|
for (int i = type.GetArrayRank(); i > 1; i--) Write(',');
|
||
|
Write(']');
|
||
|
}
|
||
|
else if (type.IsByRef)
|
||
|
{
|
||
|
Write("ref ");
|
||
|
WriteType(type.GetElementType());
|
||
|
}
|
||
|
else if (type.IsPointer)
|
||
|
{
|
||
|
WriteType(type.GetElementType());
|
||
|
Write('*');
|
||
|
}
|
||
|
#if GENERICS
|
||
|
else if (type.HasGenericArguments)
|
||
|
{
|
||
|
WriteSimpleTypeName(type);
|
||
|
Write("<");
|
||
|
WriteTypeList(type.GetGenericArguments());
|
||
|
Write(">");
|
||
|
}
|
||
|
#endif
|
||
|
else
|
||
|
{
|
||
|
WriteSimpleTypeName(type);
|
||
|
}
|
||
|
}
|
||
|
private void WriteTypeList(Type[] types)
|
||
|
{
|
||
|
for (int i = 0; i < types.Length; i++)
|
||
|
{
|
||
|
if (i != 0) Write(",");
|
||
|
WriteType(types[i]);
|
||
|
}
|
||
|
}
|
||
|
private void WriteSimpleTypeName(Type type)
|
||
|
{
|
||
|
string name = (string)typeNames[type];
|
||
|
if (name == null) name = type.Name;
|
||
|
Write(name);
|
||
|
}
|
||
|
|
||
|
public void WriteCustomAttribute(Attribute att)
|
||
|
{
|
||
|
Write("[");
|
||
|
Write(att.GetType().Name);
|
||
|
Write("(..)");
|
||
|
Write("]");
|
||
|
WriteLine();
|
||
|
|
||
|
}
|
||
|
|
||
|
public void WriteTypeDecl(Type type)
|
||
|
{
|
||
|
|
||
|
Attribute[] attrs = Attribute.GetCustomAttributes(type);
|
||
|
foreach (Attribute a in attrs)
|
||
|
{
|
||
|
WriteCustomAttribute(a);
|
||
|
}
|
||
|
|
||
|
if (type.IsPublic || type.IsNestedPublic)
|
||
|
{
|
||
|
Write("public ");
|
||
|
}
|
||
|
else if (type.IsNestedPrivate)
|
||
|
{
|
||
|
Write("private ");
|
||
|
}
|
||
|
else if (type.IsNestedAssembly)
|
||
|
{
|
||
|
Write("internal ");
|
||
|
}
|
||
|
else if (type.IsNestedFamily)
|
||
|
{
|
||
|
Write("protected ");
|
||
|
}
|
||
|
else if (type.IsNestedFamORAssem)
|
||
|
{
|
||
|
Write("protected internal ");
|
||
|
}
|
||
|
if (IsDelegate(type))
|
||
|
{
|
||
|
Write("delegate ");
|
||
|
MethodInfo method = type.GetMethod("Invoke");
|
||
|
WriteType(method.ReturnType);
|
||
|
Write(' ');
|
||
|
WriteTypeName(type);
|
||
|
Write('(');
|
||
|
WriteParamList(method.GetParameters());
|
||
|
Write(")");
|
||
|
WriteTypeConstraints(type);
|
||
|
Write(";");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ArrayList list = new ArrayList();
|
||
|
AddMemberEntries(list, type, true);
|
||
|
if (type.IsEnum)
|
||
|
{
|
||
|
Write("enum ");
|
||
|
WriteTypeName(type);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bool colonWritten = false;
|
||
|
if (type.IsValueType)
|
||
|
{
|
||
|
Write("struct ");
|
||
|
WriteTypeName(type);
|
||
|
}
|
||
|
else if (type.IsInterface)
|
||
|
{
|
||
|
Write("interface ");
|
||
|
WriteTypeName(type);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (type.IsAbstract) Write("abstract ");
|
||
|
if (type.IsSealed) Write("sealed ");
|
||
|
Write("class ");
|
||
|
WriteTypeName(type);
|
||
|
Type baseType = type.BaseType;
|
||
|
if (baseType != null && baseType != typeof(object))
|
||
|
{
|
||
|
Write(": ");
|
||
|
Write(baseType.Name);
|
||
|
colonWritten = true;
|
||
|
}
|
||
|
}
|
||
|
foreach (string s in GetInterfaceNames(type))
|
||
|
{
|
||
|
Write(colonWritten ? ", " : ": ");
|
||
|
Write(s);
|
||
|
colonWritten = true;
|
||
|
}
|
||
|
}
|
||
|
WriteTypeConstraints(type);
|
||
|
WriteLine();
|
||
|
Write('{');
|
||
|
WriteLine();
|
||
|
list.Sort();
|
||
|
indent++;
|
||
|
foreach (MemberEntry entry in list)
|
||
|
{
|
||
|
if (!entry.IsSecured)
|
||
|
WriteMember(entry.Member);
|
||
|
}
|
||
|
indent--;
|
||
|
Write('}');
|
||
|
}
|
||
|
WriteLine();
|
||
|
WriteLine();
|
||
|
}
|
||
|
|
||
|
void WriteTypeName(Type type)
|
||
|
{
|
||
|
|
||
|
Write(fullTypeNames ? type.FullName : type.Name);
|
||
|
#if GENERICS
|
||
|
if (type.IsGenericTypeDefinition)
|
||
|
{
|
||
|
Write("<");
|
||
|
WriteTypeList(type.GetGenericArguments());
|
||
|
Write(">");
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
void WriteTypeConstraints(Type type)
|
||
|
{
|
||
|
|
||
|
#if GENERICS
|
||
|
foreach (Type t in type.GetGenericArguments())
|
||
|
{
|
||
|
Type[] arr = t.GetInterfaces();
|
||
|
|
||
|
object[] arr2 = t.GetCustomAttributes(true);
|
||
|
if (t.BaseType != typeof(object) || arr.Length+arr2.Length > 0)
|
||
|
{
|
||
|
Write(" where ");
|
||
|
WriteTypeName(t);
|
||
|
Write(":");
|
||
|
}
|
||
|
if (t.BaseType != typeof(Object))
|
||
|
{
|
||
|
WriteTypeName(t.BaseType);
|
||
|
if (arr.Length + arr2.Length > 0) Write(",");
|
||
|
}
|
||
|
for (int i = 0; i < arr.Length; i++ )
|
||
|
{
|
||
|
WriteTypeName(arr[i]);
|
||
|
if (i < arr.Length-1 || arr2.Length>0) Write(",");
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < arr2.Length; i++)
|
||
|
{
|
||
|
if (arr2[i].GetType() == typeof(System.Runtime.CompilerServices.NewConstraintAttribute))
|
||
|
{
|
||
|
Write("new()");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Write(arr2[i].ToString());
|
||
|
}
|
||
|
if (i < arr.Length - 1) Write(",");
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
class MemberEntry : IComparable
|
||
|
{
|
||
|
MemberInfo member;
|
||
|
string sortKey;
|
||
|
bool secured = false;
|
||
|
|
||
|
public MemberEntry(MemberInfo member)
|
||
|
{
|
||
|
this.member = member;
|
||
|
try
|
||
|
{
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
switch (member.MemberType)
|
||
|
{
|
||
|
case MemberTypes.Constructor:
|
||
|
sb.Append('A');
|
||
|
AppendParams(sb, ((ConstructorInfo)member).GetParameters());
|
||
|
break;
|
||
|
case MemberTypes.Field:
|
||
|
sb.Append('B');
|
||
|
sb.Append(member.Name);
|
||
|
break;
|
||
|
case MemberTypes.Property:
|
||
|
ParameterInfo[] parameters = ((PropertyInfo)member).GetIndexParameters();
|
||
|
if (parameters.Length == 0)
|
||
|
{
|
||
|
sb.Append('C');
|
||
|
sb.Append(member.Name);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sb.Append('D');
|
||
|
AppendParams(sb, parameters);
|
||
|
}
|
||
|
break;
|
||
|
case MemberTypes.Method:
|
||
|
if (((MethodInfo)member).IsSpecialName && opSortKeys.Contains(member.Name))
|
||
|
{
|
||
|
sb.Append('F');
|
||
|
sb.Append((string)opSortKeys[member.Name]);
|
||
|
if (member.Name == "op_Implicit" || member.Name == "op_Explicit")
|
||
|
{
|
||
|
AppendType(sb, ((MethodInfo)member).ReturnType);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sb.Append('E');
|
||
|
sb.Append(member.Name);
|
||
|
}
|
||
|
AppendParams(sb, ((MethodInfo)member).GetParameters());
|
||
|
break;
|
||
|
case MemberTypes.Event:
|
||
|
sb.Append('G');
|
||
|
sb.Append(member.Name);
|
||
|
((EventInfo)member).GetAddMethod(); // Force strong name security exception here
|
||
|
break;
|
||
|
}
|
||
|
sortKey = sb.ToString();
|
||
|
}
|
||
|
catch (System.Security.SecurityException)
|
||
|
{
|
||
|
secured = true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
public MemberInfo Member
|
||
|
{
|
||
|
get { return member; }
|
||
|
}
|
||
|
|
||
|
public bool IsSecured
|
||
|
{
|
||
|
get { return secured; }
|
||
|
}
|
||
|
|
||
|
int IComparable.CompareTo(object other)
|
||
|
{
|
||
|
if (sortKey == null)
|
||
|
return -1;
|
||
|
return sortKey.CompareTo(((MemberEntry)other).sortKey);
|
||
|
}
|
||
|
|
||
|
static void AppendParams(StringBuilder sb, ParameterInfo[] parameters)
|
||
|
{
|
||
|
foreach (ParameterInfo param in parameters)
|
||
|
{
|
||
|
AppendType(sb, param.ParameterType);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void AppendType(StringBuilder sb, Type type)
|
||
|
{
|
||
|
if (IsArray(type))
|
||
|
{
|
||
|
AppendType(sb, type.GetElementType());
|
||
|
sb.Append("[]");
|
||
|
}
|
||
|
else if (type.IsByRef)
|
||
|
{
|
||
|
AppendType(sb, type.GetElementType());
|
||
|
sb.Append("@");
|
||
|
}
|
||
|
else if (type.IsPointer)
|
||
|
{
|
||
|
AppendType(sb, type.GetElementType());
|
||
|
sb.Append("*");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sb.Append(',');
|
||
|
string name = (string)typeNames[type];
|
||
|
if (name == null) name = type.Name;
|
||
|
sb.Append(name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class TXRef
|
||
|
{
|
||
|
static void Main(string[] args)
|
||
|
{
|
||
|
#if GENERICS
|
||
|
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Idle;
|
||
|
#endif
|
||
|
|
||
|
TypeWriter writer = new TypeWriter(Console.Out);
|
||
|
foreach (string s in args)
|
||
|
{
|
||
|
Assembly a = null;
|
||
|
try
|
||
|
{
|
||
|
a = Assembly.LoadFrom(s);
|
||
|
if (a == null)
|
||
|
a = Assembly.Load(s);
|
||
|
}
|
||
|
catch (Exception e) { Console.WriteLine(e); }
|
||
|
if (a == null)
|
||
|
{
|
||
|
Console.WriteLine("TxRef: could not load assembly '{0}'.", s);
|
||
|
return;
|
||
|
}
|
||
|
ArrayList l = new ArrayList();
|
||
|
Type[] types;
|
||
|
try
|
||
|
{
|
||
|
types = a.GetTypes();
|
||
|
}
|
||
|
catch (ReflectionTypeLoadException re)
|
||
|
{
|
||
|
foreach (Exception e in re.LoaderExceptions)
|
||
|
{
|
||
|
Console.WriteLine(e);
|
||
|
}
|
||
|
types = RemoveNulls(re.Types);
|
||
|
|
||
|
}
|
||
|
|
||
|
Array.Sort(types, new TypeComparer());
|
||
|
|
||
|
foreach (Type t in types)
|
||
|
{
|
||
|
if (t.IsPublic)
|
||
|
{
|
||
|
if (!l.Contains(t.Namespace))
|
||
|
l.Add(t.Namespace);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
l.Sort(null);
|
||
|
|
||
|
foreach (string namespaceName in l)
|
||
|
{
|
||
|
writer.WriteNamespace(namespaceName, types);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static Type[] RemoveNulls(Type[] types)
|
||
|
{
|
||
|
ArrayList l = new ArrayList();
|
||
|
foreach (Type t in types)
|
||
|
{
|
||
|
if (t != null) l.Add(t);
|
||
|
}
|
||
|
return (Type[])l.ToArray(typeof(Type));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class TypeComparer : IComparer
|
||
|
{
|
||
|
internal enum TypeGroup {
|
||
|
MainGroup = 0,
|
||
|
Enums = 1,
|
||
|
Collections = 2,
|
||
|
DelegatesAndEventArgs = 3,
|
||
|
Attributes = 4,
|
||
|
Exceptions = 5
|
||
|
}
|
||
|
|
||
|
internal static TypeGroup GetGroupForType(Type type) {
|
||
|
if (type.IsEnum) return TypeGroup.Enums;
|
||
|
if ((typeof(IEnumerable).IsAssignableFrom(type))) return TypeGroup.Collections;
|
||
|
if (type.IsSubclassOf(typeof(Delegate)) || type.IsSubclassOf(typeof(EventArgs))) return TypeGroup.DelegatesAndEventArgs;
|
||
|
if (type.IsSubclassOf(typeof(Attribute))) return TypeGroup.Attributes;
|
||
|
if (type.IsSubclassOf(typeof(Exception))) return TypeGroup.Exceptions;
|
||
|
return TypeGroup.MainGroup;
|
||
|
}
|
||
|
|
||
|
public int Compare(object obj1, object obj2)
|
||
|
{
|
||
|
Type t1 = obj1 as Type;
|
||
|
Type t2 = obj2 as Type;
|
||
|
|
||
|
// these are used to group by (for example all enums together)
|
||
|
TypeGroup t1Group = TypeComparer.GetGroupForType(t1);
|
||
|
TypeGroup t2Group = TypeComparer.GetGroupForType(t2);
|
||
|
|
||
|
if (t2Group != t1Group) return ((int)t1Group) < ((int)t2Group) ? -1 : 1;
|
||
|
return t1.Name.CompareTo(t2.Name);
|
||
|
}
|
||
|
}
|