using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Xml.Linq;
using UnityEditor.Build;
namespace Unity.VisualScripting
{
public static class DocumentationGenerator
{
public static string GenerateDocumentation(string projectPath)
{
PathUtility.CreateDirectoryIfNeeded(BoltCore.Paths.assemblyDocumentations);
var projectName = Path.GetFileNameWithoutExtension(projectPath);
if (!File.Exists(projectPath))
{
throw new FileNotFoundException($"Project file not found: '{projectPath}'.");
}
var projectBuilderPath = Paths.projectBuilder;
if (!File.Exists(projectBuilderPath))
{
throw new FileNotFoundException($"Project builder not found: '{projectBuilderPath}'.\nYou can download the latest MSBuild from: {Paths.MsBuildDownloadLink}");
}
using (var process = new Process())
{
var projectXml = XDocument.Load(projectPath);
var projectRootNamespace = projectXml.Root.GetDefaultNamespace();
var assemblyName = projectXml.Descendants(projectRootNamespace + "AssemblyName").Single().Value;
var documentationPath = Path.Combine(BoltCore.Paths.assemblyDocumentations, assemblyName + ".xml");
process.StartInfo = new ProcessStartInfo();
process.StartInfo.FileName = projectBuilderPath;
process.StartInfo.Arguments =
"/p:Configuration=Debug " +
"/p:GenerateDocumentation=true " +
"/p:WarningLevel=0 " +
$"/p:DocumentationFile=\"{documentationPath}\" " +
$"\"{projectPath}\"";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
var timeout = 20000;
var output = new StringBuilder();
var error = new StringBuilder();
using (var outputWaitHandle = new AutoResetEvent(false))
using (var errorWaitHandle = new AutoResetEvent(false))
{
process.OutputDataReceived += (sender, e) =>
{
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
output.AppendLine(e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (e.Data == null)
{
errorWaitHandle.Set();
}
else
{
error.AppendLine(e.Data);
}
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (process.WaitForExit(timeout) &&
outputWaitHandle.WaitOne(timeout) &&
errorWaitHandle.WaitOne(timeout))
{
if (process.ExitCode != 0)
{
throw new BuildFailedException($"Failed to build project '{projectName}':\n{process.StartInfo.Arguments}\n{error}\n{output}");
}
XmlDocumentation.ClearCache();
return output.ToString();
}
else
{
throw new TimeoutException("Build process timed out.");
}
}
}
}
}
}