Ejemplo n.º 1
0
        public void Error_During_Generation_With_Dependent_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 exception = new InvalidOperationException("generate error");

            var generator = new CallbackGenerator((ic) => { }, (sgc) => throw exception, source: "public class D { }");

            GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create <ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray <AdditionalText> .Empty);

            driver.RunFullGeneration(compilation, out var outputCompilation, out var generatorDiagnostics);

            outputCompilation.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)
                );
            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)
                );
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Runs a Roslyn generator over a set of source files.
        /// </summary>
        public static async Task <(ImmutableArray <Diagnostic>, ImmutableArray <GeneratedSourceResult>)> RunGenerator(
            ISourceGenerator generator,
            IEnumerable <Assembly>?references,
            IEnumerable <string> sources,
            AnalyzerConfigOptionsProvider?optionsProvider = null,
            bool includeBaseReferences          = true,
            CancellationToken cancellationToken = default)
        {
            Project proj = CreateTestProject(references, includeBaseReferences);

            proj = proj.WithDocuments(sources);

            Assert.True(proj.Solution.Workspace.TryApplyChanges(proj.Solution));

            Compilation?comp = await proj !.GetCompilationAsync(CancellationToken.None).ConfigureAwait(false);

            CSharpGeneratorDriver cgd = CSharpGeneratorDriver.Create(new[] { generator }, optionsProvider: optionsProvider);
            GeneratorDriver       gd  = cgd.RunGenerators(comp !, cancellationToken);

            GeneratorDriverRunResult r = gd.GetRunResult();

            return(r.Results[0].Diagnostics, r.Results[0].GeneratedSources);
        }
Ejemplo n.º 3
0
    /// <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 expected diagnostics ids to be generated.</param>
    private static void VerifyGeneratedDiagnostics <TGenerator>(string source, params string[] diagnosticsIds)
        where TGenerator : class, IIncrementalGenerator, new()
    {
        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));

        IIncrementalGenerator 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));
    }
Ejemplo n.º 4
0
    public void Test(string source, string expectedGeneratedFileName, string expectedGeneratedSource)
    {
        var inputCompilation = CreateCompilation(source);

        var generator = new PrimitiveGenerator();
        var driver    = CSharpGeneratorDriver.Create(generator).RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out _);
        var runResult = driver.GetRunResult();

        Assert.True(runResult.Diagnostics.IsEmpty);
        Assert.Single(runResult.Results);
        var generatorResult = runResult.Results[0];

        Assert.Equal(generator, generatorResult.Generator);
        Assert.True(generatorResult.Diagnostics.IsEmpty);
        Assert.Null(generatorResult.Exception);
        Assert.Single(generatorResult.GeneratedSources);
        var generatedSource = generatorResult.GeneratedSources[0];

        Assert.Equal(expectedGeneratedFileName, generatedSource.HintName);
        var generatedSourceText = generatedSource.SourceText.ToString();

        Assert.Equal(expectedGeneratedSource, generatedSourceText);
    }
Ejemplo n.º 5
0
        private static (Compilation Input, Compilation Output) CreateInputOutputCompilation()
        {
            Compilation inputCompilation            = CreateCompilation(@"
namespace TestCode
{
    public class Dto1 { public System.Int32 NumberProp { get; set; } }

    public class Dto2 { public System.String Property { get; set; } public Dto1 OtherDto { get; set; } }

    public class Program2
    {
        public void SomeMethod2(LaDeak.JsonMergePatch.Abstractions.Patch<Dto2> data)
        {
        }
    }
}
");
            JsonMergePatchSourceGenerator generator = new JsonMergePatchSourceGenerator();
            GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);

            driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics);
            return(inputCompilation, outputCompilation);
        }
