Skip to content

Commit

Permalink
cleanup & tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidVollmers committed Jun 22, 2024
1 parent e44ef2e commit f6106ea
Show file tree
Hide file tree
Showing 13 changed files with 250 additions and 151 deletions.
7 changes: 7 additions & 0 deletions Doki.sln
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Doki.Extensions", "src\Doki
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Doki.CommandLine.Tests", "tests\Doki.CommandLine.Tests\Doki.CommandLine.Tests.csproj", "{67B12AF1-2696-411F-ADFD-B5C32A43BA71}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Doki.Extensions.Tests", "tests\Doki.Extensions.Tests\Doki.Extensions.Tests.csproj", "{863614BC-38CF-4CF5-BE4B-B8EC01AE4FB6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -57,6 +59,7 @@ Global
{0293D689-DFDC-4A78-80D8-BFC11DB0A175} = {08041208-BE3D-4BE8-9AF7-806B73985275}
{0FA0FF7A-6EDA-4CB1-8D81-2DFB1A4077CC} = {8C7B5305-B599-4F08-B28B-DD9F1715DD51}
{67B12AF1-2696-411F-ADFD-B5C32A43BA71} = {8C7B5305-B599-4F08-B28B-DD9F1715DD51}
{863614BC-38CF-4CF5-BE4B-B8EC01AE4FB6} = {8C7B5305-B599-4F08-B28B-DD9F1715DD51}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6F31B87A-2BD3-4FB4-8C08-7E059A338D4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -123,5 +126,9 @@ Global
{67B12AF1-2696-411F-ADFD-B5C32A43BA71}.Debug|Any CPU.Build.0 = Debug|Any CPU
{67B12AF1-2696-411F-ADFD-B5C32A43BA71}.Release|Any CPU.ActiveCfg = Release|Any CPU
{67B12AF1-2696-411F-ADFD-B5C32A43BA71}.Release|Any CPU.Build.0 = Release|Any CPU
{863614BC-38CF-4CF5-BE4B-B8EC01AE4FB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{863614BC-38CF-4CF5-BE4B-B8EC01AE4FB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{863614BC-38CF-4CF5-BE4B-B8EC01AE4FB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{863614BC-38CF-4CF5-BE4B-B8EC01AE4FB6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
20 changes: 0 additions & 20 deletions src/Doki.Abstractions/DocumentationObjectExtensions.cs

This file was deleted.

112 changes: 7 additions & 105 deletions src/Doki.Extensions/DocumentationObjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,117 +2,19 @@

public static class DocumentationObjectExtensions
{
public static DocumentationObject? TryGetParent(this DocumentationRoot root, DocumentationObject child)
public static T? TryGetByParents<T>(this DocumentationObject obj, DocumentationContentType? expectedContent = null)
where T : DocumentationObject
{
ArgumentNullException.ThrowIfNull(root);
ArgumentNullException.ThrowIfNull(child);
ArgumentNullException.ThrowIfNull(obj);

return child.Parent ?? SearchParent(root, child);
}

private static DocumentationObject? SearchParent(DocumentationObject from, DocumentationObject to)
{
if (from == to) return from;

switch (from)
var parent = obj.Parent;
while (parent != null)
{
case DocumentationRoot root: return SearchParentIn(root.Assemblies, to);
case AssemblyDocumentation assemblyDocumentation:
return SearchParentIn(assemblyDocumentation.Namespaces, to);
case NamespaceDocumentation namespaceDocumentation: return SearchParentIn(namespaceDocumentation.Types, to);
case TypeDocumentation typeDocumentation:
{
var constructor = SearchParentIn(typeDocumentation.Constructors, to);
if (constructor != null) return constructor;

var method = SearchParentIn(typeDocumentation.Methods, to);
if (method != null) return method;

var property = SearchParentIn(typeDocumentation.Properties, to);
if (property != null) return property;

var field = SearchParentIn(typeDocumentation.Fields, to);
if (field != null) return field;

var interfaceDocumentation = SearchParentIn(typeDocumentation.Interfaces, to);
if (interfaceDocumentation != null) return interfaceDocumentation;

var derivedType = SearchParentIn(typeDocumentation.DerivedTypes, to);
if (derivedType != null) return derivedType;

var result = SearchParentInTypeDocumentationReference(typeDocumentation, to);
if (result != null) return result;

break;
}
case GenericTypeArgumentDocumentation genericTypeArgumentDocumentation:
{
if (genericTypeArgumentDocumentation.Description != null)
{
var description = SearchParent(genericTypeArgumentDocumentation.Description, to);
if (description != null) return description;
}

var result = SearchParentInTypeDocumentationReference(genericTypeArgumentDocumentation, to);
if (result != null) return result;

break;
}
case TypeDocumentationReference typeDocumentationReference:
{
var result = SearchParentInTypeDocumentationReference(typeDocumentationReference, to);
if (result != null) return result;

break;
}
case MemberDocumentation memberDocumentation:
{
var result = SearchParentInMemberDocumentation(memberDocumentation, to);
if (result != null) return result;

break;
}
case XmlDocumentation xmlDocumentation:
{
var result = SearchParentIn(xmlDocumentation.Contents, to);
if (result != null) return result;
if (parent is T t && (expectedContent == null || t.ContentType == expectedContent)) return t;

break;
}
parent = parent.Parent;
}

return null;
}

private static DocumentationObject? SearchParentInTypeDocumentationReference(
TypeDocumentationReference typeDocumentationReference, DocumentationObject to)
{
if (typeDocumentationReference.BaseType != null)
{
var baseType = SearchParent(typeDocumentationReference.BaseType, to);
if (baseType != null) return baseType;
}

var genericArgument = SearchParentIn(typeDocumentationReference.GenericArguments, to);
return genericArgument ?? SearchParentInMemberDocumentation(typeDocumentationReference, to);
}

private static DocumentationObject? SearchParentInMemberDocumentation(MemberDocumentation memberDocumentation,
DocumentationObject to)
{
var summary = SearchParentIn(memberDocumentation.Summaries, to);
if (summary != null) return summary;

var remarks = SearchParentIn(memberDocumentation.Remarks, to);
if (remarks != null) return remarks;

var example = SearchParentIn(memberDocumentation.Examples, to);
return example;
}

private static DocumentationObject? SearchParentIn(IEnumerable<DocumentationObject> children,
DocumentationObject to)
{
return children.Select(child => SearchParent(child, to)).OfType<DocumentationObject>().FirstOrDefault();
}
}
118 changes: 118 additions & 0 deletions src/Doki.Extensions/DocumentationRootExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
namespace Doki.Extensions;

public static class DocumentationRootExtensions
{
public static DocumentationObject? TryGetParent(this DocumentationRoot root, DocumentationObject child)
{
ArgumentNullException.ThrowIfNull(root);
ArgumentNullException.ThrowIfNull(child);

return child.Parent ?? SearchParent(root, child);
}

private static DocumentationObject? SearchParent(DocumentationObject from, DocumentationObject to)
{
if (from == to) return from;

switch (from)
{
case DocumentationRoot root: return SearchParentIn(root.Assemblies, to);
case AssemblyDocumentation assemblyDocumentation:
return SearchParentIn(assemblyDocumentation.Namespaces, to);
case NamespaceDocumentation namespaceDocumentation: return SearchParentIn(namespaceDocumentation.Types, to);
case TypeDocumentation typeDocumentation:
{
var constructor = SearchParentIn(typeDocumentation.Constructors, to);
if (constructor != null) return constructor;

var method = SearchParentIn(typeDocumentation.Methods, to);
if (method != null) return method;

var property = SearchParentIn(typeDocumentation.Properties, to);
if (property != null) return property;

var field = SearchParentIn(typeDocumentation.Fields, to);
if (field != null) return field;

var interfaceDocumentation = SearchParentIn(typeDocumentation.Interfaces, to);
if (interfaceDocumentation != null) return interfaceDocumentation;

var derivedType = SearchParentIn(typeDocumentation.DerivedTypes, to);
if (derivedType != null) return derivedType;

var result = SearchParentInTypeDocumentationReference(typeDocumentation, to);
if (result != null) return result;

break;
}
case GenericTypeArgumentDocumentation genericTypeArgumentDocumentation:
{
if (genericTypeArgumentDocumentation.Description != null)
{
var description = SearchParent(genericTypeArgumentDocumentation.Description, to);
if (description != null) return description;
}

var result = SearchParentInTypeDocumentationReference(genericTypeArgumentDocumentation, to);
if (result != null) return result;

break;
}
case TypeDocumentationReference typeDocumentationReference:
{
var result = SearchParentInTypeDocumentationReference(typeDocumentationReference, to);
if (result != null) return result;

break;
}
case MemberDocumentation memberDocumentation:
{
var result = SearchParentInMemberDocumentation(memberDocumentation, to);
if (result != null) return result;

break;
}
case XmlDocumentation xmlDocumentation:
{
var result = SearchParentIn(xmlDocumentation.Contents, to);
if (result != null) return result;

break;
}
}

return null;
}

private static DocumentationObject? SearchParentInTypeDocumentationReference(
TypeDocumentationReference typeDocumentationReference, DocumentationObject to)
{
if (typeDocumentationReference.BaseType != null)
{
var baseType = SearchParent(typeDocumentationReference.BaseType, to);
if (baseType != null) return baseType;
}

var genericArgument = SearchParentIn(typeDocumentationReference.GenericArguments, to);
return genericArgument ?? SearchParentInMemberDocumentation(typeDocumentationReference, to);
}

private static DocumentationObject? SearchParentInMemberDocumentation(MemberDocumentation memberDocumentation,
DocumentationObject to)
{
var summary = SearchParentIn(memberDocumentation.Summaries, to);
if (summary != null) return summary;

var remarks = SearchParentIn(memberDocumentation.Remarks, to);
if (remarks != null) return remarks;

var example = SearchParentIn(memberDocumentation.Examples, to);
return example;
}

private static DocumentationObject? SearchParentIn(IEnumerable<DocumentationObject> children,
DocumentationObject to)
{
return children.Select(child => SearchParent(child, to)).OfType<DocumentationObject>().FirstOrDefault();
}
}
1 change: 1 addition & 0 deletions src/Doki.Output.Markdown/Doki.Output.Markdown.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Doki.Extensions\Doki.Extensions.csproj" />
<ProjectReference Include="..\Doki.Output.Extensions\Doki.Output.Extensions.csproj"/>
</ItemGroup>

Expand Down
6 changes: 3 additions & 3 deletions src/Doki.Output.Markdown/MarkdownOutput.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.RegularExpressions;
using Doki.Extensions;
using Doki.Output.Markdown.Elements;

namespace Doki.Output.Markdown;
Expand Down Expand Up @@ -90,14 +91,13 @@ public async Task WriteAsync(TypeDocumentation typeDocumentation, CancellationTo
.Add(new Heading(typeDocumentation.Name, 1).Append($" {Enum.GetName(typeDocumentation.ContentType)}"))
.Add(new Heading(nameof(TypeDocumentation.Definition), 2));

var namespaceDocumentation =
typeDocumentation.TryGetParent<NamespaceDocumentation>(DocumentationContentType.Namespace);
var namespaceDocumentation = typeDocumentation.TryGetByParents<NamespaceDocumentation>();
if (namespaceDocumentation != null)
{
markdown.Add(new Text("Namespace: ").Append(markdown.BuildLinkTo(namespaceDocumentation)));
}

var assemblyAssemblyDocumentation = typeDocumentation.TryGetParent<AssemblyDocumentation>();
var assemblyAssemblyDocumentation = typeDocumentation.TryGetByParents<AssemblyDocumentation>();
if (assemblyAssemblyDocumentation != null)
{
markdown.Add(new Text("Assembly: ").Append(markdown.BuildLinkTo(assemblyAssemblyDocumentation,
Expand Down
2 changes: 1 addition & 1 deletion tests/Doki.CommandLine.Tests/NuGetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Doki.CommandLine.Tests;
public class NuGetTests(ITestOutputHelper testOutputHelper)
{
[Fact]
public async Task NuGetLoader_TestAsync()
public async Task Test_NuGetLoader()
{
const string packageId = "Doki.Output.Json";
var tmpDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Expand Down
40 changes: 40 additions & 0 deletions tests/Doki.Extensions.Tests/DocumentationRootExtensionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Xml.XPath;
using Doki.TestAssembly.InheritanceChain;
using Doki.Tests.Common;
using Microsoft.Extensions.Logging.Abstractions;

namespace Doki.Extensions.Tests;

public class DocumentationRootExtensionTests
{
[Fact]
public async Task Test_TryGetParent_ParentPropertyIsNotNull()
{
var testOutput = new DocumentationRootCapture();

var documentationGenerator = new DocumentationGenerator();

var emptyDocumentation = new XPathDocument(new StringReader("""<?xml version="1.0"?><doc></doc>"""));

documentationGenerator.AddOutput(testOutput);

documentationGenerator.AddAssembly(typeof(SimpleClass).Assembly, emptyDocumentation);

await documentationGenerator.GenerateAsync(NullLogger.Instance);

Assert.NotNull(testOutput.Root);

var assemblyDocumentation = testOutput.Root.Assemblies.Single();

var namespaceDocumentation = assemblyDocumentation.Namespaces.Single();

var simpleClassDocumentation = namespaceDocumentation.Types.First();

Assert.NotNull(simpleClassDocumentation.Parent);

var parent = testOutput.Root.TryGetParent(simpleClassDocumentation);

Assert.NotNull(parent);
Assert.Equal(namespaceDocumentation, parent);
}
}
Loading

0 comments on commit f6106ea

Please sign in to comment.