Skip to content

Commit 27a338b

Browse files
chsienkijjonescz
andauthored
Global namespace component bind (#10798)
* Don't create a taghelper with no matching rules * Add test --------- Co-authored-by: Jan Jones <jan.jones.cz@gmail.com>
1 parent a530667 commit 27a338b

File tree

8 files changed

+249
-5
lines changed

8 files changed

+249
-5
lines changed

src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2743,6 +2743,36 @@ public class MyComponent<T> : ComponentBase
27432743
CompileToAssembly(generated);
27442744
}
27452745

2746+
[IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/10609")]
2747+
public void BindToComponent_SpecifiesValue_WithMatchingProperties_GlobalNamespaceComponent()
2748+
{
2749+
// Arrange
2750+
AdditionalSyntaxTrees.Add(Parse(@"
2751+
using System;
2752+
using Microsoft.AspNetCore.Components;
2753+
2754+
public class MyComponent : ComponentBase
2755+
{
2756+
[Parameter]
2757+
public int Value { get; set; }
2758+
2759+
[Parameter]
2760+
public Action<int> ValueChanged { get; set; }
2761+
}"));
2762+
2763+
// Act
2764+
var generated = CompileToCSharp(@"
2765+
<MyComponent @bind-Value=""ParentValue"" />
2766+
@code {
2767+
public int ParentValue { get; set; } = 42;
2768+
}");
2769+
2770+
// Assert
2771+
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
2772+
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
2773+
CompileToAssembly(generated);
2774+
}
2775+
27462776
[IntegrationTestFact]
27472777
public void BindToElement_WritesAttributes()
27482778
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// <auto-generated/>
2+
#pragma warning disable 1591
3+
namespace Test
4+
{
5+
#line default
6+
using global::System;
7+
using global::System.Collections.Generic;
8+
using global::System.Linq;
9+
using global::System.Threading.Tasks;
10+
using global::Microsoft.AspNetCore.Components;
11+
#line default
12+
#line hidden
13+
#nullable restore
14+
public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase
15+
#nullable disable
16+
{
17+
#pragma warning disable 219
18+
private void __RazorDirectiveTokenHelpers__() {
19+
}
20+
#pragma warning restore 219
21+
#pragma warning disable 0414
22+
private static object __o = null;
23+
#pragma warning restore 0414
24+
#pragma warning disable 1998
25+
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
26+
{
27+
__o = global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<global::System.Int32>(
28+
#nullable restore
29+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
30+
ParentValue
31+
32+
#line default
33+
#line hidden
34+
#nullable disable
35+
);
36+
__o = new global::System.Action<System.Int32>(
37+
__value => ParentValue = __value);
38+
__builder.AddAttribute(-1, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => {
39+
}
40+
));
41+
#pragma warning disable BL0005
42+
((global::MyComponent)default).
43+
#nullable restore
44+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
45+
Value
46+
47+
#line default
48+
#line hidden
49+
#nullable disable
50+
= default;
51+
#pragma warning restore BL0005
52+
#nullable restore
53+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
54+
__o = typeof(global::MyComponent);
55+
56+
#line default
57+
#line hidden
58+
#nullable disable
59+
}
60+
#pragma warning restore 1998
61+
#nullable restore
62+
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
63+
64+
public int ParentValue { get; set; } = 42;
65+
66+
#line default
67+
#line hidden
68+
#nullable disable
69+
}
70+
}
71+
#pragma warning restore 1591
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Document -
2+
NamespaceDeclaration - - Test
3+
UsingDirective - (3:1,1 [20] ) - global::System
4+
UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic
5+
UsingDirective - (69:3,1 [25] ) - global::System.Linq
6+
UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks
7+
UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components
8+
ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase -
9+
DesignTimeDirective -
10+
CSharpCode -
11+
IntermediateToken - - CSharp - #pragma warning disable 0414
12+
CSharpCode -
13+
IntermediateToken - - CSharp - private static object __o = null;
14+
CSharpCode -
15+
IntermediateToken - - CSharp - #pragma warning restore 0414
16+
MethodDeclaration - - protected override - void - BuildRenderTree
17+
Component - (0:0,0 [41] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
18+
ComponentAttribute - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes
19+
CSharpExpression -
20+
LazyIntermediateToken - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
21+
ComponentAttribute - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - ValueChanged - AttributeStructure.DoubleQuotes
22+
CSharpExpression -
23+
IntermediateToken - - CSharp - __value => ParentValue = __value
24+
HtmlContent - (41:0,41 [2] x:\dir\subdir\Test\TestComponent.cshtml)
25+
LazyIntermediateToken - (41:0,41 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
26+
CSharpCode - (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml)
27+
LazyIntermediateToken - (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml)
2+
|ParentValue|
3+
Generated Location: (1135:29,26 [11] )
4+
|ParentValue|
5+
6+
Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml)
7+
|Value|
8+
Generated Location: (1663:44,19 [5] )
9+
|Value|
10+
11+
Source Location: (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml)
12+
|
13+
public int ParentValue { get; set; } = 42;
14+
|
15+
Generated Location: (2071:62,7 [50] )
16+
|
17+
public int ParentValue { get; set; } = 42;
18+
|
19+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// <auto-generated/>
2+
#pragma warning disable 1591
3+
namespace Test
4+
{
5+
#line default
6+
using global::System;
7+
using global::System.Collections.Generic;
8+
using global::System.Linq;
9+
using global::System.Threading.Tasks;
10+
using global::Microsoft.AspNetCore.Components;
11+
#line default
12+
#line hidden
13+
#nullable restore
14+
public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase
15+
#nullable disable
16+
{
17+
#pragma warning disable 1998
18+
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
19+
{
20+
__builder.OpenComponent<global::MyComponent>(0);
21+
__builder.AddComponentParameter(1, nameof(global::MyComponent.
22+
#nullable restore
23+
#line (1,20)-(1,25) "x:\dir\subdir\Test\TestComponent.cshtml"
24+
Value
25+
26+
#line default
27+
#line hidden
28+
#nullable disable
29+
), global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<global::System.Int32>(
30+
#nullable restore
31+
#line (1,27)-(1,38) "x:\dir\subdir\Test\TestComponent.cshtml"
32+
ParentValue
33+
34+
#line default
35+
#line hidden
36+
#nullable disable
37+
));
38+
__builder.AddComponentParameter(2, nameof(global::MyComponent.ValueChanged), (global::System.Action<System.Int32>)(__value => ParentValue = __value));
39+
__builder.CloseComponent();
40+
}
41+
#pragma warning restore 1998
42+
#nullable restore
43+
#line (2,8)-(4,1) "x:\dir\subdir\Test\TestComponent.cshtml"
44+
45+
public int ParentValue { get; set; } = 42;
46+
47+
#line default
48+
#line hidden
49+
#nullable disable
50+
51+
}
52+
}
53+
#pragma warning restore 1591
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Document -
2+
NamespaceDeclaration - - Test
3+
UsingDirective - (3:1,1 [22] ) - global::System
4+
UsingDirective - (26:2,1 [42] ) - global::System.Collections.Generic
5+
UsingDirective - (69:3,1 [27] ) - global::System.Linq
6+
UsingDirective - (97:4,1 [38] ) - global::System.Threading.Tasks
7+
UsingDirective - (136:5,1 [47] ) - global::Microsoft.AspNetCore.Components
8+
ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase -
9+
MethodDeclaration - - protected override - void - BuildRenderTree
10+
Component - (0:0,0 [41] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
11+
ComponentAttribute - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - Value - AttributeStructure.DoubleQuotes
12+
CSharpExpression -
13+
LazyIntermediateToken - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
14+
ComponentAttribute - (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - ValueChanged - AttributeStructure.DoubleQuotes
15+
CSharpExpression -
16+
IntermediateToken - - CSharp - __value => ParentValue = __value
17+
CSharpCode - (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml)
18+
LazyIntermediateToken - (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Source Location: (19:0,19 [5] x:\dir\subdir\Test\TestComponent.cshtml)
2+
|Value|
3+
Generated Location: (874:23,0 [5] )
4+
|Value|
5+
6+
Source Location: (26:0,26 [11] x:\dir\subdir\Test\TestComponent.cshtml)
7+
|ParentValue|
8+
Generated Location: (1134:31,0 [11] )
9+
|ParentValue|
10+
11+
Source Location: (50:1,7 [50] x:\dir\subdir\Test\TestComponent.cshtml)
12+
|
13+
public int ParentValue { get; set; } = 42;
14+
|
15+
Generated Location: (1548:43,0 [50] )
16+
|
17+
public int ParentValue { get; set; } = 42;
18+
|
19+

src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/CSharp/ComponentTagHelperDescriptorProvider.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,22 @@ protected override void Collect(ISymbol symbol, ICollection<TagHelperDescriptor>
5555
var shortNameMatchingDescriptor = CreateShortNameMatchingDescriptor(type, properties);
5656
results.Add(shortNameMatchingDescriptor);
5757

58-
var fullyQualifiedNameMatchingDescriptor = CreateFullyQualifiedNameMatchingDescriptor(type, properties);
59-
results.Add(fullyQualifiedNameMatchingDescriptor);
58+
// If the component is in the global namespace, skip adding this descriptor which will be the same as the short name one.
59+
TagHelperDescriptor? fullyQualifiedNameMatchingDescriptor = null;
60+
if (!type.ContainingNamespace.IsGlobalNamespace)
61+
{
62+
fullyQualifiedNameMatchingDescriptor = CreateFullyQualifiedNameMatchingDescriptor(type, properties);
63+
results.Add(fullyQualifiedNameMatchingDescriptor);
64+
}
6065

6166
foreach (var childContent in shortNameMatchingDescriptor.GetChildContentProperties())
6267
{
6368
// Synthesize a separate tag helper for each child content property that's declared.
6469
results.Add(CreateChildContentDescriptor(shortNameMatchingDescriptor, childContent));
65-
results.Add(CreateChildContentDescriptor(fullyQualifiedNameMatchingDescriptor, childContent));
70+
if (fullyQualifiedNameMatchingDescriptor is not null)
71+
{
72+
results.Add(CreateChildContentDescriptor(fullyQualifiedNameMatchingDescriptor, childContent));
73+
}
6674
}
6775
}
6876
}
@@ -111,8 +119,7 @@ private static TagHelperDescriptor CreateNameMatchingDescriptor(
111119

112120
metadata.Add(ComponentMetadata.Component.NameMatchKey, ComponentMetadata.Component.FullyQualifiedNameMatch);
113121
}
114-
// If the component is in the global namespace, skip adding this rule which is the same as the fully qualified one.
115-
else if (!type.ContainingNamespace.IsGlobalNamespace)
122+
else
116123
{
117124
builder.TagMatchingRule(r =>
118125
{

0 commit comments

Comments
 (0)