File: RazorSourceGeneratorTests.cs
Web Access
Project: src\src\Razor\src\Compiler\test\Microsoft.NET.Sdk.Razor.SourceGenerators.UnitTests\Microsoft.NET.Sdk.Razor.SourceGenerators.UnitTests.csproj (Microsoft.NET.Sdk.Razor.SourceGenerators.UnitTests)
// 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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 SourceGeneratorEvents_RazorFiles_Works()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
            // Verify all the incremental steps ran as expected for the initial generation
            result.VerifyIncrementalSteps("RazorSourceGeneratorOptions", IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("GeneratedDeclarationCode", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.New);
            result.VerifyIncrementalSteps("TagHelpersFromReferences", IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("ParsedDocuments", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("RewrittenTagHelpers", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("GeneratedCode", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("CSharpDocuments", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
        }
 
        [Fact]
        public async Task IncrementalCompilation_DoesNotReexecuteSteps_WhenRazorFilesAreUnchanged()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
            // Verify that when nothing changes, all steps are cached/unchanged
            result.VerifyIncrementalSteps("RazorSourceGeneratorOptions", IncrementalStepRunReason.Cached);
            result.VerifyIncrementalStepsMultiple("GeneratedDeclarationCode", IncrementalStepRunReason.Cached, IncrementalStepRunReason.Cached);
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Cached);
            result.VerifyIncrementalSteps("TagHelpersFromReferences", IncrementalStepRunReason.Cached);
            result.VerifyIncrementalStepsMultiple("ParsedDocuments", IncrementalStepRunReason.Cached, IncrementalStepRunReason.Cached);
            result.VerifyIncrementalStepsMultiple("RewrittenTagHelpers", IncrementalStepRunReason.Cached, IncrementalStepRunReason.Cached);
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers", IncrementalStepRunReason.Cached, IncrementalStepRunReason.Cached);
            result.VerifyIncrementalStepsMultiple("GeneratedCode", IncrementalStepRunReason.Cached, IncrementalStepRunReason.Cached);
            result.VerifyIncrementalStepsMultiple("CSharpDocuments", IncrementalStepRunReason.Cached, IncrementalStepRunReason.Cached);
        }
 
        [Fact]
        public async Task IncrementalCompilation_WhenRazorFileMarkupChanges()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
            // Verify that when nothing changes, all steps are cached
            result.VerifyIncrementalStepsMultiple("ParsedDocuments", IncrementalStepRunReason.Cached, IncrementalStepRunReason.Cached);
            result.VerifyIncrementalStepsMultiple("GeneratedCode", IncrementalStepRunReason.Cached, IncrementalStepRunReason.Cached);
            result.VerifyIncrementalStepsMultiple("CSharpDocuments", IncrementalStepRunReason.Cached, IncrementalStepRunReason.Cached);
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
            // Verify that when Counter markup changes, only Counter steps re-run
            result.VerifyIncrementalStepsMultiple("ParsedDocuments",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Counter changed
            result.VerifyIncrementalStepsMultiple("RewrittenTagHelpers",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Counter changed
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Counter changed
            result.VerifyIncrementalStepsMultiple("GeneratedCode",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Counter changed
            result.VerifyIncrementalStepsMultiple("CSharpDocuments",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Counter changed
        }
 
        [ConditionalFact(typeof(IsEnglishLocal))]
        public async Task IncrementalCompilation_RazorFiles_WhenNewTypeIsAdded()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
            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);
 
            // Verify that when a new C# type is added, only TagHelpersFromCompilation re-runs
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Unchanged); // Re-ran but no new tag helpers
        }
 
        [ConditionalFact(typeof(IsEnglishLocal))]
        public async Task IncrementalCompilation_RazorFiles_WhenCSharpTypeChanges()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
            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);
 
            // When a C# type changes, TagHelpersFromCompilation re-runs but the output is unchanged
            // because Person is not a component and doesn't affect tag helpers
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Unchanged);
        }
 
        [Fact]
        public async Task IncrementalCompilation_RazorFiles_WhenChildComponentsAreAdded()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
 
            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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,2)-(11,1) ""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);
 
            // Verify that when Counter adds code block, only Counter steps re-run
            result.VerifyIncrementalStepsMultiple("ParsedDocuments",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Counter changed
            result.VerifyIncrementalStepsMultiple("GeneratedDeclarationCode",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Counter changed (new code block)
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Unchanged); // Re-run but no new tag helpers
            result.VerifyIncrementalStepsMultiple("RewrittenTagHelpers",
                IncrementalStepRunReason.Cached,    // Index - document and tag helpers unchanged
                IncrementalStepRunReason.Modified); // Counter - document changed
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers",
                IncrementalStepRunReason.Cached,     // Index unchanged
                IncrementalStepRunReason.Modified);  // Counter changed
            result.VerifyIncrementalStepsMultiple("GeneratedCode",
                IncrementalStepRunReason.Cached,     // Index unchanged
                IncrementalStepRunReason.Modified);  // Counter changed
            result.VerifyIncrementalStepsMultiple("CSharpDocuments",
                IncrementalStepRunReason.Cached,     // Index unchanged
                IncrementalStepRunReason.Modified);  // Counter changed
        }
 
        [Fact]
        public async Task IncrementalCompilation_RazorFiles_WhenNewComponentParameterIsAdded()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
 
            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
 
            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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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,2)-(13,1) ""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);
 
            // Verify that when Counter adds Parameter, the necessary steps re-run
            result.VerifyIncrementalStepsMultiple("ParsedDocuments",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Counter changed
            result.VerifyIncrementalStepsMultiple("GeneratedDeclarationCode",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Counter changed (new Parameter)
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Modified); // Parameter metadata changed
            result.VerifyIncrementalStepsMultiple("RewrittenTagHelpers",
                IncrementalStepRunReason.Cached,    // Index - document didn't change (comparer only checks document)
                IncrementalStepRunReason.Modified); // Counter - document changed and tag helpers updated
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers",
                IncrementalStepRunReason.Modified,   // Index - tag helper collection changed, needs re-check
                IncrementalStepRunReason.Modified);  // Counter changed
            result.VerifyIncrementalStepsMultiple("GeneratedCode",
                IncrementalStepRunReason.Modified,   // Index - re-generated with new tag helper metadata
                IncrementalStepRunReason.Modified);  // Counter changed
            result.VerifyIncrementalStepsMultiple("CSharpDocuments",
                IncrementalStepRunReason.Unchanged,  // Index - output unchanged (doesn't use Counter)
                IncrementalStepRunReason.Modified);  // Counter changed
        }
 
        [Fact]
        public async Task IncrementalCompilation_RazorFiles_WhenProjectReferencesChange()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            var result = RunGenerator(compilation!, ref driver,
                // Pages/Index.razor(2,8): 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, 8)
            );
 
            result.VerifyPageOutput(
@"#pragma checksum ""Pages/Index.razor"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""4745828f8a0ab77b58022ed5d1095a0242f2a7ee""
// <auto-generated/>
#pragma warning disable 1591
namespace MyApp.Pages
{
    #line default
    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,2)-(2,33) ""Pages/Index.razor""
using SurveyPromptRootNamspace;
 
#nullable disable
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Counter : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
 
            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 default
    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,2)-(2,33) ""Pages/Index.razor""
