Skip to content

Instantly share code, notes, and snippets.

@tm-nti
Created September 24, 2024 11:04
Show Gist options
  • Select an option

  • Save tm-nti/bb374b36d815a1166bc0cbc4febb8515 to your computer and use it in GitHub Desktop.

Select an option

Save tm-nti/bb374b36d815a1166bc0cbc4febb8515 to your computer and use it in GitHub Desktop.
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace ExternalJsonFile.SourceGenerator.Test
{
public static class TestUtil
{
[ModuleInitializer]
public static void Init()
{
VerifySourceGenerators.Initialize();
}
public static Task Verify<T>(string source) where T : IIncrementalGenerator, new()
{
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source);
IEnumerable<PortableExecutableReference> references = [MetadataReference.CreateFromFile(typeof(object).Assembly.Location)];
CSharpCompilation cSharpCompilation = CSharpCompilation.Create("Tests", [syntaxTree], references);
T generator = new T();
GeneratorDriver driver = CSharpGeneratorDriver.Create(generator).RunGenerators(cSharpCompilation);
return Verifier.Verify(driver).UseDirectory("Snapshots");
}
public static Task Verify<T>(string source, IEnumerable<AddFile> additionalFilesPath, IEnumerable<(string key, string value)> globalOptions) where T : IIncrementalGenerator, new()
{
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source);
IEnumerable<PortableExecutableReference> references = [MetadataReference.CreateFromFile(typeof(object).Assembly.Location)];
CSharpCompilation cSharpCompilation = CSharpCompilation.Create("Tests", [syntaxTree], references);
T generator = new T();
List<AdditionalText> additionalFiles = new List<AdditionalText>();
TestAnalyzerConfigOptionsProvider analyzer = new TestAnalyzerConfigOptionsProvider(globalOptions.Select(e => ("build_property." + e.key, e.value)));
foreach (AddFile addFile in additionalFilesPath)
{
var file = new TestingAdditionalText(addFile.Path);
additionalFiles.Add(file);
if (!string.IsNullOrEmpty(addFile.MetadataName) && !string.IsNullOrEmpty(addFile.MetadataValue))
{
analyzer.AddOptions(file, [("build_metadata.AdditionalFiles." + addFile.MetadataName, addFile.MetadataValue)]);
}
}
GeneratorDriver driver = CSharpGeneratorDriver.Create(generator).AddAdditionalTexts([.. additionalFiles]).WithUpdatedAnalyzerConfigOptions(analyzer).RunGenerators(cSharpCompilation);
return Verifier.Verify(driver).UseDirectory("Snapshots");
}
}
public record AddFile(string Path, string? MetadataName = null, string? MetadataValue = null);
public class TestingAdditionalText : AdditionalText
{
public override string Path { get; }
private readonly string _text;
public override SourceText? GetText(CancellationToken cancellationToken = default)
{
return SourceText.From(_text, System.Text.Encoding.UTF8);
}
public TestingAdditionalText(string path)
{
Path = path;
_text = File.ReadAllText(Path);
}
}
internal class TestAnalyzerConfigOptionsProvider : AnalyzerConfigOptionsProvider
{
public TestAnalyzerConfigOptionsProvider(IEnumerable<(string, string)> options)
=> GlobalOptions = new TestAnalyzerConfigOptions(options);
private readonly Dictionary<AdditionalText, AnalyzerConfigOptions> _addtionalFilesOptions = new Dictionary<AdditionalText, AnalyzerConfigOptions>();
public override AnalyzerConfigOptions GlobalOptions { get; }
public override AnalyzerConfigOptions GetOptions(SyntaxTree tree) => GlobalOptions;
public override AnalyzerConfigOptions GetOptions(AdditionalText textFile)
{
var first = (TestAnalyzerConfigOptions)_addtionalFilesOptions.GetValueOrDefault(textFile, TestAnalyzerConfigOptions.Empty);
return ((TestAnalyzerConfigOptions)GlobalOptions).Combine(first);
}
public void AddOptions(AdditionalText additionalText, IEnumerable<(string key, string value)> options)
{
_addtionalFilesOptions[additionalText] = new TestAnalyzerConfigOptions(options);
}
}
internal class TestAnalyzerConfigOptions : AnalyzerConfigOptions
{
private readonly Dictionary<string, string> _options;
public TestAnalyzerConfigOptions(IEnumerable<(string key, string value)> options)
=> _options = options.ToDictionary(e => e.key, e => e.value);
private TestAnalyzerConfigOptions(Dictionary<string, string> options)
{
_options = new Dictionary<string, string>(options);
}
private TestAnalyzerConfigOptions()
{
_options = new Dictionary<string, string>(0);
}
public override bool TryGetValue(string key, [NotNullWhen(true)] out string? value)
=> _options.TryGetValue(key, out value);
public TestAnalyzerConfigOptions Combine(TestAnalyzerConfigOptions other)
{
TestAnalyzerConfigOptions result = new TestAnalyzerConfigOptions(_options);
foreach (var item in other._options)
{
result._options.Add(item.Key, item.Value);
}
return result;
}
public static TestAnalyzerConfigOptions Empty => new TestAnalyzerConfigOptions();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment