Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Cesil/Cesil.SourceGenerator.Tests/Helpers/TestHelper.cs
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
179 lines (145 sloc)
6.98 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Immutable; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
using System.Threading.Tasks; | |
using Microsoft.CodeAnalysis; | |
using Microsoft.CodeAnalysis.CSharp; | |
namespace Cesil.SourceGenerator.Tests | |
{ | |
internal static class TestHelper | |
{ | |
internal static string GetFlaggedSource(Diagnostic diag) | |
{ | |
var tree = diag.Location.SourceTree; | |
if (tree == null) | |
{ | |
throw new Exception("Couldn't find source for diagnostic"); | |
} | |
var root = tree.GetRoot(); | |
var node = root.FindNode(diag.Location.SourceSpan); | |
var sourceFlagged = node.ToFullString(); | |
return sourceFlagged; | |
} | |
internal static async Task<(Compilation Compilation, ImmutableArray<Diagnostic> Diagnostic)> RunSourceGeneratorAsync( | |
string testFile, | |
ISourceGenerator generator, | |
NullableContextOptions nullableContext = NullableContextOptions.Enable, | |
[CallerMemberName] string caller = null | |
) | |
{ | |
var compilation = await GetCompilationAsync(testFile, caller, nullableContext); | |
var parseOptions = (CSharpParseOptions)compilation.SyntaxTrees.ElementAt(0).Options; | |
var generators = ImmutableArray.Create(generator); | |
GeneratorDriver driver = CSharpGeneratorDriver.Create(generators, parseOptions: parseOptions); | |
driver.RunGeneratorsAndUpdateCompilation(compilation, out var producedCompilation, out var diagnostics); | |
return (producedCompilation, diagnostics); | |
} | |
internal static Task<Compilation> GetCompilationAsync( | |
string testFile, | |
string caller, | |
NullableContextOptions nullableContext | |
) | |
{ | |
var trustedAssemblies = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")).Split(Path.PathSeparator); | |
var systemAssemblies = trustedAssemblies.Where(p => Path.GetFileName(p).StartsWith("System.")).ToList(); | |
var references = systemAssemblies.Select(s => MetadataReference.CreateFromFile(s)).ToList(); | |
var projectName = $"Cesil.SourceGenerator.Tests.{nameof(TestHelper)}"; | |
var projectId = ProjectId.CreateNewId(projectName); | |
var compilationOptions = | |
new CSharpCompilationOptions( | |
OutputKind.DynamicallyLinkedLibrary, | |
allowUnsafe: true, | |
nullableContextOptions: nullableContext | |
); | |
var parseOptions = new CSharpParseOptions(LanguageVersion.CSharp8); | |
var projectInfo = | |
ProjectInfo.Create( | |
projectId, | |
VersionStamp.Create(), | |
projectName, | |
projectName, | |
LanguageNames.CSharp, | |
compilationOptions: compilationOptions, | |
parseOptions: parseOptions | |
); | |
var workspace = new AdhocWorkspace(); | |
var solution = | |
workspace | |
.CurrentSolution | |
.AddProject(projectInfo); | |
foreach (var reference in references) | |
{ | |
solution = solution.AddMetadataReference(projectId, reference); | |
} | |
var csFile = $"{caller}.cs"; | |
var docId = DocumentId.CreateNewId(projectId, csFile); | |
var project = solution.GetProject(projectId); | |
project = project.AddDocument(csFile, testFile).Project; | |
// find the Cesil folder to include code from | |
string cesilRootDir; | |
{ | |
cesilRootDir = Environment.CurrentDirectory; | |
while (cesilRootDir != null) | |
{ | |
if (Directory.GetDirectories(cesilRootDir).Any(c => Path.GetFileName(c) == "Cesil")) | |
{ | |
cesilRootDir = Path.Combine(cesilRootDir, "Cesil"); | |
break; | |
} | |
cesilRootDir = Path.GetDirectoryName(cesilRootDir); | |
} | |
if (cesilRootDir == null) | |
{ | |
throw new Exception("Couldn't find Cesil root directory, are tests not being run from within the solution?"); | |
} | |
} | |
//var files = | |
// new[] | |
// { | |
// new [] { "Interface", "Attributes", "GenerateSerializerAttribute.cs" }, | |
// new [] { "Interface", "Attributes", "SerializerMemberAttribute.cs" }, | |
// new [] { "Interface", "Attributes", "DeserializerMemberAttribute.cs" }, | |
// new [] { "Interface", "Attributes", "GenerateDeserializerAttribute.cs" }, | |
// new [] { "Interface", "Attributes", "DeserializerInstanceProviderAttribute.cs" }, | |
// new [] { "Context", "WriteContext.cs" }, | |
// new [] { "Context", "ReadContext.cs" }, | |
// new [] { "TypeDescriber", "Wrappers", "MemberRequired.cs" }, | |
// new [] { "TypeDescriber", "Wrappers", "EmitDefaultValue.cs" }, | |
// new [] { "TypeDescriber", "GeneratorAttributes", "ConstructorInstanceProviderAttribute.cs" }, | |
// new [] { "TypeDescriber", "GeneratorAttributes", "DoesNotEmitDefaultValueAttribute.cs" }, | |
// new [] { "TypeDescriber", "GeneratorAttributes", "GeneratedSourceVersionAttribute.cs" }, | |
// new [] { "TypeDescriber", "GeneratorAttributes", "IsRequiredAttribute.cs" }, | |
// new [] { "TypeDescriber", "GeneratorAttributes", "SetterBackedByConstructorParameterAttribute.cs" }, | |
// }; | |
//foreach (var fileParts in files) | |
//{ | |
// var toAddFilePath = cesilRootDir; | |
// foreach (var part in fileParts) | |
// { | |
// toAddFilePath = Path.Combine(toAddFilePath, part); | |
// } | |
// var fileText = File.ReadAllText(toAddFilePath); | |
// project = project.AddDocument(Path.GetFileName(toAddFilePath), fileText).Project; | |
//} | |
var cesilRef = GetCesilReference(); | |
project = project.AddMetadataReference(cesilRef); | |
var netstandardRef = GetNetStandard20Reference(); | |
project = project.AddMetadataReference(netstandardRef); | |
return project.GetCompilationAsync(); | |
} | |
private static MetadataReference GetCesilReference() | |
{ | |
var optsType = typeof(Options); | |
var cesilLoc = optsType.Assembly.Location; | |
return MetadataReference.CreateFromFile(cesilLoc); | |
} | |
private static MetadataReference GetNetStandard20Reference() | |
{ | |
var asm = Assembly.Load("netstandard, Version=2.0.0.0").Location; | |
return MetadataReference.CreateFromFile(asm); | |
} | |
} | |
} |