170 lines
6.5 KiB
C#
170 lines
6.5 KiB
C#
using Microsoft.CodeAnalysis;
|
|
using System.Text;
|
|
using System.Xml;
|
|
|
|
namespace RobotNet.WebApp.Scripts.Monaco.Documentation;
|
|
|
|
public class DocumentationConverter
|
|
{/// <summary>
|
|
/// Converts the xml documentation string into a plain text string.
|
|
/// </summary>
|
|
public static string ConvertDocumentation(string xmlDocumentation, string lineEnding)
|
|
{
|
|
if (string.IsNullOrEmpty(xmlDocumentation))
|
|
return string.Empty;
|
|
|
|
var reader = new StringReader("<docroot>" + xmlDocumentation + "</docroot>");
|
|
using var xml = XmlReader.Create(reader);
|
|
var ret = new StringBuilder();
|
|
|
|
try
|
|
{
|
|
xml.Read();
|
|
string? elementName = null;
|
|
do
|
|
{
|
|
if (xml.NodeType == XmlNodeType.Element)
|
|
{
|
|
elementName = xml.Name.ToLowerInvariant();
|
|
switch (elementName)
|
|
{
|
|
case "filterpriority":
|
|
xml.Skip();
|
|
break;
|
|
case "remarks":
|
|
ret.Append(lineEnding);
|
|
ret.Append("Remarks:");
|
|
ret.Append(lineEnding);
|
|
break;
|
|
case "example":
|
|
ret.Append(lineEnding);
|
|
ret.Append("Example:");
|
|
ret.Append(lineEnding);
|
|
break;
|
|
case "exception":
|
|
ret.Append(lineEnding);
|
|
ret.Append(GetCref(xml["cref"]).TrimEnd());
|
|
ret.Append(": ");
|
|
break;
|
|
case "returns":
|
|
ret.Append(lineEnding);
|
|
ret.Append("Returns: ");
|
|
break;
|
|
case "see":
|
|
ret.Append(GetCref(xml["cref"]));
|
|
ret.Append(xml["langword"]);
|
|
break;
|
|
case "seealso":
|
|
ret.Append(lineEnding);
|
|
ret.Append("See also: ");
|
|
ret.Append(GetCref(xml["cref"]));
|
|
break;
|
|
case "paramref":
|
|
ret.Append(xml["name"]);
|
|
ret.Append(' ');
|
|
break;
|
|
case "typeparam":
|
|
ret.Append(lineEnding);
|
|
ret.Append('<');
|
|
ret.Append(TrimMultiLineString(xml["name"], lineEnding));
|
|
ret.Append(">: ");
|
|
break;
|
|
case "param":
|
|
ret.Append(lineEnding);
|
|
ret.Append(TrimMultiLineString(xml["name"], lineEnding));
|
|
ret.Append(": ");
|
|
break;
|
|
case "value":
|
|
ret.Append(lineEnding);
|
|
ret.Append("Value: ");
|
|
ret.Append(lineEnding);
|
|
break;
|
|
case "br":
|
|
case "para":
|
|
ret.Append(lineEnding);
|
|
break;
|
|
}
|
|
}
|
|
else if (xml.NodeType == XmlNodeType.Text)
|
|
{
|
|
if (elementName == "code")
|
|
{
|
|
ret.Append(xml.Value);
|
|
}
|
|
else
|
|
{
|
|
ret.Append(TrimMultiLineString(xml.Value, lineEnding));
|
|
}
|
|
}
|
|
} while (xml.Read());
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return xmlDocumentation;
|
|
}
|
|
return ret.ToString();
|
|
}
|
|
|
|
private static readonly string[] separator = ["\n", "\r\n"];
|
|
|
|
private static string TrimMultiLineString(string? input, string lineEnding)
|
|
{
|
|
if (string.IsNullOrEmpty(input)) return "";
|
|
var lines = input.Split(separator, StringSplitOptions.RemoveEmptyEntries);
|
|
return string.Join(lineEnding, lines.Select(l => l.TrimStart()));
|
|
}
|
|
|
|
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 cref[2..] + " ";
|
|
}
|
|
return cref + " ";
|
|
}
|
|
|
|
public static DocumentationComment? GetStructuredDocumentation(string? xmlDocumentation, string lineEnding)
|
|
{
|
|
if (string.IsNullOrEmpty(xmlDocumentation)) return null;
|
|
return DocumentationComment.From(xmlDocumentation, lineEnding);
|
|
}
|
|
|
|
public static DocumentationComment? GetStructuredDocumentation(ISymbol symbol, string lineEnding = "\n")
|
|
{
|
|
return symbol switch
|
|
{
|
|
IParameterSymbol parameter => new DocumentationComment(summaryText: GetParameterDocumentation(parameter, lineEnding) ?? ""),
|
|
ITypeParameterSymbol typeParam => new DocumentationComment(summaryText: GetTypeParameterDocumentation(typeParam, lineEnding) ?? ""),
|
|
IAliasSymbol alias => new DocumentationComment(summaryText: GetAliasDocumentation(alias, lineEnding) ?? ""),
|
|
_ => GetStructuredDocumentation(symbol.GetDocumentationCommentXml(), lineEnding),
|
|
};
|
|
}
|
|
|
|
private static string? GetParameterDocumentation(IParameterSymbol parameter, string lineEnding = "\n")
|
|
{
|
|
var contaningSymbolDef = parameter.ContainingSymbol.OriginalDefinition;
|
|
return GetStructuredDocumentation(contaningSymbolDef.GetDocumentationCommentXml(), lineEnding)
|
|
?.GetParameterText(parameter.Name);
|
|
}
|
|
|
|
private static string? GetTypeParameterDocumentation(ITypeParameterSymbol typeParam, string lineEnding = "\n")
|
|
{
|
|
var contaningSymbol = typeParam.ContainingSymbol;
|
|
return GetStructuredDocumentation(contaningSymbol.GetDocumentationCommentXml(), lineEnding)
|
|
?.GetTypeParameterText(typeParam.Name);
|
|
}
|
|
|
|
private static string? GetAliasDocumentation(IAliasSymbol alias, string lineEnding = "\n")
|
|
{
|
|
return GetStructuredDocumentation(alias.Target.GetDocumentationCommentXml(), lineEnding)?.SummaryText;
|
|
}
|
|
}
|