Skip to content

Propagate DynamicallyAccessedMembersAttribute to type inference method #11856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9483,6 +9483,70 @@ @typeparam TItem
CompileToAssembly(generated);
}

[IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/11718")]
public void GenericInference_DynamicallyAccessedMembers_01()
{
var generated = CompileToCSharp("""
@using Microsoft.AspNetCore.Components.Forms

<InputRadioGroup @bind-Value="value1">
<InputRadio Value="@("false")" />
<InputRadio Value="@("true")" />
</InputRadioGroup>

@code {
private string value1 = "true";
}
""");

AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);

Assert.Contains("DynamicallyAccessedMembers", generated.Code);
}

[IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/11718")]
public void GenericInference_DynamicallyAccessedMembers_02()
{
AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
using System;
using System.Diagnostics.CodeAnalysis;
using DAM = System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute;
using DAMT = System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;
namespace Test;
public class MyComponent<T1,
[Attr, DAM(DAMT.PublicMethods | DAMT.PublicFields)] T2,
[DAM(DAMT.None)] [x: DAM(DAMT.All)] T3>
: ComponentBase
{
[Parameter] public required T1 P1 { get; set; }
[Parameter] public required T2 P2 { get; set; }
[Parameter] public required T3 P3 { get; set; }
}
class Attr : Attribute;
"""));

var expectedDiagnostics = new[]
{
// (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.
// [DAM(DAMT.None)] [x: DAM(DAMT.All)] T3>
Diagnostic(ErrorCode.WRN_InvalidAttributeLocation, "x").WithArguments("x", "typevar").WithLocation(9, 23)
};

var generated = CompileToCSharp("""
<MyComponent P1="s" P2="2" P3="s" />
@code {
private string s = "x";
}
""", expectedDiagnostics);

AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated, expectedDiagnostics);

Assert.Contains("DynamicallyAccessedMembers", generated.Code);
}

#endregion

#region Key
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// <auto-generated/>
#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;
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
using Microsoft.AspNetCore.Components.Forms;

#line default
#line hidden
#nullable disable
#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)
{
var __typeInference_CreateInputRadioGroup_0 = global::__Blazor.Test.TestComponent.TypeInference.CreateInputRadioGroup_0(__builder, -1, -1,
#nullable restore
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
value1

#line default
#line hidden
#nullable disable
, -1, global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this,
global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => value1 = __value, value1)), -1, () => value1, -1, (__builder2) => {
var __typeInference_CreateInputRadio_1 = global::__Blazor.Test.TestComponent.TypeInference.CreateInputRadio_1(__builder2, -1, -1,
#nullable restore
#line 4 "x:\dir\subdir\Test\TestComponent.cshtml"
"false"

#line default
#line hidden
#nullable disable
);
#pragma warning disable BL0005
__typeInference_CreateInputRadio_1.
#nullable restore
#line 4 "x:\dir\subdir\Test\TestComponent.cshtml"
Value

#line default
#line hidden
#nullable disable
= default;
#pragma warning restore BL0005
#nullable restore
#line 4 "x:\dir\subdir\Test\TestComponent.cshtml"
__o = typeof(global::Microsoft.AspNetCore.Components.Forms.InputRadio<>);

#line default
#line hidden
#nullable disable
var __typeInference_CreateInputRadio_2 = global::__Blazor.Test.TestComponent.TypeInference.CreateInputRadio_2(__builder2, -1, -1,
#nullable restore
#line 5 "x:\dir\subdir\Test\TestComponent.cshtml"
"true"

#line default
#line hidden
#nullable disable
);
#pragma warning disable BL0005
__typeInference_CreateInputRadio_2.
#nullable restore
#line 5 "x:\dir\subdir\Test\TestComponent.cshtml"
Value

#line default
#line hidden
#nullable disable
= default;
#pragma warning restore BL0005
#nullable restore
#line 5 "x:\dir\subdir\Test\TestComponent.cshtml"
__o = typeof(global::Microsoft.AspNetCore.Components.Forms.InputRadio<>);

#line default
#line hidden
#nullable disable
}
);
#pragma warning disable BL0005
__typeInference_CreateInputRadioGroup_0.
#nullable restore
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
Value

#line default
#line hidden
#nullable disable
= default;
#pragma warning restore BL0005
#nullable restore
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
__o = typeof(global::Microsoft.AspNetCore.Components.Forms.InputRadioGroup<>);

#line default
#line hidden
#nullable disable
}
#pragma warning restore 1998
#nullable restore
#line 8 "x:\dir\subdir\Test\TestComponent.cshtml"

private string value1 = "true";

#line default
#line hidden
#nullable disable
}
}
namespace __Blazor.Test.TestComponent
{
#line hidden
internal static class TypeInference
{
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)
{
__builder.OpenComponent<global::Microsoft.AspNetCore.Components.Forms.InputRadioGroup<TValue>>(seq);
__builder.AddAttribute(__seq0, "Value", (object)__arg0);
__builder.AddAttribute(__seq1, "ValueChanged", (object)__arg1);
__builder.AddAttribute(__seq2, "ValueExpression", (object)__arg2);
__builder.AddAttribute(__seq3, "ChildContent", (object)__arg3);
__builder.CloseComponent();
return default;
}
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)
{
__builder.OpenComponent<global::Microsoft.AspNetCore.Components.Forms.InputRadio<TValue>>(seq);
__builder.AddAttribute(__seq0, "Value", (object)__arg0);
__builder.CloseComponent();
return default;
}
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)
{
__builder.OpenComponent<global::Microsoft.AspNetCore.Components.Forms.InputRadio<TValue>>(seq);
__builder.AddAttribute(__seq0, "Value", (object)__arg0);
__builder.CloseComponent();
return default;
}
}
}
#pragma warning restore 1591
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Source Location: (1:0,1 [43] x:\dir\subdir\Test\TestComponent.cshtml)
|using Microsoft.AspNetCore.Components.Forms|
Generated Location: (361:12,0 [43] )
|using Microsoft.AspNetCore.Components.Forms|

Source Location: (78:2,30 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|value1|
Generated Location: (1297:34,30 [6] )
|value1|

Source Location: (113:3,25 [7] x:\dir\subdir\Test\TestComponent.cshtml)
|"false"|
Generated Location: (1891:44,25 [7] )
|"false"|

Source Location: (104:3,16 [5] x:\dir\subdir\Test\TestComponent.cshtml)
|Value|
Generated Location: (2157:54,16 [5] )
|Value|

Source Location: (152:4,25 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|"true"|
Generated Location: (2729:71,25 [6] )
|"true"|

Source Location: (143:4,16 [5] x:\dir\subdir\Test\TestComponent.cshtml)
|Value|
Generated Location: (2994:81,16 [5] )
|Value|

Source Location: (71:2,23 [5] x:\dir\subdir\Test\TestComponent.cshtml)
|Value|
Generated Location: (3545:101,23 [5] )
|Value|

Source Location: (194:7,7 [39] x:\dir\subdir\Test\TestComponent.cshtml)
|
private string value1 = "true";
|
Generated Location: (3997:119,7 [39] )
|
private string value1 = "true";
|

Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// <auto-generated/>
#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)
{
var __typeInference_CreateMyComponent_0 = global::__Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0(__builder, -1, -1,
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
s

#line default
#line hidden
#nullable disable
, -1,
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
2

#line default
#line hidden
#nullable disable
, -1,
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
s

#line default
#line hidden
#nullable disable
);
#pragma warning disable BL0005
__typeInference_CreateMyComponent_0.
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
P1

#line default
#line hidden
#nullable disable
= default;
__typeInference_CreateMyComponent_0.
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
P2

#line default
#line hidden
#nullable disable
= default;
__typeInference_CreateMyComponent_0.
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
P3

#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
#nullable restore
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"

private string s = "x";

#line default
#line hidden
#nullable disable
}
}
namespace __Blazor.Test.TestComponent
{
#line hidden
internal static class TypeInference
{
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)
{
__builder.OpenComponent<global::Test.MyComponent<T1, T2, T3>>(seq);
__builder.AddAttribute(__seq0, "P1", (object)__arg0);
__builder.AddAttribute(__seq1, "P2", (object)__arg1);
__builder.AddAttribute(__seq2, "P3", (object)__arg2);
__builder.CloseComponent();
return default;
}
}
}
#pragma warning restore 1591
Loading