Пример #1
0
        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));
        }
Пример #2
0
        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());
        }
Пример #3
0
        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)
                );
        }
Пример #4
0
        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)
                );
        }
Пример #5
0
        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());
        }
Пример #6
0
        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);
        }
Пример #7
0
        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());
        }
Пример #8
0
#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);
            });
        }
Пример #9
0
        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);
        }
Пример #11
0
#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);
        }
Пример #13
0
        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());
        }
Пример #14
0
        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));
        }
Пример #15
0
        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);
        }
Пример #16
0
        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);
        }
Пример #17
0
        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();
        }
Пример #18
0
        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);
            });
        }
Пример #19
0
        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);
        }
Пример #20
0
        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));
            });
        }
Пример #21
0
        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));
            });
        }
Пример #23
0
        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));
            });
        }
Пример #25
0
        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)
                );
        }
Пример #26
0
        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);
        }
Пример #27
0
        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);
        }
Пример #28
0
        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);
        }
Пример #29
0
        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);
        }
Пример #30
0
        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));
        }