|
|
|
|
|
using Microsoft.CodeAnalysis;
|
|
|
|
|
|
using Microsoft.CodeAnalysis.CSharp;
|
|
|
|
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.Reflection.Metadata;
|
|
|
|
|
|
using System.Security.Cryptography.X509Certificates;
|
|
|
|
|
|
using System.Xml;
|
|
|
|
|
|
|
|
|
|
|
|
namespace DocGenerator
|
|
|
|
|
|
{
|
|
|
|
|
|
internal class Program
|
|
|
|
|
|
{
|
|
|
|
|
|
internal class CommentBlock
|
|
|
|
|
|
{
|
|
|
|
|
|
public string MethodComment { get; set; } = string.Empty;
|
|
|
|
|
|
public Dictionary<string, string> ParametersComment { get; set; } = new Dictionary<string, string>();
|
|
|
|
|
|
public string ReturnComment { get; set; } = string.Empty;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static CommentBlock ParseComment(string comment)
|
|
|
|
|
|
{
|
|
|
|
|
|
CommentBlock block = new();
|
|
|
|
|
|
|
|
|
|
|
|
string newComment = "<root>\n" + comment.Replace("///", "") + "</root>";
|
|
|
|
|
|
|
|
|
|
|
|
XmlDocument? xmlDoc = new();
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
xmlDoc.LoadXml(newComment);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
return block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
XmlNode? summaryNode = xmlDoc.SelectSingleNode("//summary");
|
|
|
|
|
|
string? methodSummary = summaryNode?.InnerText.Trim();
|
|
|
|
|
|
|
|
|
|
|
|
XmlNodeList? paramNodes = xmlDoc.SelectNodes("//param");
|
|
|
|
|
|
if (paramNodes != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (XmlNode paramNode in paramNodes)
|
|
|
|
|
|
{
|
|
|
|
|
|
string? paramName = paramNode?.Attributes?["name"]?.Value;
|
|
|
|
|
|
string? paramDescription = paramNode?.InnerText.Trim();
|
|
|
|
|
|
if (paramName != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (block.ParametersComment.ContainsKey(paramName))
|
|
|
|
|
|
{
|
|
|
|
|
|
block.ParametersComment[paramName] = paramDescription ?? "";
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
block.ParametersComment.Add(paramName, paramDescription ?? "");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
XmlNode? returnsNode = xmlDoc.SelectSingleNode("//returns");
|
|
|
|
|
|
string? returnsDescription = returnsNode?.InnerText.Trim();
|
|
|
|
|
|
|
|
|
|
|
|
block.MethodComment = methodSummary ?? "";
|
|
|
|
|
|
block.ReturnComment = returnsDescription ?? "";
|
|
|
|
|
|
|
|
|
|
|
|
return block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void ParseClass(ClassDeclarationSyntax classDeclaration)
|
|
|
|
|
|
{
|
|
|
|
|
|
string className = classDeclaration.Identifier.ValueText;
|
|
|
|
|
|
Directory.CreateDirectory(className);
|
|
|
|
|
|
|
|
|
|
|
|
var methodDeclarations = classDeclaration.Members.OfType<MethodDeclarationSyntax>();
|
|
|
|
|
|
foreach (MethodDeclarationSyntax methodDeclaration in methodDeclarations)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 忽略非 public 方法
|
|
|
|
|
|
if (methodDeclaration.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.PublicKeyword)))
|
|
|
|
|
|
{
|
|
|
|
|
|
string methodName = methodDeclaration.Identifier.ValueText;
|
|
|
|
|
|
string ReturnType = methodDeclaration.ReturnType.ToString();
|
|
|
|
|
|
|
|
|
|
|
|
// 忽略点击事件
|
|
|
|
|
|
if (methodName.EndsWith("Click"))
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取注释
|
|
|
|
|
|
string comment = methodDeclaration.GetLeadingTrivia().ToString();
|
|
|
|
|
|
CommentBlock commentBlock = ParseComment(comment);
|
|
|
|
|
|
|
|
|
|
|
|
using var streamerWriter = File.CreateText(Path.Combine(className, $"{methodName}.md"));
|
|
|
|
|
|
|
|
|
|
|
|
streamerWriter.WriteLine($"# {methodName}\n");
|
|
|
|
|
|
|
|
|
|
|
|
streamerWriter.WriteLine("## 定义\n");
|
|
|
|
|
|
streamerWriter.WriteLine(commentBlock.MethodComment + "\n");
|
|
|
|
|
|
|
|
|
|
|
|
/// 方法原型
|
|
|
|
|
|
streamerWriter.WriteLine("```CSharp");
|
|
|
|
|
|
streamerWriter.WriteLine(methodDeclaration.ToString().Split("\n")[0]);
|
|
|
|
|
|
streamerWriter.WriteLine("```");
|
|
|
|
|
|
|
|
|
|
|
|
streamerWriter.WriteLine();
|
|
|
|
|
|
|
|
|
|
|
|
streamerWriter.WriteLine("## 请求参数\n");
|
|
|
|
|
|
|
|
|
|
|
|
if (methodDeclaration.ParameterList.Parameters.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
streamerWriter.WriteLine("| 参数 | 类型 | 约束 | 说明 |");
|
|
|
|
|
|
streamerWriter.WriteLine("| - | - | - | - |");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var parameter in methodDeclaration.ParameterList.Parameters)
|
|
|
|
|
|
{
|
|
|
|
|
|
var paramName = parameter.Identifier.ValueText;
|
|
|
|
|
|
var paramType = parameter.Type.ToString();
|
|
|
|
|
|
var desc = string.Empty;
|
|
|
|
|
|
if (commentBlock.ParametersComment.ContainsKey(paramName))
|
|
|
|
|
|
{
|
|
|
|
|
|
desc = commentBlock.ParametersComment[paramName];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
streamerWriter.WriteLine($"| {paramName} | {paramType} | | {desc} |");
|
|
|
|
|
|
}
|
|
|
|
|
|
streamerWriter.WriteLine("\n");
|
|
|
|
|
|
|
|
|
|
|
|
streamerWriter.WriteLine("## 返回\n");
|
|
|
|
|
|
streamerWriter.WriteLine($"类型: {ReturnType}");
|
|
|
|
|
|
streamerWriter.WriteLine(commentBlock.ReturnComment);
|
|
|
|
|
|
streamerWriter.WriteLine("\n");
|
|
|
|
|
|
|
|
|
|
|
|
streamerWriter.WriteLine("## 请求示例\n");
|
|
|
|
|
|
streamerWriter.WriteLine("## 错误处理\n");
|
|
|
|
|
|
streamerWriter.WriteLine("## 注意事项\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void ParseFile(string filePath)
|
|
|
|
|
|
{
|
|
|
|
|
|
string code = File.ReadAllText(filePath);
|
|
|
|
|
|
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
|
|
|
|
|
|
CompilationUnitSyntax root = syntaxTree.GetCompilationUnitRoot();
|
|
|
|
|
|
|
|
|
|
|
|
var classDeclarations = root.Members.OfType<NamespaceDeclarationSyntax>()
|
|
|
|
|
|
.SelectMany(namespaceDeclaration => namespaceDeclaration.Members)
|
|
|
|
|
|
.OfType<ClassDeclarationSyntax>();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var classDeclaration in classDeclarations)
|
|
|
|
|
|
{
|
|
|
|
|
|
ParseClass(classDeclaration);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void Main(string[] args)
|
|
|
|
|
|
{
|
|
|
|
|
|
/*
|
|
|
|
|
|
if (args.Length == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine($"Usage: {Process.GetCurrentProcess().ProcessName} <xxx.cs>");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
ParseFile(@"D:\project\Drawer\Drawer\UCDraw\UCDraw\UC\MainView.cs");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|