diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentBindLoweringPass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentBindLoweringPass.cs index a28fac0543..990c3d35f5 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentBindLoweringPass.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentBindLoweringPass.cs @@ -48,13 +48,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Components } // First, collect all the non-parameterized bind or bind-* attributes. - var bindEntries = new Dictionary(); + // The dict key is a tuple of (parent, attributeName) to differentiate attributes with the same name in two different elements. + // We don't have to worry about duplicate bound attributes in the same element + // like, , because IR lowering takes care of that. + var bindEntries = new Dictionary<(IntermediateNode, string), BindEntry>(); for (var i = 0; i < references.Count; i++) { var reference = references[i]; + var parent = reference.Parent; var node = (TagHelperPropertyIntermediateNode)reference.Node; - if (!reference.Parent.Children.Contains(node)) + if (!parent.Children.Contains(node)) { // This node was removed as a duplicate, skip it. continue; @@ -62,7 +66,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components if (node.TagHelper.IsBindTagHelper() && node.AttributeName.StartsWith("bind")) { - bindEntries[node.AttributeName] = new BindEntry(reference); + bindEntries[(parent, node.AttributeName)] = new BindEntry(reference); } } @@ -70,9 +74,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Components for (var i = 0; i < parameterReferences.Count; i++) { var parameterReference = parameterReferences[i]; + var parent = parameterReference.Parent; var node = (TagHelperAttributeParameterIntermediateNode)parameterReference.Node; - if (!parameterReference.Parent.Children.Contains(node)) + if (!parent.Children.Contains(node)) { // This node was removed as a duplicate, skip it. continue; @@ -80,7 +85,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Components if (node.TagHelper.IsBindTagHelper() && node.AttributeName.StartsWith("bind")) { - if (!bindEntries.TryGetValue(node.AttributeNameWithoutParameter, out var entry)) + // Check if this tag contains a corresponding non-parameterized bind node. + if (!bindEntries.TryGetValue((parent, node.AttributeNameWithoutParameter), out var entry)) { // There is no corresponding bind node. Add a diagnostic and move on. parameterReference.Parent.Diagnostics.Add(ComponentDiagnosticFactory.CreateBindAttributeParameter_MissingBind( diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs index d9fcc74ccc..09ba658797 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs @@ -2573,6 +2573,7 @@ namespace Test // Act var generated = CompileToCSharp(@" + @code { string Value; }"); diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs index c41b5245ec..d852967c80 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs @@ -34,13 +34,30 @@ namespace Test #line 1 "x:\dir\subdir\Test\TestComponent.cshtml" __o = typeof(MyComponent<>); +#line default +#line hidden +#nullable disable + __Blazor.Test.TestComponent.TypeInference.CreateMyComponent_1(builder, -1, -1, Microsoft.AspNetCore.Components.BindMethods.GetValue( +#nullable restore +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" + Value + +#line default +#line hidden +#nullable disable + ), -1, + __value => Value = __value); +#nullable restore +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" +__o = typeof(MyComponent<>); + #line default #line hidden #nullable disable } #pragma warning restore 1998 #nullable restore -#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" +#line 3 "x:\dir\subdir\Test\TestComponent.cshtml" string Value; @@ -61,6 +78,13 @@ namespace __Blazor.Test.TestComponent builder.AddAttribute(__seq1, "ItemChanged", __arg1); builder.CloseComponent(); } + public static void CreateMyComponent_1(global::Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, int seq, int __seq0, TItem __arg0, int __seq1, global::System.Action __arg1) + { + builder.OpenComponent>(seq); + builder.AddAttribute(__seq0, "Item", __arg0); + builder.AddAttribute(__seq1, "ItemChanged", __arg1); + builder.CloseComponent(); + } } } #pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.ir.txt index bad13d8f03..43136b9b58 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.ir.txt +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.ir.txt @@ -25,8 +25,20 @@ Document - IntermediateToken - - CSharp - __value => Value = __value HtmlContent - (30:0,30 [2] x:\dir\subdir\Test\TestComponent.cshtml) IntermediateToken - (30:0,30 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n - CSharpCode - (39:1,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) - IntermediateToken - (39:1,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n string Value;\n + Component - (32:1,0 [30] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (55:1,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Item - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindMethods.GetValue( + IntermediateToken - (55:1,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - Value + IntermediateToken - - CSharp - ) + ComponentAttribute - (55:1,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) - ItemChanged - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - __value => Value = __value + HtmlContent - (62:1,30 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (62:1,30 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (71:2,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (71:2,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n string Value;\n NamespaceDeclaration - - __Blazor.Test.TestComponent ClassDeclaration - - internal static - TypeInference - - ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateMyComponent_0 + ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateMyComponent_1 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt index 8c9be647da..6619288315 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt @@ -3,11 +3,16 @@ Source Location: (23:0,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) Generated Location: (1012:25,23 [5] ) |Value| -Source Location: (39:1,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (55:1,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) +|Value| +Generated Location: (1521:42,23 [5] ) +|Value| + +Source Location: (71:2,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) | string Value; | -Generated Location: (1408:43,7 [21] ) +Generated Location: (1917:60,7 [21] ) | string Value; | diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs index 9dd67956f1..9ff80d8a2d 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.codegen.cs @@ -22,10 +22,20 @@ namespace Test #line hidden #nullable disable ), 2, __value => Value = __value); + builder.AddMarkupContent(3, "\r\n"); + __Blazor.Test.TestComponent.TypeInference.CreateMyComponent_1(builder, 4, 5, Microsoft.AspNetCore.Components.BindMethods.GetValue( +#nullable restore +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" + Value + +#line default +#line hidden +#nullable disable + ), 6, __value => Value = __value); } #pragma warning restore 1998 #nullable restore -#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" +#line 3 "x:\dir\subdir\Test\TestComponent.cshtml" string Value; @@ -46,6 +56,13 @@ namespace __Blazor.Test.TestComponent builder.AddAttribute(__seq1, "ItemChanged", __arg1); builder.CloseComponent(); } + public static void CreateMyComponent_1(global::Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, int seq, int __seq0, TItem __arg0, int __seq1, global::System.Action __arg1) + { + builder.OpenComponent>(seq); + builder.AddAttribute(__seq0, "Item", __arg0); + builder.AddAttribute(__seq1, "ItemChanged", __arg1); + builder.CloseComponent(); + } } } #pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.ir.txt index 253fd39767..0d3dc296f3 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.ir.txt +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.ir.txt @@ -16,8 +16,20 @@ Document - ComponentAttribute - (23:0,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) - ItemChanged - AttributeStructure.DoubleQuotes CSharpExpression - IntermediateToken - - CSharp - __value => Value = __value - CSharpCode - (39:1,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) - IntermediateToken - (39:1,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n string Value;\n + HtmlContent - (30:0,30 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (30:0,30 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + Component - (32:1,0 [30] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (55:1,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Item - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindMethods.GetValue( + IntermediateToken - (55:1,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - Value + IntermediateToken - - CSharp - ) + ComponentAttribute - (55:1,23 [5] x:\dir\subdir\Test\TestComponent.cshtml) - ItemChanged - AttributeStructure.DoubleQuotes + CSharpExpression - + IntermediateToken - - CSharp - __value => Value = __value + CSharpCode - (71:2,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (71:2,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n string Value;\n NamespaceDeclaration - - __Blazor.Test.TestComponent ClassDeclaration - - internal static - TypeInference - - ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateMyComponent_0 + ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateMyComponent_1 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt index 65853a0095..5f2383089e 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/ChildComponent_GenericBind_TypeInference/TestComponent.mappings.txt @@ -1,8 +1,8 @@ -Source Location: (39:1,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) +Source Location: (71:2,7 [21] x:\dir\subdir\Test\TestComponent.cshtml) | string Value; | -Generated Location: (973:28,7 [21] ) +Generated Location: (1365:38,7 [21] ) | string Value; |