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