175 lines
5.4 KiB
C#
175 lines
5.4 KiB
C#
using NetDocsForLLM.Models;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace NetDocsForLLM.Services
|
|
{
|
|
public interface IDocFxService
|
|
{
|
|
Task<string> GenerateMetadataAsync(IEnumerable<AssemblyModel> assemblies);
|
|
}
|
|
|
|
public class DocFxService : IDocFxService
|
|
{
|
|
private readonly string _workingDirectory;
|
|
private readonly string _docfxPath;
|
|
|
|
public DocFxService()
|
|
{
|
|
// Create a temporary working directory
|
|
_workingDirectory = Path.Combine(Path.GetTempPath(), "NetDocsForLLM_" + Guid.NewGuid().ToString("N"));
|
|
Directory.CreateDirectory(_workingDirectory);
|
|
|
|
// Locate DocFX executable in the packages directory
|
|
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
|
|
_docfxPath = Path.Combine(baseDir, "docfx", "docfx.exe");
|
|
|
|
// If not found in the default location, try to locate it in the packages directory
|
|
if (!File.Exists(_docfxPath))
|
|
{
|
|
var packagesDir = Path.Combine(baseDir, "..", "..", "..", "packages");
|
|
var docfxPaths = Directory.GetFiles(packagesDir, "docfx.exe", SearchOption.AllDirectories);
|
|
if (docfxPaths.Length > 0)
|
|
{
|
|
_docfxPath = docfxPaths[0];
|
|
}
|
|
else
|
|
{
|
|
throw new FileNotFoundException("No se pudo encontrar docfx.exe. Asegúrese de que el paquete docfx.console esté instalado.");
|
|
}
|
|
}
|
|
}
|
|
|
|
public async Task<string> GenerateMetadataAsync(IEnumerable<AssemblyModel> assemblies)
|
|
{
|
|
try
|
|
{
|
|
// Create DocFX configuration
|
|
var configPath = Path.Combine(_workingDirectory, "docfx.json");
|
|
var config = CreateDocFxConfig(assemblies);
|
|
File.WriteAllText(configPath, config);
|
|
|
|
// Run DocFX metadata
|
|
var result = await RunDocFxMetadataAsync(configPath);
|
|
|
|
// Return path to the generated metadata
|
|
var apiPath = Path.Combine(_workingDirectory, "obj", "api");
|
|
return apiPath;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new InvalidOperationException($"Error al generar metadatos con DocFX: {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
private string CreateDocFxConfig(IEnumerable<AssemblyModel> assemblies)
|
|
{
|
|
var assemblyPaths = new List<string>();
|
|
var xmlPaths = new List<string>();
|
|
|
|
foreach (var assembly in assemblies)
|
|
{
|
|
assemblyPaths.Add(assembly.FilePath);
|
|
if (assembly.HasXmlDocumentation)
|
|
{
|
|
xmlPaths.Add(assembly.XmlDocPath);
|
|
}
|
|
}
|
|
|
|
return $@"
|
|
{{
|
|
""metadata"": [
|
|
{{
|
|
""src"": [
|
|
{{
|
|
""files"": [
|
|
""{string.Join("\",\n \"", assemblyPaths.Select(p => p.Replace("\\", "\\\\")))}""
|
|
],
|
|
""src"": "".""
|
|
}}
|
|
],
|
|
""dest"": ""obj/api"",
|
|
""properties"": {{
|
|
""TargetFramework"": ""net6.0""
|
|
}},
|
|
""disableGitFeatures"": true,
|
|
""disableDefaultFilter"": false
|
|
}}
|
|
],
|
|
""build"": {{
|
|
""content"": [
|
|
{{
|
|
""files"": [""*.yml""],
|
|
""src"": ""obj/api"",
|
|
""dest"": ""api""
|
|
}}
|
|
],
|
|
""resource"": [
|
|
{{
|
|
""files"": [""images/**""],
|
|
""exclude"": [""obj/**"", ""_site/**""]
|
|
}}
|
|
],
|
|
""dest"": ""_site"",
|
|
""globalMetadataFiles"": [],
|
|
""fileMetadataFiles"": [],
|
|
""template"": [""default""],
|
|
""postProcessors"": [],
|
|
""markdownEngineName"": ""markdig"",
|
|
""noLangKeyword"": false,
|
|
""keepFileLink"": false,
|
|
""cleanupCacheHistory"": false,
|
|
""disableGitFeatures"": false
|
|
}}
|
|
}}";
|
|
}
|
|
|
|
private async Task<string> RunDocFxMetadataAsync(string configPath)
|
|
{
|
|
var startInfo = new ProcessStartInfo
|
|
{
|
|
FileName = _docfxPath,
|
|
Arguments = $"metadata \"{configPath}\"",
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true,
|
|
WorkingDirectory = _workingDirectory
|
|
};
|
|
|
|
using var process = new Process { StartInfo = startInfo };
|
|
var outputBuilder = new System.Text.StringBuilder();
|
|
var errorBuilder = new System.Text.StringBuilder();
|
|
|
|
process.OutputDataReceived += (sender, e) =>
|
|
{
|
|
if (!string.IsNullOrEmpty(e.Data))
|
|
outputBuilder.AppendLine(e.Data);
|
|
};
|
|
|
|
process.ErrorDataReceived += (sender, e) =>
|
|
{
|
|
if (!string.IsNullOrEmpty(e.Data))
|
|
errorBuilder.AppendLine(e.Data);
|
|
};
|
|
|
|
process.Start();
|
|
process.BeginOutputReadLine();
|
|
process.BeginErrorReadLine();
|
|
|
|
await process.WaitForExitAsync();
|
|
|
|
if (process.ExitCode != 0)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"DocFX metadata falló con código de salida {process.ExitCode}. Error: {errorBuilder}");
|
|
}
|
|
|
|
return outputBuilder.ToString();
|
|
}
|
|
}
|
|
}
|