Skip to content

Commit

Permalink
Match component properties as case insensitive (#10657)
Browse files Browse the repository at this point in the history
* Add tests

* Match component properties as case insensitive

* Allow mapped code to differ in case

* Update new baselines

* Update pre-existing baselines

* Add more tests

* Match bind attributes case insensitive too

* Update baselines

* Test EditorRequired with different casing

* Use CaseSensitive property during bind matching

* Improve loop efficiency
  • Loading branch information
jjonescz authored Jul 26, 2024
1 parent 1d3de62 commit 5f0c07a
Show file tree
Hide file tree
Showing 54 changed files with 1,365 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,25 @@ public class ComponentWithEditorRequiredParameters : ComponentBase
Assert.Empty(generated.RazorDiagnostics);
}

[IntegrationTestFact]
public void Component_WithEditorRequiredParameter_ValueSpecified_DifferentCasing()
{
AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
namespace Test;
public class ComponentWithEditorRequiredParameters : ComponentBase
{
[Parameter, EditorRequired] public string Property1 { get; set; }
}
"""));
var generated = CompileToCSharp("""
<ComponentWithEditorRequiredParameters property1="Some Value" />
""");
generated.RazorDiagnostics.Verify(
// x:\dir\subdir\Test\TestComponent.cshtml(1,1): warning RZ2012: Component 'ComponentWithEditorRequiredParameters' expects a value for the parameter 'Property1', but a value may not have been provided.
Diagnostic("RZ2012").WithLocation(1, 1));
}

[IntegrationTestFact]
public void Component_WithEditorRequiredParameter_ValuesSpecifiedUsingSplatting()
{
Expand Down Expand Up @@ -1198,6 +1217,25 @@ public class ComponentWithEditorRequiredParameters : ComponentBase
Assert.Empty(generated.RazorDiagnostics);
}

[IntegrationTestFact]
public void Component_WithEditorRequiredParameter_ValueSpecifiedUsingBind_DifferentCasing()
{
AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
namespace Test;
public class ComponentWithEditorRequiredParameters : ComponentBase
{
[Parameter, EditorRequired] public string Property1 { get; set; }
}
"""));
var generated = CompileToCSharp("""
<ComponentWithEditorRequiredParameters @bind-property1="Some Value" />
""");
generated.RazorDiagnostics.Verify(
// x:\dir\subdir\Test\TestComponent.cshtml(1,1): warning RZ2012: Component 'ComponentWithEditorRequiredParameters' expects a value for the parameter 'Property1', but a value may not have been provided.
Diagnostic("RZ2012").WithLocation(1, 1));
}

[IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/10553")]
public void Component_WithEditorRequiredParameter_ValueSpecifiedUsingBindGetSet()
{
Expand Down Expand Up @@ -1257,6 +1295,28 @@ public class ComponentWithEditorRequiredParameters : ComponentBase
Assert.Empty(generated.RazorDiagnostics);
}

[IntegrationTestFact]
public void Component_WithEditorRequiredParameter_ValueSpecifiedUsingBindGet_DifferentCasing()
{
AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
namespace Test;
public class ComponentWithEditorRequiredParameters : ComponentBase
{
[Parameter, EditorRequired] public string Property1 { get; set; }
}
"""));
var generated = CompileToCSharp("""
<ComponentWithEditorRequiredParameters @bind-property1:get="myField" />
@code {
private string myField = "Some Value";
}
""");
generated.RazorDiagnostics.Verify(
// x:\dir\subdir\Test\TestComponent.cshtml(1,1): warning RZ2012: Component 'ComponentWithEditorRequiredParameters' expects a value for the parameter 'Property1', but a value may not have been provided.
Diagnostic("RZ2012").WithLocation(1, 1));
}

[IntegrationTestFact, WorkItem("https://github.com/dotnet/razor/issues/10553")]
public void Component_WithEditorRequiredParameter_ValueSpecifiedUsingBindSet()
{
Expand Down Expand Up @@ -1733,6 +1793,178 @@ public class MyComponent<T> : ComponentBase
CompileToAssembly(generated);
}

[IntegrationTestFact, WorkItem("https://github.com/dotnet/aspnetcore/issues/48778")]
public void ImplicitStringConversion_ParameterCasing_AddAttribute()
{
_configuration = base.Configuration with { LanguageVersion = RazorLanguageVersion.Version_7_0 };

AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
namespace Test;
public class MyClass
{
public static implicit operator string(MyClass c) => "";
}
public class MyComponent : ComponentBase
{
[Parameter] public string Placeholder { get; set; } = "";
}
"""));

var generated = CompileToCSharp("""
<MyComponent PlaceHolder="@(new MyClass())" />
""");

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

[IntegrationTestFact, WorkItem("https://github.com/dotnet/aspnetcore/issues/48778")]
public void ImplicitStringConversion_ParameterCasing_AddComponentParameter()
{
AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
namespace Test;
public class MyClass
{
public static implicit operator string(MyClass c) => "";
}
public class MyComponent : ComponentBase
{
[Parameter] public string Placeholder { get; set; } = "";
}
"""));

var generated = CompileToCSharp("""
<MyComponent PlaceHolder="@(new MyClass())" />
""");

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

[IntegrationTestFact, WorkItem("https://github.com/dotnet/aspnetcore/issues/48778")]
public void ImplicitStringConversion_ParameterCasing_Multiple()
{
AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
namespace Test;
public class MyClass
{
public static implicit operator string(MyClass c) => "";
}
public class MyComponent : ComponentBase
{
[Parameter] public string Placeholder { get; set; } = "";
[Parameter] public string PlaceHolder { get; set; } = "";
}
"""));

