Skip to content

Commit 013cbf5

Browse files
authored
Propagate DynamicallyAccessedMembersAttribute to type inference method (#11856)
* Add tests * Propagate DynamicallyAccessedMembers * Simplify
1 parent 761db5d commit 013cbf5

File tree

13 files changed

+800
-1
lines changed

13 files changed

+800
-1
lines changed

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

+64
Original file line numberDiff line numberDiff line change
@@ -9483,6 +9483,70 @@ @typeparam TItem
94839483
CompileToAssembly(generated);
94849484
}
94859485

9486+
[IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/11718")]
9487+
public void GenericInference_DynamicallyAccessedMembers_01()
9488+
{
9489+
var generated = CompileToCSharp("""
9490+
@using Microsoft.AspNetCore.Components.Forms
9491+
9492+
<InputRadioGroup @bind-Value="value1">
9493+
<InputRadio Value="@("false")" />
9494+
<InputRadio Value="@("true")" />
9495+
</InputRadioGroup>
9496+
9497+
@code {
9498+
private string value1 = "true";
9499+
}
9500+
""");
9501+
9502+
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
9503+
CompileToAssembly(generated);
9504+
9505+
Assert.Contains("DynamicallyAccessedMembers", generated.Code);
9506+
}
9507+
9508+
[IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/11718")]
9509+
public void GenericInference_DynamicallyAccessedMembers_02()
9510+
{
9511+
AdditionalSyntaxTrees.Add(Parse("""
9512+
using Microsoft.AspNetCore.Components;
9513+
using System;
9514+
using System.Diagnostics.CodeAnalysis;
9515+
using DAM = System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute;
9516+
using DAMT = System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;
9517+
namespace Test;
9518+
public class MyComponent<T1,
9519+
[Attr, DAM(DAMT.PublicMethods | DAMT.PublicFields)] T2,
9520+
[DAM(DAMT.None)] [x: DAM(DAMT.All)] T3>
9521+
: ComponentBase
9522+
{
9523+
[Parameter] public required T1 P1 { get; set; }
9524+
[Parameter] public required T2 P2 { get; set; }
9525+
[Parameter] public required T3 P3 { get; set; }
9526+
}
9527+
class Attr : Attribute;
9528+
"""));
9529+
9530+
var expectedDiagnostics = new[]
9531+
{
9532+
// (9,23): warning CS0658: 'x' is not a recognized attribute location. Valid attribute locations for this declaration are 'typevar'. All attributes in this block will be ignored.
9533+
// [DAM(DAMT.None)] [x: DAM(DAMT.All)] T3>
9534+
Diagnostic(ErrorCode.WRN_InvalidAttributeLocation, "x").WithArguments("x", "typevar").WithLocation(9, 23)
9535+
};
9536+
9537+
var generated = CompileToCSharp("""
9538+
<MyComponent P1="s" P2="2" P3="s" />
9539+
@code {
9540+
private string s = "x";
9541+
}
9542+
""", expectedDiagnostics);
9543+
9544+
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
9545+
CompileToAssembly(generated, expectedDiagnostics);
9546+
9547+
Assert.Contains("DynamicallyAccessedMembers", generated.Code);
9548+
}
9549+
94869550
#endregion
94879551

94889552
#region Key
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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+
#nullable restore
12+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
13+
using Microsoft.AspNetCore.Components.Forms;
14+
15+
#line default
16+
#line hidden
17+
#nullable disable
18+
#nullable restore
19+
public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase
20+
#nullable disable
21+
{
22+
#pragma warning disable 219
23+
private void __RazorDirectiveTokenHelpers__() {
24+
}
25+
#pragma warning restore 219
26+
#pragma warning disable 0414
27+
private static object __o = null;
28+
#pragma warning restore 0414
29+
#pragma warning disable 1998
30+
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
31+
{
32+
var __typeInference_CreateInputRadioGroup_0 = global::__Blazor.Test.TestComponent.TypeInference.CreateInputRadioGroup_0(__builder, -1, -1,
33+
#nullable restore
34+
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
35+
value1
36+
37+
#line default
38+
#line hidden
39+
#nullable disable
40+
, -1, global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this,
41+
global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => value1 = __value, value1)), -1, () => value1, -1, (__builder2) => {
42+
var __typeInference_CreateInputRadio_1 = global::__Blazor.Test.TestComponent.TypeInference.CreateInputRadio_1(__builder2, -1, -1,
43+
#nullable restore
44+
#line 4 "x:\dir\subdir\Test\TestComponent.cshtml"
45+
"false"
46+
47+
#line default
48+
#line hidden
49+
#nullable disable
50+
);
51+
#pragma warning disable BL0005
52+
__typeInference_CreateInputRadio_1.
53+
#nullable restore
54+
#line 4 "x:\dir\subdir\Test\TestComponent.cshtml"
55+
Value
56+
57+
#line default
58+
#line hidden
59+
#nullable disable
60+
= default;
61+
#pragma warning restore BL0005
62+
#nullable restore
63+
#line 4 "x:\dir\subdir\Test\TestComponent.cshtml"
64+
__o = typeof(global::Microsoft.AspNetCore.Components.Forms.InputRadio<>);
65+
66+
#line default
67+
#line hidden
68+
#nullable disable
69+
var __typeInference_CreateInputRadio_2 = global::__Blazor.Test.TestComponent.TypeInference.CreateInputRadio_2(__builder2, -1, -1,
70+
#nullable restore
71+
#line 5 "x:\dir\subdir\Test\TestComponent.cshtml"
72+
"true"
73+
74+
#line default
75+
#line hidden
76+
#nullable disable
77+
);
78+
#pragma warning disable BL0005
79+
__typeInference_CreateInputRadio_2.
80+
#nullable restore
81+
#line 5 "x:\dir\subdir\Test\TestComponent.cshtml"
82+
Value
83+
84+
#line default
85+
#line hidden
86+
#nullable disable
87+
= default;
88+
#pragma warning restore BL0005
89+
#nullable restore
90+
#line 5 "x:\dir\subdir\Test\TestComponent.cshtml"
91+
__o = typeof(global::Microsoft.AspNetCore.Components.Forms.InputRadio<>);
92+
93+
#line default
94+
#line hidden
95+
#nullable disable
96+
}
97+
);
98+
#pragma warning disable BL0005
99+
__typeInference_CreateInputRadioGroup_0.
100+
#nullable restore
101+
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
102+
Value
103+
104+
#line default
105+
#line hidden
106+
#nullable disable
107+
= default;
108+
#pragma warning restore BL0005
109+
#nullable restore
110+
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
111+
__o = typeof(global::Microsoft.AspNetCore.Components.Forms.InputRadioGroup<>);
112+
113+
#line default
114+
#line hidden
115+
#nullable disable
116+
}
117+
#pragma warning restore 1998
118+
#nullable restore
119+
#line 8 "x:\dir\subdir\Test\TestComponent.cshtml"
120+
121+
private string value1 = "true";
122+
123+
#line default
124+
#line hidden
125+
#nullable disable
126+
}
127+
}
128+
namespace __Blazor.Test.TestComponent
129+
{
130+
#line hidden
131+
internal static class TypeInference
132+
{
133+
public static global::Microsoft.AspNetCore.Components.Forms.InputRadioGroup<TValue> CreateInputRadioGroup_0<[global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(unchecked((global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes)0xffffffff))] TValue>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0, int __seq1, global::Microsoft.AspNetCore.Components.EventCallback<TValue> __arg1, int __seq2, global::System.Linq.Expressions.Expression<global::System.Func<TValue>> __arg2, int __seq3, global::Microsoft.AspNetCore.Components.RenderFragment __arg3)
134+
{
135+
__builder.OpenComponent<global::Microsoft.AspNetCore.Components.Forms.InputRadioGroup<TValue>>(seq);
136+
__builder.AddAttribute(__seq0, "Value", (object)__arg0);
137+
__builder.AddAttribute(__seq1, "ValueChanged", (object)__arg1);
138+
__builder.AddAttribute(__seq2, "ValueExpression", (object)__arg2);
139+
__builder.AddAttribute(__seq3, "ChildContent", (object)__arg3);
140+
__builder.CloseComponent();
141+
return default;
142+
}
143+
public static global::Microsoft.AspNetCore.Components.Forms.InputRadio<TValue> CreateInputRadio_1<[global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(unchecked((global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes)0xffffffff))] TValue>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0)
144+
{
145+
__builder.OpenComponent<global::Microsoft.AspNetCore.Components.Forms.InputRadio<TValue>>(seq);
146+
__builder.AddAttribute(__seq0, "Value", (object)__arg0);
147+
__builder.CloseComponent();
148+
return default;
149+
}
150+
public static global::Microsoft.AspNetCore.Components.Forms.InputRadio<TValue> CreateInputRadio_2<[global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(unchecked((global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes)0xffffffff))] TValue>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, TValue __arg0)
151+
{
152+
__builder.OpenComponent<global::Microsoft.AspNetCore.Components.Forms.InputRadio<TValue>>(seq);
153+
__builder.AddAttribute(__seq0, "Value", (object)__arg0);
154+
__builder.CloseComponent();
155+
return default;
156+
}
157+
}
158+
}
159+
#pragma warning restore 1591
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
Source Location: (1:0,1 [43] x:\dir\subdir\Test\TestComponent.cshtml)
2+
|using Microsoft.AspNetCore.Components.Forms|
3+
Generated Location: (361:12,0 [43] )
4+
|using Microsoft.AspNetCore.Components.Forms|
5+
6+
Source Location: (78:2,30 [6] x:\dir\subdir\Test\TestComponent.cshtml)
7+
|value1|
8+
Generated Location: (1297:34,30 [6] )
9+
|value1|
10+
11+
Source Location: (113:3,25 [7] x:\dir\subdir\Test\TestComponent.cshtml)
12+
|"false"|
13+
Generated Location: (1891:44,25 [7] )
14+
|"false"|
15+
16+
Source Location: (104:3,16 [5] x:\dir\subdir\Test\TestComponent.cshtml)
17+
|Value|
18+
Generated Location: (2157:54,16 [5] )
19+
|Value|
20+
21+
Source Location: (152:4,25 [6] x:\dir\subdir\Test\TestComponent.cshtml)
22+
|"true"|
23+
Generated Location: (2729:71,25 [6] )
24+
|"true"|
25+
26+
Source Location: (143:4,16 [5] x:\dir\subdir\Test\TestComponent.cshtml)
27+
|Value|
28+
Generated Location: (2994:81,16 [5] )
29+
|Value|
30+
31+
Source Location: (71:2,23 [5] x:\dir\subdir\Test\TestComponent.cshtml)
32+
|Value|
33+
Generated Location: (3545:101,23 [5] )
34+
|Value|
35+
36+
Source Location: (194:7,7 [39] x:\dir\subdir\Test\TestComponent.cshtml)
37+
|
38+
private string value1 = "true";
39+
|
40+
Generated Location: (3997:119,7 [39] )
41+
|
42+
private string value1 = "true";
43+
|
44+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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+
var __typeInference_CreateMyComponent_0 = global::__Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0(__builder, -1, -1,
28+
#nullable restore
29+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
30+
s
31+
32+
#line default
33+
#line hidden
34+
#nullable disable
35+
, -1,
36+
#nullable restore
37+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
38+
2
39+
40+
#line default
41+
#line hidden
42+
#nullable disable
43+
, -1,
44+
#nullable restore
45+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
46+
s
47+
48+
#line default
49+
#line hidden
50+
#nullable disable
51+
);
52+
#pragma warning disable BL0005
53+
__typeInference_CreateMyComponent_0.
54+
#nullable restore
55+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
56+
P1
57+
58+
#line default
59+
#line hidden
60+
#nullable disable
61+
= default;
62+
__typeInference_CreateMyComponent_0.
63+
#nullable restore
64+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
65+
P2
66+
67+
#line default
68+
#line hidden
69+
#nullable disable
70+
= default;
71+
__typeInference_CreateMyComponent_0.
72+
#nullable restore
73+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
74+
P3
75+
76+
#line default
77+
#line hidden
78+
#nullable disable
79+
= default;
80+
#pragma warning restore BL0005
81+
#nullable restore
82+
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
83+
__o = typeof(global::Test.MyComponent<,,>);
84+
85+
#line default
86+
#line hidden
87+
#nullable disable
88+
}
89+
#pragma warning restore 1998
90+
#nullable restore
91+
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
92+
93+
private string s = "x";
94+
95+
#line default
96+
#line hidden
97+
#nullable disable
98+
}
99+
}
100+
namespace __Blazor.Test.TestComponent
101+
{
102+
#line hidden
103+
internal static class TypeInference
104+
{
105+
public static global::Test.MyComponent<T1, T2, T3> CreateMyComponent_0<T1, [global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(unchecked((global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes)0x00000028))] T2, [global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(unchecked((global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes)0x00000000))] T3>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, T1 __arg0, int __seq1, T2 __arg1, int __seq2, T3 __arg2)
106+
{
107+
__builder.OpenComponent<global::Test.MyComponent<T1, T2, T3>>(seq);
108+
__builder.AddAttribute(__seq0, "P1", (object)__arg0);
109+
__builder.AddAttribute(__seq1, "P2", (object)__arg1);
110+
__builder.AddAttribute(__seq2, "P3", (object)__arg2);
111+
__builder.CloseComponent();
112+
return default;
113+
}
114+
}
115+
}
116+
#pragma warning restore 1591

0 commit comments

Comments
 (0)