Example #1
0
        static async Task Main(string[] args)
        {
            // Attempt to set the version of MSBuild.
            var visualStudioInstances = MSBuildLocator.QueryVisualStudioInstances().ToArray();
            var instance = visualStudioInstances.FirstOrDefault(i => i.Name.Contains("2019"));

            Console.WriteLine($"Using MSBuild at '{instance.MSBuildPath}' to load projects.");

            // NOTE: Be sure to register an instance with the MSBuildLocator
            //       before calling MSBuildWorkspace.Create()
            //       otherwise, MSBuildWorkspace won't MEF compose.
            MSBuildLocator.RegisterInstance(instance);

            using (var workspace = MSBuildWorkspace.Create())
            {
                // Print message for WorkspaceFailed event to help diagnosing project load failures.
                workspace.WorkspaceFailed += (o, e) => Console.WriteLine(e.Diagnostic.Message);

                var solutionPath = Path.GetFullPath(Path.Combine(Assembly.GetExecutingAssembly().Location, @"..\..\..\..\..", "MetaJson.sln"));
                Console.WriteLine($"Loading solution '{solutionPath}'");

                // Attach progress reporter so we print projects as they are loaded.
                var solution = await workspace.OpenSolutionAsync(solutionPath, new ConsoleProgressReporter());

                Console.WriteLine($"Finished loading solution '{solutionPath}'");

                // TODO: Do analysis on the projects in the loaded solution
                Project     sampleProject = solution.Projects.FirstOrDefault(p => p.Name.Equals("SampleApp"));
                Compilation sampleAppProjectCompilation = await sampleProject.GetCompilationAsync();


                CSharpGeneratorDriver driver = CSharpGeneratorDriver.Create(new MetaJson.MetaJsonSourceGenerator());
                driver.RunGenerators(sampleAppProjectCompilation);
            }
        }
Example #2
0
        public void RunResults_Are_Available_After_Generation()
        {
            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)); });

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

            driver = driver.RunGenerators(compilation);

            var results = driver.GetRunResult();

            Assert.Single(results.GeneratedTrees);
            Assert.Single(results.Results);
            Assert.Empty(results.Diagnostics);

            var result = results.Results.Single();

            Assert.Null(result.Exception);
            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);
            Assert.Equal(results.GeneratedTrees.Single(), result.GeneratedSources.Single().SyntaxTree);
        }
Example #3
0
        /// <inheritdoc cref="CreateExecutionContext(Compilation, GeneratorInitialize)"/>
        public static GeneratorExecutionContext CreateExecutionContext(Compilation?compilation)
        {
            SourceGeneratorProxy  proxy  = new();
            CSharpGeneratorDriver driver = CSharpGeneratorDriver.Create(proxy);

            _ = driver.RunGenerators(compilation ?? CreateBaseCompilation());
            return(proxy.ExecutionContext);
        }
Example #4
0
        /// <summary>
        /// Creates a new, non-defaulted <see cref="GeneratorExecutionContext"/> using a <see cref="CSharpGeneratorDriver"/>.
        /// </summary>
        /// <param name="compilation">A <see cref="Compilation"/> to be assigned to the newly-created <see cref="GeneratorExecutionContext"/>.</param>
        /// <param name="onInitialize">Action to be performed instead of the proper <see cref="ISourceGenerator.Initialize(GeneratorInitializationContext)"/> method.</param>
        /// <remarks>
        /// This method accepts <see cref="Compilation"/> instead of <see cref="CSharpCompilation"/>
        /// to allow the user to intentionally pass invalid <see cref="Compilation"/> to the <see cref="ISourceGenerator.Execute(GeneratorExecutionContext)"/>
        /// to perform proper unit tests regarding validation.
        /// </remarks>
        public static GeneratorExecutionContext CreateExecutionContext(Compilation?compilation, GeneratorInitialize?onInitialize)
        {
            SourceGeneratorProxy proxy = new();

            if (onInitialize is not null)
            {
                proxy.OnInitialize += onInitialize;
            }

            CSharpGeneratorDriver driver = CSharpGeneratorDriver.Create(proxy);

            _ = driver.RunGenerators(compilation ?? CreateBaseCompilation());
            return(proxy.ExecutionContext);
        }
