using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; namespace ExtractMethod.Tooling; /// /// Turns a plain .cs file into a Roslyn that a /// semantic model can be queried against. /// /// Shared by the CLI (Program.cs) and the tests so both exercise the same /// loading path — the tests should not re-implement this, or they would be /// testing their own assumptions instead of the tool. /// public static class CompilationLoader { /// /// Parse a file into a using the latest language /// version. Nothing here is project-specific: no .sln, no .csproj, no /// generated files — the tool is a micro-tool that runs on a single file. /// public static SyntaxTree ParseFile(string path) { var text = File.ReadAllText(Path.GetFullPath(path)); return CSharpSyntaxTree.ParseText( text, path: path, options: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest)); } /// /// Build a scratch compilation over . /// /// WHY TRUSTED_PLATFORM_ASSEMBLIES: it is the runtime-resolved list /// of the actual BCL assemblies this process (net10.0) runs on, e.g. /// System.Private.CoreLib, System.Runtime, System.Console. Referencing /// them means an arbitrary fixture can bind List<T>, string, and the /// rest of the BCL without any NuGet/EF/SQLite haul. (A single /// typeof(object) reference is NOT enough on modern .NET — that only pulls /// in the core library, and Console/GC/enums etc. fail to bind.) /// public static CSharpCompilation CreateCompilation(SyntaxTree tree, string assemblyName) { var refs = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")!) .Split(Path.PathSeparator) .Select(p => (MetadataReference)MetadataReference.CreateFromFile(p)); return CSharpCompilation.Create( assemblyName, new[] { tree }, refs, new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, // Match the repo's net10.0 projects so the fixture's nullable // annotations compile without warnings. nullableContextOptions: NullableContextOptions.Enable)); } }