// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable enable

using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;

namespace Microsoft.NET.Sdk.Razor.SourceGenerators
{
    public sealed class RazorSourceGeneratorTests : RazorSourceGeneratorTestsBase
    {
        [Fact]
        public async Task SourceGenerator_RazorFiles_Works()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
            });

            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);
        }

        [Fact, WorkItem("https://github.com/dotnet/razor/issues/8610")]
        public async Task SourceGenerator_RazorFiles_Using_NestedClass()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = """
                    @code {
                        public class MyModel { }
                    }
                    """,
                ["Shared/MyComponent.razor"] = """

                    <MyComponent Data="@Data" />

                    @code {
                        [Parameter]
                        public Pages.Index.MyModel? Data { get; set; }
                    }
                    """,
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project, options =>
            {
                options.TestGlobalOptions["build_property.RazorLangVersion"] = "7.0";
            });

            // Act
            var result = RunGenerator(compilation!, ref driver);

            // Assert
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
        }

        [Fact, WorkItem("https://github.com/dotnet/razor/issues/8610")]
        public async Task SourceGenerator_RazorFiles_UsingAlias_NestedClass()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = """
                    @code {
                        public class MyModel { }
                    }
                    """,
                ["Shared/MyComponent.razor"] = """
                    @using MyAlias = Pages.Index.MyModel;

                    <MyComponent Data="@Data" />

                    @code {
                        [Parameter]
                        public MyAlias? Data { get; set; }
                    }
                    """,
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project, options =>
            {
                options.TestGlobalOptions["build_property.RazorLangVersion"] = "7.0";
            });

            // Act
            var result = RunGenerator(compilation!, ref driver);

            // Assert
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
        }

        [Fact]
        public async Task SourceGenerator_RazorFiles_DesignTime()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
            });

            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts, optionsProvider) = await GetDriverWithAdditionalTextAndProviderAsync(project, hostOutputs: true);

            // Enable design-time.
            var options = optionsProvider.Clone();
            options.TestGlobalOptions["build_property.RazorDesignTime"] = "true";
            options.TestGlobalOptions["build_property.EnableRazorHostOutputs"] = "true";
            var driver2 = driver.WithUpdatedAnalyzerConfigOptions(options);

            var result = RunGenerator(compilation!, ref driver2);

            var pageOutput =
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
";
            result.VerifyPageOutput(pageOutput);

            result.VerifyHostOutput(
                (@"Pages_Index_razor.rsg.cs", @"// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 219
        private void __RazorDirectiveTokenHelpers__() {
        }
        #pragma warning restore 219
        #pragma warning disable 0414
        private static object __o = null;
        #pragma warning restore 0414
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
"),
                (@"Pages_Index_razor.rsg.html", @"<h1>Hello world</h1>"));

            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);

            // Enable design-time without host outputs.
            options = optionsProvider.Clone();
            options.TestGlobalOptions["build_property.RazorDesignTime"] = "true";
            driver2 = driver.WithUpdatedAnalyzerConfigOptions(options);

            result = RunGenerator(compilation!, ref driver2);
            result.VerifyPageOutput(pageOutput);
            result.VerifyHostOutput();

            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);
        }

        [Fact]
        public async Task SourceGeneratorEvents_RazorFiles_Works()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
                ["Pages/Counter.razor"] = "<h1>Counter</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""0de17e526cd536d59072aa0e924e99111b16b97a""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Counter</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
                e => Assert.Equal("ComputeRazorSourceGeneratorOptions", e.EventName),
                e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Index.razor"),
                e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Index.razor"),
                e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Counter.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Index.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Index.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Counter.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Counter.razor"),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
                e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Index.razor"),
                e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Index.razor"),
                e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Counter.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Index.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Index.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Counter.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Counter.razor", "Runtime"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_razor.g.cs"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
            );
        }

        [Fact]
        public async Task IncrementalCompilation_DoesNotReexecuteSteps_WhenRazorFilesAreUnchanged()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
                ["Pages/Counter.razor"] = "<h1>Counter</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(@"