Example #5
0
        public void RunResults_Combine_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 generatorDiagnostic1 = new DiagnosticDescriptor("TG001", "Test Diagnostic", description, "Generators", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: description);
            DiagnosticDescriptor generatorDiagnostic2 = new DiagnosticDescriptor("TG002", "Test Diagnostic", description, "Generators", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: description);
            DiagnosticDescriptor generatorDiagnostic3 = new DiagnosticDescriptor("TG003", "Test Diagnostic", description, "Generators", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: description);

            var diagnostic1 = Microsoft.CodeAnalysis.Diagnostic.Create(generatorDiagnostic1, Location.None);
            var diagnostic2 = Microsoft.CodeAnalysis.Diagnostic.Create(generatorDiagnostic2, Location.None);
            var diagnostic3 = Microsoft.CodeAnalysis.Diagnostic.Create(generatorDiagnostic3, Location.None);

            var generator  = new CallbackGenerator((ic) => { }, (sgc) => { sgc.ReportDiagnostic(diagnostic1); sgc.ReportDiagnostic(diagnostic2); });
            var generator2 = new CallbackGenerator2((ic) => { }, (sgc) => { sgc.ReportDiagnostic(diagnostic3); });

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

            driver = driver.RunGenerators(compilation);

            var results = driver.GetRunResult();

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

            var result1 = results.Results[0];
            var result2 = results.Results[1];

            Assert.Null(result1.Exception);
            Assert.Equal(2, result1.Diagnostics.Length);
            Assert.Empty(result1.GeneratedSources);
            Assert.Equal(results.Diagnostics[0], result1.Diagnostics[0]);
            Assert.Equal(results.Diagnostics[1], result1.Diagnostics[1]);

            Assert.Null(result2.Exception);
            Assert.Single(result2.Diagnostics);
            Assert.Empty(result2.GeneratedSources);
            Assert.Equal(results.Diagnostics[2], result2.Diagnostics[0]);
        }
Example #6
0
        public void RunResults_Combine_SyntaxTrees()
        {
            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)); sgc.AddSource("test2", SourceText.From("public class E {}", Encoding.UTF8)); });
            var generator2 = new SingleFileTestGenerator("public class F{}");
            var generator3 = new SingleFileTestGenerator2("public class G{}");

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

            driver = driver.RunGenerators(compilation);

            var results = driver.GetRunResult();

            Assert.Equal(4, results.GeneratedTrees.Length);
            Assert.Equal(3, results.Results.Length);
            Assert.Empty(results.Diagnostics);

            var result1 = results.Results[0];
            var result2 = results.Results[1];
            var result3 = results.Results[2];

            Assert.Null(result1.Exception);
            Assert.Empty(result1.Diagnostics);
            Assert.Equal(2, result1.GeneratedSources.Length);
            Assert.Equal(results.GeneratedTrees[0], result1.GeneratedSources[0].SyntaxTree);
            Assert.Equal(results.GeneratedTrees[1], result1.GeneratedSources[1].SyntaxTree);

            Assert.Null(result2.Exception);
            Assert.Empty(result2.Diagnostics);
            Assert.Single(result2.GeneratedSources);
            Assert.Equal(results.GeneratedTrees[2], result2.GeneratedSources[0].SyntaxTree);

            Assert.Null(result3.Exception);
            Assert.Empty(result3.Diagnostics);
            Assert.Single(result3.GeneratedSources);
            Assert.Equal(results.GeneratedTrees[3], result3.GeneratedSources[0].SyntaxTree);
        }