private string GetGeneratedOutput(string source) { var syntaxTree = CSharpSyntaxTree.ParseText(source); var references = new List <MetadataReference>(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { if (!assembly.IsDynamic) { references.Add(MetadataReference.CreateFromFile(assembly.Location)); } } var compilation = CSharpCompilation.Create("foo", new SyntaxTree[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); // TODO: Uncomment this line if you want to fail tests when the injected program isn't valid _before_ running generators // var compileDiagnostics = compilation.GetDiagnostics(); // Assert.False(compileDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), "Failed: " + compileDiagnostics.FirstOrDefault()?.GetMessage()); ISourceGenerator generator = new Generator(); var driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generateDiagnostics); Assert.False(generateDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), "Failed: " + generateDiagnostics.FirstOrDefault()?.GetMessage()); string output = outputCompilation.SyntaxTrees.Last().ToString(); _output.WriteLine(output); return(output); }
public void Execute_ShouldHandleInvalidSyntax() { Compilation compilation = CreateCompilation ( @" using System.Collections; using Solti.Utils.Proxy; using Solti.Utils.Proxy.Attributes; using Solti.Utils.Proxy.Generators; [assembly: EmbedGeneratedType(typeof(DuckGenerator<IEnumerable,>))] ", new[] { typeof(EmbedGeneratedTypeAttribute).Assembly.Location }, suppressErrors: true ); Assert.That(compilation.SyntaxTrees.Count(), Is.EqualTo(1)); GeneratorDriver driver = CSharpGeneratorDriver.Create(new ProxyEmbedder()); driver.RunGeneratorsAndUpdateCompilation(compilation, out compilation, out ImmutableArray <Diagnostic> diags); Assert.That(diags, Is.Empty); Assert.That(compilation.SyntaxTrees.Count(), Is.EqualTo(1)); }
public void Execute_ShouldWarnOnUnsupportedLanguageVersion() { Compilation compilation = CreateCompilation ( @" using System.Collections; using Solti.Utils.Proxy; using Solti.Utils.Proxy.Attributes; using Solti.Utils.Proxy.Generators; [assembly: EmbedGeneratedType(typeof(DuckGenerator<IEnumerable, IEnumerable>))] ", Runtime .Assemblies .Select(asm => asm.Location) .Append(typeof(EmbedGeneratedTypeAttribute).Assembly.Location) .Distinct(), Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp6 ); GeneratorDriver driver = CSharpGeneratorDriver.Create ( new ISourceGenerator[] { new ProxyEmbedder() }, parseOptions: new CSharpParseOptions(Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp6) ); driver.RunGeneratorsAndUpdateCompilation(compilation, out compilation, out ImmutableArray <Diagnostic> diags); Assert.That(diags.Any(diag => diag.Id == "PGE00" && diag.Severity == DiagnosticSeverity.Warning && diag.GetMessage() == SGResources.LNG_NOT_SUPPORTED)); Assert.That(diags.Length, Is.EqualTo(1)); }
public void DoNotGenerateGetServicesForNamedServicesWhenNotNeeded() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export] public sealed class Foo : IFoo { } }"); var sourceGenerator = new IocContainerGenerator(); var runtime = CSharpGeneratorDriver.Create(sourceGenerator); // When runtime.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.False(output.ContainsTypeWithMethodSignature( "IocContainer", "public T? GetService<T>(string serviceId) where T : class")); }
public void GenerateInterfaceStubsSmokeTest() { var fixture = new InterfaceStubGenerator(); var driver = CSharpGeneratorDriver.Create(fixture); var inputCompilation = CreateCompilation( IntegrationTestHelper.GetPath("RestService.cs"), IntegrationTestHelper.GetPath("GitHubApi.cs"), IntegrationTestHelper.GetPath("InheritedInterfacesApi.cs"), IntegrationTestHelper.GetPath("InheritedGenericInterfacesApi.cs")); var diags = inputCompilation.GetDiagnostics(); // Make sure we don't have any errors Assert.Empty(diags.Where(d => d.Severity == DiagnosticSeverity.Error)); var rundriver = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompiliation, out var diagnostics); var runResult = rundriver.GetRunResult(); var generated = runResult.Results[0]; var text = generated.GeneratedSources.First().SourceText.ToString(); Assert.Contains("IGitHubApi", text); Assert.Contains("IAmInterfaceC", text); }
public void Generator_Can_Report_Diagnostics() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); string description = "This is a test diagnostic"; DiagnosticDescriptor generatorDiagnostic = new DiagnosticDescriptor("TG001", "Test Diagnostic", description, "Generators", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: description); var diagnostic = Microsoft.CodeAnalysis.Diagnostic.Create(generatorDiagnostic, Location.None); var generator = new CallbackGenerator((ic) => { }, (sgc) => sgc.ReportDiagnostic(diagnostic)); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatorDiagnostics); outputCompilation.VerifyDiagnostics(); generatorDiagnostics.Verify( Diagnostic("TG001").WithLocation(1, 1) ); }
private static (ImmutableArray <Diagnostic> Diagnostics, string Output) GetGeneratedOutput(string source) { var syntaxTree = CSharpSyntaxTree.ParseText(source); var references = new List <MetadataReference>(); foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (!assembly.IsDynamic) { references.Add(MetadataReference.CreateFromFile(assembly.Location)); } } var compilation = CSharpCompilation.Create("foo", new SyntaxTree[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); var diagnostics = compilation.GetDiagnostics(); if (diagnostics.Any()) { return(diagnostics, string.Empty); } var generator = new EventGenerator(); var driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out diagnostics); return(diagnostics, outputCompilation.SyntaxTrees.Last().ToString()); }
public void Syntax_Receiver_Can_Be_Registered_Only_Once() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); var testGenerator = new CallbackGenerator( onInit: initialize, onExecute: (e) => { } ); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out _, out _); void initialize(GeneratorInitializationContext initContext) { initContext.RegisterForSyntaxNotifications(() => new TestSyntaxReceiver()); Assert.Throws <InvalidOperationException>(() => { initContext.RegisterForSyntaxNotifications(() => new TestSyntaxReceiver()); }); } }
protected Task Verify(string source, Action <Compilation, ImmutableArray <Diagnostic> >?verifyCompilation) { var syntaxTree = CSharpSyntaxTree.ParseText(source); var assemblyDirectory = Path.GetDirectoryName(typeof(object).Assembly.Location) !; var references = new[] { typeof(object), typeof(Enumerable) }.Select(t => MetadataReference.CreateFromFile(t.Assembly.Location)) .Concat(new [] { MetadataReference.CreateFromFile(Path.Combine(assemblyDirectory, "System.Runtime.dll")), MetadataReference.CreateFromFile(Path.Combine(assemblyDirectory, "System.Collections.dll")), }); var compilation = CSharpCompilation.Create( assemblyName: "Tests", syntaxTrees: new[] { syntaxTree }, references: references, options: new(OutputKind.DynamicallyLinkedLibrary)); GeneratorDriver driver = CSharpGeneratorDriver.Create(new ResultTypeGenerator(), new UnionTypeGenerator()); driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var updatedCompilation, out var diagnostics); verifyCompilation?.Invoke(updatedCompilation, diagnostics); return(Verify(driver) .UseDirectory("Snapshots")); }
public void Syntax_Receiver_Is_Present_When_Registered() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); ISyntaxReceiver?receiver = null; var testGenerator = new CallbackGenerator( onInit: (i) => i.RegisterForSyntaxNotifications(() => new TestSyntaxReceiver()), onExecute: (e) => receiver = e.SyntaxReceiver ); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out _, out _); Assert.NotNull(receiver); Assert.IsType <TestSyntaxReceiver>(receiver); }
public void Syntax_Receiver_Is_Null_WhenNot_Registered() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); ISyntaxReceiver?receiver = null; var testGenerator = new CallbackGenerator( onInit: (i) => { }, onExecute: (e) => receiver = e.SyntaxReceiver ); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _); Assert.Null(receiver); }
private static (ImmutableArray <Diagnostic>, string) GetGeneratedOutput(string source) { var syntaxTree = CSharpSyntaxTree.ParseText(source); var references = new List <MetadataReference>(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { if (!assembly.IsDynamic) { references.Add(MetadataReference.CreateFromFile(assembly.Location)); } } var compilation = CSharpCompilation.Create("foo", new SyntaxTree[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); // TODO: Uncomment these lines if you want to return immediately if the injected program isn't valid _before_ running generators // // ImmutableArray<Diagnostic> compilationDiagnostics = compilation.GetDiagnostics(); // // if (diagnostics.Any()) // { // return (diagnostics, ""); // } ISourceGenerator generator = new Generator(); var driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generateDiagnostics); return(generateDiagnostics, outputCompilation.SyntaxTrees.Last().ToString()); }
/// <summary> /// Verifies the output of a source generator. /// </summary> /// <typeparam name="TGenerator">The generator type to use.</typeparam> /// <param name="source">The input source to process.</param> /// <param name="diagnosticsIds">The diagnostic ids to expect for the input source code.</param> private void VerifyGeneratedDiagnostics <TGenerator>(string source, params string[] diagnosticsIds) where TGenerator : class, ISourceGenerator, new() { Type validationAttributeType = typeof(ValidationAttribute); SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source); IEnumerable <MetadataReference> references = from assembly in AppDomain.CurrentDomain.GetAssemblies() where !assembly.IsDynamic let reference = MetadataReference.CreateFromFile(assembly.Location) select reference; CSharpCompilation compilation = CSharpCompilation.Create("original", new SyntaxTree[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); ISourceGenerator generator = new TGenerator(); CSharpGeneratorDriver driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(compilation, out Compilation outputCompilation, out ImmutableArray <Diagnostic> diagnostics); HashSet <string> resultingIds = diagnostics.Select(diagnostic => diagnostic.Id).ToHashSet(); Assert.IsTrue(resultingIds.SetEquals(diagnosticsIds)); GC.KeepAlive(validationAttributeType); }
private GeneratorDriverRunResult RunGenerator(Compilation compilation) { _testOutputHelper.WriteLine("Running generator and updating compilation..."); var subject = new ScenarioTestGenerator(); var driver = CSharpGeneratorDriver .Create(subject) .RunGenerators(compilation); var result = driver.GetRunResult(); if (result.Diagnostics.IsEmpty) { _testOutputHelper.WriteLine("Run did not produce diagnostics"); } else { _testOutputHelper.WriteLine($"Diagnostics produced:"); foreach (var diagnostic in result.Diagnostics) { _testOutputHelper.WriteLine($" > " + diagnostic.ToString()); } } foreach (var newSyntaxTree in result.GeneratedTrees) { _testOutputHelper.WriteLine($"Produced syntax tree with path produced: {newSyntaxTree.FilePath}"); _testOutputHelper.WriteLine(newSyntaxTree.GetText().ToString()); } return(driver.GetRunResult()); }
public void Error_During_Generation_Does_Not_Affect_Other_Generators() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); var exception = new InvalidOperationException("generate error"); var generator = new CallbackGenerator((ic) => { }, (sgc) => throw exception); var generator2 = new CallbackGenerator2((ic) => { }, (sgc) => { }, source: "public class D { }"); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator, generator2 }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatorDiagnostics); outputCompilation.VerifyDiagnostics(); Assert.Equal(2, outputCompilation.SyntaxTrees.Count()); generatorDiagnostics.Verify( // warning CS8785: Generator 'CallbackGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was 'InvalidOperationException' with message 'generate error' Diagnostic("CS" + (int)ErrorCode.WRN_GeneratorFailedDuringGeneration).WithArguments("CallbackGenerator", "InvalidOperationException", "generate error").WithLocation(1, 1) ); }
public void Single_File_Is_Added_OnlyOnce_For_Multiple_Calls() { var source = @" class C { } "; var generatorSource = @" class GeneratedClass { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); SingleFileTestGenerator testGenerator = new SingleFileTestGenerator(generatorSource); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation1, out _); driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation2, out _); driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation3, out _); Assert.Equal(2, outputCompilation1.SyntaxTrees.Count()); Assert.Equal(2, outputCompilation2.SyntaxTrees.Count()); Assert.Equal(2, outputCompilation3.SyntaxTrees.Count()); Assert.NotEqual(compilation, outputCompilation1); Assert.NotEqual(compilation, outputCompilation2); Assert.NotEqual(compilation, outputCompilation3); }
public void Error_During_Generation_Has_Exception_In_Description() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); var exception = new InvalidOperationException("generate error"); var generator = new CallbackGenerator((ic) => { }, (sgc) => throw exception); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatorDiagnostics); outputCompilation.VerifyDiagnostics(); // Since translated description strings can have punctuation that differs based on locale, simply ensure the // exception message is contains in the diagnostic description. Assert.Contains(exception.ToString(), generatorDiagnostics.Single().Descriptor.Description.ToString()); }
public void User_Source_Can_Depend_On_Generated_Source() { var source = @" #pragma warning disable CS0649 class C { public D d; } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics( // (5,12): error CS0246: The type or namespace name 'D' could not be found (are you missing a using directive or an assembly reference?) // public D d; Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "D").WithArguments("D").WithLocation(5, 12) ); Assert.Single(compilation.SyntaxTrees); var generator = new SingleFileTestGenerator("public class D { }"); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatorDiagnostics); outputCompilation.VerifyDiagnostics(); generatorDiagnostics.Verify(); }
public void Generator_HintName_MustBe_Unique() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); var generator = new CallbackGenerator((ic) => { }, (sgc) => { sgc.AddSource("test", SourceText.From("public class D{}", Encoding.UTF8)); // the assert should swallow the exception, so we'll actually successfully generate Assert.Throws <ArgumentException>("hintName", () => sgc.AddSource("test", SourceText.From("public class D{}", Encoding.UTF8))); // also throws for <name> vs <name>.cs Assert.Throws <ArgumentException>("hintName", () => sgc.AddSource("test.cs", SourceText.From("public class D{}", Encoding.UTF8))); }); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatorDiagnostics); outputCompilation.VerifyDiagnostics(); generatorDiagnostics.Verify(); Assert.Equal(2, outputCompilation.SyntaxTrees.Count()); }
public void TryApply_Edits_Does_Nothing_When_Nothing_Pending() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); // run an initial generation pass driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _); Assert.Single(outputCompilation.SyntaxTrees); // now try apply edits (which should succeed, but do nothing) driver = driver.TryApplyEdits(compilation, out var editedCompilation, out var succeeded); Assert.True(succeeded); Assert.Equal(outputCompilation, editedCompilation); }
public static async Task Main(string[] args) { string sln = @"G:\github\FlorianGrimm\Latrans\Brimborium.Latrans.sln"; string csproj = @"G:\github\FlorianGrimm\Latrans\src\DemoWebApp.Logic\DemoWebApp.Logic.csproj"; csproj = System.IO.Path.GetFullPath(csproj); Console.WriteLine($"SourceGen csproj:{csproj};"); MSBuildLocatorHelper.Init(); var workspace = MSBuildLocatorHelper.CreateWorkspace(null); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();; var cancellationToken = cancellationTokenSource.Token; cancellationToken.ThrowIfCancellationRequested(); System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { cancellationTokenSource.Cancel(); }; var solution = await workspace.OpenSolutionAsync(sln, null, cancellationToken); var project = solution.Projects.Where(prj => string.Equals(prj.FilePath, csproj, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (project is null) { System.Console.Error.WriteLine($"csproj: {csproj} not found."); return; } else { //var project = await workspace.OpenProjectAsync(csproj, null, cancellationToken); // project.AnalyzerReferences // project.ProjectReferences //foreach (var projectReference in project.ProjectReferences) { // var projectId = projectReference.ProjectId; //} var inputCompilation = await project.GetCompilationAsync(cancellationToken); if (inputCompilation is null) { // } else { var generator = new ConfigureHandlersSourceGenerator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(generator); driver = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics); var lstDiagnostics = diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).ToList(); if (lstDiagnostics.Count > 0) { foreach (var diagnostic in lstDiagnostics) { System.Console.Error.WriteLine(diagnostic.GetMessage()); } } else { } } } }
public void Failed_Edit_Does_Not_Change_Compilation() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator() { CanApplyChanges = false }; GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _); Assert.Single(outputCompilation.SyntaxTrees); // create an edit AdditionalFileAddedEdit edit = new AdditionalFileAddedEdit(new InMemoryAdditionalText("a\\file2.cs", "")); driver = driver.WithPendingEdits(ImmutableArray.Create <PendingEdit>(edit)); // now try apply edits (which will fail) driver = driver.TryApplyEdits(compilation, out var editedCompilation, out var succeeded); Assert.False(succeeded); Assert.Single(editedCompilation.SyntaxTrees); Assert.Equal(compilation, editedCompilation); }
/// <summary> /// Runs a Roslyn generator over a set of source files. /// </summary> public static async Task <(IReadOnlyList <Diagnostic>, ImmutableArray <GeneratedSourceResult>)> RunGenerator( ISourceGenerator generator, IEnumerable <Assembly>?references, IEnumerable <string> sources, AnalyzerConfigOptionsProvider?optionsProvider = null, bool includeBaseReferences = true, CancellationToken cancellationToken = default) { var proj = CreateTestProject(references, includeBaseReferences); var count = 0; foreach (var s in sources) { proj = proj.WithDocument($"src-{count++}.cs", s); } proj.CommitChanges(); var comp = await proj !.GetCompilationAsync(CancellationToken.None).ConfigureAwait(false); var cgd = CSharpGeneratorDriver.Create(new[] { generator }, optionsProvider: optionsProvider); var gd = cgd.RunGenerators(comp !, cancellationToken); var r = gd.GetRunResult(); return(Sort(r.Results[0].Diagnostics), r.Results[0].GeneratedSources); }
public void Added_Additional_File() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); // run initial generation pass driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _); Assert.Single(outputCompilation.SyntaxTrees); // create an edit AdditionalFileAddedEdit edit = new AdditionalFileAddedEdit(new InMemoryAdditionalText("a\\file1.cs", "")); driver = driver.WithPendingEdits(ImmutableArray.Create <PendingEdit>(edit)); // now try apply edits driver = driver.TryApplyEdits(compilation, out outputCompilation, out var succeeded); Assert.True(succeeded); Assert.Equal(2, outputCompilation.SyntaxTrees.Count()); }
public static void RunGenerator(SourceText sourceText, ISourceGenerator generator) { var compilation = CSharpCompilation .Create("MyTestAssembly") .WithOptions(new(OutputKind.DynamicallyLinkedLibrary)) .WithReferences( MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(DependencyObject).Assembly.Location), MetadataReference.CreateFromFile(typeof(FrameworkPropertyMetadataOptions).Assembly.Location), MetadataReference.CreateFromFile(typeof(RoutedEvent).Assembly.Location)) .AddSyntaxTrees(CSharpSyntaxTree.ParseText(sourceText)); var rr = CSharpGeneratorDriver .Create(generator) .RunGenerators(compilation) .GetRunResult(); foreach (var result in rr.Results) { foreach (var generatedSourceResult in result.GeneratedSources) { Console.WriteLine(generatedSourceResult.SyntaxTree.ToString()); } } }
public void Edits_Are_Applied_During_Full_Generation() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); AdditionalFileAddedGenerator testGenerator = new AdditionalFileAddedGenerator(); var text = new InMemoryAdditionalText("a\\file1.cs", ""); GeneratorDriver driver = CSharpGeneratorDriver.Create(parseOptions: parseOptions, generators: ImmutableArray.Create <ISourceGenerator>(testGenerator), optionsProvider: CompilerAnalyzerConfigOptionsProvider.Empty, additionalTexts: ImmutableArray.Create <AdditionalText>(new InMemoryAdditionalText("a\\file1.cs", ""))); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _); Assert.Equal(2, outputCompilation.SyntaxTrees.Count()); // add multiple edits driver = driver.WithPendingEdits(ImmutableArray.Create <PendingEdit>(new AdditionalFileAddedEdit(new InMemoryAdditionalText("a\\file2.cs", "")), new AdditionalFileAddedEdit(new InMemoryAdditionalText("a\\file3.cs", "")), new AdditionalFileAddedEdit(new InMemoryAdditionalText("a\\file4.cs", "")))); // but just do a full generation (don't try apply) driver.RunGeneratorsAndUpdateCompilation(compilation, out outputCompilation, out _); Assert.Equal(5, outputCompilation.SyntaxTrees.Count()); }
public void Execute_ShouldReportDiagnosticOnError() { Compilation compilation = CreateCompilation ( @" using System.Collections; using Solti.Utils.Proxy; using Solti.Utils.Proxy.Attributes; using Solti.Utils.Proxy.Generators; [assembly: EmbedGeneratedType(typeof(DuckGenerator<IEnumerable, object>))] ", new[] { typeof(EmbedGeneratedTypeAttribute).Assembly.Location }, suppressErrors: true ); Assert.That(compilation.SyntaxTrees.Count(), Is.EqualTo(1)); GeneratorDriver driver = CSharpGeneratorDriver.Create(new ProxyEmbedder()); driver.RunGeneratorsAndUpdateCompilation(compilation, out compilation, out ImmutableArray <Diagnostic> diags); Assert.That(diags.Any(diag => diag.Id.StartsWith("PGE") && diag.Severity == DiagnosticSeverity.Warning && diag.GetMessage().Contains(string.Format(Resources.MISSING_IMPLEMENTATION, nameof(IEnumerable.GetEnumerator))))); Assert.That(diags.Length, Is.EqualTo(1)); Assert.That(compilation.SyntaxTrees.Count(), Is.EqualTo(1)); }
public void Error_During_Initialization_Is_Reported() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); var exception = new InvalidOperationException("init error"); var generator = new CallbackGenerator((ic) => throw exception, (sgc) => { }); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatorDiagnostics); outputCompilation.VerifyDiagnostics(); generatorDiagnostics.Verify( // warning CS8784: Generator 'CallbackGenerator' failed to initialize. It will not contribute to the output and compilation errors may occur as a result. Exception was 'InvalidOperationException' with message 'init error' Diagnostic("CS" + (int)ErrorCode.WRN_GeneratorFailedDuringInitialization).WithArguments("CallbackGenerator", "InvalidOperationException", "init error").WithLocation(1, 1) ); }
public static async Task <SyntaxTree> GenerateAsync <T>(string source) where T : ISourceGenerator, new() { var document = CreateProject(source).Documents.Single(); var tree = await document.GetSyntaxTreeAsync(); if (tree is null) { throw new InvalidOperationException("Could not get the syntax tree of the sources"); } var compilation = (CSharpCompilation)(await document.Project.GetCompilationAsync()) !; if (compilation is null) { throw new InvalidOperationException("Could not compile the sources"); } var diagnostics = compilation.GetDiagnostics(); // Assert.Empty(diagnostics.Where(x => x.Severity >= DiagnosticSeverity.Warning)); ISourceGenerator generator = new T(); var driver = CSharpGeneratorDriver.Create( ImmutableArray.Create(generator), ImmutableArray <AdditionalText> .Empty, compilation.SyntaxTrees[0].Options as CSharpParseOptions ); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out diagnostics); Assert.Empty(diagnostics.Where(x => x.Severity >= DiagnosticSeverity.Warning)); // the syntax tree added by the generator will be the last one in the compilation return(outputCompilation.SyntaxTrees.Last(z => !z.FilePath.Contains("AssemblyRegistrationOptions") && !z.FilePath.Contains("GeneratedAssemblyJsonRpcHandlers"))); }
public void GenerateDefaultServiceCache() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export] public sealed class Foo : IFoo { } }"); var sourceGenerator = new ServiceCacheGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsClass("ServiceCache")); Assert.False(output.ContainsTypeWithMethodSignature( "ServiceCache", "public object GetOrAdd(Type key, string serviceId, Func<string, object> valueFactory)")); }