-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#86 AI Context friendly documentation - API
- Loading branch information
1 parent
c50d6b8
commit 826b278
Showing
28 changed files
with
10,460 additions
and
56 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace Build.Core.Doc; | ||
|
||
using System.Xml.Linq; | ||
|
||
record DocumentElement(XElement Source); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace Build.Core.Doc; | ||
|
||
record DocumentMember(DocumentTypeName TypeName, DocumentMemberKind Kind); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace Build.Core.Doc; | ||
|
||
enum DocumentMemberKind | ||
{ | ||
Field, | ||
Property, | ||
Method, | ||
Constructor, | ||
ImplicitOperator | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
namespace Build.Core.Doc; | ||
|
||
using System.Text; | ||
|
||
class DocumentParts : IMarkdownParts | ||
{ | ||
public Memory<string> GetParts(string? text) | ||
{ | ||
var result = new List<string>(); | ||
if (text is null) | ||
{ | ||
return Memory<string>.Empty; | ||
} | ||
|
||
var sb = new StringBuilder(); | ||
var isArgs = false; | ||
foreach (var symbol in text) | ||
{ | ||
switch (symbol) | ||
{ | ||
case '.' when !isArgs: | ||
result.Add(sb.ToString()); | ||
sb.Clear(); | ||
continue; | ||
|
||
case '(': | ||
isArgs = true; | ||
break; | ||
} | ||
|
||
sb.Append(symbol); | ||
} | ||
|
||
if (sb.Length > 0) | ||
{ | ||
result.Add(sb.ToString()); | ||
} | ||
|
||
return result.ToArray(); | ||
} | ||
|
||
public string Join(ReadOnlyMemory<string> parts) => string.Join('.', parts.ToArray()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace Build.Core.Doc; | ||
|
||
using System.Xml.Linq; | ||
|
||
public record DocumentText(XText Text); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace Build.Core.Doc; | ||
|
||
record DocumentType(DocumentTypeName TypeName); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace Build.Core.Doc; | ||
|
||
public record DocumentTypeName( | ||
string NamespaceName, | ||
string TypeName, | ||
string MemberName = ""); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
namespace Build.Core.Doc; | ||
|
||
using System.Xml.Linq; | ||
using System.Xml.XPath; | ||
|
||
class DotNetXmlDocumentWalker<T>(IMarkdownParts markdownParts) : IDocumentWalker<T> | ||
{ | ||
public async Task WalkAsync( | ||
T ctx, | ||
XDocument document, | ||
IDocumentVisitor<T> visitor, | ||
CancellationToken cancellationToken) | ||
{ | ||
var items = ( | ||
from element in document.XPathSelectElements("/doc/members/member") | ||
let name = element.Attribute("name")?.Value | ||
where !string.IsNullOrWhiteSpace(name) | ||
where name.Length >= 3 | ||
let kind = char.ToUpper(name[0]) | ||
let parts = markdownParts.GetParts(name[2..]) | ||
where parts.Length > 1 | ||
let typeFullNameParts = kind == 'T' ? parts : parts[..^1] | ||
let namespaceName = markdownParts.Join(typeFullNameParts[..^1]) | ||
let typeName = markdownParts.Join(typeFullNameParts[^1..]) ?? "" | ||
let memberName = markdownParts.Join(parts[^1..]) ?? "" | ||
select (name: new DocumentTypeName(namespaceName, typeName, memberName), kind, element)) | ||
.OrderBy(i => i.name.NamespaceName).ThenBy(i => i.name.TypeName); | ||
|
||
DocumentType? type = null; | ||
foreach (var (name, kind, element) in items) | ||
{ | ||
if (cancellationToken.IsCancellationRequested) | ||
{ | ||
break; | ||
} | ||
|
||
var memberName = name.MemberName; | ||
DocumentMember? member = null; | ||
switch (kind) | ||
{ | ||
case 'T': | ||
if (type is {} curType) | ||
{ | ||
ctx = await visitor.FinishTypeVisitAsync(ctx, curType, cancellationToken); | ||
} | ||
|
||
type = new DocumentType(name); | ||
ctx = await visitor.StartTypeVisitAsync(ctx, type, cancellationToken); | ||
ctx = await ExplorerContainerAsync(ctx, element, visitor, cancellationToken); | ||
break; | ||
|
||
case 'F': | ||
member = new DocumentMember(name, DocumentMemberKind.Field); | ||
break; | ||
|
||
case 'P': | ||
member = new DocumentMember(name, DocumentMemberKind.Property); | ||
break; | ||
|
||
case 'M': | ||
if (memberName.StartsWith("#ctor")) | ||
{ | ||
member = | ||
new DocumentMember( | ||
name with { MemberName = name.MemberName.Replace("#ctor", name.TypeName) }, | ||
DocumentMemberKind.Constructor); | ||
} | ||
else | ||
{ | ||
if (memberName.StartsWith("op_Implicit")) | ||
{ | ||
member = | ||
new DocumentMember( | ||
name with { MemberName = name.MemberName.Replace("op_Implicit", "") }, | ||
DocumentMemberKind.ImplicitOperator); | ||
} | ||
else | ||
{ | ||
member = new DocumentMember(name, DocumentMemberKind.Method); | ||
} | ||
} | ||
|
||
break; | ||
} | ||
|
||
if (member is not {} curMember) | ||
{ | ||
continue; | ||
} | ||
|
||
ctx = await visitor.StartMemberVisitAsync(ctx, curMember, cancellationToken); | ||
ctx = await ExplorerContainerAsync(ctx, element, visitor, cancellationToken); | ||
ctx = await visitor.FinishMemberVisitAsync(ctx, curMember, cancellationToken); | ||
} | ||
|
||
if (type is {} lastType) | ||
{ | ||
ctx = await visitor.FinishTypeVisitAsync(ctx, lastType, cancellationToken); | ||
} | ||
|
||
await visitor.CompletedAsync(ctx, cancellationToken); | ||
} | ||
|
||
private static async Task<T> ExplorerContainerAsync(T ctx, XContainer container, IDocumentVisitor<T> visitor, CancellationToken cancellationToken) | ||
{ | ||
foreach (var node in container.Nodes()) | ||
{ | ||
if (cancellationToken.IsCancellationRequested) | ||
{ | ||
break; | ||
} | ||
|
||
switch (node) | ||
{ | ||
case XElement element: | ||
var markdownElement = new DocumentElement(element); | ||
ctx = await visitor.StartElementVisitAsync(ctx, markdownElement, cancellationToken); | ||
ctx = await ExplorerContainerAsync(ctx, element, visitor, cancellationToken); | ||
ctx = await visitor.FinishElementVisitAsync(ctx, markdownElement, cancellationToken); | ||
|
||
break; | ||
|
||
case XText text: | ||
ctx = await visitor.TextVisitAsync(ctx, new DocumentText(text), cancellationToken); | ||
break; | ||
} | ||
} | ||
|
||
return ctx; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// ReSharper disable UnusedParameter.Global | ||
|
||
namespace Build.Core.Doc; | ||
|
||
interface IDocumentVisitor<T> | ||
{ | ||
Task<T> StartTypeVisitAsync(T ctx, DocumentType type, CancellationToken cancellationToken); | ||
|
||
Task<T> FinishTypeVisitAsync(T ctx, DocumentType type, CancellationToken cancellationToken); | ||
|
||
Task<T> StartMemberVisitAsync(T ctx, DocumentMember member, CancellationToken cancellationToken); | ||
|
||
Task<T> FinishMemberVisitAsync(T ctx, DocumentMember member, CancellationToken cancellationToken); | ||
|
||
Task<T> StartElementVisitAsync(T ctx, DocumentElement element, CancellationToken cancellationToken); | ||
|
||
Task<T> FinishElementVisitAsync(T ctx, DocumentElement element, CancellationToken cancellationToken); | ||
|
||
Task<T> TextVisitAsync(T ctx, DocumentText text, CancellationToken cancellationToken); | ||
|
||
Task<T> CompletedAsync(T ctx, CancellationToken cancellationToken); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Build.Core.Doc; | ||
|
||
using System.Xml.Linq; | ||
|
||
interface IDocumentWalker<T> | ||
{ | ||
Task WalkAsync( | ||
T ctx, | ||
XDocument document, | ||
IDocumentVisitor<T> visitor, | ||
CancellationToken cancellationToken); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Build.Core.Doc; | ||
|
||
using System.Xml.Linq; | ||
|
||
public interface IMarkdown | ||
{ | ||
Task ConvertAsync( | ||
XDocument document, | ||
TextWriter markdownWriter, | ||
Predicate<DocumentTypeName> filter, | ||
CancellationToken cancellationToken); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Build.Core.Doc; | ||
|
||
interface IMarkdownParts | ||
{ | ||
Memory<string> GetParts(string? text); | ||
|
||
string Join(ReadOnlyMemory<string> parts); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Build.Core.Doc; | ||
|
||
using System.Xml.Linq; | ||
|
||
interface IXDocumentTools | ||
{ | ||
Task<XDocument> LoadAsync(TextReader textReader, LoadOptions options, CancellationToken cancellationToken); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
namespace Build.Core.Doc; | ||
|
||
using System.Xml.Linq; | ||
|
||
[ExcludeFromCodeCoverage] | ||
class Markdown( | ||
IDocumentWalker<MarkdownWriterContext> dotNetXmlDocumentWalker, | ||
IDocumentVisitor<MarkdownWriterContext> markdownWriterVisitor) | ||
: IMarkdown | ||
{ | ||
public Task ConvertAsync( | ||
XDocument document, | ||
TextWriter markdownWriter, | ||
Predicate<DocumentTypeName> filter, | ||
CancellationToken cancellationToken) | ||
=> dotNetXmlDocumentWalker.WalkAsync( | ||
new MarkdownWriterContext(filter, markdownWriter), | ||
document, | ||
markdownWriterVisitor, | ||
cancellationToken); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Build.Core.Doc; | ||
|
||
record MarkdownWriterContext( | ||
Predicate<DocumentTypeName> Filter, | ||
TextWriter Writer, | ||
string Namespace = "", | ||
bool IsSkipping = false, | ||
bool TrimStart = false); |
Oops, something went wrong.