#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591",
@"
#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""0de17e526cd536d59072aa0e924e99111b16b97a""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Counter</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Empty(eventListener.Events);
        }

        [Fact]
        public async Task IncrementalCompilation_WhenRazorFileMarkupChanges()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
                ["Pages/Counter.razor"] = "<h1>Counter</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""0de17e526cd536d59072aa0e924e99111b16b97a""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Counter</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Empty(eventListener.Events);

            var updatedText = new TestAdditionalText("Pages/Counter.razor", SourceText.From("<h2>Counter</h2>", Encoding.UTF8));
            driver = driver.ReplaceAdditionalText(additionalTexts.First(f => f.Path == updatedText.Path), updatedText);

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result, (1,
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""e022c3eac864ad044e9b7d56f4c493ab4eab36da""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h2>Counter</h2>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
"));

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
                e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Counter.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Counter.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Counter.razor"),
                e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Counter.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Counter.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Counter.razor", "Runtime"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
            );
        }

        [Fact]
        public async Task IncrementalCompilation_RazorFiles_WhenNewTypeIsAdded()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
                ["Pages/Counter.razor"] = "<h1>Counter</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""0de17e526cd536d59072aa0e924e99111b16b97a""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Counter</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            project = project.AddDocument("Person.cs", SourceText.From("""
                public class Person
                {
                    public string Name { get; set; }
                }
                """, Encoding.UTF8)).Project;
            compilation = await project.GetCompilationAsync();

            result = RunGenerator(compilation!, ref driver,
                // Person.cs(3,19): warning CS8618: Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
                //     public string Name { get; set; }
                Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Name").WithArguments("property", "Name").WithLocation(3, 19)
            );

            result.VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
               e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
               e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName));
        }

        [Fact]
        public async Task IncrementalCompilation_RazorFiles_WhenCSharpTypeChanges()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
                ["Pages/Counter.razor"] = "<h1>Counter</h1>",
            },
            new()
            {
                ["Person.cs"] = @"
public class Person
{
    public string Name { get; set; }
}"
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var expectedDiagnostics = new DiagnosticDescription[]
            {
                // Person.cs(4,19): warning CS8618: Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
                //     public string Name { get; set; }
                Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Name").WithArguments("property", "Name").WithLocation(4, 19)
            };

            var result = RunGenerator(compilation!, ref driver, expectedDiagnostics)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""0de17e526cd536d59072aa0e924e99111b16b97a""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Counter</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            result = RunGenerator(compilation!, ref driver, expectedDiagnostics)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            project = project.Documents.First().WithText(SourceText.From(@"
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}", Encoding.UTF8)).Project;
            compilation = await project.GetCompilationAsync();

            result = RunGenerator(compilation!, ref driver, expectedDiagnostics)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
               e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
               e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName));
        }

        [Fact]
        public async Task IncrementalCompilation_RazorFiles_WhenChildComponentsAreAdded()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
                ["Pages/Counter.razor"] = "<h1>Counter</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""0de17e526cd536d59072aa0e924e99111b16b97a""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Counter</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Empty(eventListener.Events);

            var updatedText = new TestAdditionalText("Pages/Counter.razor", SourceText.From(@"
<h2>Counter</h2>
<h3>Current count: @count</h3>
<button @onclick=""Click"">Click me</button>

@code
{
    private int count;

    public void Click() => count++;
}

", Encoding.UTF8));
            driver = driver.ReplaceAdditionalText(additionalTexts.First(f => f.Path == updatedText.Path), updatedText);

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result, (1,
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""1ea7ff43d3a2eecc5502dd3771378e334a8fb068""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h2>Counter</h2>\r\n"");
            __builder.OpenElement(1, ""h3"");
            __builder.AddContent(2, ""Current count: "");
#nullable restore
#line (3,21)-(3,26) 24 ""Pages/Counter.razor""
__builder.AddContent(3, count);

#line default
#line hidden
#nullable disable
            __builder.CloseElement();
            __builder.AddMarkupContent(4, ""\r\n"");
            __builder.AddMarkupContent(5, ""<button @onclick=\""Click\"">Click me</button>"");
        }
        #pragma warning restore 1998
#nullable restore
#line 7 ""Pages/Counter.razor""

    private int count;

    public void Click() => count++;

#line default
#line hidden
#nullable disable
    }
}
#pragma warning restore 1591
"));

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
                e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Counter.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Counter.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Counter.razor"),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
                e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Counter.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Counter.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Counter.razor", "Runtime"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
            );
        }

        [Fact]
        public async Task IncrementalCompilation_RazorFiles_WhenNewComponentParameterIsAdded()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
                ["Pages/Counter.razor"] = "<h1>Counter</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""0de17e526cd536d59072aa0e924e99111b16b97a""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Counter</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Empty(eventListener.Events);

            var updatedText = new TestAdditionalText("Pages/Counter.razor", SourceText.From(@"
<h2>Counter</h2>
<h3>Current count: @count</h3>
<button @onclick=""Click"">Click me</button>

@code
{
    private int count;

    public void Click() => count++;

    [Parameter] public int IncrementAmount { get; set; }
}

", Encoding.UTF8));
            driver = driver.ReplaceAdditionalText(additionalTexts.First(f => f.Path == updatedText.Path), updatedText);

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result, (1,
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""fb93b97dc0d4885250500697f41ffde70decc444""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h2>Counter</h2>\r\n"");
            __builder.OpenElement(1, ""h3"");
            __builder.AddContent(2, ""Current count: "");
#nullable restore
#line (3,21)-(3,26) 24 ""Pages/Counter.razor""
__builder.AddContent(3, count);

#line default
#line hidden
#nullable disable
            __builder.CloseElement();
            __builder.AddMarkupContent(4, ""\r\n"");
            __builder.AddMarkupContent(5, ""<button @onclick=\""Click\"">Click me</button>"");
        }
        #pragma warning restore 1998
#nullable restore
#line 7 ""Pages/Counter.razor""

    private int count;

    public void Click() => count++;

    [Parameter] public int IncrementAmount { get; set; }

#line default
#line hidden
#nullable disable
    }
}
#pragma warning restore 1591
"));

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
               e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Counter.razor"),
               e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Counter.razor"),
               e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Counter.razor"),
               e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Counter.razor"),
               e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
               e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
               e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Counter.razor"),
               e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Counter.razor"),
               e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.razor"),
               e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.razor"),
               e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
               e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
               e => e.AssertPair("RazorCodeGenerateStart", "Pages/Index.razor", "Runtime"),
               e => e.AssertPair("RazorCodeGenerateStop", "Pages/Index.razor", "Runtime"),
               e => e.AssertPair("RazorCodeGenerateStart", "Pages/Counter.razor", "Runtime"),
               e => e.AssertPair("RazorCodeGenerateStop", "Pages/Counter.razor", "Runtime"),
               e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
            );
        }

        [Fact]
        public async Task IncrementalCompilation_RazorFiles_WhenProjectReferencesChange()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] =
@"
@using SurveyPromptRootNamspace;
<h1>Hello world</h1>
<SurveyPrompt />
",
                ["Pages/Counter.razor"] = "<h1>Counter</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var result = RunGenerator(compilation!, ref driver,
                // Pages/Index.razor(2,7): error CS0246: The type or namespace name 'SurveyPromptRootNamspace' could not be found (are you missing a using directive or an assembly reference?)
                // using SurveyPromptRootNamspace;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "SurveyPromptRootNamspace").WithArguments("SurveyPromptRootNamspace").WithLocation(2, 7)
            );

            result.VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""4745828f8a0ab77b58022ed5d1095a0242f2a7ee""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
#nullable restore
#line 2 ""Pages/Index.razor""
using SurveyPromptRootNamspace;

#line default
#line hidden
#nullable disable
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>\r\n"");
            __builder.OpenElement(1, ""SurveyPrompt"");
            __builder.CloseElement();
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""0de17e526cd536d59072aa0e924e99111b16b97a""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Counter</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            var diagnostic = Assert.Single(result.Diagnostics);
            Assert.Equal("RZ10012", diagnostic.Id);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            var surveyPromptAssembly = GetSurveyPromptMetadataReference(compilation!);
            compilation = compilation!.AddReferences(surveyPromptAssembly);

            result = RunGenerator(compilation, ref driver)
                        .VerifyOutputsMatch(result, (0,
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""4745828f8a0ab77b58022ed5d1095a0242f2a7ee""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
#nullable restore
#line 2 ""Pages/Index.razor""
using SurveyPromptRootNamspace;

#line default
#line hidden
#nullable disable
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>\r\n"");
            __builder.OpenComponent<global::SurveyPromptRootNamspace.SurveyPrompt>(1);
            __builder.CloseComponent();
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
"
));

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Index.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Index.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Counter.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Counter.razor", "Runtime"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_razor.g.cs")
            );

            // Verify caching
            eventListener.Events.Clear();
            result = RunGenerator(compilation, ref driver);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
            Assert.Empty(eventListener.Events);

            static MetadataReference GetSurveyPromptMetadataReference(Compilation currentCompilation)
            {
                var updatedCompilation = currentCompilation.RemoveAllSyntaxTrees()
                    .WithAssemblyName("SurveyPromptAssembly")
                    .AddSyntaxTrees(CSharpSyntaxTree.ParseText(@"
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace SurveyPromptRootNamspace;
public class SurveyPrompt : ComponentBase
{
    protected override void BuildRenderTree(RenderTreeBuilder builder) {}
}"));
                var stream = new MemoryStream();
                var emitResult = updatedCompilation.Emit(stream);
                Assert.True(emitResult.Success);

                stream.Position = 0;
                return MetadataReference.CreateFromStream(stream);
            }
        }

        [Fact]
        public async Task SourceGenerator_CshtmlFiles_Works()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.cshtml"] = "<h1>Hello world</h1>",
                ["Views/Shared/_Layout.cshtml"] = "<h1>Layout</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Pages_Index), @""mvc.1.0.view"", @""/Pages/Index.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Pages/Index.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Pages_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Views/Shared/_Layout.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""99939b97abcdd846bd8ea59f7a08dacbe060cb3e""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Views_Shared__Layout), @""mvc.1.0.view"", @""/Views/Shared/_Layout.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Views/Shared/_Layout.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Views_Shared__Layout : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Layout</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
                e => Assert.Equal("ComputeRazorSourceGeneratorOptions", e.EventName),
                e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Index.cshtml"),
                e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Index.cshtml"),
                e => e.AssertSingleItem("ParseRazorDocumentStart", "Views/Shared/_Layout.cshtml"),
                e => e.AssertSingleItem("ParseRazorDocumentStop", "Views/Shared/_Layout.cshtml"),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
                e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Index.cshtml"),
                e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Index.cshtml"),
                e => e.AssertSingleItem("RewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
                e => e.AssertSingleItem("RewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.cshtml"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.cshtml"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Index.cshtml", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Index.cshtml", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStart", "Views/Shared/_Layout.cshtml", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Views/Shared/_Layout.cshtml", "Runtime"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_cshtml.g.cs"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Views_Shared__Layout_cshtml.g.cs")
            );
        }

        [Fact, WorkItem("https://github.com/dotnet/razor/issues/7049")]
        public async Task SourceGenerator_CshtmlFiles_TagHelperInFunction()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Pages/Index.cshtml"] = """
                @addTagHelper *, TestProject
                @{ await RenderMyRazor(); }
                @functions {
                    async Task RenderMyRazor()
                    {
                        <email>first tag helper</email>
                        <email>
                            second tag helper
                            <email>nested tag helper</email>
                        </email>
                    }
                }
                """,
            }, new()
            {
                ["EmailTagHelper.cs"] = """
                using Microsoft.AspNetCore.Razor.TagHelpers;
                public class EmailTagHelper : TagHelper
                {
                    public override void Process(TagHelperContext context, TagHelperOutput output)
                    {
                        output.TagName = "a";
                    }
                }
                """
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            // Act
            var result = RunGenerator(compilation!, ref driver,
                // Microsoft.NET.Sdk.Razor.SourceGenerators/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Pages_Index_cshtml.g.cs(64,167): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         __tagHelperExecutionContext = __tagHelperScopeManager.Begin("email", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "test", async() => {
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(64, 167),
                // Microsoft.NET.Sdk.Razor.SourceGenerators/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Pages_Index_cshtml.g.cs(80,171): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //             __tagHelperExecutionContext = __tagHelperScopeManager.Begin("email", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "test", async() => {
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(80, 171)
            );

            // Assert
            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);
        }

        [Fact, WorkItem("https://github.com/dotnet/razor/issues/7049")]
        public async Task SourceGenerator_CshtmlFiles_TagHelperInFunction_ManualSuppression()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Pages/Index.cshtml"] = """
                @addTagHelper *, TestProject

                @{ await RenderMyRazor(); }

                @functions {
                    #pragma warning disable 1998
                    async Task RenderMyRazor()
                    {
                        var lambdaWithUnnecessaryAsync1 = async () => { };
                        <email>first tag helper</email>
                        <email>
                            second tag helper
                            <email>nested tag helper</email>
                        </email>
                        var lambdaWithUnnecessaryAsync2 = async () => { };
                    }
                }
                """,
            }, new()
            {
                ["EmailTagHelper.cs"] = """
                using Microsoft.AspNetCore.Razor.TagHelpers;

                public class EmailTagHelper : TagHelper
                {
                    public override void Process(TagHelperContext context, TagHelperOutput output)
                    {
                        output.TagName = "a";
                    }
                }
                """
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            // Act
            var result = RunGenerator(compilation!, ref driver);

            // Assert
            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);
        }

        [Fact, WorkItem("https://github.com/dotnet/razor/issues/7049")]
        public async Task SourceGenerator_CshtmlFiles_TagHelperInBody()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Pages/Index.cshtml"] = """
                @addTagHelper *, TestProject

                <email>tag helper</email>
                @section MySection {
                    <p>my section</p>
                }
                """,
            }, new()
            {
                ["EmailTagHelper.cs"] = """
                using Microsoft.AspNetCore.Razor.TagHelpers;

                public class EmailTagHelper : TagHelper
                {
                    public override void Process(TagHelperContext context, TagHelperOutput output)
                    {
                        output.TagName = "a";
                    }
                }
                """
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            // Act
            var result = RunGenerator(compilation!, ref driver);

            // Assert
            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);
        }

        [Fact]
        public async Task SourceGenerator_CshtmlFiles_WhenMarkupChanges()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.cshtml"] = "<h1>Hello world</h1>",
                ["Views/Shared/_Layout.cshtml"] = "<h1>Layout</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Pages_Index), @""mvc.1.0.view"", @""/Pages/Index.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Pages/Index.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Pages_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Views/Shared/_Layout.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""99939b97abcdd846bd8ea59f7a08dacbe060cb3e""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Views_Shared__Layout), @""mvc.1.0.view"", @""/Views/Shared/_Layout.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Views/Shared/_Layout.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Views_Shared__Layout : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Layout</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Empty(eventListener.Events);

            var updatedText = new TestAdditionalText("Views/Shared/_Layout.cshtml", SourceText.From("<h2>Updated Layout</h2>", Encoding.UTF8));
            driver = driver.ReplaceAdditionalText(additionalTexts.First(f => f.Path == updatedText.Path), updatedText);

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result, (1,
@"#pragma checksum ""Views/Shared/_Layout.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""525ae8e5f9273913494d7a628b965837c601aed4""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Views_Shared__Layout), @""mvc.1.0.view"", @""/Views/Shared/_Layout.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Views/Shared/_Layout.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Views_Shared__Layout : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h2>Updated Layout</h2>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
"));

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
               e => e.AssertSingleItem("ParseRazorDocumentStart", "Views/Shared/_Layout.cshtml"),
               e => e.AssertSingleItem("ParseRazorDocumentStop", "Views/Shared/_Layout.cshtml"),
               e => e.AssertSingleItem("RewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
               e => e.AssertSingleItem("RewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
               e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
               e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
               e => e.AssertPair("RazorCodeGenerateStart", "Views/Shared/_Layout.cshtml", "Runtime"),
               e => e.AssertPair("RazorCodeGenerateStop", "Views/Shared/_Layout.cshtml", "Runtime"),
               e => e.AssertSingleItem("AddSyntaxTrees", "Views_Shared__Layout_cshtml.g.cs")
            );
        }

        [Fact]
        public async Task SourceGenerator_CshtmlFiles_CSharpTypeChanges()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.cshtml"] = "<h1>Hello world</h1>",
                ["Views/Shared/_Layout.cshtml"] = "<h1>Layout</h1>",
            },
            new()
            {
                ["Person.cs"] = @"
public class Person
{
    public string Name { get; set; }
}"
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var expectedDiagnostics = new DiagnosticDescription[]
            {
                // Person.cs(4,19): warning CS8618: Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
                //     public string Name { get; set; }
                Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "Name").WithArguments("property", "Name").WithLocation(4, 19)
            };

            var result = RunGenerator(compilation!, ref driver, expectedDiagnostics)
                        .VerifyPageOutput(@"#pragma checksum ""Pages/Index.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Pages_Index), @""mvc.1.0.view"", @""/Pages/Index.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Pages/Index.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Pages_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Views/Shared/_Layout.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""99939b97abcdd846bd8ea59f7a08dacbe060cb3e""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Views_Shared__Layout), @""mvc.1.0.view"", @""/Views/Shared/_Layout.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Views/Shared/_Layout.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Views_Shared__Layout : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Layout</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            result = RunGenerator(compilation!, ref driver, expectedDiagnostics)
                       .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            project = project.Documents.First().WithText(SourceText.From(@"
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}", Encoding.UTF8)).Project;
            compilation = await project.GetCompilationAsync();

            result = RunGenerator(compilation!, ref driver, expectedDiagnostics)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
               e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
               e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName));

        }

        [Fact]
        public async Task SourceGenerator_CshtmlFiles_NewTagHelper()
        {
            // Arrange
            using var eventListener = new RazorEventListener();
            var project = CreateTestProject(new()
            {
                ["Pages/Index.cshtml"] =
@"
@addTagHelper *, TestProject
<h2>Hello world</h2>",
                ["Views/Shared/_Layout.cshtml"] = "<h1>Layout</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""5d59ecd7b7cf7355d7f60234988be34b81a8b614""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Pages_Index), @""mvc.1.0.view"", @""/Pages/Index.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Pages/Index.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Pages_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""\r\n"");
            WriteLiteral(""<h2>Hello world</h2>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Views/Shared/_Layout.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""99939b97abcdd846bd8ea59f7a08dacbe060cb3e""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Views_Shared__Layout), @""mvc.1.0.view"", @""/Views/Shared/_Layout.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Views/Shared/_Layout.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Views_Shared__Layout : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Layout</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            eventListener.Events.Clear();

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            project = project.AddDocument("HeaderTagHelper.cs", SourceText.From(@"
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace MyApp;

[HtmlTargetElement(""h2"")]
public class HeaderTagHelper : TagHelper
{
    public override int Order => 0;

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.Attributes.Add(""role"", ""heading"");
    }
}", Encoding.UTF8)).Project;
            compilation = await project.GetCompilationAsync();

            result = RunGenerator(compilation!, ref driver);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            Assert.Collection(eventListener.Events,
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.cshtml"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.cshtml"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Views/Shared/_Layout.cshtml"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Views/Shared/_Layout.cshtml"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Index.cshtml", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Index.cshtml", "Runtime"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_cshtml.g.cs")
           );
        }

        [Fact]
        public async Task SourceGenerator_CshtmlFiles_RazorDiagnostics_Fixed()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Pages/Index.cshtml"] =
@"
@{
<h1>Malformed h1
}
</h1>",
                ["Views/Shared/_Layout.cshtml"] = "<h1>Layout</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""8e83eb537e49cadda4aff01de0bd33aa716fc633""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Pages_Index), @""mvc.1.0.view"", @""/Pages/Index.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Pages/Index.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Pages_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""\r\n"");
            WriteLiteral(""<h1>Malformed h1\r\n}\r\n</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Views/Shared/_Layout.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""99939b97abcdd846bd8ea59f7a08dacbe060cb3e""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Views_Shared__Layout), @""mvc.1.0.view"", @""/Views/Shared/_Layout.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Views/Shared/_Layout.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Views_Shared__Layout : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Layout</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
");

            var diagnostic = Assert.Single(result.Diagnostics);
            Assert.Equal("RZ1006", diagnostic.Id);
            Assert.Equal(2, result.GeneratedSources.Length);

            var updatedText = new TestAdditionalText("Pages/Index.cshtml", SourceText.From("<h1>Fixed header</h1>", Encoding.UTF8));
            driver = driver.ReplaceAdditionalText(additionalTexts.First(f => f.Path == updatedText.Path), updatedText);

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result, (0,
@"#pragma checksum ""Pages/Index.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""26b4fe0ac8d17fb3e02d5cba709603ceba9ae3ef""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Pages_Index), @""mvc.1.0.view"", @""/Pages/Index.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Pages/Index.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Pages_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Fixed header</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
"));

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
        }

        [Fact]
        public async Task SourceGenerator_CshtmlFiles_RazorDiagnostics_Introduced()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Pages/Index.cshtml"] = "<h1>Valid h1</h1>",
                ["Views/Shared/_Layout.cshtml"] = "<h1>Layout</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);

            var result = RunGenerator(compilation!, ref driver)
                            .VerifyPageOutput(
@"#pragma checksum ""Pages/Index.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""7f59d2951cc70dc08bc4e89b90bd3c5ba68459b9""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Pages_Index), @""mvc.1.0.view"", @""/Pages/Index.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Pages/Index.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Pages_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Valid h1</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Views/Shared/_Layout.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""99939b97abcdd846bd8ea59f7a08dacbe060cb3e""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Views_Shared__Layout), @""mvc.1.0.view"", @""/Views/Shared/_Layout.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Views/Shared/_Layout.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Views_Shared__Layout : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""<h1>Layout</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);

            var updatedText = new TestAdditionalText("Pages/Index.cshtml", SourceText.From(@"
@{
<h1>Malformed h1
}
</h1>", Encoding.UTF8));
            driver = driver.ReplaceAdditionalText(additionalTexts.First(f => f.Path == updatedText.Path), updatedText);

            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result, (0,
@"#pragma checksum ""Pages/Index.cshtml"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""d088006c7620c4503e95ef0b4cd1dbc82362bf8b""
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Pages_Index), @""mvc.1.0.view"", @""/Pages/Index.cshtml"")]
namespace AspNetCoreGeneratedDocument
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Mvc;
    using global::Microsoft.AspNetCore.Mvc.Rendering;
    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute(""Identifier"", ""/Pages/Index.cshtml"")]
    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
    #nullable restore
    internal sealed class Pages_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
    #nullable disable
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral(""\r\n"");
            WriteLiteral(""<h1>Malformed h1\r\n}\r\n</h1>"");
        }
        #pragma warning restore 1998
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
        #nullable disable
        #nullable restore
        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
        #nullable disable
    }
}
#pragma warning restore 1591
"));

            var diagnostic = Assert.Single(result.Diagnostics);
            Assert.Equal("RZ1006", diagnostic.Id);
            Assert.Equal(2, result.GeneratedSources.Length);
        }

        [Fact, WorkItem("https://github.com/dotnet/razor/issues/8281")]
        public async Task SourceGenerator_CshtmlFiles_ViewComponentTagHelper()
        {
            // Arrange
            var project = CreateTestProject(new()
            {
                ["Views/Home/Index.cshtml"] = """
                @addTagHelper *, TestProject
                <vc:test first-name="Jan" />
                """,
            }, new()
            {
                ["TestViewComponent.cs"] = """
                public class TestViewComponent
                {
                    public string Invoke(string firstName)
                    {
                        return firstName;
                    }
                }
                """,
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            // Act
            var result = RunGenerator(compilation!, ref driver);

            // Assert
            result.VerifyPageOutput(
                """
                #pragma checksum "Views/Home/Index.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "209ff2a910aa467bb7942ed3e6cb586652327a44"
                // <auto-generated/>
                #pragma warning disable 1591
                [assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCoreGeneratedDocument.Views_Home_Index), @"mvc.1.0.view", @"/Views/Home/Index.cshtml")]
                namespace AspNetCoreGeneratedDocument
                {
                    #line hidden
                    using global::System;
                    using global::System.Collections.Generic;
                    using global::System.Linq;
                    using global::System.Threading.Tasks;
                    using global::Microsoft.AspNetCore.Mvc;
                    using global::Microsoft.AspNetCore.Mvc.Rendering;
                    using global::Microsoft.AspNetCore.Mvc.ViewFeatures;
                    [global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Home/Index.cshtml")]
                    [global::System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute]
                    #nullable restore
                    internal sealed class Views_Home_Index : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
                    #nullable disable
                    {
                        #line hidden
                        #pragma warning disable 0649
                        private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext __tagHelperExecutionContext;
                        #pragma warning restore 0649
                        private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner __tagHelperRunner = new global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner();
                        #pragma warning disable 0169
                        private string __tagHelperStringValueBuffer;
                        #pragma warning restore 0169
                        private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __backed__tagHelperScopeManager = null;
                        private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager __tagHelperScopeManager
                        {
                            get
                            {
                                if (__backed__tagHelperScopeManager == null)
                                {
                                    __backed__tagHelperScopeManager = new global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager(StartTagHelperWritingScope, EndTagHelperWritingScope);
                                }
                                return __backed__tagHelperScopeManager;
                            }
                        }
                        private global::AspNetCoreGeneratedDocument.Views_Home_Index.__Generated__TestViewComponentTagHelper __TestViewComponentTagHelper;
                        #pragma warning disable 1998
                        public async override global::System.Threading.Tasks.Task ExecuteAsync()
                        {
                            __tagHelperExecutionContext = __tagHelperScopeManager.Begin("vc:test", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, "test", async() => {
                            }
                            );
                            __TestViewComponentTagHelper = CreateTagHelper<global::AspNetCoreGeneratedDocument.Views_Home_Index.__Generated__TestViewComponentTagHelper>();
                            __tagHelperExecutionContext.Add(__TestViewComponentTagHelper);
                            BeginWriteTagHelperAttribute();
                            WriteLiteral("Jan");
                            __tagHelperStringValueBuffer = EndWriteTagHelperAttribute();
                            __TestViewComponentTagHelper.firstName = __tagHelperStringValueBuffer;
                            __tagHelperExecutionContext.AddTagHelperAttribute("first-name", __TestViewComponentTagHelper.firstName, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
                            await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
                            if (!__tagHelperExecutionContext.Output.IsContentModified)
                            {
                                await __tagHelperExecutionContext.SetOutputContentAsync();
                            }
                            Write(__tagHelperExecutionContext.Output);
                            __tagHelperExecutionContext = __tagHelperScopeManager.End();
                        }
                        #pragma warning restore 1998
                        #nullable restore
                        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
                        public global::Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider { get; private set; } = default!;
                        #nullable disable
                        #nullable restore
                        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
                        public global::Microsoft.AspNetCore.Mvc.IUrlHelper Url { get; private set; } = default!;
                        #nullable disable
                        #nullable restore
                        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
                        public global::Microsoft.AspNetCore.Mvc.IViewComponentHelper Component { get; private set; } = default!;
                        #nullable disable
                        #nullable restore
                        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
                        public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; } = default!;
                        #nullable disable
                        #nullable restore
                        [global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
                        public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; } = default!;
                        #nullable disable
                        [Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute("vc:test")]
                        public class __Generated__TestViewComponentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
                        {
                            private readonly global::Microsoft.AspNetCore.Mvc.IViewComponentHelper __helper = null;
                            public __Generated__TestViewComponentTagHelper(global::Microsoft.AspNetCore.Mvc.IViewComponentHelper helper)
                            {
                                __helper = helper;
                            }
                            [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute, global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute]
                            public global::Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get; set; }
                            public System.String firstName { get; set; }
                            public override async global::System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext __context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput __output)
                            {
                                (__helper as global::Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware)?.Contextualize(ViewContext);
                                var __helperContent = await __helper.InvokeAsync("Test", ProcessInvokeAsyncArgs(__context));
                                __output.TagName = null;
                                __output.Content.SetHtmlContent(__helperContent);
                            }
                            private Dictionary<string, object> ProcessInvokeAsyncArgs(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext __context)
                            {
                                Dictionary<string, object> args = new Dictionary<string, object>();
                                if (__context.AllAttributes.ContainsName("first-name"))
                                {
                                    args[nameof(firstName)] = firstName;
                                }
                                return args;
                            }
                        }
                    }
                }
                #pragma warning restore 1591

                """);
            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);
        }

        [Fact, WorkItem("https://github.com/dotnet/aspnetcore/issues/36227")]
        public async Task SourceGenerator_DoesNotUpdateSources_WhenSourceGeneratorIsSuppressed()
        {
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
                ["Pages/Counter.razor"] = "<h1>Counter</h1>",
            });

            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts, optionsProvider) = await GetDriverWithAdditionalTextAndProviderAsync(project);

            var result = RunGenerator(compilation!, ref driver);
            result.VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
",
@"#pragma checksum ""Pages/Counter.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""0de17e526cd536d59072aa0e924e99111b16b97a""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Counter</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            // now run the generator with suppression
            var suppressedOptions = optionsProvider.Clone();
            suppressedOptions.TestGlobalOptions["build_property.SuppressRazorSourceGenerator"] = "true";
            driver = driver.WithUpdatedAnalyzerConfigOptions(suppressedOptions);

            // results should be empty
            using var eventListener = new RazorEventListener();
            var emptyResult = RunGenerator(compilation!, ref driver)
                    .VerifyPageOutput();

            // Check that none of the steps actually ran
            Assert.Empty(eventListener.Events);

            // now unsuppress and re-run
            driver = driver.WithUpdatedAnalyzerConfigOptions(optionsProvider);

            result = RunGenerator(compilation!, ref driver)
                .VerifyOutputsMatch(result);

            Assert.Collection(eventListener.Events,
                e => Assert.Equal("ComputeRazorSourceGeneratorOptions", e.EventName),
                e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Index.razor"),
                e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Index.razor"),
                e => e.AssertSingleItem("ParseRazorDocumentStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("ParseRazorDocumentStop", "Pages/Counter.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Index.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Index.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStart", "/Pages/Counter.razor"),
                e => e.AssertSingleItem("GenerateDeclarationCodeStop", "/Pages/Counter.razor"),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromCompilationStop", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromReferencesStart", e.EventName),
                e => Assert.Equal("DiscoverTagHelpersFromReferencesStop", e.EventName),
                e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Index.razor"),
                e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Index.razor"),
                e => e.AssertSingleItem("RewriteTagHelpersStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("RewriteTagHelpersStop", "Pages/Counter.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Index.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Index.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStart", "Pages/Counter.razor"),
                e => e.AssertSingleItem("CheckAndRewriteTagHelpersStop", "Pages/Counter.razor"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Index.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Index.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStart", "Pages/Counter.razor", "Runtime"),
                e => e.AssertPair("RazorCodeGenerateStop", "Pages/Counter.razor", "Runtime"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Index_razor.g.cs"),
                e => e.AssertSingleItem("AddSyntaxTrees", "Pages_Counter_razor.g.cs")
                );
        }

        [Fact, WorkItem("https://github.com/dotnet/razor/issues/7914")]
        public async Task SourceGenerator_UppercaseRazor_GeneratesComponent()
        {
            var project = CreateTestProject(new()
            {
                ["Component.Razor"] = "<h1>Hello world</h1>",
            });

            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            var result = RunGenerator(compilation!, ref driver).VerifyPageOutput(@"
#pragma checksum ""Component.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""6b5db227a6aa2228c777b0771108b184b1fc5df3""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp
{
    #line hidden
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    public partial class Component : global::Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.AddMarkupContent(0, ""<h1>Hello world</h1>"");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591
");

            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);
        }

        [Theory, WorkItem("https://github.com/dotnet/razor/issues/7236")]
        [InlineData("")]
        [InlineData(" ")]
        [InlineData("\n")]
        public async Task SourceGenerator_EmptyTargetPath(string targetPath)
        {
            const string componentPath = "Component.razor";
            var project = CreateTestProject(new()
            {
                [componentPath] = "<h1>Hello world</h1>",
            });

            var compilation = await project.GetCompilationAsync();
            var (driver, _, _) = await GetDriverWithAdditionalTextAndProviderAsync(project, optionsProvider =>
            {
                optionsProvider.AdditionalTextOptions[componentPath] = new TestAnalyzerConfigOptions
                {
                    ["build_metadata.AdditionalFiles.TargetPath"] = targetPath
                };
            });

            var result = RunGenerator(compilation!, ref driver);

            var diagnostic = Assert.Single(result.Diagnostics);
            // RSG002: TargetPath not specified for additional file
            Assert.Equal("RSG002", diagnostic.Id);

            Assert.Empty(result.GeneratedSources);
        }

        [Fact]
        public async Task SourceGenerator_Class_Inside_CodeBlock()
        {
            var project = CreateTestProject(new()
            {
                ["Component.Razor"] =
"""
<h1>Hello world</h1>

