private void WriteMethods(Type type, MarkdownWriter writer) { var methods = type.GetMethods(MemberSearchFlags) // Exclude compiler-generated and internal methods .Where(m => !m.IsSpecialName && !m.IsAssembly) // Exclude protected methods when class is sealed .Where(m => type.IsSealed ? m.IsPublic : !m.IsPrivate) // Sort alphabetically... .OrderBy(m => m.Name) // ... then by parameter count. .ThenBy(m => m.GetParameters().Length) .ToArray(); if (methods.Length > 0) { writer.WriteHeader(3, "Methods"); foreach (var method in methods) { var methodDocs = Docs[ID.GetIDString(method)]; // Heading writer.WriteHeader(4, DocUtilities.GetMethodSignature(method, false, false), true); PrintObsoleteWarning(method, writer); Summary(methodDocs, writer); writer.WriteCodeBlock(Lang, DocUtilities.GetMethodSignature(method, true, true)); // Parameters WriteParamList(4, method, writer, methodDocs); Returns(4, methodDocs, writer); Remarks(4, methodDocs, writer); } } }
private void WriteConstructors(Type type, MarkdownWriter writer) { // Constructor list var ctors = type.GetConstructors(); if (ctors.Length > 0) { writer.WriteHeader(3, "Constructors"); for (int i = 0; i < ctors.Length; i++) { // Heading for constructor section var ctorDocs = Docs[ID.GetIDString(ctors[i])]; writer.WriteHeader(4, DocUtilities.GetMethodSignature(ctors[i], false, false)); PrintObsoleteWarning(ctors[i], writer); Summary(ctorDocs, writer); // Signature writer.WriteCodeBlock(Lang, DocUtilities.GetMethodSignature(ctors[i], true, true)); // Get constructor's parameters and associated docs WriteParamList(5, ctors[i], writer, ctorDocs); Remarks(5, ctorDocs, writer); } } }
public override void BuildDocs(string outputPath) { outputPath = DocUtilities.ChangeExtension(outputPath, "md"); // Write markdown file using (var writer = new MarkdownWriter(outputPath)) { foreach (var type in Library.ExportedTypes.Where(t => !t.Name.StartsWith("_")).OrderBy(t => t.Name)) { // Pull XML docs for type var typeDocs = Docs[ID.GetIDString(type)]; // Header, e.g. "StringBuilder class (System)" writer.WriteHeader(2, DocUtilities.GetTypeTitle(type, true), true); // Summary and other info PrintObsoleteWarning(type, writer); writer.WriteParagraph($"**Namespace:** {type.Namespace}"); writer.WriteParagraph($"**Inheritance:** {DocUtilities.GetInheritanceString(type)}", true); Summary(typeDocs, writer); // Signature writer.WriteCodeBlock(Lang, DocUtilities.GetClassSignature(type)); // Members WriteConstructors(type, writer); WriteProperties(type, writer); WriteIndexers(type, writer); WriteFields(type, writer); WriteMethods(type, writer); } } }
private void WriteFields(Type type, MarkdownWriter writer) { var fields = type.GetFields() .Where(f => !f.IsSpecialName) .OrderBy(f => f.Name) .ToArray(); if (fields.Length == 0) { return; } writer.WriteHeader(3, "Fields"); for (int i = 0; i < fields.Length; i++) { var fieldDocs = Docs[ID.GetIDString(fields[i])]; writer.WriteHeader(4, DocUtilities.GetFieldSignature(fields[i], false)); PrintObsoleteWarning(fields[i], writer); Summary(fieldDocs, writer); writer.WriteCodeBlock(Lang, DocUtilities.GetFieldSignature(fields[i], true)); Remarks(5, fieldDocs, writer); } }
private void WriteIndexers(Type type, MarkdownWriter writer) { var indexers = type.GetProperties() .Where(p => p.GetIndexParameters().Length > 0) .OrderBy(p => p.GetIndexParameters().Length) .ToArray(); if (indexers.Length == 0) { return; } writer.WriteHeader(3, "Indexers"); for (int i = 0; i < indexers.Length; i++) { var indexDocs = Docs[ID.GetIDString(indexers[i])]; writer.WriteHeader(4, DocUtilities.GetPropertySignature(indexers[i], false, true, false)); PrintObsoleteWarning(indexers[i], writer); Summary(indexDocs, writer); writer.WriteCodeBlock(Lang, DocUtilities.GetPropertySignature(indexers[i], true, true, true)); Remarks(5, indexDocs, writer); } }
private void WriteProperties(Type type, MarkdownWriter writer) { var props = type.GetProperties(MemberSearchFlags) // Show protected members if class is not sealed .Where(p => type.IsSealed ? (p.CanRead && p.GetMethod.IsPublic) || (p.CanWrite && p.SetMethod.IsPublic) : (p.CanRead && !p.GetMethod.IsPrivate) || (p.CanWrite && !p.SetMethod.IsPrivate)) // Indexers are technically properties, but we want to handle them separately .Where(p => p.GetIndexParameters().Length == 0) // Sort alphabetically .OrderBy(p => p.Name) .ToArray(); if (props.Length == 0) { return; } writer.WriteHeader(3, "Properties"); for (int i = 0; i < props.Length; i++) { var propDocs = Docs[ID.GetIDString(props[i])]; writer.WriteHeader(4, DocUtilities.GetPropertySignature(props[i], false, false, false)); PrintObsoleteWarning(props[i], writer); Summary(propDocs, writer); writer.WriteCodeBlock(Lang, DocUtilities.GetPropertySignature(props[i], true, true, true)); Remarks(5, propDocs, writer); } }
static void Main(string[] args) { var paths = Args.GetPaths(); if (paths.Length == 0 || Args.Help) { Console.WriteLine($"Usage: {AppDomain.CurrentDomain.FriendlyName} [OPTIONS]... <dll_pathfilename>"); Console.WriteLine(); Console.WriteLine($"Options:"); Console.WriteLine($" -out <path> Specifies the path where the docs will be saved."); Console.WriteLine($" -xml <path> Specifies a custom XML documentation path."); Console.WriteLine($" --slim Specifies that the docs will be combined into a single .md file."); Console.WriteLine($" --noxml Don't use XML."); Console.WriteLine($" --mgtable methods groups in type page will reported in a table with summary foreach method in the group"); Console.WriteLine($" --mgspace space vertically each method when reported in groups"); Console.WriteLine($" --proptable properties in type page will reported in a table with summary foreach"); return; } var dllPath = Path.GetFullPath(paths[0]); var xmlPath = Args.Property("xml", DocUtilities.ChangeExtension(dllPath, "xml")); var outputPath = Args.Property("out", "docs"); var outputDir = Path.GetDirectoryName(outputPath); bool ignoreXML = Args.Flag("noxml"); // Check whether the file even exists if (!File.Exists(dllPath)) { Console.WriteLine($"File '{dllPath}' does not exist."); return; } try { Console.WriteLine("Building docs..."); var dll = Assembly.LoadFrom(dllPath); DocpalGenerator docpal; var xmlData = new XmlDocument(); // Load XML document if (File.Exists(xmlPath) && !ignoreXML) { xmlData.Load(xmlPath); Console.WriteLine($"Found XML: {xmlPath}"); } else { Console.WriteLine("No XML docs found, using only assembly..."); } var xmlDocs = new ProjectXmlDocs(xmlData); // Determine type of docs generator to use if (Args.Flag("slim")) { docpal = new DocpalSlim(xmlDocs, dll); } else { docpal = new DocpalPages(xmlDocs, dll); } Directory.CreateDirectory(outputDir); // Run build docpal.BuildDocs(outputPath); Console.WriteLine("Done, enjoy!"); } catch (Exception e) { Console.WriteLine($"Unfortunately, there was an error.\n\n{e}"); Environment.Exit(1); } }
public override void BuildDocs(string outputPath) { var pages = new PageTree("docs"); var PageTrees = new List <PageTree>(); foreach (var type in Library.GetExportedTypes()) { var typePath = $"{type.Namespace.Replace('.', '/')}/{DocUtilities.GetURLTitle(type)}"; var typeData = Docs[ID.GetIDString(type)]; pages[typePath] = new TypePage(type, typeData, Docs); PageTrees.Add(pages.GetNode(typePath)); // Constructors var ctors = type.GetConstructors(); if (ctors.Length > 0) { // Path to ctors group var ctorsGroupPath = $"{typePath}/ctors"; var ctorsData = new Dictionary <ConstructorInfo, MemberXmlDocs>(); foreach (var ctor in ctors) { var ctorData = Docs[ID.GetIDString(ctor)]; ctorsData.Add(ctor, ctorData); } pages[ctorsGroupPath] = new ConstructorsPage(type, ctors, ctorsData); PageTrees.Add(pages.GetNode(ctorsGroupPath)); } // Method groups foreach (var methodGroup in type.GetMethods() .Where(m => !m.Name.StartsWith("get_") && !m.Name.StartsWith("set_")) .GroupBy(m => m.Name)) { // Path to method group var methodGroupPath = $"{typePath}/{methodGroup.Key}"; // Map of reflected methods and documentation var methods = new Dictionary <MethodInfo, MemberXmlDocs>(); foreach (var method in methodGroup) { var methodData = Docs[ID.GetIDString(method)]; methods[method] = methodData; } pages[methodGroupPath] = new MethodGroupPage(type, methodGroup.Key, methods); PageTrees.Add(pages.GetNode(methodGroupPath)); } // Fields foreach (var field in type.GetFields().Where(f => (f.IsPublic || !f.IsPrivate) && (!f.DeclaringType.IsEnum || !f.IsSpecialName))) { var fieldPath = Path.Combine(typePath, field.Name).Replace('\\', '/'); var fieldData = Docs[ID.GetIDString(field)]; pages[fieldPath] = new FieldPage(field, fieldData); PageTrees.Add(pages.GetNode(fieldPath)); } // Properties and Indexers int numIndexers = 0; foreach (var property in type.GetProperties()) { var propData = Docs[ID.GetIDString(property)]; string propPath; if (property.GetIndexParameters().Length > 0) { propPath = $"{typePath}/this/{++numIndexers}"; } else { propPath = $"{typePath}/{property.Name}"; } pages[propPath] = new PropertyPage(property, propData); PageTrees.Add(pages.GetNode(propPath)); } } // Create a task for each document that needs to be exported, run them all at once var exportTasks = new Task[PageTrees.Count]; for (int i = 0; i < PageTrees.Count; i++) { var node = PageTrees[i]; exportTasks[i] = Task.Run(() => { var documentDir = Directory.GetParent($"{outputPath}/{node.Path}").FullName; var documentPath = $"{outputPath}/{node.Path}.md"; Directory.CreateDirectory(documentDir); using (var writer = new MarkdownWriter(documentPath)) { node.Page.Render(node, writer); } }); } // Wait for all export tasks to finish Task.WaitAll(exportTasks); }
static void Main(string[] args) { var paths = Args.GetPaths(); if (paths.Length == 0) { Console.WriteLine("No path specified."); return; } var dllPath = Path.GetFullPath(paths[0]); var xmlPath = Args.Property("xml", DocUtilities.ChangeExtension(dllPath, "xml")); var outputPath = Args.Property("out", "docs"); var outputDir = Path.GetDirectoryName(outputPath); bool ignoreXML = Args.Flag("noxml"); // Check whether the file even exists if (!File.Exists(dllPath)) { Console.WriteLine($"File '{dllPath}' does not exist."); return; } try { Console.WriteLine("Building docs..."); var dll = Assembly.LoadFile(dllPath); DocpalGenerator docpal; var xmlData = new XmlDocument(); // Load XML document if (File.Exists(xmlPath) && !ignoreXML) { xmlData.Load(xmlPath); Console.WriteLine($"Found XML: {xmlPath}"); } else { Console.WriteLine("No XML docs found, using only assembly..."); } var xmlDocs = new ProjectXmlDocs(xmlData); // Determine type of docs generator to use if (Args.Flag("slim")) { docpal = new DocpalSlim(xmlDocs, dll); } else { docpal = new DocpalPages(xmlDocs, dll); } Directory.CreateDirectory(outputDir); // Run build docpal.BuildDocs(outputPath); Console.WriteLine("Done, enjoy!"); } catch (Exception e) { Console.WriteLine($"Unfortunately, there was an error.\n\n{e}"); Environment.Exit(1); } }