using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace NodePipeline.Engine.Tests.CodeGeneratorTests.Fixtures;
public static class RoslynTestHelpers
{
///
/// Создаёт Roslyn Compilation из исходников мок-нод, находит и возвращает INamedTypeSymbol по полному имени типа.
///
///
/// Полное имя типа, например,
/// "NodePipeline.Engine.Tests.CodeGeneratorTests.Fixtures.MockNodes.ThreePortNode2"
///
/// Путь к папке с исходниками мок-нод (например, в тестовом проекте)
/// INamedTypeSymbol для указанного типа
public static INamedTypeSymbol GetNamedTypeSymbolFromSource(string fullTypeName, string sourceFilesDirectory)
{
if (!Directory.Exists(sourceFilesDirectory))
throw new DirectoryNotFoundException($"Source files directory not found: {sourceFilesDirectory}");
var sourceFiles = Directory.GetFiles(sourceFilesDirectory, "*.cs", SearchOption.AllDirectories);
var syntaxTrees = new List();
foreach (var file in sourceFiles)
{
var sourceText = File.ReadAllText(file);
var syntaxTree = CSharpSyntaxTree.ParseText(sourceText, path: file);
syntaxTrees.Add(syntaxTree);
}
var references = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location))
.Select(a => MetadataReference.CreateFromFile(a.Location))
.Cast()
.ToList();
var compilation = CSharpCompilation.Create("MockNodesCompilation",
syntaxTrees,
references,
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
var typeSymbol = compilation.GetTypeByMetadataName(fullTypeName);
if (typeSymbol == null)
throw new InvalidOperationException($"Type symbol '{fullTypeName}' not found in compilation.");
return typeSymbol;
}
}