@code
{
    public class X {}
}
"""});

            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            var result = RunGenerator(compilation!, ref driver).VerifyPageOutput(
                """
                #pragma checksum "Component.Razor" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "20b14071a74e1fd554d7b3dff6ff41722270ebee"
                // <auto-generated/>
                #pragma warning disable 1591
                namespace MyApp
                {
                    #line hidden
                    using global::System;
                    using global::System.Collections.Generic;
                    using global::System.Linq;
                    using global::System.Threading.Tasks;
                    using global::Microsoft.AspNetCore.Components;
                    public partial class Component : global::Microsoft.AspNetCore.Components.ComponentBase
                    {
                        #pragma warning disable 1998
                        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
                        {
                            __builder.AddMarkupContent(0, "<h1>Hello world</h1>");
                        }
                        #pragma warning restore 1998
                #nullable restore
                #line 4 "Component.Razor"

                    public class X {}

                #line default
                #line hidden
                #nullable disable
                    }
                }
                #pragma warning restore 1591

                """);

            Assert.Empty(result.Diagnostics);
            Assert.Single(result.GeneratedSources);
        }

        [Fact, WorkItem("https://github.com/dotnet/razor/issues/8850")]
        public async Task SystemFolder()
        {
            var project = CreateTestProject(new()
            {
                ["Pages/__Host.cshtml"] = """
                    @page "/"
                    @namespace MyApp.Pages
                    """,
                ["Pages/System/MyComponent.razor"] = """
                    <h1>My component</h1>
                    """,
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project);

            var result = RunGenerator(compilation!, ref driver);

            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
        }
    }
}
