public static void Main(string[] args) { var sgopts = new StubGenOptions (); var opts = new OptionSet () { { "o=|output-dir=", "Directory to generate classes in. Defaults to current directory", v => sgopts.OutputDir = v }, { "no-header", "Do not put header with license in generated files", v => sgopts.NoHeader = true }, { "l|license=", "Name of the license or path to a text file with license text (defaults to MIT/X11)", v => sgopts.LicenseName = v }, { "a|author=", "Author name", v => sgopts.AuthorName = v }, { "e|email=", "Author email", v => sgopts.AuthorEmail = v }, { "c|copyright=", "Copyright holder", v => sgopts.CopyrightHolder = v }, { "f|force|overwrite-all", "Overwrite all files without prompting.", v => sgopts.OverwriteAll = true }, { "d|debug", "Show more information on errors.", v => sgopts.Debug = true }, { "p|private|non-public", "Include private/internal members in the outline.", v => sgopts.IncludeNonPublic = true }, { "h|help|?", "Show this help screen", v => sgopts.ShowHelp = true } }; if (sgopts.ShowHelp) ShowHelp (opts); List <string> assemblies = opts.Parse (args); if (assemblies == null || assemblies.Count == 0) ShowHelp (opts); foreach (string ap in assemblies) ProcessAssembly (ap, sgopts); }
static void ProcessAssembly(string path, StubGenOptions opts) { string aname = Path.GetFileNameWithoutExtension (path); Console.Error.WriteLine ("Processing assembly {0}", aname); string outdir = Path.Combine (opts.OutputDir, aname); try { if (!Directory.Exists (outdir)) Directory.CreateDirectory (outdir); Generator.Run (path, opts, outdir); } catch (Exception ex) { Console.Error.WriteLine ("\tFailure. {0}", ex.Message); if (opts.Debug) { Console.Error.WriteLine (ex.StackTrace); Console.Error.WriteLine (); } } }
public static void Run(string filePath, string license, StreamWriter writer, TypeDefinition type, StubGenOptions opts) { string ns = type.Namespace; if (String.IsNullOrEmpty (ns)) ns = null; if (ns != null) Utils.Indent++; try { List <string> usings = Utils.Usings; usings.Clear (); var sb = new StringBuilder (); usings.AddUsing ("System"); WriteType (sb, usings, type, opts); if (usings.Count > 0) { usings.Sort (); foreach (string u in usings) { if (ns != null && String.Compare (u, ns, StringComparison.Ordinal) == 0) continue; writer.WriteLine ("using {0};", u); } writer.WriteLine (); } if (ns != null) { writer.WriteLine ("namespace {0}", ns); writer.WriteLine ("{"); } writer.Write (sb.ToString ()); if (ns != null) writer.WriteLine ("}"); } finally { if (ns != null) Utils.Indent--; } }
public static void Run(string assemblyPath, StubGenOptions opts, string outDir) { sgopts = opts; string license = GetLicenseBlock (opts.LicenseName); bool overwrite = opts.OverwriteAll; ModuleDefinition module = ModuleDefinition.ReadModule (assemblyPath); Console.Error.WriteLine ("\tTarget runtime: {0}", module.Runtime.Format ()); if (module.HasAssemblyReferences) { var typesPerAsm = new SortedDictionary <string, ulong> (StringComparer.Ordinal); AssemblyNameReference asmname; foreach (ModuleDefinition m in AssemblyDefinition.ReadAssembly (assemblyPath).Modules) { foreach (TypeReference tref in m.GetTypeReferences ().OnlyVisible (true)) { asmname = tref.Scope as AssemblyNameReference; if (asmname == null) continue; if (typesPerAsm.ContainsKey (asmname.FullName)) typesPerAsm [asmname.FullName]++; else typesPerAsm [asmname.FullName] = 1; } } var refs = new List <string> (); Console.Error.WriteLine ("\tAssembly references:"); foreach (AssemblyNameReference aref in module.AssemblyReferences) refs.Add (aref.FullName); refs.Sort (StringComparer.Ordinal); var unused = new List <string> (); bool present; ulong count; foreach (string s in refs) { present = AssemblyPresent (s); if (!typesPerAsm.TryGetValue (s, out count)) count = 0; if (count == 0) unused.Add (s); Console.Error.Write ("\t ["); if (present) Console.Error.Write ("present]"); else { Console.ForegroundColor = ConsoleColor.Red; Console.Error.Write ("missing]"); Console.ForegroundColor = ConsoleColor.DarkRed; } Console.Error.WriteLine (" {0}", s); Console.ResetColor (); } if (unused.Count > 0) { Console.Error.WriteLine (); Console.Error.WriteLine ("\tAssemblies referenced but not used by public APIs:"); unused.Sort (); foreach (string s in unused) Console.Error.WriteLine ("\t {0}", s); } } OutputAssemblyInfo (module, outDir, license, overwrite); foreach (TypeDefinition type in module.Types) { if (type.IsNotPublic) continue; try { currentFilePath = FilePathForType (outDir, type); if (!overwrite && File.Exists (currentFilePath)) { currentFilePath = null; continue; } using (FileStream fs = File.Open (currentFilePath, FileMode.Create, FileAccess.Write)) { using (var sw = new StreamWriter (fs, Encoding.UTF8)) { WriteHeader (sw, license); Outline.Run (currentFilePath, license, sw, type, opts); } } } catch (Exception ex) { Console.WriteLine ("\tFailure. Unable to generate file for type {0}. {1}", type.FullName, ex.Message); if (opts.Debug) Console.WriteLine (ex); } } }
static void ClassWriter(StringBuilder sb, List <string> usings, TypeDefinition type, StubGenOptions opts) { // TODO: process nested types bool includePrivate = opts.IncludeNonPublic; if (type.HasFields) { foreach (FieldDefinition field in type.Fields.OnlyVisible (includePrivate)) sb.Append (field.FormatName ()); } if (type.HasEvents) { foreach (EventDefinition ev in type.Events.OnlyVisible (includePrivate)) sb.Append (ev.FormatName ()); } if (type.HasProperties) { foreach (PropertyDefinition prop in type.Properties.OnlyVisible (includePrivate)) sb.Append (prop.FormatName ()); } if (type.HasMethods) { foreach (MethodDefinition method in type.Methods.OnlyVisible (includePrivate)) sb.Append (method.FormatName ()); } }
static void WriteType(StringBuilder sb, List <string> usings, TypeDefinition type, StubGenOptions opts) { Action <StringBuilder, List <string>, TypeDefinition, StubGenOptions> typeWriter = null; // TODO: security attributes if (type.IsSerializable) sb.AppendLineIndent ("[Serializable]"); if (type.HasCustomAttributes) sb.Append (type.CustomAttributes.Format ()); sb.AppendIndent (); FormatTypeAttributes (sb, type); if (type.IsEnum) { sb.Append ("enum"); typeWriter = EnumWriter; } else if (type.IsClass) { sb.Append ("class"); typeWriter = ClassWriter; } else if (type.IsInterface) { sb.Append ("interface"); typeWriter = InterfaceWriter; } else if (type.IsValueType) { if (type.FullName == "System.Delegate" || type.FullName == "System.MulticastDelegate") sb.Append ("delegate"); else sb.Append ("struct"); } sb.AppendFormat (" {0}", type.FormatName ()); bool haveColon = false; bool first = true; TypeReference tref = type.BaseType; if (WritableBaseType (tref)) { sb.Append (" : "); haveColon = true; first = false; usings.AddUsing (tref.Namespace); sb.Append (tref.FormatName ()); } if (type.HasInterfaces) { foreach (TypeReference tr in type.Interfaces.OnlyVisible (opts.IncludeNonPublic)) { if (first) { if (!haveColon) sb.Append (" : "); first = false; } else sb.Append (", "); usings.AddUsing (tr.Namespace); sb.Append (tr.FormatName ()); } } // TODO: output generic parameter constraints sb.AppendLine (); sb.AppendLineIndent ("{"); if (typeWriter != null) { Utils.Indent++; try { typeWriter (sb, usings, type, opts); } finally { Utils.Indent--; } } sb.AppendLineIndent ("}"); }
static void EnumWriter(StringBuilder sb, List <string> usings, TypeDefinition type, StubGenOptions opts) { if (!type.HasFields) return; bool includePrivate = opts.IncludeNonPublic; int count = type.Fields.Count; foreach (FieldDefinition field in type.Fields.OnlyVisible (includePrivate)) { count--; if (!field.HasConstant) continue; sb.AppendFormatIndent ("{0} = 0x{1:x2}", field.Name, field.Constant); if (count > 0) sb.Append (","); sb.AppendLine (); } }