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