singrdk/base/Windows/txref/TxRef.cs

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);
}
}