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 GenerateDocumentation(IEnumerable 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 GenerateDocumentation(IEnumerable 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(); // 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 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(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(); } } }