196 lines
8.3 KiB
C#
196 lines
8.3 KiB
C#
using System.Text;
|
|
using System.Xml;
|
|
|
|
namespace RobotNet.WebApp.Scripts.Monaco.Documentation;
|
|
|
|
public class DocumentationComment(
|
|
string summaryText = "",
|
|
DocumentationItem[]? typeParamElements = null,
|
|
DocumentationItem[]? paramElements = null,
|
|
string returnsText = "",
|
|
string remarksText = "",
|
|
string exampleText = "",
|
|
string valueText = "",
|
|
DocumentationItem[]? exception = null)
|
|
{
|
|
public string SummaryText { get; } = summaryText;
|
|
public DocumentationItem[] TypeParamElements { get; } = typeParamElements ?? [];
|
|
public DocumentationItem[] ParamElements { get; } = paramElements ?? [];
|
|
public string ReturnsText { get; } = returnsText;
|
|
public string RemarksText { get; } = remarksText;
|
|
public string ExampleText { get; } = exampleText;
|
|
public string ValueText { get; } = valueText;
|
|
public DocumentationItem[] Exception { get; } = exception ?? [];
|
|
|
|
public static DocumentationComment? From(string xmlDocumentation, string lineEnding)
|
|
{
|
|
if (string.IsNullOrEmpty(xmlDocumentation))
|
|
return Empty;
|
|
|
|
var reader = new StringReader("<docroot>" + xmlDocumentation + "</docroot>");
|
|
var summaryText = new StringBuilder();
|
|
var typeParamElements = new List<DocumentationItemBuilder>();
|
|
var paramElements = new List<DocumentationItemBuilder>();
|
|
var returnsText = new StringBuilder();
|
|
var remarksText = new StringBuilder();
|
|
var exampleText = new StringBuilder();
|
|
var valueText = new StringBuilder();
|
|
var exception = new List<DocumentationItemBuilder>();
|
|
|
|
using (var xml = XmlReader.Create(reader))
|
|
{
|
|
try
|
|
{
|
|
xml.Read();
|
|
string? elementName = null;
|
|
StringBuilder? currentSectionBuilder = null;
|
|
do
|
|
{
|
|
if (xml.NodeType == XmlNodeType.Element)
|
|
{
|
|
elementName = xml.Name.ToLowerInvariant();
|
|
switch (elementName)
|
|
{
|
|
case "filterpriority":
|
|
xml.Skip();
|
|
break;
|
|
case "remarks":
|
|
currentSectionBuilder = remarksText;
|
|
break;
|
|
case "example":
|
|
currentSectionBuilder = exampleText;
|
|
break;
|
|
case "exception":
|
|
DocumentationItemBuilder exceptionInstance = new(GetCref(xml["cref"]).TrimEnd());
|
|
currentSectionBuilder = exceptionInstance.Documentation;
|
|
exception.Add(exceptionInstance);
|
|
break;
|
|
case "returns":
|
|
currentSectionBuilder = returnsText;
|
|
break;
|
|
case "summary":
|
|
currentSectionBuilder = summaryText;
|
|
break;
|
|
case "see":
|
|
if (currentSectionBuilder is null) continue;
|
|
currentSectionBuilder.Append(GetCref(xml["cref"]));
|
|
currentSectionBuilder.Append(xml["langword"]);
|
|
break;
|
|
case "seealso":
|
|
if (currentSectionBuilder is null) continue;
|
|
currentSectionBuilder.Append("See also: ");
|
|
currentSectionBuilder.Append(GetCref(xml["cref"]));
|
|
break;
|
|
case "paramref":
|
|
if (currentSectionBuilder is null) continue;
|
|
currentSectionBuilder.Append(xml["name"]);
|
|
currentSectionBuilder.Append(' ');
|
|
break;
|
|
case "param":
|
|
|
|
DocumentationItemBuilder paramInstance = new(TrimMultiLineString(xml["name"] ?? "", lineEnding));
|
|
currentSectionBuilder = paramInstance.Documentation;
|
|
paramElements.Add(paramInstance);
|
|
break;
|
|
case "typeparamref":
|
|
if (currentSectionBuilder is null) continue;
|
|
currentSectionBuilder.Append(xml["name"]);
|
|
currentSectionBuilder.Append(' ');
|
|
break;
|
|
case "typeparam":
|
|
DocumentationItemBuilder typeParamInstance = new(TrimMultiLineString(xml["name"] ?? "", lineEnding));
|
|
currentSectionBuilder = typeParamInstance.Documentation;
|
|
typeParamElements.Add(typeParamInstance);
|
|
break;
|
|
case "value":
|
|
currentSectionBuilder = valueText;
|
|
break;
|
|
case "br":
|
|
case "para":
|
|
if (currentSectionBuilder is null) continue;
|
|
currentSectionBuilder.Append(lineEnding);
|
|
break;
|
|
}
|
|
}
|
|
else if (xml.NodeType == XmlNodeType.Text && currentSectionBuilder != null)
|
|
{
|
|
if (elementName == "code")
|
|
{
|
|
currentSectionBuilder.Append(xml.Value);
|
|
}
|
|
else
|
|
{
|
|
currentSectionBuilder.Append(TrimMultiLineString(xml.Value, lineEnding));
|
|
}
|
|
}
|
|
} while (xml.Read());
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return new DocumentationComment(
|
|
summaryText.ToString(),
|
|
typeParamElements.Select(s => s.ConvertToDocumentedObject()).ToArray(),
|
|
paramElements.Select(s => s.ConvertToDocumentedObject()).ToArray(),
|
|
returnsText.ToString(),
|
|
remarksText.ToString(),
|
|
exampleText.ToString(),
|
|
valueText.ToString(),
|
|
exception.Select(s => s.ConvertToDocumentedObject()).ToArray());
|
|
}
|
|
|
|
private static string TrimMultiLineString(string input, string lineEnding)
|
|
{
|
|
var lines = input.Split(separator, StringSplitOptions.RemoveEmptyEntries);
|
|
return string.Join(lineEnding, lines.Select(l => TrimStartRetainingSingleLeadingSpace(l)));
|
|
}
|
|
|
|
private static string GetCref(string? cref)
|
|
{
|
|
if (cref == null || cref.Trim().Length == 0)
|
|
{
|
|
return "";
|
|
}
|
|
if (cref.Length < 2)
|
|
{
|
|
return cref;
|
|
}
|
|
if (cref.Substring(1, 1) == ":")
|
|
{
|
|
return string.Concat(cref.AsSpan(2, cref.Length - 2), " ");
|
|
}
|
|
return cref + " ";
|
|
}
|
|
|
|
private static string TrimStartRetainingSingleLeadingSpace(string input)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(input))
|
|
return string.Empty;
|
|
if (!char.IsWhiteSpace(input[0]))
|
|
return input;
|
|
return $" {input.TrimStart()}";
|
|
}
|
|
|
|
public string GetParameterText(string name)
|
|
=> Array.Find(ParamElements, parameter => parameter.Name == name)?.Documentation ?? string.Empty;
|
|
|
|
public string GetTypeParameterText(string name)
|
|
=> Array.Find(TypeParamElements, typeParam => typeParam.Name == name)?.Documentation ?? string.Empty;
|
|
|
|
public static readonly DocumentationComment Empty = new();
|
|
private static readonly string[] separator = ["\n", "\r\n"];
|
|
}
|
|
|
|
class DocumentationItemBuilder(string name)
|
|
{
|
|
public string Name { get; set; } = name;
|
|
public StringBuilder Documentation { get; set; } = new StringBuilder();
|
|
|
|
public DocumentationItem ConvertToDocumentedObject()
|
|
{
|
|
return new DocumentationItem(Name, Documentation.ToString());
|
|
}
|
|
} |