var generated = CompileToCSharp("""
<MyComponent PlaceHolder="@(new MyClass())" />
""");

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

[IntegrationTestFact, WorkItem("https://github.com/dotnet/aspnetcore/issues/48778")]
public void ImplicitStringConversion_ParameterCasing_Bind()
{
AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
namespace Test;
public class MyComponent : ComponentBase
{
[Parameter] public string Placeholder { get; set; } = "";
[Parameter] public EventCallback<string> PlaceholderChanged { get; set; }
}
"""));

var generated = CompileToCSharp("""
<MyComponent @bind-PlaceHolder="s" />
@code {
private string s = "abc";
}
""");

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

[IntegrationTestFact, WorkItem("https://github.com/dotnet/aspnetcore/issues/48778")]
public void ImplicitStringConversion_ParameterCasing_Bind_02()
{
AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
namespace Test;
public class MyComponent : ComponentBase
{
[Parameter] public string Placeholder { get; set; } = "";
[Parameter] public EventCallback<string> PlaceholderChanged { get; set; }
}
"""));

var generated = CompileToCSharp("""
<MyComponent @Bind-Placeholder="@s" />
@code {
private string s = "abc";
}
""");

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

[IntegrationTestFact, WorkItem("https://github.com/dotnet/aspnetcore/issues/48778")]
public void ImplicitStringConversion_ParameterCasing_Bind_03()
{
AdditionalSyntaxTrees.Add(Parse("""
using Microsoft.AspNetCore.Components;
namespace Test;
public class MyComponent : ComponentBase
{
[Parameter] public string Placeholder { get; set; } = "";
[Parameter] public EventCallback<string> PlaceholderChanged { get; set; }
}
"""));

var generated = CompileToCSharp("""
<MyComponent @bind-Placeholder:Get="s" @bind-Placeholder:set="Changed" />
@code {
private string s = "abc";
private void Changed(string s) { }
}
""");

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

[IntegrationTestFact, WorkItem("https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1869483")]
public void AddComponentParameter()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,15 @@ protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.
#line default
#line hidden
#nullable disable
__o = "";
__o = global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<global::System.Int32>(
#nullable restore
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
1

#line default
#line hidden
#nullable disable
);
__o = global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<global::System.Boolean>(
#nullable restore
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
HtmlContent - (32:1,15 [2] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (32:1,15 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
Component - (34:2,0 [51] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
ComponentAttribute - - intproperty - - AttributeStructure.SingleQuotes
HtmlContent - (60:2,26 [1] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (60:2,26 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Html - 1
ComponentAttribute - (60:2,26 [1] x:\dir\subdir\Test\TestComponent.cshtml) - intproperty - IntProperty - AttributeStructure.SingleQuotes
LazyIntermediateToken - (60:2,26 [1] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 1
ComponentAttribute - (77:2,43 [4] x:\dir\subdir\Test\TestComponent.cshtml) - BoolProperty - BoolProperty - AttributeStructure.SingleQuotes
LazyIntermediateToken - (77:2,43 [4] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - true
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
Source Location: (77:2,43 [4] x:\dir\subdir\Test\TestComponent.cshtml)
Source Location: (60:2,26 [1] x:\dir\subdir\Test\TestComponent.cshtml)
|1|
Generated Location: (1459:39,26 [1] )
|1|

Source Location: (77:2,43 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|true|
Generated Location: (1501:40,43 [4] )
Generated Location: (1767:48,43 [4] )
|true|

Source Location: (63:2,29 [12] x:\dir\subdir\Test\TestComponent.cshtml)
|BoolProperty|
Generated Location: (1929:53,29 [12] )
Generated Location: (2195:61,29 [12] )
|BoolProperty|

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// <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)
{
__o = global::Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<global::System.String>(
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
new MyClass()

#line default
#line hidden
#nullable disable
);
__builder.AddAttribute(-1, "ChildContent", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => {
}
));
#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
}
}
#pragma warning restore 1591
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [20] ) - global::System
UsingDirective - (26:2,1 [40] ) - global::System.Collections.Generic
UsingDirective - (69:3,1 [25] ) - global::System.Linq
UsingDirective - (97:4,1 [36] ) - global::System.Threading.Tasks
UsingDirective - (136:5,1 [45] ) - global::Microsoft.AspNetCore.Components
ClassDeclaration - - public partial - TestComponent - global::Microsoft.AspNetCore.Components.ComponentBase -
DesignTimeDirective -
CSharpCode -
IntermediateToken - - CSharp - #pragma warning disable 0414
CSharpCode -
IntermediateToken - - CSharp - private static object __o = null;
CSharpCode -
IntermediateToken - - CSharp - #pragma warning restore 0414
MethodDeclaration - - protected override - void - BuildRenderTree
Component - (0:0,0 [46] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
ComponentAttribute - (26:0,26 [16] x:\dir\subdir\Test\TestComponent.cshtml) - PlaceHolder - Placeholder - AttributeStructure.DoubleQuotes
CSharpExpression - (28:0,28 [13] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (28:0,28 [13] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - new MyClass()
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Source Location: (28:0,28 [13] x:\dir\subdir\Test\TestComponent.cshtml)
|new MyClass()|
Generated Location: (1138:29,28 [13] )
|new MyClass()|

Loading

0 comments on commit 5f0c07a

Please sign in to comment.