Ejemplo n.º 6
0
    private static Compilation Compile(string source)
    {
        var opt  = new CSharpParseOptions(languageVersion: LanguageVersion.Preview, kind: SourceCodeKind.Regular, documentationMode: DocumentationMode.Parse);
        var copt = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);

        var dotnetCoreDirectory = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
        var compilation         = CSharpCompilation.Create("test",
                                                           syntaxTrees: new[] { SyntaxFactory.ParseSyntaxTree(source, opt) },
                                                           references: new[]
        {
            AssemblyMetadata.CreateFromFile(typeof(object).Assembly.Location).GetReference(),
            MetadataReference.CreateFromFile(Path.Combine(dotnetCoreDirectory, "netstandard.dll")),
            MetadataReference.CreateFromFile(Path.Combine(dotnetCoreDirectory, "System.Runtime.dll")),
        },
                                                           options: copt);

        // apply the source generator
        var driver = new CSharpGeneratorDriver(opt, ImmutableArray.Create <ISourceGenerator>(new MemberAccessGenerator.MemberAccessGenerator()), null, ImmutableArray <AdditionalText> .Empty);

        driver.RunFullGeneration(compilation, out var resultCompilation, out _);

        return(resultCompilation);
    }
        public Compilation Generate(string dllName, ISourceGenerator sourceGenerator)
        {
            var analyzerOptionsConfigProvider = new TestAnalyzerOptionsConfigProvider(globalOptions);

            var driver           = CSharpGeneratorDriver.Create(new[] { sourceGenerator }, optionsProvider: analyzerOptionsConfigProvider);
            var inputCompilation = this.Create(dllName);

            driver.AddAdditionalTexts(additionalTexts.ToImmutableArray());

            driver.RunGeneratorsAndUpdateCompilation(
                inputCompilation,
                out var outputCompilation,
                out var diags
                );
            foreach (var diag in diags)
            {
                if (diag.Severity == DiagnosticSeverity.Error)
                {
                    throw new ArgumentException(diag.GetMessage());
                }
            }
            return(outputCompilation);
        }
        public void GenerateGetServicesForNamedServicesWithScopes()
        {
            // Given
            var input = CompilationBuilder.CreateAssemblyWithCode(
                @"namespace Demo.Domain
                  {
                      public interface IFoo
                      { }
                  }",
                @"namespace Demo.Domain
                  {
                      using CustomCode.CompileTimeInject.Annotations;

                      [Export(Lifetime.Scoped, ServiceId = ""1"")]
                      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.True(output.ContainsTypeWithMethodImplementation(
                            "IocContainer",
                            @"public T? GetService<T>(string serviceId) where T : class
                 {
                     var scope = GetActiveScope();
                     var service = scope.GetService<T>(serviceId);
                     return service;
                 }"));
        }
        public string GetGeneratedOutput(string source)
        {
            CSharpCompilation compilation = Compile(source);

            ThrowIfInvalid(compilation, before: true);

            ISourceGenerator generator = new TGenerator();

            var driver = CSharpGeneratorDriver.Create(generator);

            driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatedDiagnostics);

            // Intentionally writing the output before potentially generating an exception if diagnostics are presented.
            string output = outputCompilation.SyntaxTrees.Last().ToString();

            _output.WriteLine($"Generated output:" + Environment.NewLine + output);

            if (generatedDiagnostics.Length != 0)
            {
                _output.WriteLine("Generated diagnostics:");
                _output.WriteLine(string.Join(Environment.NewLine, generatedDiagnostics.Select(d => d.ToString())));

                generatedDiagnostics = generatedDiagnostics.Where(d => d.Severity is DiagnosticSeverity.Warning or DiagnosticSeverity.Error).ToImmutableArray();

                // Throw only when there are warnings or errors.
                if (generatedDiagnostics.Length != 0)
                {
                    // The tests does not expect any diagnostics before running the generator!
                    string errors = string.Join(Environment.NewLine, generatedDiagnostics);
                    throw new InvalidOperationException($"Unexpected diagnostics from source generators: {errors}");
                }
            }

            ThrowIfInvalid(outputCompilation, before: false);

            return(output);
        }
        public void TwoSuitableMethodsDiagnostic()
        {
            var                sourceCode       = @"using DevExpress.Mvvm.CodeGenerators;
using System.Threading.Tasks;

namespace Test {
    [GenerateViewModel]
    partial class TwoSuitableMethods {
        [GenerateProperty(OnChangedMethod = ""TwoChangedMethods"", OnChangingMethod = ""TwoChangingMethods"")]
        int value;

        public void TwoChangedMethods() { }
        public void TwoChangedMethods(int arg) { }

        public void TwoChangingMethods() { }
        public void TwoChangingMethods(int arg) { }
    }

    public class Program {
        public static void Main(string[] args) { }
    }
}
";
            Compilation        inputCompilation = Helper.CreateCompilation(sourceCode);
            ViewModelGenerator generator        = new ViewModelGenerator();

            GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);

            _ = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics);

            Assert.AreEqual(3, outputCompilation.SyntaxTrees.Count());
            Assert.AreEqual(2, diagnostics.Count());
            foreach (var diagnostic in diagnostics)
            {
                Assert.AreEqual(GeneratorDiagnostics.TwoSuitableMethods.Id, diagnostic.Id);
            }
        }
Ejemplo n.º 11
0
        static string GetGeneratedOutput(string source)
        {
            var references =
                from assembly in AppDomain.CurrentDomain.GetAssemblies()
                where !assembly.IsDynamic && !string.IsNullOrWhiteSpace(assembly.Location)
                select MetadataReference.CreateFromFile(assembly.Location);

            var compilation =
                CSharpCompilation.Create("generated.dll",
                                         syntaxTrees: null,
                                         references,
                                         new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            ISourceGenerator generator = new Generator();

            AdditionalText additionalText = new AdditionalTextString("Test.txt", source);

            RsAnalyzerConfigOptions options =
                new AnalyzerConfigOptions(
                    KeyValuePair.Create("build_metadata.AdditionalFiles.SourceItemType", "Transplate"));

            var driver =
                CSharpGeneratorDriver.Create(
                    new[] { generator },
                    new[] { additionalText },
                    parseOptions: null,
                    new AnalyzerConfigOptionsProvider(KeyValuePair.Create(additionalText, options)));

            driver.RunGeneratorsAndUpdateCompilation(compilation,
                                                     out var outputCompilation,
                                                     out var generateDiagnostics);

            Assert.False(generateDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
                         "Failed: " + generateDiagnostics.FirstOrDefault()?.GetMessage());

            return(outputCompilation.SyntaxTrees.Last().ToString());
        }
Ejemplo n.º 12
0
        static (ImmutableArray <Diagnostic>, Compilation) GetGeneratedOutput(string source, [CallerMemberName] string?test = null)
        {
            var syntaxTree = CSharpSyntaxTree.ParseText(source, path: test + ".cs");

            var references = new List <MetadataReference>();
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

            foreach (var assembly in assemblies)
            {
                if (!assembly.IsDynamic && !string.IsNullOrEmpty(assembly.Location))
                {
                    references.Add(MetadataReference.CreateFromFile(assembly.Location));
                }
            }

            var compilation = CSharpCompilation.Create(test,
                                                       new SyntaxTree[]
            {
                syntaxTree,
                CSharpSyntaxTree.ParseText(File.ReadAllText("Avatar/Avatar.cs"), path: "Avatar.cs"),
                CSharpSyntaxTree.ParseText(File.ReadAllText("Avatar/Avatar.StaticFactory.cs"), path: "Avatar.StaticFactory.cs"),
            }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            var diagnostics = compilation.GetDiagnostics().RemoveAll(d => d.Severity == DiagnosticSeverity.Hidden || d.Severity == DiagnosticSeverity.Info);

            if (diagnostics.Any())
            {
                return(diagnostics, compilation);
            }

            var generator = new AvatarGenerator();
            var driver    = CSharpGeneratorDriver.Create(generator);

            driver.RunGeneratorsAndUpdateCompilation(compilation, out var output, out diagnostics);

            return(diagnostics, output);
        }
        public void GenerateServiceCacheForNamedServices()
        {
            // Given
            var input = CompilationBuilder.CreateAssemblyWithCode(
                @"namespace Demo.Domain
                  {
                      public interface IFoo
                      { }
                  }",
                @"namespace Demo.Domain
                  {
                      using CustomCode.CompileTimeInject.Annotations;

                      [Export(ServiceId = ""1"")]
                      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.True(output.ContainsTypeWithMethodImplementation(
                            "ServiceCache",
                            @"public object GetOrAdd(Type key, string serviceId, Func<string, object> valueFactory)
                 {
                     var cache = NamedServiceCache.GetOrAdd(key, new ConcurrentDictionary<string, object>());
                     return cache.GetOrAdd(serviceId, valueFactory);
                 }"));
        }
Ejemplo n.º 14
0
        public void Generator_HintName_Is_Appended_With_GeneratorName()
        {
            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 SingleFileTestGenerator("public class D {}", "source.cs");
            var generator2 = new SingleFileTestGenerator2("public class E {}", "source.cs");

            GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator, generator2 }, parseOptions: parseOptions);

            driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generatorDiagnostics);
            outputCompilation.VerifyDiagnostics();
            generatorDiagnostics.Verify();
            Assert.Equal(3, outputCompilation.SyntaxTrees.Count());

            var filePaths = outputCompilation.SyntaxTrees.Skip(1).Select(t => t.FilePath).ToArray();

            Assert.Equal(new[] {
Ejemplo n.º 15
0
        public void TryApply_Edits_Fails_If_FullGeneration_Has_Not_Run()
        {
            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);

            // try apply edits should fail if we've not run a full compilation yet
            driver = driver.TryApplyEdits(compilation, out var outputCompilation, out var succeeded);
            Assert.False(succeeded);
            Assert.Equal(compilation, outputCompilation);
        }
Ejemplo n.º 16
0
        public void Generator_Is_Only_Initialized_Once()
        {
            var         source       = @"
class C { }
";
            var         parseOptions = TestOptions.Regular;
            Compilation compilation  = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions);

            compilation.VerifyDiagnostics();

            Assert.Single(compilation.SyntaxTrees);

            int initCount = 0, executeCount = 0;
            var generator = new CallbackGenerator((ic) => initCount++, (sgc) => executeCount++, source: "public class C { }");

            GeneratorDriver driver = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create <ISourceGenerator>(generator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray <AdditionalText> .Empty);

            driver = driver.RunFullGeneration(compilation, out var outputCompilation, out _);
            driver = driver.RunFullGeneration(outputCompilation, out outputCompilation, out _);
            driver.RunFullGeneration(outputCompilation, out outputCompilation, out _);

            Assert.Equal(1, initCount);
            Assert.Equal(3, executeCount);
        }
        public void DtoWithProperties_WrapperTypeAddedToSource()
        {
            Compilation inputCompilation            = CreateCompilation(@"
namespace TestCode3
{
    public class Dto4 { public System.String Property { get; set; } }

    public class Program2
    {
        public void SomeMethod2(LaDeak.JsonMergePatch.Abstractions.Patch<Dto4> 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);
        }
Ejemplo n.º 18
0
        public void Cancellation_During_Execution_Doesnt_Report_As_Generator_Error()
        {
            var         source       = @"
class C 
{
}
";
            var         parseOptions = TestOptions.Regular;
            Compilation compilation  = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions);

            compilation.VerifyDiagnostics();

            Assert.Single(compilation.SyntaxTrees);

            CancellationTokenSource cts = new CancellationTokenSource();

            var testGenerator = new CallbackGenerator(
                onInit: (i) => { },
                onExecute: (e) => { cts.Cancel(); }
                );

            // test generator cancels the token. Check that the call to this generator doesn't make it look like it errored.
            var testGenerator2 = new CallbackGenerator2(
                onInit: (i) => { },
                onExecute: (e) => { e.AddSource("a", SourceText.From("public class E {}", Encoding.UTF8)); }
                );


            GeneratorDriver driver    = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create <ISourceGenerator>(testGenerator, testGenerator2), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray <AdditionalText> .Empty);
            var             oldDriver = driver;

            Assert.Throws <OperationCanceledException>(() =>
                                                       driver = driver.RunFullGeneration(compilation, out var outputCompilation, out var outputDiagnostics, cts.Token)
                                                       );
            Assert.Same(oldDriver, driver);
        }
Ejemplo n.º 19
0
        public static async Task <IEnumerable <SyntaxTree> > GenerateAsync <T>(string source) where T : IIncrementalGenerator, 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));

            IIncrementalGenerator generator = new T();

            var driver = CSharpGeneratorDriver.Create(
                ImmutableArray.Create(generator.AsSourceGenerator()),
                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.Where(
                       z => !z.FilePath.Contains("AssemblyRegistrationOptions") && !z.FilePath.Contains("GeneratedAssemblyJsonRpcHandlers")
                       ));
        }
Ejemplo n.º 20
0
        public static string GetGeneratedOutput <TGenerator>(string sourceCode)
            where TGenerator : class, ISourceGenerator, new()
        {
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);
            IEnumerable <MetadataReference> references =
                AppDomain.CurrentDomain.GetAssemblies()
                .Where(assembly => !assembly.IsDynamic)
                .Select(assembly => MetadataReference.CreateFromFile(assembly.Location))
                .Cast <MetadataReference>();

            var compilation =
                CSharpCompilation
                .Create
                (
                    assemblyName: "SourceGeneratorTests",
                    syntaxTrees: new[] { syntaxTree },
                    references: references,
                    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                );

            var generator = new TGenerator();

            CSharpGeneratorDriver
            .Create(generator)
            .RunGeneratorsAndUpdateCompilation
            (
                compilation,
                out Compilation outputCompilation,
                out ImmutableArray <Diagnostic> diagnostics
            );

            // optional
            diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).Should().BeEmpty();

            return(outputCompilation.SyntaxTrees.Skip(1).LastOrDefault()?.ToString());
        }
        private string GetGeneratedOutput(string source, NullableContextOptions nullableContextOptions)
        {
            var syntaxTree = CSharpSyntaxTree.ParseText(source);

            var references = new List <MetadataReference>();

            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in assemblies)
            {
                if (!assembly.IsDynamic && !string.IsNullOrWhiteSpace(assembly.Location))
                {
                    references.Add(MetadataReference.CreateFromFile(assembly.Location));
                }
            }

            var compilation = CSharpCompilation.Create(
                "foo",
                new SyntaxTree[] { syntaxTree },
                references,
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: nullableContextOptions));

            // var compileDiagnostics = compilation.GetDiagnostics();
            // Assert.IsFalse(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.IsFalse(generateDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), "Failed: " + generateDiagnostics.FirstOrDefault()?.GetMessage());

            string output = outputCompilation.SyntaxTrees.Last().ToString();

            Console.WriteLine(output);

            return(output);
        }
