diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs index 15a06d45518..9447c57692f 100644 --- a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs @@ -9279,6 +9279,31 @@ private class String CompileToAssembly(generated); } + [IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/11505")] + public void CaptureParametersConstraint() + { + AdditionalSyntaxTrees.Add(Parse(""" + using Microsoft.AspNetCore.Components; + + namespace Test; + + public interface IMyInterface; + + public class MyClass where T : IMyInterface; + + [CascadingTypeParameter(nameof(T))] + public class MyComponent : ComponentBase where T : IMyInterface + { + [Parameter] public MyClass Param { get; set; } + } + """)); + var generated = CompileToCSharp(""" + + """); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + #endregion #region Key diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.codegen.cs new file mode 100644 index 00000000000..baabb1e2cad --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.codegen.cs @@ -0,0 +1,82 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #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 TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 219 + private void __RazorDirectiveTokenHelpers__() { + } + #pragma warning restore 219 + #pragma warning disable 0414 + private static object __o = null; + #pragma warning restore 0414 + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { + { + global::__Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0_CaptureParameters( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + new MyClass() + +#line default +#line hidden +#nullable disable + , out var __typeInferenceArg_0___arg0); + var __typeInference_CreateMyComponent_0 = global::__Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0(__builder, -1, -1, __typeInferenceArg_0___arg0); + #pragma warning disable BL0005 + __typeInference_CreateMyComponent_0. +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Param + +#line default +#line hidden +#nullable disable + = default; + #pragma warning restore BL0005 + } +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" +__o = typeof(global::Test.MyComponent<>); + +#line default +#line hidden +#nullable disable + } + #pragma warning restore 1998 + } +} +namespace __Blazor.Test.TestComponent +{ + #line hidden + internal static class TypeInference + { + public static global::Test.MyComponent CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::Test.MyClass __arg0) + where T : global::Test.IMyInterface + { + __builder.OpenComponent>(seq); + __builder.AddAttribute(__seq0, "Param", (object)__arg0); + __builder.CloseComponent(); + return default; + } + + public static void CreateMyComponent_0_CaptureParameters(global::Test.MyClass __arg0, out global::Test.MyClass __arg0_out) + where T : global::Test.IMyInterface + { + __arg0_out = __arg0; + } + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.mappings.txt new file mode 100644 index 00000000000..60fd86c0e0a --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.mappings.txt @@ -0,0 +1,10 @@ +Source Location: (20:0,20 [27] x:\dir\subdir\Test\TestComponent.cshtml) +|new MyClass()| +Generated Location: (1126:30,20 [27] ) +|new MyClass()| + +Source Location: (13:0,13 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Param| +Generated Location: (1625:41,13 [5] ) +|Param| + diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.codegen.cs b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.codegen.cs new file mode 100644 index 00000000000..c2eb3028ef2 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.codegen.cs @@ -0,0 +1,65 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #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 TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase + #nullable disable + { + #pragma warning disable 1998 + protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) + { + { + global::__Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0_CaptureParameters( +#nullable restore +#line (1,21)-(1,48) "x:\dir\subdir\Test\TestComponent.cshtml" +new MyClass() + +#line default +#line hidden +#nullable disable + , out var __typeInferenceArg_0___arg0); + global::__Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0(__builder, 0, 1, __typeInferenceArg_0___arg0); + __typeInferenceArg_0___arg0 = default; + } + } + #pragma warning restore 1998 + } +} +namespace __Blazor.Test.TestComponent +{ + #line hidden + internal static class TypeInference + { + public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::Test.MyClass __arg0) + where T : global::Test.IMyInterface + { + __builder.OpenComponent>(seq); + __builder.AddComponentParameter(__seq0, nameof(global::Test.MyComponent. +#nullable restore +#line (1,14)-(1,19) "x:\dir\subdir\Test\TestComponent.cshtml" +Param + +#line default +#line hidden +#nullable disable + ), __arg0); + __builder.CloseComponent(); + } + + public static void CreateMyComponent_0_CaptureParameters(global::Test.MyClass __arg0, out global::Test.MyClass __arg0_out) + where T : global::Test.IMyInterface + { + __arg0_out = __arg0; + } + } +} +#pragma warning restore 1591 diff --git a/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.mappings.txt b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.mappings.txt new file mode 100644 index 00000000000..796a76d02e2 --- /dev/null +++ b/src/Compiler/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/CaptureParametersConstraint/TestComponent.mappings.txt @@ -0,0 +1,10 @@ +Source Location: (20:0,20 [27] x:\dir\subdir\Test\TestComponent.cshtml) +|new MyClass()| +Generated Location: (857:23,0 [27] ) +|new MyClass()| + +Source Location: (13:0,13 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Param| +Generated Location: (1843:48,0 [5] ) +|Param| + diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs index 79b270262fb..29362cc1f91 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/Components/ComponentNodeWriter.cs @@ -153,19 +153,7 @@ protected void WriteComponentTypeInferenceMethod(CodeRenderingContext context, C writer.Write(")"); - // Writes out a list of generic type constraints with indentation - // public void Foo(T t, U u) - // where T: new() - // where U: Foo, notnull - foreach (var constraint in node.GenericTypeConstraints) - { - writer.WriteLine(); - writer.Indent(writer.CurrentIndent + writer.TabSize); - writer.Write(constraint); - - } - - writer.WriteLine(); + writeConstraints(writer, node); writer.WriteLine("{"); @@ -319,7 +307,10 @@ protected void WriteComponentTypeInferenceMethod(CodeRenderingContext context, C writer.Write("_out"); } - writer.WriteLine(")"); + writer.Write(")"); + + writeConstraints(writer, node); + writer.WriteLine("{"); foreach (var parameter in parameters.Where(p => p.UsedForTypeInference)) { @@ -331,6 +322,22 @@ protected void WriteComponentTypeInferenceMethod(CodeRenderingContext context, C } writer.WriteLine("}"); } + + static void writeConstraints(CodeWriter writer, ComponentTypeInferenceMethodIntermediateNode node) + { + // Writes out a list of generic type constraints with indentation + // public void Foo(T t, U u) + // where T: new() + // where U: Foo, notnull + foreach (var constraint in node.GenericTypeConstraints) + { + writer.WriteLine(); + writer.Indent(writer.CurrentIndent + writer.TabSize); + writer.Write(constraint); + } + + writer.WriteLine(); + } } protected static void WriteComponentAttributeName(CodeRenderingContext context, ComponentAttributeIntermediateNode attribute, bool allowNameof = true)