Author SHA1 Message Date
ds5678 82d9e144fd Analyze web documentation 2024-05-21 02:35:12 -04:00
5 changed files with 171 additions and 0 deletions

No files matched your search

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="8.0.0-preview.6.23329.7" />
</ItemGroup>
</Project>
@@ -0,0 +1,6 @@
using AssetRipper.Mining.Unity.Documentation.Web;
TocNode root = TocNode.FromJsonFile(@"toc.json") ?? throw new NullReferenceException();
Dictionary<string, string> dictionary = TocAnalyzer.Analyze(root);
Dictionary<string, string> reverseDictionary = dictionary.OrderBy(pair => pair.Value).ToDictionary(pair => pair.Value, pair => pair.Key);
_ = reverseDictionary;
@@ -0,0 +1,69 @@
using System.Diagnostics;
namespace AssetRipper.Mining.Unity.Documentation.Web;
public static class TocAnalyzer
{
public static Dictionary<string, string> Analyze(TocNode root)
{
Debug.Assert(root.IsRoot);
Debug.Assert(root.HasChildren);
//Link : Full name
Dictionary<string, string> result = new();
Stack<(TocNode, int)> stack = new();
foreach (TocNode rootChild in root.Children)
{
if (rootChild.Title is "Other")
{
continue;
}
stack.Push((rootChild, -1));
while (stack.Count > 0)
{
(TocNode node, int childIndex) = stack.Pop();
if (childIndex == -1)
{
if (node.IsType)
{
string @namespace = GetNamespace(stack, result);
string fullName = $"{@namespace}.{node.Title}";
result.Add(node.Link, fullName);
}
if (node.HasChildren && !node.IsAssemblyCollection)
{
stack.Push((node, 0));
}
}
else if (childIndex < node.Children!.Length)
{
stack.Push((node, childIndex + 1));
stack.Push((node.Children[childIndex], -1));
}
}
}
return result;
}
private static string GetNamespace(Stack<(TocNode, int)> stack, Dictionary<string, string> dictionary)
{
foreach ((TocNode node, _) in stack)
{
if (node.IsNamespace)
{
return node.Title;
}
if (node.IsType)
{
return dictionary[node.Link];
}
}
if (stack.Count == 0)
{
throw new InvalidOperationException("The stack is empty.");
}
else
{
throw new InvalidOperationException("Could not determine the namespace from the stack.");
}
}
}
@@ -0,0 +1,73 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetRipper.Mining.Unity.Documentation.Web;
[DebuggerDisplay($"{{{nameof(GetDebuggerDisplay)}(),nq}}")]
public sealed class TocNode
{
private const string TOC = "toc";
private const string Classes = "Classes";
private const string Interfaces = "Interfaces";
private const string Enumerations = "Enumerations";
private const string Attributes = "Attributes";
private const string Assemblies = "Assemblies";
private string? link;
[JsonPropertyName("link")]
public required string? Link
{
get => link;
init
{
link = value is "null" ? null : value;
}
}
[JsonPropertyName("title")]
public required string Title { get; init; }
[JsonPropertyName("children")]
public required TocNode[]? Children { get; init; }
[JsonIgnore]
[MemberNotNullWhen(true, nameof(Link))]
public bool IsRoot => Link is TOC && Title is TOC;
[JsonIgnore]
[MemberNotNullWhen(true, nameof(Link))]
public bool IsType => Link is not null and not TOC;
[JsonIgnore]
[MemberNotNullWhen(false, nameof(Link))]
public bool IsTypeCollection => Link is null && Title is Classes or Interfaces or Enumerations or Attributes;
[JsonIgnore]
[MemberNotNullWhen(false, nameof(Link))]
public bool IsAssemblyCollection => Link is null && Title is Assemblies;
[JsonIgnore]
[MemberNotNullWhen(false, nameof(Link))]
public bool IsNamespace => Link is null && Title is not Classes and not Interfaces and not Enumerations and not Attributes and not Assemblies;
[JsonIgnore]
[MemberNotNullWhen(true, nameof(Children))]
public bool HasChildren => Children is not null && Children.Length > 0;
public static TocNode? FromJsonText(string json)
{
return JsonSerializer.Deserialize(json, TocSerializerContext.Default.TocNode);
}
public static TocNode? FromJsonFile(string path)
{
return JsonSerializer.Deserialize(File.OpenRead(path), TocSerializerContext.Default.TocNode);
}
private string GetDebuggerDisplay()
{
return Title;
}
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace AssetRipper.Mining.Unity.Documentation.Web;
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(TocNode))]
internal partial class TocSerializerContext : JsonSerializerContext
{
}