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 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 Syntax_Receiver_Is_Not_Created_If_Exception_During_PostInitialize() { var source = @" class C { int Property { get; set; } void Function() { var x = 5; x += 4; } } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation( source, options: TestOptions.DebugDll, parseOptions: parseOptions ); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); TestSyntaxReceiver?receiver = null; var exception = new Exception("test exception"); var testGenerator = new CallbackGenerator( onInit: (i) => { i.RegisterForSyntaxNotifications(() => receiver = new TestSyntaxReceiver()); i.RegisterForPostInitialization((pic) => throw exception); }, onExecute: (e) => { Assert.True(false); } ); GeneratorDriver driver = CSharpGeneratorDriver.Create( new[] { testGenerator }, parseOptions: parseOptions ); driver = driver.RunGeneratorsAndUpdateCompilation( compilation, out var outputCompilation, out var outputDiagnostics ); var results = driver.GetRunResult(); Assert.Null(receiver); outputDiagnostics.Verify( Diagnostic("CS" + (int)ErrorCode.WRN_GeneratorFailedDuringInitialization) .WithArguments("CallbackGenerator", "Exception", "test exception") .WithLocation(1, 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 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 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 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()); }
#pragma warning restore public async Task AppendingUnrelatedSource_DoesNotRegenerateSource() { string source = $"namespace NS{{{CodeSnippets.BasicParametersAndModifiers<int>()}}}"; SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)); Compilation comp1 = await TestUtils.CreateCompilation(new[] { syntaxTree }); Microsoft.Interop.DllImportGenerator generator = new(); GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }); driver = driver.RunGenerators(comp1); generator.IncrementalTracker = new IncrementalityTracker(); SyntaxTree newTree = syntaxTree.WithRootAndOptions(syntaxTree.GetCompilationUnitRoot().AddMembers(SyntaxFactory.ParseMemberDeclaration("struct Foo {}") !), syntaxTree.Options); Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), newTree); driver.RunGenerators(comp2); Assert.Collection(generator.IncrementalTracker.ExecutedSteps, step => { Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step); }); }
public void SyntaxContext_Receiver_Return_Null_During_Creation() { var source = @" class C { } "; var parseOptions = TestOptions.Regular; Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); Assert.Single(compilation.SyntaxTrees); ISyntaxReceiver? syntaxRx = null; ISyntaxContextReceiver?syntaxContextRx = null; var testGenerator = new CallbackGenerator( onInit: (i) => i.RegisterForSyntaxNotifications((SyntaxContextReceiverCreator)(() => null !)), onExecute: (e) => { syntaxRx = e.SyntaxReceiver; syntaxContextRx = e.SyntaxContextReceiver; } ); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var outputDiagnostics); outputDiagnostics.Verify(); var results = driver.GetRunResult(); Assert.Empty(results.GeneratedTrees); Assert.Null(syntaxContextRx); Assert.Null(syntaxRx); }
public void MultiplePatchType_ExtensionAndTypeAddedToSource() { Compilation inputCompilation = CreateCompilation(@" namespace TestCode2 { public class Dto0 { public double Property { get; set; } } public class Dto1 { public Dto0 Property { get; set; } } public class Program { public void SomeMethod(LaDeak.JsonMergePatch.Abstractions.Patch<Dto0> data) { } public void SomeMethod(LaDeak.JsonMergePatch.Abstractions.Patch<Dto1> data) { } } } "); JsonMergePatchSourceGenerator generator = new JsonMergePatchSourceGenerator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(generator); driver = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics); Assert.True(diagnostics.IsEmpty); Assert.True(outputCompilation.SyntaxTrees.Count() == 4); Assert.True(outputCompilation.GetDiagnostics().IsEmpty); GeneratorDriverRunResult runResult = driver.GetRunResult(); Assert.Equal(3, runResult.GeneratedTrees.Length); Assert.Empty(runResult.Diagnostics); }
#pragma warning restore public async Task ChangingMarshallingAttributes_SameStrategy_DoesNotRegenerate() { string source = CodeSnippets.BasicParametersAndModifiers <bool>(); SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)); Compilation comp1 = await TestUtils.CreateCompilation(new[] { syntaxTree }); Microsoft.Interop.DllImportGenerator generator = new(); GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }); driver = driver.RunGenerators(comp1); generator.IncrementalTracker = new IncrementalityTracker(); SyntaxTree newTree = syntaxTree.WithRootAndOptions( syntaxTree.GetCompilationUnitRoot().AddMembers( SyntaxFactory.ParseMemberDeclaration( CodeSnippets.MarshalAsParametersAndModifiers <bool>(System.Runtime.InteropServices.UnmanagedType.Bool)) !), syntaxTree.Options); Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), newTree); driver.RunGenerators(comp2); Assert.Collection(generator.IncrementalTracker.ExecutedSteps, step => { Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step); }, step => { Assert.Equal(IncrementalityTracker.StepName.GenerateSingleStub, step.Step); }); }
public void DefaultRecordType_ExtensionAndTypeAddedToSource() { // Create the 'input' compilation that the generator will act on Compilation inputCompilation = CreateCompilation(@" namespace TestCode1 { public record Dto(int Property0, string Property1); public class Program { public void SomeMethod(LaDeak.JsonMergePatch.Abstractions.Patch<Dto> data) { } } } "); JsonMergePatchSourceGenerator generator = new JsonMergePatchSourceGenerator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(generator); driver = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics); Assert.True(diagnostics.IsEmpty); Assert.True(outputCompilation.SyntaxTrees.Count() == 3); Assert.True(outputCompilation.GetDiagnostics().IsEmpty); GeneratorDriverRunResult runResult = driver.GetRunResult(); Assert.Equal(2, runResult.GeneratedTrees.Length); Assert.Empty(runResult.Diagnostics); }
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(); Assert.EndsWith(exception.ToString() + "'.", generatorDiagnostics.Single().Descriptor.Description.ToString()); }
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 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 AddJsonMergePatch_AddsExtensionMethod() { // Create the 'input' compilation that the generator will act on Compilation inputCompilation = CreateCompilation(@" namespace TestCode1 { public class Dto { public int Property { get; set; } } public class Program { public void SomeMethod(LaDeak.JsonMergePatch.Abstractions.Patch<Dto> data) { } } } "); var commonGenerator = new JsonMergePatchSourceGenerator(); var sut = new AspNetJsonMergePatchSourceGenerator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(commonGenerator, sut); driver = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics); Assert.True(diagnostics.IsEmpty); GeneratorDriverRunResult runResult = driver.GetRunResult(); GeneratorRunResult testedGenerator = runResult.Results[1]; Assert.Single(testedGenerator.GeneratedSources); Assert.Empty(testedGenerator.Diagnostics); }
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 DiagnosticRaisedForMissingPartial() { var inputCompilation = CreateCompilation(@" using TypedIds; namespace T { [TypedId] public struct ValueItem { } } "); var generator = new Generator(); GeneratorDriver driver = CSharpGeneratorDriver.Create(generator); driver = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics); var result = driver.GetRunResult(); Assert.Collection(result.Diagnostics, el => { Assert.Equal("TYPEDID001", el.Id); }); }
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); }
public async Task ReplacingFileWithNewLibraryImport_DoesNotRegenerateStubsInOtherFiles() { Compilation comp1 = await TestUtils.CreateCompilation(new string[] { CodeSnippets.BasicParametersAndModifiers <int>(), CodeSnippets.MarshalAsParametersAndModifiers <bool>(UnmanagedType.I1) }); Microsoft.Interop.LibraryImportGenerator generator = new(); GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }, EnableIncrementalTrackingDriverOptions); driver = driver.RunGenerators(comp1); Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), CSharpSyntaxTree.ParseText(CodeSnippets.BasicParametersAndModifiers <ulong>(), new CSharpParseOptions(LanguageVersion.Preview))); GeneratorDriver driver2 = driver.RunGenerators(comp2); GeneratorRunResult runResult = driver2.GetRunResult().Results[0]; Assert.Collection(runResult.TrackedSteps[StepNames.CalculateStubInformation], step => { Assert.Collection(step.Outputs, output => Assert.Equal(IncrementalStepRunReason.Modified, output.Reason)); }, step => { Assert.Collection(step.Outputs, output => Assert.Equal(IncrementalStepRunReason.Unchanged, output.Reason)); }); }
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 async Task AppendingUnrelatedSource_DoesNotRegenerateSource() { string source = $"namespace NS{{{CodeSnippets.BasicParametersAndModifiers<int>()}}}"; SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)); Compilation comp1 = await TestUtils.CreateCompilation(new[] { syntaxTree }); Microsoft.Interop.LibraryImportGenerator generator = new(); GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }, EnableIncrementalTrackingDriverOptions); driver = driver.RunGenerators(comp1); SyntaxTree newTree = syntaxTree.WithRootAndOptions(syntaxTree.GetCompilationUnitRoot().AddMembers(SyntaxFactory.ParseMemberDeclaration("struct Foo {}") !), syntaxTree.Options); Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), newTree); GeneratorDriver driver2 = driver.RunGenerators(comp2); GeneratorRunResult runResult = driver2.GetRunResult().Results[0]; Assert.Collection(runResult.TrackedSteps[StepNames.CalculateStubInformation], step => { // The input contains symbols and Compilation objects, so it will always be different. // However, we validate that the calculated stub information is identical. Assert.Collection(step.Outputs, output => Assert.Equal(IncrementalStepRunReason.Unchanged, output.Reason)); }); }
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 async Task AddingFileWithNewLibraryImport_DoesNotRegenerateOriginalMethod() { string source = CodeSnippets.BasicParametersAndModifiers <int>(); Compilation comp1 = await TestUtils.CreateCompilation(source); Microsoft.Interop.LibraryImportGenerator generator = new(); GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }, EnableIncrementalTrackingDriverOptions); driver = driver.RunGenerators(comp1); Compilation comp2 = comp1.AddSyntaxTrees(CSharpSyntaxTree.ParseText(CodeSnippets.BasicParametersAndModifiers <bool>(), new CSharpParseOptions(LanguageVersion.Preview))); GeneratorDriver driver2 = driver.RunGenerators(comp2); GeneratorRunResult runResult = driver2.GetRunResult().Results[0]; Assert.Collection(runResult.TrackedSteps[StepNames.CalculateStubInformation], step => { Assert.Collection(step.Outputs, output => Assert.Equal(IncrementalStepRunReason.Unchanged, output.Reason)); }, step => { Assert.Collection(step.Outputs, output => Assert.Equal(IncrementalStepRunReason.New, output.Reason)); }); }
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) ); }
public void Single_File_Is_Added() { 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.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _); Assert.Equal(2, outputCompilation.SyntaxTrees.Count()); Assert.NotEqual(compilation, outputCompilation); var generatedClass = outputCompilation.GlobalNamespace.GetTypeMembers("GeneratedClass").Single(); Assert.True(generatedClass.Locations.Single().IsInSource); }
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); }
public void Analyzer_Is_Run() { var source = @" class C { } "; var generatorSource = @" class GeneratedClass { } "; var parseOptions = TestOptions.Regular; var analyzer = new Analyzer_Is_Run_Analyzer(); Compilation compilation = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions); compilation.VerifyDiagnostics(); compilation.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); Assert.Equal(0, analyzer.GeneratedClassCount); SingleFileTestGenerator testGenerator = new SingleFileTestGenerator(generatorSource); GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }, parseOptions: parseOptions); driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _); outputCompilation.GetAnalyzerDiagnostics(new[] { analyzer }, null).Verify(); Assert.Equal(1, analyzer.GeneratedClassCount); }
public void SyntaxContext_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); ISyntaxContextReceiver?receiver = null; var testGenerator = new CallbackGenerator( onInit: (i) => i.RegisterForSyntaxNotifications(() => new TestSyntaxContextReceiver()), onExecute: (e) => receiver = e.SyntaxContextReceiver ); GeneratorDriver driver = CSharpGeneratorDriver.Create( new[] { testGenerator }, parseOptions: parseOptions ); driver.RunGeneratorsAndUpdateCompilation(compilation, out _, out _); Assert.NotNull(receiver); Assert.IsType <TestSyntaxContextReceiver>(receiver); }
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)); }