public async Task IncrementalSourceGeneratorInvokedCorrectNumberOfTimes()
        {
            using var workspace = CreateWorkspace();
            var generator         = new GenerateFileForEachAdditionalFileWithContentsCommented();
            var analyzerReference = new TestGeneratorReference(generator);
            var project           = WithPreviewLanguageVersion(AddEmptyProject(workspace.CurrentSolution))
                                    .AddAnalyzerReference(analyzerReference)
                                    .AddAdditionalDocument("Test.txt", "Hello, world!").Project
                                    .AddAdditionalDocument("Test2.txt", "Hello, world!").Project;

            var compilation = await project.GetRequiredCompilationAsync(CancellationToken.None);

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

            // Change one of the additional documents, and rerun; we should only reprocess that one change, since this
            // is an incremental generator.
            project = project.AdditionalDocuments.First().WithAdditionalDocumentText(SourceText.From("Changed text!")).Project;

            compilation = await project.GetRequiredCompilationAsync(CancellationToken.None);

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

            // We should now have converted three additional files -- the two from the original run and then the one that was changed.
            // The other one should have been kept constant because that didn't change.
            Assert.Equal(3, generator.AdditionalFilesConvertedCount);

            // Change one of the source documents, and rerun; we should again only reprocess that one change.
            project = project.AddDocument("Source.cs", SourceText.From("")).Project;

            compilation = await project.GetRequiredCompilationAsync(CancellationToken.None);

            // We have one extra syntax tree now, but it did not require any invocations of the incremental generator.
            Assert.Equal(3, compilation.SyntaxTrees.Count());
            Assert.Equal(3, generator.AdditionalFilesConvertedCount);
        }
예제 #2
0
        public async Task IncrementalSourceGeneratorInvokedCorrectNumberOfTimes()
        {
            using var workspace = CreateWorkspace(new[] { typeof(TestCSharpCompilationFactoryServiceWithIncrementalGeneratorTracking) });
            var generator         = new GenerateFileForEachAdditionalFileWithContentsCommented();
            var analyzerReference = new TestGeneratorReference(generator);
            var project           = AddEmptyProject(workspace.CurrentSolution)
                                    .AddAnalyzerReference(analyzerReference)
                                    .AddAdditionalDocument("Test.txt", "Hello, world!").Project
                                    .AddAdditionalDocument("Test2.txt", "Hello, world!").Project;

            var compilation = await project.GetRequiredCompilationAsync(CancellationToken.None);

            var generatorDriver = project.Solution.State.GetTestAccessor().GetGeneratorDriver(project) !;

            var runResult = generatorDriver !.GetRunResult().Results[0];

            Assert.Equal(2, compilation.SyntaxTrees.Count());
            Assert.Equal(2, runResult.TrackedSteps[GenerateFileForEachAdditionalFileWithContentsCommented.StepName].Length);
            Assert.All(runResult.TrackedSteps[GenerateFileForEachAdditionalFileWithContentsCommented.StepName],
                       step =>
            {
                Assert.Collection(step.Inputs,
                                  source => Assert.Equal(IncrementalStepRunReason.New, source.Source.Outputs[source.OutputIndex].Reason));
                Assert.Collection(step.Outputs,
                                  output => Assert.Equal(IncrementalStepRunReason.New, output.Reason));
            });

            // Change one of the additional documents, and rerun; we should only reprocess that one change, since this
            // is an incremental generator.
            project = project.AdditionalDocuments.First().WithAdditionalDocumentText(SourceText.From("Changed text!")).Project;

            compilation = await project.GetRequiredCompilationAsync(CancellationToken.None);

            generatorDriver = project.Solution.State.GetTestAccessor().GetGeneratorDriver(project) !;
            runResult       = generatorDriver.GetRunResult().Results[0];

            Assert.Equal(2, compilation.SyntaxTrees.Count());
            Assert.Equal(2, runResult.TrackedSteps[GenerateFileForEachAdditionalFileWithContentsCommented.StepName].Length);
            Assert.Contains(runResult.TrackedSteps[GenerateFileForEachAdditionalFileWithContentsCommented.StepName],
                            step =>
            {
                return(step.Inputs.Length == 1 &&
                       step.Inputs[0].Source.Outputs[step.Inputs[0].OutputIndex].Reason == IncrementalStepRunReason.Modified &&
                       step.Outputs.Length == 1 &&
                       step.Outputs[0].Reason == IncrementalStepRunReason.Modified);
            });
            Assert.Contains(runResult.TrackedSteps[GenerateFileForEachAdditionalFileWithContentsCommented.StepName],
                            step =>
            {
                return(step.Inputs.Length == 1 &&
                       step.Inputs[0].Source.Outputs[step.Inputs[0].OutputIndex].Reason == IncrementalStepRunReason.Cached &&
                       step.Outputs.Length == 1 &&
                       step.Outputs[0].Reason == IncrementalStepRunReason.Cached);
            });

            // Change one of the source documents, and rerun; we should again only reprocess that one change.
            project = project.AddDocument("Source.cs", SourceText.From("")).Project;

            compilation = await project.GetRequiredCompilationAsync(CancellationToken.None);

            generatorDriver = project.Solution.State.GetTestAccessor().GetGeneratorDriver(project) !;
            runResult       = generatorDriver.GetRunResult().Results[0];

            // We have one extra syntax tree now, but it did not require any invocations of the incremental generator.
            Assert.Equal(3, compilation.SyntaxTrees.Count());
            Assert.Equal(2, runResult.TrackedSteps[GenerateFileForEachAdditionalFileWithContentsCommented.StepName].Length);
            Assert.All(runResult.TrackedSteps[GenerateFileForEachAdditionalFileWithContentsCommented.StepName],
                       step =>
            {
                Assert.Collection(step.Inputs,
                                  source => Assert.Equal(IncrementalStepRunReason.Cached, source.Source.Outputs[source.OutputIndex].Reason));
                Assert.Collection(step.Outputs,
                                  output => Assert.Equal(IncrementalStepRunReason.Cached, output.Reason));
            });
        }