Ejemplo n.º 22
0
        public void GenerateScopeGetServiceMethod()
        {
            // Given
            var input = CompilationBuilder.CreateAssemblyWithCode(
                @"namespace Demo.Domain
                  {
                      public interface IFoo
                      { }
                  }",
                @"namespace Demo.Domain
                  {
                      using CustomCode.CompileTimeInject.Annotations;

                      [Export(Lifetime.Scoped)]
                      public sealed class Foo : IFoo
                      { }
                  }");
            var sourceGenerator = new ScopeGenerator();
            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.ContainsTypeWithMethodImplementation(
                            "Scope",
                            @"public T? GetService<T>() where T : class
                 {
                     var factory = Factory as IServiceFactory<T>;
                     return factory?.CreateOrGetService();
                 }"));
        }
Ejemplo n.º 23
0
        public void Generator_Is_Only_Initialized_Once()
        {
            var         source       = @"
class C { }
";
            var         parseOptions = TestOptions.Regular;
            Compilation compilation  = CreateCompilation(source, options: TestOptions.DebugDll, parseOptions: parseOptions);

            compilation.VerifyDiagnostics();

            Assert.Single(compilation.SyntaxTrees);

            int initCount = 0, executeCount = 0;
            var generator = new CallbackGenerator((ic) => initCount++, (sgc) => executeCount++, source: "public class C { }");

            GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { generator }, parseOptions: parseOptions);

            driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _);
            driver = driver.RunGeneratorsAndUpdateCompilation(outputCompilation, out outputCompilation, out _);
            driver.RunGeneratorsAndUpdateCompilation(outputCompilation, out outputCompilation, out _);

            Assert.Equal(1, initCount);
            Assert.Equal(3, executeCount);
        }
