public override async Task Generate(DirectoryInfo directory, ProgrammableBlockApi api) { var fileName = Path.Combine(directory.FullName, "Namespace-Index.md"); using (var file = File.CreateText(fileName)) { var writer = new MarkdownWriter(file); await writer.BeginParagraphAsync(); await writer.WriteAsync($"← {MarkdownInline.HRef("Index", "Api-Index")}"); await writer.EndParagraphAsync(); await writer.WriteHeaderAsync(3, "Assemblies"); await writer.BeginParagraphAsync(); await writer.WriteLineAsync("These are the game assemblies used by programmable block scripts."); await writer.WriteLineAsync(); foreach (var assembly in api.Entries.Select(e => e.AssemblyName).Distinct().OrderBy(n => n)) await writer.WriteLineAsync($"{assembly}.dll "); await writer.EndParagraphAsync(); await writer.WriteHeaderAsync(3, "Types"); await writer.BeginParagraphAsync(); await writer.WriteAsync("This index contains all types and members available to ingame scripting - with exception to the .NET types, because including those would have made the listing far too big. There will be links to Microsoft's own documentation for those types where appropriate."); await writer.EndParagraphAsync(); foreach (var blockGroup in api.Entries.Where(e => e.Member is Type).GroupBy(e => e.Member.GetNamespace()).OrderBy(g => g.Key)) { await writer.WriteHeaderAsync(3, blockGroup.Key); await writer.BeginParagraphAsync(); foreach (var type in blockGroup.OrderBy(e => e.ToString(ApiEntryStringFlags.ShortDisplayName | ApiEntryStringFlags.DeclaringTypes))) await writer.WriteLineAsync(MemberGenerator.LinkTo(WebUtility.HtmlEncode(type.ToString(ApiEntryStringFlags.ShortDisplayName | ApiEntryStringFlags.DeclaringTypes)), type)); await writer.EndParagraphAsync(); } await writer.FlushAsync(); } }
protected static async Task WriteDocumentation(ProgrammableBlockApi api, XmlDocNode docs, MarkdownWriter writer) { if (docs != null) { var context = new XmlDocWriteContext(key => ResolveTypeReference(api, key)); await docs.WriteMarkdown(context, writer); } }
string GetTypeInfo(ProgrammableBlockApi api, Type type) { var entry = api.GetEntry(type); if (entry == null) { return(type.GetHumanReadableName()); } return(LinkTo(entry.ToString(ApiEntryStringFlags.ShortDisplayName), entry)); }
async Task WriteMembers(ProgrammableBlockApi api, ApiEntry entry, MarkdownWriter writer) { var memberEntries = AllInheritedEntriesOf(entry).ToList(); await WriteTable("Fields", memberEntries.Where(m => m.Member is FieldInfo), api, entry, writer); await WriteTable("Events", memberEntries.Where(m => m.Member is EventInfo), api, entry, writer); await WriteTable("Properties", memberEntries.Where(m => m.Member is PropertyInfo), api, entry, writer); await WriteTable("Constructors", memberEntries.Where(m => m.Member is ConstructorInfo), api, entry, writer); await WriteTable("Methods", memberEntries.Where(m => m.Member is MethodInfo), api, entry, writer); }
async Task WriteTable(string title, IEnumerable <ApiEntry> entries, ProgrammableBlockApi api, ApiEntry entry, MarkdownWriter writer) { var items = entries.ToList(); if (items.Count == 0) { return; } await writer.WriteHeaderAsync(4, title); await writer.BeginTableAsync("Member", "Description"); foreach (var item in items) { await writer.BeginTableCellAsync(); await writer.WriteAsync(MemberGenerator.LinkTo(item.ToString(ApiEntryStringFlags.ParameterTypes), item)); await writer.EndTableCellAsync(); await writer.BeginTableCellAsync(); var obsoleteAttribute = item.Member.GetCustomAttribute <ObsoleteAttribute>(false); if (obsoleteAttribute != null) { await writer.BeginParagraphAsync(); if (string.IsNullOrWhiteSpace(obsoleteAttribute.Message)) { await writer.WriteAsync(MarkdownInline.Emphasized(MarkdownInline.Strong("Obsolete"))); } else { await writer.WriteAsync(MarkdownInline.Emphasized($"{MarkdownInline.Strong("Obsolete:")} {obsoleteAttribute.Message}")); } await writer.EndParagraphAsync(); } var context = new XmlDocWriteContext(key => ResolveTypeReference(api, key)); item.Documentation?.Summary?.WriteMarkdown(context, writer); if (entry != item.DeclaringEntry) { await writer.BeginParagraphAsync(); await writer.WriteAsync(MarkdownInline.Emphasized($"Inherited from {MemberGenerator.LinkTo(item.DeclaringEntry.ToString(ApiEntryStringFlags.ShortDisplayName), item.DeclaringEntry)}")); await writer.EndParagraphAsync(); } await writer.EndTableCellAsync(); } await writer.EndTableAsync(); }
async Task GeneratePage(ProgrammableBlockApi api, DirectoryInfo directory, IGrouping <string, ApiEntry> entries) { var fileName = Path.Combine(directory.FullName, entries.Key); using (var file = File.CreateText(fileName)) { var writer = new MarkdownWriter(file); var firstEntry = entries.First(); await writer.BeginParagraphAsync(); await writer.WriteAsync($"← {MarkdownInline.HRef("Index", "Api-Index")} ← {MarkdownInline.HRef("Namespace Index", "Namespace-Index")} ← {LinkTo(firstEntry.DeclaringEntry.ToString(ApiEntryStringFlags.ShortDisplayName), firstEntry.DeclaringEntry)}"); await writer.EndParagraphAsync(); foreach (var overload in entries) { await writer.WriteHeaderAsync(3, "Summary"); switch (overload.Member) { case ConstructorInfo constructorInfo: await WriteConstructor(api, overload, writer, constructorInfo); break; case FieldInfo fieldInfo: await WriteField(api, overload, writer, fieldInfo); break; case PropertyInfo propertyInfo: await WriteProperty(api, overload, writer, propertyInfo); break; case EventInfo eventInfo: await WriteEvent(api, overload, writer, eventInfo); break; case MethodInfo methodInfo: await WriteMethod(api, overload, writer, methodInfo); break; } } await writer.FlushAsync(); } }
async Task WriteConstructor(ProgrammableBlockApi api, ApiEntry overload, MarkdownWriter writer, ConstructorInfo constructorInfo) { await writer.BeginCodeBlockAsync(); await writer.WriteLineAsync(overload.ToString(ApiEntryStringFlags.Modifiers | ApiEntryStringFlags.GenericParameters | ApiEntryStringFlags.ParameterTypes | ApiEntryStringFlags.ParameterNames | ApiEntryStringFlags.ReturnValue | ApiEntryStringFlags.Accessors)); await writer.EndCodeBlockAsync(); if (overload.Documentation?.Summary != null) { await WriteDocumentation(api, overload.Documentation?.Summary, writer); } var parameters = constructorInfo.GetParameters(); if (parameters.Length > 0) { await writer.WriteHeaderAsync(3, "Parameters"); foreach (var parameter in parameters) { var returnEntry = api.GetEntry(parameter.GetActualParameterType(), true); await writer.WriteAsync("* "); await writer.WriteAsync(LinkTo(returnEntry.ToString(ApiEntryStringFlags.ShortDisplayName), returnEntry)); await writer.WriteAsync(" "); await writer.WriteAsync(parameter.Name); await writer.WriteLineAsync(); } } if (overload.Documentation?.Example != null) { await writer.WriteHeaderAsync(3, "Example"); await WriteDocumentation(api, overload.Documentation?.Example, writer); } if (overload.Documentation?.Remarks != null) { await writer.WriteHeaderAsync(3, "Remarks"); await WriteDocumentation(api, overload.Documentation?.Remarks, writer); } }
protected static KeyValuePair <string, string> ResolveTypeReference(ProgrammableBlockApi api, string key) { if (key.StartsWith("!:")) { return(new KeyValuePair <string, string>(null, key.Substring(2))); } var entry = api.Entries.FirstOrDefault(e => e.XmlDocKey == key); if (entry == null) { // Assume MS type var name = key.Substring(2); return(new KeyValuePair <string, string>($"https://docs.microsoft.com/en-us/dotnet/api/{name.ToLower()}?view=netframework-4.6", name)); } return(new KeyValuePair <string, string>(Path.GetFileNameWithoutExtension(entry.SuggestedFileName), entry.ToString(ApiEntryStringFlags.ShortDisplayName))); }
async Task WriteField(ProgrammableBlockApi api, ApiEntry overload, MarkdownWriter writer, FieldInfo fieldInfo) { await writer.BeginCodeBlockAsync(); await writer.WriteLineAsync(overload.ToString(ApiEntryStringFlags.Modifiers | ApiEntryStringFlags.GenericParameters | ApiEntryStringFlags.ParameterTypes | ApiEntryStringFlags.ParameterNames | ApiEntryStringFlags.ReturnValue | ApiEntryStringFlags.Accessors)); await writer.EndCodeBlockAsync(); if (overload.Documentation?.Summary != null) { await WriteDocumentation(api, overload.Documentation?.Summary, writer); } await writer.WriteHeaderAsync(3, "Returns"); var returnEntry = api.GetEntry(fieldInfo.FieldType, true); await writer.BeginParagraphAsync(); await writer.WriteAsync(LinkTo(returnEntry.ToString(ApiEntryStringFlags.ShortDisplayName), returnEntry)); await writer.EndParagraphAsync(); if (overload.Documentation?.Returns != null) { await WriteDocumentation(api, overload.Documentation?.Returns, writer); } if (overload.Documentation?.Example != null) { await writer.WriteHeaderAsync(3, "Example"); await WriteDocumentation(api, overload.Documentation?.Example, writer); } if (overload.Documentation?.Remarks != null) { await writer.WriteHeaderAsync(3, "Remarks"); await WriteDocumentation(api, overload.Documentation?.Remarks, writer); } }
public override async Task Generate(DirectoryInfo directory, ProgrammableBlockApi api) { var tasks = api.Entries.Where(e => !(e.Member is Type) && !ShouldBeIgnored(e)).GroupBy(e => e.SuggestedFileName).Select(g => GeneratePage(api, directory, g)); await Task.WhenAll(tasks); }
public abstract Task Generate(DirectoryInfo directory, ProgrammableBlockApi api);
async Task GeneratePage(ProgrammableBlockApi api, DirectoryInfo directory, ApiEntry entry) { var fileName = Path.Combine(directory.FullName, entry.SuggestedFileName); Debug.WriteLine(entry.FullName + " " + fileName); using (var file = File.CreateText(fileName)) { var writer = new MarkdownWriter(file); await writer.BeginParagraphAsync(); await writer.WriteAsync($"← {MarkdownInline.HRef("Index", "Api-Index")} ← {MarkdownInline.HRef("Namespace Index", "Namespace-Index")}"); await writer.EndParagraphAsync(); await writer.WriteHeaderAsync(4, $"{WebUtility.HtmlEncode(entry.ToString(ApiEntryStringFlags.GenericParameters))} {ConstructOf(entry)}"); await writer.BeginCodeBlockAsync(); await writer.WriteLineAsync(entry.ToString(ApiEntryStringFlags.Modifiers | ApiEntryStringFlags.GenericParameters | ApiEntryStringFlags.Inheritance)); await writer.EndCodeBlockAsync(); if (entry.Documentation?.Summary != null) { await WriteDocumentation(api, entry.Documentation?.Summary, writer); } await writer.BeginParagraphAsync(); await writer.WriteLineAsync($"{MarkdownInline.Strong("Namespace:")} {MarkdownInline.HRef(entry.NamespaceName, Path.GetFileNameWithoutExtension(ToMdFileName(entry.NamespaceName)))}"); await writer.WriteLineAsync($"{MarkdownInline.Strong("Assembly:")} {entry.AssemblyName}.dll"); await writer.EndParagraphAsync(); if (entry.BaseEntry != null) { await WriteInheritance(entry, writer); } if (entry.InheritedEntries.Count > 0) { await WriteInterfaces(entry, writer); } if (entry.InheritorEntries.Count > 0) { await WriteInheritors(entry, writer); } await WriteTypeDefinitions(entry, writer); var obsoleteAttribute = entry.Member.GetCustomAttribute <ObsoleteAttribute>(false); if (obsoleteAttribute != null) { await writer.WriteHeaderAsync(2, "Obsolete"); await writer.BeginParagraphAsync(); await writer.WriteLineAsync("This type should no longer be used and may be removed in the future. If you're using it, you should replace it as soon as possible. "); await writer.WriteAsync(obsoleteAttribute.Message); await file.WriteLineAsync(); } if (entry.Documentation?.Example != null) { await writer.WriteHeaderAsync(4, "Example"); await WriteDocumentation(api, entry.Documentation?.Example, writer); } if (entry.Documentation?.Remarks != null) { await writer.WriteHeaderAsync(4, "Remarks"); await WriteDocumentation(api, entry.Documentation?.Remarks, writer); } await WriteMembers(api, entry, writer); await writer.FlushAsync(); } }
public override async Task Generate(DirectoryInfo directory, ProgrammableBlockApi api) { var tasks = api.Entries.Where(e => e.DeclaringEntry == null || e.Member.MemberType == MemberTypes.NestedType).Select(g => GeneratePage(api, directory, g)); await Task.WhenAll(tasks); }
public override async Task Generate(DirectoryInfo directory, ProgrammableBlockApi api) { var namespaces = api.Entries.GroupBy(e => e.NamespaceName); await Task.WhenAll(namespaces.Select(ns => GenerateNamespaceDoc(directory, ns))); }