using SurveyPromptRootNamspace;
 
#nullable disable
    #line default
    #line hidden
    #nullable restore
    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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);
 
            // Verify that adding a metadata reference triggers tag helper discovery
            result.VerifyIncrementalSteps("RazorSourceGeneratorOptions", IncrementalStepRunReason.Unchanged); // Re-ran but unchanged
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Unchanged); // Re-ran but compilation tag helpers unchanged
            result.VerifyIncrementalSteps("TagHelpersFromReferences", IncrementalStepRunReason.Modified); // New reference added
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers",
                IncrementalStepRunReason.Modified,   // Index - new tag helper discovered  
                IncrementalStepRunReason.Modified);  // Counter - tag helpers changed, needs recheck
            result.VerifyIncrementalStepsMultiple("GeneratedCode",
                IncrementalStepRunReason.Modified,   // Index - re-generated with tag helper
                IncrementalStepRunReason.Modified);  // Counter - re-generated due to tag helper changes
            result.VerifyIncrementalStepsMultiple("CSharpDocuments",
                IncrementalStepRunReason.Modified,   // Index - output changed
                IncrementalStepRunReason.Unchanged); // Counter - output unchanged (doesn't use new tag helper)
 
            // Verify caching
            result = RunGenerator(compilation, ref driver);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
            static MetadataReference GetSurveyPromptMetadataReference(Compilation currentCompilation)
            {
                var updatedCompilation = currentCompilation.RemoveAllSyntaxTrees()
                    .WithAssemblyName("SurveyPromptAssembly")
                    .AddSyntaxTrees(CSharpSyntaxTree.ParseText(Microsoft.CodeAnalysis.Text.SourceText.From(@"
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace SurveyPromptRootNamspace;
public class SurveyPrompt : ComponentBase
{
    protected override void BuildRenderTree(RenderTreeBuilder builder) {}
}", System.Text.Encoding.UTF8)));
                var stream = new MemoryStream();
                var emitResult = updatedCompilation.Emit(stream);
                Assert.True(emitResult.Success);
 
                stream.Position = 0;
                return MetadataReference.CreateFromStream(stream);
            }
        }
 
        [Fact]
        public async Task IncrementalCompilation_RazorFiles_CssScopeRemoved()
        {
            // Compile with CssScope set.
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var (driver, _, options) = await GetDriverWithAdditionalTextAndProviderAsync(project, static options =>
            {
                options.AdditionalTextOptions["Pages/Index.razor"]["build_metadata.AdditionalFiles.CssScope"] = "test-css-scope";
            });
 
            var result = RunGenerator(compilation!, ref driver);
            result.Diagnostics.Verify();
 
            // CSS isolation is enabled.
            Assert.Contains("<h1 test-css-scope>Hello world</h1>", result.GeneratedSources.Single().SourceText.ToString());
 
            // Unset CssScope.
            options = options.Clone();
            options.AdditionalTextOptions["Pages/Index.razor"].Options.Remove("build_metadata.AdditionalFiles.CssScope");
            driver = driver.WithUpdatedAnalyzerConfigOptions(options);
 
            result = RunGenerator(compilation!, ref driver);
            result.Diagnostics.Verify();
 
            // CSS isolation is disabled.
            Assert.Contains("<h1>Hello world</h1>", result.GeneratedSources.Single().SourceText.ToString());
        }
 
        [Fact]
        public async Task SourceGenerator_CshtmlFiles_Works()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    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;
    #line default
    #line hidden
    [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 default
    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;
    #line default
    #line hidden
    [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);
 
            // Verify all steps ran for initial generation
            result.VerifyIncrementalSteps("RazorSourceGeneratorOptions", IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("ParsedDocuments", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.New);
            result.VerifyIncrementalSteps("TagHelpersFromReferences", IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("RewrittenTagHelpers", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("GeneratedCode", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
            result.VerifyIncrementalStepsMultiple("CSharpDocuments", IncrementalStepRunReason.New, IncrementalStepRunReason.New);
 
        }
 
        [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);
 
            // 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
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    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;
    #line default
    #line hidden
    [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 default
    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;
    #line default
    #line hidden
    [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);
 
 
            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
 
            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 default
    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;
    #line default
    #line hidden
    [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);
 
            // Verify that when Layout markup changes, only Layout steps re-run
            result.VerifyIncrementalStepsMultiple("ParsedDocuments",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Layout changed
            result.VerifyIncrementalStepsMultiple("RewrittenTagHelpers",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Layout changed
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Layout changed
            result.VerifyIncrementalStepsMultiple("GeneratedCode",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Layout changed
            result.VerifyIncrementalStepsMultiple("CSharpDocuments",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // Layout changed
 
        }
 
        [ConditionalFact(typeof(IsEnglishLocal))]
        public async Task SourceGenerator_CshtmlFiles_CSharpTypeChanges()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    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;
    #line default
    #line hidden
    [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 default
    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;
    #line default
    #line hidden
    [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);
 
 
            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);
 
            // Verify that when C# type changes, only TagHelpersFromCompilation re-runs
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Unchanged);
 
        }
 
        [Fact]
        public async Task SourceGenerator_CshtmlFiles_NewTagHelper()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            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 default
    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;
    #line default
    #line hidden
    [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 default
    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;
    #line default
    #line hidden
    [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);
 
 
            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);
 
            // Verify that when new tag helper is added, tag helper discovery and rewrite steps re-run
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Modified); // New tag helper discovered
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers",
                IncrementalStepRunReason.Modified,   // Index - new tag helper affects h2
                IncrementalStepRunReason.Unchanged); // Layout - doesn't use h2
            result.VerifyIncrementalStepsMultiple("GeneratedCode",
                IncrementalStepRunReason.Modified,   // Index - re-generated with tag helper
                IncrementalStepRunReason.Cached);    // Layout - unchanged
 
        }
 
        [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 default
    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;
    #line default
    #line hidden
    [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 default
    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;
    #line default
    #line hidden
    [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 default
    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;
    #line default
    #line hidden
    [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 default
    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;
    #line default
    #line hidden
    [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 default
    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;
    #line default
    #line hidden
    [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 default
    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;
    #line default
    #line hidden
    [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 default
                    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;
                    #line default
                    #line hidden
                    [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/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 default
    using global::System;
    using global::System.Collections.Generic;
    using global::System.Linq;
    using global::System.Threading.Tasks;
    using global::Microsoft.AspNetCore.Components;
    #line default
    #line hidden
    #nullable restore
    public partial class Component : global::Microsoft.AspNetCore.Components.ComponentBase
    #nullable disable
    {
        #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 default
                    using global::System;
                    using global::System.Collections.Generic;
                    using global::System.Linq;
                    using global::System.Threading.Tasks;
                    using global::Microsoft.AspNetCore.Components;
                    #line default
                    #line hidden
                    #nullable restore
                    public partial class Component : global::Microsoft.AspNetCore.Components.ComponentBase
                    #nullable disable
                    {
                        #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,2)-(6,1) "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);
        }
 
        [Theory, CombinatorialData]
        public async Task RazorLangVersion_Incorrect([CombinatorialValues("incorrect", "-1", "10000")] string langVersion)
        {
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project, options =>
            {
                options.TestGlobalOptions["build_property.RazorLangVersion"] = langVersion;
            });
 
            var result = RunGenerator(compilation!, ref driver);
 
            result.Diagnostics.Verify(
                // error RZ3600: Invalid value '{0}' for RazorLangVersion. Valid values include 'Latest', 'Preview', or a valid version in range 1.0 to {1}.
                Diagnostic("RZ3600").WithArguments(langVersion, RazorLanguageVersion.Preview.ToString()).WithLocation(1, 1));
            Assert.Single(result.GeneratedSources);
        }
 
        [Theory, CombinatorialData]
        public async Task RazorWarningLevel_Incorrect(
            [CombinatorialValues("incorrect", "1.2", "0x1", "-1")] string warningLevel)
        {
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project, options =>
            {
                options.TestGlobalOptions["build_property.RazorWarningLevel"] = warningLevel;
            });
 
            var result = RunGenerator(compilation!, ref driver);
 
            result.Diagnostics.Verify(
                // error RZ3601: Invalid value '{0}' for RazorWarningLevel. Must be empty or a non-negative integer.
                Diagnostic("RZ3601").WithArguments(warningLevel).WithLocation(1, 1));
            Assert.Single(result.GeneratedSources);
        }
 
        [Theory, CombinatorialData]
        public async Task RazorWarningLevel_ValidValues(
            [CombinatorialValues("0", "10", "11", "9999")] string warningLevel)
        {
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project, options =>
            {
                options.TestGlobalOptions["build_property.RazorWarningLevel"] = warningLevel;
            });
 
            var result = RunGenerator(compilation!, ref driver);
 
            result.Diagnostics.Verify();
            Assert.Single(result.GeneratedSources);
        }
 
        [Fact]
        public async Task RazorWarningLevel_Empty_IsValid()
        {
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<h1>Hello world</h1>",
            });
            var compilation = await project.GetCompilationAsync();
            var driver = await GetDriverAsync(project, options =>
            {
                options.TestGlobalOptions["build_property.RazorWarningLevel"] = "";
            });
 
            var result = RunGenerator(compilation!, ref driver);
 
            result.Diagnostics.Verify();
            Assert.Single(result.GeneratedSources);
        }
 
#pragma warning disable RS1041 // This compiler extension should not be implemented in an assembly with target framework '.NET 8.0'. References to other target frameworks will cause the compiler to behave unpredictably.
#pragma warning disable RS1038 // This compiler extension should not be implemented in an assembly containing a reference to Microsoft.CodeAnalysis.Workspaces.
        [Generator]
#pragma warning restore RS1038 // This compiler extension should not be implemented in an assembly containing a reference to Microsoft.CodeAnalysis.Workspaces.
#pragma warning restore RS1041 // This compiler extension should not be implemented in an assembly with target framework '.NET 8.0'. References to other target frameworks will cause the compiler to behave unpredictably.
#pragma warning disable RS1036 // Specify analyzer banned API enforcement setting
        public class LambdaGenerator(Action<IncrementalGeneratorInitializationContext> action) : IIncrementalGenerator
#pragma warning restore RS1036 // Specify analyzer banned API enforcement setting
        {
            public void Initialize(IncrementalGeneratorInitializationContext context) => action(context);
        }
 
        [Fact]
        public async Task IncrementalCompilation_NothingRuns_When_AdditionalFiles_HaveSameContent()
        {
            // Arrange
            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);
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
 
            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
            project = project.RemoveAdditionalDocument(project.AdditionalDocumentIds[1])
                             .AddAdditionalDocument("Counter.razor", SourceText.From("<h1>Counter</h1>", Encoding.UTF8))
                             .Project;
 
            compilation = await project.GetCompilationAsync();
 
            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
        }
 
        [Fact]
        public async Task IncrementalCompilation_OnlyCompilationRuns_When_MetadataReferences_SameAssembly()
        {
            // Arrange
            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 GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            var result = RunGenerator(compilation!, ref driver);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
 
            result = RunGenerator(compilation!, ref driver)
                .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
            var reference = (PortableExecutableReference)project.MetadataReferences[^1];
 
            project = project.RemoveMetadataReference(reference)
                             .AddMetadataReference(MetadataReference.CreateFromFile(reference.FilePath!));
 
            compilation = await project.GetCompilationAsync();
 
            result = RunGenerator(compilation!, ref driver)
                .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
            // reference causes the compilation to change so we re-run tag helper discovery there
            // but we didn't re-check the actual reference itself
            result.VerifyIncrementalSteps("RazorSourceGeneratorOptions", IncrementalStepRunReason.Unchanged); // Re-ran but unchanged
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Unchanged); // Re-ran but unchanged
        }
 
        [Theory]
        [InlineData("true")]
        [InlineData("True")]
        [InlineData("TRUE")]
        [InlineData("tRuE")]
        public async Task RoslynTokenizerEnabledWithTrue(string value)
        {
            var parseOptions = CSharpParseOptions.Default.WithFeatures([new("use-roslyn-tokenizer", value)]);
 
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = """"
                    <div>@("""
                        nested "
                        """)</div>
                    """",
            }, cSharpParseOptions: parseOptions);
 
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);
 
            var result = RunGenerator(compilation!, ref driver);
            result.VerifyPageOutput(
                """"
                #pragma checksum "Pages/Index.razor" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "c6855f3cabbcb69477e3f5a61f8d77fcfed086c2"
                // <auto-generated/>
                #pragma warning disable 1591
                namespace MyApp.Pages
                {
                    #line default
                    using global::System;
                    using global::System.Collections.Generic;
                    using global::System.Linq;
                    using global::System.Threading.Tasks;
                    using global::Microsoft.AspNetCore.Components;
                    #line default
                    #line hidden
                    #nullable restore
                    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
                    #nullable disable
                    {
                        #pragma warning disable 1998
                        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
                        {
                            __builder.OpenElement(0, "div");
                #nullable restore
                #line (1,8)-(3,8) 24 "Pages/Index.razor"
                __builder.AddContent(1, """
                    nested "
                    """
 
                #line default
                #line hidden
                #nullable disable
                            );
                            __builder.CloseElement();
                        }
                        #pragma warning restore 1998
                    }
                }
                #pragma warning restore 1591
 
                """");
        }
 
        [Theory]
        [InlineData("false")]
        [InlineData("False")]
        [InlineData("FALSE")]
        [InlineData("FaLsE")]
        [InlineData("")]
        [InlineData(null)]
        public async Task RoslynTokenizerDisabledWithFalseOrNothing(string? value)
        {
            var parseOptions = CSharpParseOptions.Default;
 
            if (value != null)
            {
                parseOptions = parseOptions.WithFeatures([new("use-roslyn-tokenizer", value)]);
            }
 
            var project = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = """"
                    <div>@("""
                        nested "
                        """)</div>
                    """",
            }, cSharpParseOptions: parseOptions);
 
            var compilation = await project.GetCompilationAsync();
            var (driver, additionalTexts) = await GetDriverWithAdditionalTextAsync(project);
 
            var result = RunGenerator(compilation!, ref driver,
                // Pages/Index.razor(3,10): error CS1525: Invalid expression term '/'
                //     """)</div>
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "/").WithArguments("/").WithLocation(3, 10),
                // Pages/Index.razor(3,11): error CS0103: The name 'div' does not exist in the current context
                //     """)</div>
                Diagnostic(ErrorCode.ERR_NameNotInContext, "div").WithArguments("div").WithLocation(3, 11),
                // Pages/Index.razor(3,15): error CS1525: Invalid expression term ')'
                //     """)</div>
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments(")").WithLocation(3, 15),
                // Pages/Index.razor(3,15): error CS1002: ; expected
                //     """)</div>
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(3, 15),
                // Pages/Index.razor(3,15): error CS1513: } expected
                //     """)</div>
                Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(3, 15));
 
            result.VerifyPageOutput(
                """"
                #pragma checksum "Pages/Index.razor" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "c6855f3cabbcb69477e3f5a61f8d77fcfed086c2"
                // <auto-generated/>
                #pragma warning disable 1591
                namespace MyApp.Pages
                {
                    #line default
                    using global::System;
                    using global::System.Collections.Generic;
                    using global::System.Linq;
                    using global::System.Threading.Tasks;
                    using global::Microsoft.AspNetCore.Components;
                    #line default
                    #line hidden
                    #nullable restore
                    public partial class Index : global::Microsoft.AspNetCore.Components.ComponentBase
                    #nullable disable
                    {
                        #pragma warning disable 1998
                        protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
                        {
                            __builder.OpenElement(0, "div");
                #nullable restore
                #line (1,8)-(3,15) 24 "Pages/Index.razor"
                __builder.AddContent(1, """
                    nested "
                    """)</div>
                #line default
                #line hidden
                #nullable disable
                            );
                            __builder.CloseElement();
                        }
                        #pragma warning restore 1998
                    }
                }
                #pragma warning restore 1591
 
                """");
        }
 
        [Fact]
        public async Task IncrementalCompilation_RerunsGenerator_When_AdditionalFileRenamed()
        {
            // Arrange
            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, analyzerConfigOptionProvider) = await GetDriverWithAdditionalTextAndProviderAsync(project, trackSteps: true);
 
            var result = RunGenerator(compilation!, ref driver);
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
 
            // Verify no changes when re-running
            result = RunGenerator(compilation!, ref driver)
                        .VerifyOutputsMatch(result);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
            // Rename Counter.razor to NewCounter.razor by removing and re-adding with same content
            var counterText = additionalTexts.First(f => f.Path.EndsWith("Counter.razor", StringComparison.OrdinalIgnoreCase));
            var renamedText = new TestAdditionalText("Pages/NewCounter.razor", counterText.GetText()!);
            driver = driver.RemoveAdditionalTexts([counterText])
                          .AddAdditionalTexts([renamedText]);
 
            // Update the analyzer config options with the new target path
            analyzerConfigOptionProvider.AdditionalTextOptions[renamedText.Path] = new TestAnalyzerConfigOptions
            {
                ["build_metadata.AdditionalFiles.TargetPath"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(renamedText.Path))
            };
            driver = driver.WithUpdatedAnalyzerConfigOptions(analyzerConfigOptionProvider);
 
            result = RunGenerator(compilation!, ref driver);
 
            Assert.Empty(result.Diagnostics);
            Assert.Equal(2, result.GeneratedSources.Length);
 
            // Verify the new file was processed
            result.VerifyIncrementalStepsMultiple("ParsedDocuments",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // NewCounter renamed from Counter
            result.VerifyIncrementalStepsMultiple("GeneratedDeclarationCode",
                IncrementalStepRunReason.Cached,    // Index unchanged
                IncrementalStepRunReason.Modified); // NewCounter renamed
            result.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Modified); // Re-discover (removed Counter, added NewCounter)
            result.VerifyIncrementalStepsMultiple("CheckedAndRewrittenTagHelpers",
                IncrementalStepRunReason.Modified,  // Index - tag helpers changed
                IncrementalStepRunReason.Modified); // NewCounter renamed
            result.VerifyIncrementalStepsMultiple("GeneratedCode",
                IncrementalStepRunReason.Modified,  // Index - tag helpers changed
                IncrementalStepRunReason.Modified); // NewCounter renamed
            result.VerifyIncrementalStepsMultiple("CSharpDocuments",
                IncrementalStepRunReason.Unchanged, // Index - output unchanged (doesn't use Counter/NewCounter)
                IncrementalStepRunReason.Modified); // NewCounter renamed
 
            // Verify the generated source has the correct namespace and class name
            var newCounterSource = result.GeneratedSources.FirstOrDefault(s => s.HintName.Contains("NewCounter"));
            Assert.Contains("namespace MyApp.Pages", newCounterSource.SourceText.ToString());
            Assert.Contains("public partial class NewCounter", newCounterSource.SourceText.ToString());
 
            // Do a case-only rename and make sure we update the generated class name still
            // as component names are case sensitive even on Windows.
            var renamedText2 = new TestAdditionalText("Pages/NewCouNter.razor", counterText.GetText()!);
            driver = driver.RemoveAdditionalTexts([renamedText])
                          .AddAdditionalTexts([renamedText2]);
 
            // Update the analyzer config options with the new target path
            analyzerConfigOptionProvider.AdditionalTextOptions[renamedText2.Path] = new TestAnalyzerConfigOptions
            {
                ["build_metadata.AdditionalFiles.TargetPath"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(renamedText2.Path))
            };
            driver = driver.WithUpdatedAnalyzerConfigOptions(analyzerConfigOptionProvider);
 
            result = RunGenerator(compilation!, ref driver);
 
            var newCouNterSource = result.GeneratedSources.FirstOrDefault(s => s.HintName.Contains("NewCouNter"));
            Assert.Contains("public partial class NewCouNter", newCouNterSource.SourceText.ToString());
        }
 
        [Fact, WorkItem("https://github.com/dotnet/razor/issues/12316")]
        public async Task RazorClassLibrary_Change_Updates_DependentProject_WhenReferencedAsCompilation()
        {
            var rclProject = CreateTestProject(new()
            {
                ["LibComponent.razor"] = "<p>Library component</p>",
            });
            rclProject = rclProject.WithAssemblyName("RazorClassLibrary");
 
            var rclCompilation = await rclProject.GetCompilationAsync();
            var rclDriver = await GetDriverAsync(rclProject);
            var rclRun = RunGenerator(rclCompilation!, ref rclDriver, out var rclOutputCompilation);
            Assert.Empty(rclRun.Diagnostics);
            Assert.Single(rclRun.GeneratedSources); // LibComponent
 
            // Explicitly use a CompilationReference
            var rclReference = rclOutputCompilation.ToMetadataReference();
 
            // Create the main project that references the RCL and uses its component.
            var mainProject = CreateTestProject(new()
            {
                ["Pages/Index.razor"] = "<LibComponent />",
            });
            mainProject = mainProject.AddMetadataReference(rclReference);
 
            var mainCompilation = await mainProject.GetCompilationAsync();
            var (mainDriver, mainAdditionalTexts, _) = await GetDriverWithAdditionalTextAndProviderAsync(mainProject, trackSteps: true);
            var mainRun = RunGenerator(mainCompilation!, ref mainDriver);
            Assert.Empty(mainRun.Diagnostics);
            Assert.Single(mainRun.GeneratedSources);
 
            // Rename the component in the RCL: LibComponent -> RenamedComponent
            rclProject = CreateTestProject(new()
            {
                ["RenamedComponent.razor"] = "<p>Library component</p>",
            }).WithAssemblyName("RazorClassLibrary");
 
            rclCompilation = await rclProject.GetCompilationAsync()!;
            rclDriver = await GetDriverAsync(rclProject);
            rclRun = RunGenerator(rclCompilation!, ref rclDriver, out rclOutputCompilation);
            Assert.Empty(rclRun.Diagnostics);
            Assert.Single(rclRun.GeneratedSources); // RenamedComponent
 
            var rclReference2 = rclOutputCompilation.ToMetadataReference();
 
            // Update main project to point to the new reference (with renamed component).
            mainProject = mainProject.RemoveMetadataReference(rclReference)
                                     .AddMetadataReference(rclReference2);
            mainCompilation = await mainProject.GetCompilationAsync();
 
            // Re-run generator: expect missing component diagnostic (RZ10012).
            mainRun = RunGenerator(mainCompilation!, ref mainDriver);
            var missing = Assert.Single(mainRun.Diagnostics);
            Assert.Equal("RZ10012", missing.Id);
 
            // Update main project's Index.razor to use the renamed component.
            var updatedIndex = new TestAdditionalText("Pages/Index.razor", SourceText.From("<RenamedComponent />", Encoding.UTF8));
            mainDriver = mainDriver.ReplaceAdditionalText(
                mainAdditionalTexts.First(t => t.Path.EndsWith("Index.razor", StringComparison.OrdinalIgnoreCase)),
                updatedIndex);
 
            // Re-run generator: should compile cleanly again.
            mainRun = RunGenerator(mainCompilation!, ref mainDriver);
            Assert.Empty(mainRun.Diagnostics);
            Assert.Single(mainRun.GeneratedSources);
 
            // Update the compilation, which will cause us to re-run
            mainCompilation = mainCompilation!.WithOptions(mainCompilation.Options.WithModuleName("newMain"));
            mainRun = RunGenerator(mainCompilation!, ref mainDriver);
            Assert.Empty(mainRun.Diagnostics);
            Assert.Single(mainRun.GeneratedSources);
 
            // Confirm that the tag helpers from metadata refs _didn't_ re-run
            // TagHelpersFromCompilation re-runs when compilation changes but output is unchanged
            mainRun.VerifyIncrementalSteps("TagHelpersFromCompilation", IncrementalStepRunReason.Unchanged);
        }
    }
}