Ejemplo n.º 24
0
        public void TryApply_Edits_Fails_If_FullGeneration_Has_Not_Run()
        {
            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 = new CSharpGeneratorDriver(parseOptions, ImmutableArray.Create <ISourceGenerator>(testGenerator), CompilerAnalyzerConfigOptionsProvider.Empty, ImmutableArray <AdditionalText> .Empty);

            // try apply edits should fail if we've not run a full compilation yet
            driver = driver.TryApplyEdits(compilation, out var outputCompilation, out var succeeded);
            Assert.False(succeeded);
            Assert.Equal(compilation, outputCompilation);
        }
        public void GenerateServiceFactoryForClassWithSingleInterface()
        {
            // 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 ServiceFactoryGenerator();
            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.ContainsTypeWithMethodImplementation(
                            "ServiceFactory",
                            @"Demo.Domain.IFoo IServiceFactory<Demo.Domain.IFoo>.CreateOrGetService()
                 {
                     var service = new Demo.Domain.Foo();
                     return service;
                 }"));
        }
Ejemplo n.º 26
0
        public void Execute_ShouldWarnOnNonCSharCompilation()
        {
            Compilation compilation = VisualBasicCompilation.Create
                                      (
                "cica",
                new[]
            {
                VisualBasicSyntaxTree.ParseText
                (
                    @"
                        Imports System.Collections

                        Imports Solti.Utils.Proxy
                        Imports Solti.Utils.Proxy.Attributes
                        Imports Solti.Utils.Proxy.Generators

                        <Assembly:EmbedGeneratedType(GetType(DuckGenerator(Of IEnumerable, IEnumerable)))>
                        "
                )
            },
                Runtime
                .Assemblies
                .Select(asm => asm.Location)
                .Append(typeof(EmbedGeneratedTypeAttribute).Assembly.Location)
                .Distinct()
                .Select(location => MetadataReference.CreateFromFile(location)),
                new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                                      );

            GeneratorDriver driver = CSharpGeneratorDriver.Create(new ProxyEmbedder());

            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));
        }
