NetDocsForLLM/Services/DocumentationGenerator.cs

199 lines
8.1 KiB
C#

using NetDocsForLLM.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace NetDocsForLLM.Services
{
public interface IDocumentationGenerator
{
Task<DocumentationModel> GenerateDocumentation(IEnumerable<AssemblyModel> assemblies, ExportSettings settings);
string GenerateDocumentationPreview(DocumentationModel documentation, ExportSettings settings);
}
public class DocumentationGenerator : IDocumentationGenerator
{
private readonly IDocFxService _docFxService;
public DocumentationGenerator(IDocFxService docFxService)
{
_docFxService = docFxService ?? throw new ArgumentNullException(nameof(docFxService));
}
public async Task<DocumentationModel> GenerateDocumentation(IEnumerable<AssemblyModel> assemblies, ExportSettings settings)
{
try
{
// Generate metadata with DocFX
var metadataPath = await _docFxService.GenerateMetadataAsync(assemblies);
// Process metadata files
var documentation = new DocumentationModel();
var namespaces = new Dictionary<string, NamespaceDocumentation>();
// Read YAML files produced by DocFX
var ymlFiles = Directory.GetFiles(metadataPath, "*.yml", SearchOption.AllDirectories);
foreach (var ymlFile in ymlFiles)
{
ProcessYamlMetadata(ymlFile, documentation, namespaces, settings);
}
return documentation;
}
catch (Exception ex)
{
throw new InvalidOperationException($"Error al generar documentación: {ex.Message}", ex);
}
}
private void ProcessYamlMetadata(string ymlFile, DocumentationModel documentation,
Dictionary<string, NamespaceDocumentation> namespaces,
ExportSettings settings)
{
// This is a simplified implementation. In a real application,
// you would need to use a YAML parser to read DocFX output
// For this example, we'll create sample documentation data
var typeDoc = new TypeDocumentation
{
Name = Path.GetFileNameWithoutExtension(ymlFile),
FullName = $"ExampleNamespace.{Path.GetFileNameWithoutExtension(ymlFile)}",
Description = "Descripción del tipo extraída de comentarios XML",
TypeKind = "Class"
};
// Add some members
typeDoc.Members.Add(new MemberDocumentation
{
Name = "ExampleMethod",
Description = "Un método de ejemplo con documentación",
MemberType = "Method",
Signature = "public void ExampleMethod(string parameter1, int parameter2)",
ReturnType = "void",
ReturnDescription = "Este método no devuelve ningún valor"
});
// Add parameters to the method
typeDoc.Members[0].Parameters.Add(new ParameterDocumentation
{
Name = "parameter1",
Type = "string",
Description = "Descripción del primer parámetro"
});
typeDoc.Members[0].Parameters.Add(new ParameterDocumentation
{
Name = "parameter2",
Type = "int",
Description = "Descripción del segundo parámetro"
});
// Add to namespace
var namespaceName = "ExampleNamespace";
if (!namespaces.TryGetValue(namespaceName, out var namespaceDoc))
{
namespaceDoc = new NamespaceDocumentation
{
Name = namespaceName,
Description = "Descripción del namespace"
};
namespaces[namespaceName] = namespaceDoc;
documentation.Namespaces.Add(namespaceDoc);
}
namespaceDoc.Types.Add(typeDoc);
}
public string GenerateDocumentationPreview(DocumentationModel documentation, ExportSettings settings)
{
try
{
if (settings.OutputFormat == OutputFormat.Json)
{
return JsonConvert.SerializeObject(documentation, Formatting.Indented,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
else // YAML
{
// Convert to JSON first, then to YAML (simplified)
var json = JsonConvert.SerializeObject(documentation, Formatting.None,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
// In a real application, you would use a YAML serializer
// For this example, we'll return a simple YAML representation
return ConvertJsonToSimpleYaml(json);
}
}
catch (Exception ex)
{
throw new InvalidOperationException($"Error al generar vista previa: {ex.Message}", ex);
}
}
private string ConvertJsonToSimpleYaml(string json)
{
// This is a simplified conversion for demonstration purposes
// In a real application, you would use a YAML serializer library
// Deserialize JSON
var obj = JsonConvert.DeserializeObject<dynamic>(json);
// Basic YAML builder
var yaml = new System.Text.StringBuilder();
yaml.AppendLine("namespaces:");
foreach (var ns in obj.Namespaces)
{
yaml.AppendLine($" - name: {ns.Name}");
yaml.AppendLine($" description: {ns.Description}");
yaml.AppendLine(" types:");
foreach (var type in ns.Types)
{
yaml.AppendLine($" - name: {type.Name}");
yaml.AppendLine($" fullName: {type.FullName}");
yaml.AppendLine($" typeKind: {type.TypeKind}");
yaml.AppendLine($" description: {type.Description}");
yaml.AppendLine(" members:");
foreach (var member in type.Members)
{
yaml.AppendLine($" - name: {member.Name}");
yaml.AppendLine($" memberType: {member.MemberType}");
yaml.AppendLine($" signature: {member.Signature}");
yaml.AppendLine($" description: {member.Description}");
if (member.Parameters.Count > 0)
{
yaml.AppendLine(" parameters:");
foreach (var param in member.Parameters)
{
yaml.AppendLine($" - name: {param.Name}");
yaml.AppendLine($" type: {param.Type}");
yaml.AppendLine($" description: {param.Description}");
}
}
if (!string.IsNullOrEmpty(member.ReturnType))
{
yaml.AppendLine($" returnType: {member.ReturnType}");
yaml.AppendLine($" returnDescription: {member.ReturnDescription}");
}
}
}
}
return yaml.ToString();
}
}
}