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; } }