Ejemplo n.º 27
0
        public void Syntax_Receiver_Visits_Syntax_Added_In_PostInit()
        {
            var source =
                @"
class C 
{
    int Property { get; set; }

    void Function()
    {
        var x = 5;
        x += 4;
    }
}
";

            var source2 =
                @"
class D
{
    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);

            ISyntaxReceiver?receiver = null;

            var testGenerator = new CallbackGenerator(
                onInit: (i) =>
            {
                i.RegisterForSyntaxNotifications(() => new TestSyntaxReceiver());
                i.RegisterForPostInitialization((pic) => pic.AddSource("postInit", source2));
            },
                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);

            TestSyntaxReceiver testReceiver = (TestSyntaxReceiver)receiver !;

            var classDeclarations = testReceiver.VisitedNodes
                                    .OfType <ClassDeclarationSyntax>()
                                    .Select(c => c.Identifier.Text);

            Assert.Equal(new[] { "C", "D" }, classDeclarations);
        }
Ejemplo n.º 28
0
        public void Syntax_Receiver_Exception_During_Visit_Stops_Visits_On_Other_Trees()
        {
            var source1 =
                @"
class C 
{
    int Property { get; set; }
}
";
            var source2 =
                @"
class D
{
    public void Method() { }
}
";
            var         parseOptions = TestOptions.Regular;
            Compilation compilation  = CreateCompilation(
                new[] { source1, source2 },
                options: TestOptions.DebugDll,
                parseOptions: parseOptions
                );

            compilation.VerifyDiagnostics();

            Assert.Equal(2, compilation.SyntaxTrees.Count());

            TestSyntaxReceiver receiver1 = new TestSyntaxReceiver(
                tag: 0,
                callback: (a) =>
            {
                if (a is PropertyDeclarationSyntax)
                {
                    throw new Exception("Test Exception");
                }
            }
                );
            var testGenerator1 = new CallbackGenerator(
                onInit: (i) => i.RegisterForSyntaxNotifications(() => receiver1),
                onExecute: (e) => { }
                );

            TestSyntaxReceiver receiver2 = new TestSyntaxReceiver(tag: 1);
            var testGenerator2           = new CallbackGenerator2(
                onInit: (i) => i.RegisterForSyntaxNotifications(() => receiver2),
                onExecute: (e) => { }
                );

            GeneratorDriver driver = CSharpGeneratorDriver.Create(
                new[] { testGenerator1, testGenerator2 },
                parseOptions: parseOptions
                );

            driver = driver.RunGeneratorsAndUpdateCompilation(
                compilation,
                out var outputCompilation,
                out var outputDiagnostics
                );
            var results = driver.GetRunResult();

            Assert.DoesNotContain(receiver1.VisitedNodes, n => n is MethodDeclarationSyntax);
            Assert.Contains(receiver2.VisitedNodes, n => n is MethodDeclarationSyntax);
        }
