Skip to content

Commit

Permalink
feat: adjust markdown display to align yml (#9249)
Browse files Browse the repository at this point in the history
* feat: adjust markdown display to align yml

* test(snapshot): update snapshots for 012bf83

* remove md snapshot

* comment cache

---------

Co-authored-by: Yufei Huang <[email protected]>
  • Loading branch information
yufeih and yufeih authored Sep 27, 2023
1 parent a152f33 commit b5b487c
Show file tree
Hide file tree
Showing 129 changed files with 3,564 additions and 2,734 deletions.
32 changes: 24 additions & 8 deletions samples/seed/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,34 @@
"namespaceLayout": "nested",
"enumSortOrder": "declaringOrder",
"output": "obj/api"
},
{
"src": [
{
"files": [
"assembly/bin/**/*.dll",
"project/**/*.csproj",
"solution/**/*.sln",
"csharp/**/*.cs",
"vb/**/*.vb"
],
"exclude": [
"project/Project.Core/**"
],
"src": "dotnet"
}
],
"namespaceLayout": "nested",
"enumSortOrder": "declaringOrder",
"outputFormat": "markdown",
"output": "obj/md"
}
],
"build": {
"content": [
{
"files": [ "**/*.yml" ],
"src": "obj/api",
"dest": "api"
},
{
"files": [ "articles/**/*.{md,yml}", "*.md", "toc.yml", "restapi/**", "md/**", "md2/**" ]
}
{ "files": [ "**/*.yml" ], "src": "obj/api", "dest": "api" },
{ "files": [ "**" ], "src": "obj/md", "dest": "md" },
{ "files": [ "articles/**/*.{md,yml}", "*.md", "toc.yml", "restapi/**", "md/**", "md2/**" ] }
],
"resource": [
{
Expand Down
2 changes: 2 additions & 0 deletions samples/seed/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
items:
- name: .NET API
href: obj/api/
- name: .NET API (markdown)
href: obj/md/
- name: REST API
href: restapi/
128 changes: 65 additions & 63 deletions src/Docfx.Dotnet/MarkdownFormatter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Concurrent;
using System.Text;
using Docfx.Common;
using Docfx.DataContracts.ManagedReference;
Expand Down Expand Up @@ -52,6 +53,7 @@ public static void Save(List<(IAssemblySymbol symbol, Compilation compilation)>
var filter = new SymbolFilter(config, options);
var extensionMethods = assemblies.SelectMany(assembly => assembly.symbol.FindExtensionMethods(filter)).ToArray();
var allAssemblies = new HashSet<IAssemblySymbol>(assemblies.Select(a => a.symbol), SymbolEqualityComparer.Default);
var commentCache = new ConcurrentDictionary<ISymbol, XmlComment>(SymbolEqualityComparer.Default);

var tocNodes = new Dictionary<string, TocNode>();
var allSymbols = new List<(ISymbol symbol, Compilation compilation)>();
Expand Down Expand Up @@ -225,7 +227,6 @@ static void SortToc(List<TocNode> items, bool root)

if (!root)
{
InsertCategory(TocNodeType.Namespace, "Namespaces");
InsertCategory(TocNodeType.Class, "Classes");
InsertCategory(TocNodeType.Struct, "Structs");
InsertCategory(TocNodeType.Interface, "Interfaces");
Expand Down Expand Up @@ -355,11 +356,11 @@ void Namespaces()
if (items.Count is 0)
return;

sb.AppendLine($"## Namespaces").AppendLine();
sb.AppendLine($"### Namespaces").AppendLine();

foreach (var (symbol, compilation) in items)
{
sb.AppendLine(Link(symbol, compilation)).AppendLine();
sb.AppendLine(ShortLink(symbol, compilation)).AppendLine();
var comment = Comment(symbol, compilation);
if (!string.IsNullOrEmpty(comment?.Summary))
sb.AppendLine(comment.Summary).AppendLine();
Expand All @@ -372,11 +373,11 @@ void Types(Func<INamedTypeSymbol, bool> predicate, string headingText)
if (items.Count == 0)
return;

sb.AppendLine($"## {headingText}").AppendLine();
sb.AppendLine($"### {headingText}").AppendLine();

foreach (var (symbol, compilation) in items)
{
sb.AppendLine(Link(symbol, compilation)).AppendLine();
sb.AppendLine(ShortLink(symbol, compilation)).AppendLine();
var comment = Comment(symbol, compilation);
if (!string.IsNullOrEmpty(comment?.Summary))
sb.AppendLine(comment.Summary).AppendLine();
Expand Down Expand Up @@ -562,14 +563,14 @@ void MemberSummaryList<T>(IEnumerable<(T, Compilation)> symbols) where T : ISymb
void Inheritance()
{
var items = new List<ISymbol>();
for (var i = type; i != null; i = i.BaseType)
for (var i = type; i is not null && i.SpecialType is not SpecialType.System_ValueType; i = i.BaseType)
items.Add(i);

if (items.Count <= 1)
return;

items.Reverse();
sb.AppendLine($"#### Inheritance");
sb.AppendLine($"###### Inheritance");
List(" \u2190 ", items);
}

Expand All @@ -583,7 +584,7 @@ from s in allSymbols
if (items.Count is 0)
return;

sb.AppendLine($"#### Derived");
sb.AppendLine($"###### Derived");
List(", ", items);
}

Expand All @@ -593,7 +594,7 @@ void Implements()
if (items.Count is 0)
return;

sb.AppendLine($"#### Implements");
sb.AppendLine($"###### Implements");
List(", ", items);
}

Expand All @@ -603,7 +604,7 @@ void InheritedMembers()
if (items.Count is 0)
return;

sb.AppendLine($"#### Inherited Members");
sb.AppendLine($"###### Inherited Members");
List(", ", items);
}
}
Expand All @@ -626,13 +627,13 @@ void ExtensionMethods(INamedTypeSymbol type)
if (items.Count is 0)
return;

sb.AppendLine($"#### Extension Methods");
sb.AppendLine($"###### Extension Methods");
List(", ", items);
}

void List(string separator, IEnumerable<ISymbol> items)
{
sb.AppendLine(string.Join(separator, items.Select(i => "\n" + Link(i, compilation)))).AppendLine();
sb.AppendLine(string.Join(separator, items.Select(i => "\n" + ShortLink(i, compilation)))).AppendLine();
}

void Parameters(ISymbol symbol, XmlComment? comment, string heading = "##")
Expand All @@ -645,7 +646,7 @@ void Parameters(ISymbol symbol, XmlComment? comment, string heading = "##")

foreach (var param in parameters)
{
sb.AppendLine($"`{Escape(param.Name)}` {Link(param.Type, compilation)}").AppendLine();
sb.AppendLine($"`{Escape(param.Name)}` {FullLink(param.Type, compilation)}").AppendLine();

if (comment?.Parameters?.TryGetValue(param.Name, out var value) ?? false)
sb.AppendLine($"{value}").AppendLine();
Expand All @@ -658,7 +659,7 @@ void Returns(IMethodSymbol symbol, XmlComment? comment, string heading = "##")
return;

sb.AppendLine($"{heading} Returns").AppendLine();
sb.AppendLine(Link(symbol.ReturnType, compilation)).AppendLine();
sb.AppendLine(FullLink(symbol.ReturnType, compilation)).AppendLine();

if (!string.IsNullOrEmpty(comment?.Returns))
sb.AppendLine($"{comment.Returns}").AppendLine();
Expand Down Expand Up @@ -706,8 +707,8 @@ void Field(IFieldSymbol symbol, Compilation compilation, string heading)
Summary(comment);
Syntax(symbol);

sb.AppendLine("Field Value").AppendLine();
sb.AppendLine(Link(symbol.Type, compilation)).AppendLine();
sb.AppendLine($"{heading}# Field Value").AppendLine();
sb.AppendLine(FullLink(symbol.Type, compilation)).AppendLine();

Examples(comment, $"{heading}#");
Remarks(comment, $"{heading}#");
Expand All @@ -723,8 +724,8 @@ void Property(IPropertySymbol symbol, Compilation compilation, string heading)
Summary(comment);
Syntax(symbol);

sb.AppendLine("Property Value").AppendLine();
sb.AppendLine(Link(symbol.Type, compilation)).AppendLine();
sb.AppendLine($"{heading}# Property Value").AppendLine();
sb.AppendLine(FullLink(symbol.Type, compilation)).AppendLine();

Examples(comment, $"{heading}#");
Remarks(comment, $"{heading}#");
Expand All @@ -740,8 +741,8 @@ void Event(IEventSymbol symbol, Compilation compilation, string heading)
Summary(comment);
Syntax(symbol);

sb.AppendLine("Event Type").AppendLine();
sb.AppendLine(Link(symbol.Type, compilation)).AppendLine();
sb.AppendLine($"{heading}# Event Type").AppendLine();
sb.AppendLine(FullLink(symbol.Type, compilation)).AppendLine();

Examples(comment, $"{heading}#");
Remarks(comment, $"{heading}#");
Expand Down Expand Up @@ -771,9 +772,11 @@ void EnumFields(INamedTypeSymbol type)

void Info()
{
var assemblies = string.Join(", ", symbols.Select(s => s.symbol.ContainingAssembly.Name).Distinct().Select(n => $"{n}.dll"));
sb.AppendLine($"__Namespace:__ {Link(symbol.ContainingNamespace, compilation)} ");
sb.AppendLine($"__Assembly:__ {assemblies}").AppendLine();
sb.AppendLine($"Namespace: {ShortLink(symbol.ContainingNamespace, compilation)} ");

var assemblies = symbols.Select(s => s.symbol.ContainingAssembly.Name).Where(n => n != "?").Distinct().Select(n => $"{n}.dll").ToList();
if (assemblies.Count > 0)
sb.AppendLine($"Assembly: {string.Join(", ", assemblies)}").AppendLine();
}

void Summary(XmlComment? comment)
Expand Down Expand Up @@ -843,29 +846,24 @@ void SeeAlsos(XmlComment? comment, string heading = "##")

string Cref(string commentId)
{
return DocumentationCommentId.GetFirstSymbolForDeclarationId(commentId, compilation) is { } symbol ? Link(symbol, compilation) : "";
return DocumentationCommentId.GetFirstSymbolForDeclarationId(commentId, compilation) is { } symbol ? FullLink(symbol, compilation) : "";
}
}

string Link(ISymbol symbol, Compilation compilation)
string ShortLink(ISymbol symbol, Compilation compilation)
{
return symbol.Kind is SymbolKind.Method or SymbolKind.Namespace or SymbolKind.Event or SymbolKind.Property or SymbolKind.Field ? ShortLink() : FullLink();

string ShortLink()
{
var title = SymbolFormatter.GetNameWithType(symbol, SyntaxLanguage.CSharp);
var url = SymbolUrlResolver.GetSymbolUrl(symbol, compilation, config.MemberLayout, SymbolUrlKind.Markdown, allAssemblies);
return string.IsNullOrEmpty(url) ? Escape(title) : $"[{Escape(title)}]({Escape(url)})";
}
var title = SymbolFormatter.GetNameWithType(symbol, SyntaxLanguage.CSharp);
var url = SymbolUrlResolver.GetSymbolUrl(symbol, compilation, config.MemberLayout, SymbolUrlKind.Markdown, allAssemblies);
return string.IsNullOrEmpty(url) ? Escape(title) : $"[{Escape(title)}]({Escape(url)})";
}

string FullLink()
{
var parts = SymbolFormatter.GetNameWithTypeParts(symbol, SyntaxLanguage.CSharp);
var linkItems = SymbolFormatter.ToLinkItems(parts, compilation, config.MemberLayout, allAssemblies, overload: false, SymbolUrlKind.Markdown);
string FullLink(ISymbol symbol, Compilation compilation)
{
var parts = SymbolFormatter.GetNameWithTypeParts(symbol, SyntaxLanguage.CSharp);
var linkItems = SymbolFormatter.ToLinkItems(parts, compilation, config.MemberLayout, allAssemblies, overload: false, SymbolUrlKind.Markdown);

return string.Concat(linkItems.Select(i =>
string.IsNullOrEmpty(i.Href) ? Escape(i.DisplayName) : $"[{Escape(i.DisplayName)}]({Escape(i.Href)})"));
}
return string.Concat(linkItems.Select(i =>
string.IsNullOrEmpty(i.Href) ? Escape(i.DisplayName) : $"[{Escape(i.DisplayName)}]({Escape(i.Href)})"));
}

string NameOnlyLink(ISymbol symbol, Compilation compilation)
Expand All @@ -877,34 +875,38 @@ string NameOnlyLink(ISymbol symbol, Compilation compilation)

XmlComment? Comment(ISymbol symbol, Compilation compilation)
{
var src = VisitorHelper.GetSourceDetail(symbol, compilation);
var context = new XmlCommentParserContext
// Cache XML comment to avoid duplicated parsing and warnings
return commentCache.GetOrAdd(symbol, symbol =>
{
SkipMarkup = config.ShouldSkipMarkup,
AddReferenceDelegate = (a, b) => { },
Source = src,
ResolveCode = ResolveCode,
};
var src = VisitorHelper.GetSourceDetail(symbol, compilation);
var context = new XmlCommentParserContext
{
SkipMarkup = config.ShouldSkipMarkup,
AddReferenceDelegate = (a, b) => { },
Source = src,
ResolveCode = ResolveCode,
};

var comment = symbol.GetDocumentationComment(compilation, expandIncludes: true, expandInheritdoc: true);
return XmlComment.Parse(comment.FullXmlFragment, context);
var comment = symbol.GetDocumentationComment(compilation, expandIncludes: true, expandInheritdoc: true);
return XmlComment.Parse(comment.FullXmlFragment, context);

string? ResolveCode(string source)
{
var basePath = config.CodeSourceBasePath ?? (
src?.Path is { } sourcePath
? Path.GetDirectoryName(Path.GetFullPath(Path.Combine(EnvironmentContext.BaseDirectory, sourcePath)))
: null);

var path = Path.GetFullPath(Path.Combine(basePath ?? "", source));
if (!File.Exists(path))
string? ResolveCode(string source)
{
Logger.LogWarning($"Source file '{path}' not found.");
return null;
}
var basePath = config.CodeSourceBasePath ?? (
src?.Path is { } sourcePath
? Path.GetDirectoryName(Path.GetFullPath(Path.Combine(EnvironmentContext.BaseDirectory, sourcePath)))
: null);

return File.ReadAllText(path);
}
var path = Path.GetFullPath(Path.Combine(basePath ?? "", source));
if (!File.Exists(path))
{
Logger.LogWarning($"Source file '{path}' not found.");
return null;
}

return File.ReadAllText(path);
}
});
}

static string Escape(string text)
Expand Down
5 changes: 4 additions & 1 deletion src/Docfx.Dotnet/SymbolHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,11 @@ public static IEnumerable<INamedTypeSymbol> GetAllTypes(this IAssemblySymbol ass

public static IEnumerable<ISymbol> GetInheritedMembers(this INamedTypeSymbol symbol, SymbolFilter filter)
{
for (var type = symbol.BaseType; type != null; type = type.BaseType)
for (var type = symbol.BaseType; type is not null; type = type.BaseType)
{
if (type.SpecialType is SpecialType.System_ValueType)
continue;

foreach (var m in from m in type.GetMembers()
where m is not INamedTypeSymbol
where filter.IncludeApi(m)
Expand Down
Loading

0 comments on commit b5b487c

Please sign in to comment.