Ejemplo n.º 29
0
        public void Syntax_Receiver_Exception_During_Visit_Doesnt_Stop_Other_Receivers()
        {
            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);

            var exception     = new Exception("Test Exception");
            var testGenerator = new CallbackGenerator(
                onInit: (i) =>
                i.RegisterForSyntaxNotifications(
                    () =>
                    new TestSyntaxReceiver(
                        tag: 0,
                        callback: (a) =>
            {
                if (a is AssignmentExpressionSyntax)
                {
                    throw exception;
                }
            }
                        )
                    ),
                onExecute: (e) => { }
                );

            ISyntaxReceiver?receiver       = null;
            var             testGenerator2 = new CallbackGenerator2(
                onInit: (i) =>
                i.RegisterForSyntaxNotifications(() => new TestSyntaxReceiver(tag: 1)),
                onExecute: (e) =>
            {
                receiver = e.SyntaxReceiver;
                e.AddSource("test", SourceText.From("public class D{}", Encoding.UTF8));
            }
                );

            GeneratorDriver driver = CSharpGeneratorDriver.Create(
                new[] { testGenerator, testGenerator2 },
                parseOptions: parseOptions
                );

            driver = driver.RunGeneratorsAndUpdateCompilation(
                compilation,
                out var outputCompilation,
                out var outputDiagnostics
                );
            var results = driver.GetRunResult();

            Assert.Single(results.GeneratedTrees);
            Assert.Single(results.Diagnostics);
            Assert.Equal(2, results.Results.Length);

            Assert.Single(results.Results[0].Diagnostics);
            Assert.NotNull(results.Results[0].Exception);
            Assert.Equal("Test Exception", results.Results[0].Exception?.Message);

            Assert.Empty(results.Results[1].Diagnostics);

            var testReceiver = (TestSyntaxReceiver)receiver !;

            Assert.Equal(1, testReceiver.Tag);
            Assert.Equal(21, testReceiver.VisitedNodes.Count);

            outputDiagnostics.Verify(
                Diagnostic("CS" + (int)ErrorCode.WRN_GeneratorFailedDuringGeneration)
                .WithArguments("CallbackGenerator", "Exception", "Test Exception")
                .WithLocation(1, 1)
                );
        }
Ejemplo n.º 30
0
        public void Syntax_Receiver_Exception_During_Creation()
        {
            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);

            var exception     = new Exception("Test Exception");
            var testGenerator = new CallbackGenerator(
                onInit: (i) =>
                i.RegisterForSyntaxNotifications(
                    (SyntaxReceiverCreator)(() => 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.Empty(results.GeneratedTrees);
            Assert.Single(results.Diagnostics);
            Assert.Single(results.Results);
            Assert.Single(results.Results[0].Diagnostics);

            Assert.NotNull(results.Results[0].Exception);
            Assert.Equal("Test Exception", results.Results[0].Exception?.Message);

            outputDiagnostics.Verify(
                Diagnostic("CS" + (int)ErrorCode.WRN_GeneratorFailedDuringGeneration)
                .WithArguments("CallbackGenerator", "Exception", "Test Exception")
                .WithLocation(1, 1)
                );
        }