Skip to content
This repository has been archived by the owner on Sep 26, 2024. It is now read-only.

Commit

Permalink
Several fixes to generic type constraints
Browse files Browse the repository at this point in the history
* Type constraints on type parameters are now globally fully qualified.
* Type parameter constraints that don't have type constraints will not incorrectly prevent a comma any longer.
  • Loading branch information
javiercn authored Jan 25, 2022
1 parent bad001f commit 966311e
Show file tree
Hide file tree
Showing 27 changed files with 1,168 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3893,6 +3893,220 @@ public class Column<TItem> : ComponentBase
CompileToAssembly(generated);
}

[Fact]
public void CascadingGenericInference_Inferred_WithConstraints()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
[CascadingTypeParameter(nameof(TItem))]
public class Grid<TItem> : ComponentBase
{
[Parameter] public RenderFragment ColumnsTemplate { get; set; }
}
public abstract partial class BaseColumn<TItem> : ComponentBase where TItem : class
{
[CascadingParameter]
internal Grid<TItem> Grid { get; set; }
}
public class Column<TItem> : BaseColumn<TItem>, IGridFieldColumn<TItem> where TItem : class
{
[Parameter]
public string FieldName { get; set; }
}
internal interface IGridFieldColumn<TItem> where TItem : class
{
}
public class WeatherForecast { }
}
"));

// Act
var generated = CompileToCSharp(@"
<Grid TItem=""WeatherForecast"" Items=""@(Array.Empty<WeatherForecast>())"">
<ColumnsTemplate>
<Column Title=""Date"" FieldName=""Date"" Format=""d"" Width=""10rem"" />
</ColumnsTemplate>
</Grid>
");

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

[Fact]
public void CascadingGenericInference_Inferred_MultipleConstraints()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
[CascadingTypeParameter(nameof(TItem))]
public class Grid<TItem> : ComponentBase
{
[Parameter] public RenderFragment ColumnsTemplate { get; set; }
}
public abstract partial class BaseColumn<TItem> : ComponentBase where TItem : class, new()
{
[CascadingParameter]
internal Grid<TItem> Grid { get; set; }
}
public class Column<TItem> : BaseColumn<TItem>, IGridFieldColumn<TItem> where TItem : class, new()
{
[Parameter]
public string FieldName { get; set; }
}
internal interface IGridFieldColumn<TItem> where TItem : class
{
}
public class WeatherForecast { }
}
"));

// Act
var generated = CompileToCSharp(@"
<Grid TItem=""WeatherForecast"" Items=""@(Array.Empty<WeatherForecast>())"">
<ColumnsTemplate>
<Column Title=""Date"" FieldName=""Date"" Format=""d"" Width=""10rem"" />
</ColumnsTemplate>
</Grid>
");

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

[Fact]
public void CascadingGenericInference_Inferred_MultipleConstraints_ClassesAndInterfaces()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
using Models;
namespace Test
{
[CascadingTypeParameter(nameof(TItem))]
public class Grid<TItem> : ComponentBase
{
[Parameter] public RenderFragment ColumnsTemplate { get; set; }
}
public abstract partial class BaseColumn<TItem> : ComponentBase where TItem : WeatherForecast, new()
{
[CascadingParameter]
internal Grid<TItem> Grid { get; set; }
}
public class Column<TItem> : BaseColumn<TItem>, IGridFieldColumn<TItem> where TItem : WeatherForecast, new()
{
[Parameter]
public string FieldName { get; set; }
}
internal interface IGridFieldColumn<TItem> where TItem : class
{
}
}
namespace Models {
public class WeatherForecast { }
}"));

// Act
var generated = CompileToCSharp(@"
@using Models;
<Grid TItem=""WeatherForecast"" Items=""@(Array.Empty<WeatherForecast>())"">
<ColumnsTemplate>
<Column Title=""Date"" FieldName=""Date"" Format=""d"" Width=""10rem"" />
</ColumnsTemplate>
</Grid>
");

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

[Fact]
public void CascadingGenericInference_Inferred_MultipleConstraints_GenericClassConstraints()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Components;
namespace Test
{
[CascadingTypeParameter(nameof(TItem))]
public class Grid<TItem> : ComponentBase
{
[Parameter] public RenderFragment ColumnsTemplate { get; set; }
}
public abstract partial class BaseColumn<TItem> : ComponentBase where TItem : System.Collections.Generic.IEnumerable<TItem>
{
[CascadingParameter]
internal Grid<TItem> Grid { get; set; }
}
public class Column<TItem> : BaseColumn<TItem> where TItem : System.Collections.Generic.IEnumerable<TItem>
{
[Parameter]
public string FieldName { get; set; }
}
}
namespace Models {
using System;
using System.Collections;
using System.Collections.Generic;
public class WeatherForecast : IEnumerable<WeatherForecast> {
public IEnumerator<WeatherForecast> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
}"));

// Act
var generated = CompileToCSharp(@"
@using Models;
<Grid TItem=""WeatherForecast"" Items=""@(Array.Empty<WeatherForecast>())"">
<ColumnsTemplate>
<Column Title=""Date"" FieldName=""Date"" Format=""d"" Width=""10rem"" />
</ColumnsTemplate>
</Grid>
");

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

[Fact]
public void CascadingGenericInference_Partial_CreatesError()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
public partial class TestComponent : global::Microsoft.AspNetCore.Components.ComponentBase
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
}
#pragma warning restore 219
#pragma warning disable 0414
private static System.Object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
__o = typeof(
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
WeatherForecast

#line default
#line hidden
#nullable disable
);
__o =
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
Array.Empty<WeatherForecast>()

#line default
#line hidden
#nullable disable
;
__builder.AddAttribute(-1, "ColumnsTemplate", (global::Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => {
global::__Blazor.Test.TestComponent.TypeInference.CreateColumn_0(__builder2, -1, default(WeatherForecast), -1, "", -1, "", -1, "", -1, "");
#nullable restore
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
__o = typeof(global::Test.Column<>);

#line default
#line hidden
#nullable disable
}
));
#nullable restore
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
__o = typeof(global::Test.Grid<>);

#line default
#line hidden
#nullable disable
}
#pragma warning restore 1998
}
}
namespace __Blazor.Test.TestComponent
{
#line hidden
internal static class TypeInference
{
public static void CreateColumn_0<TItem>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, TItem __syntheticArg0, int __seq0, global::System.Object __arg0, int __seq1, global::System.String __arg1, int __seq2, global::System.Object __arg2, int __seq3, global::System.Object __arg3)
where TItem : class, new()
{
__builder.OpenComponent<global::Test.Column<TItem>>(seq);
__builder.AddAttribute(__seq0, "Title", __arg0);
__builder.AddAttribute(__seq1, "FieldName", __arg1);
__builder.AddAttribute(__seq2, "Format", __arg2);
__builder.AddAttribute(__seq3, "Width", __arg3);
__builder.CloseComponent();
}
}
}
#pragma warning restore 1591
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [12] ) - System
UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
UsingDirective - (53:3,1 [17] ) - System.Linq
UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
UsingDirective - (104:5,1 [37] ) - 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 System.Object __o = null;
CSharpCode -
IntermediateToken - - CSharp - #pragma warning restore 0414
MethodDeclaration - - protected override - void - BuildRenderTree
Component - (0:0,0 [203] x:\dir\subdir\Test\TestComponent.cshtml) - Grid
ComponentChildContent - (78:1,4 [116] x:\dir\subdir\Test\TestComponent.cshtml) - ColumnsTemplate - context
HtmlContent - (95:1,21 [10] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (95:1,21 [10] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
Component - (105:2,8 [65] x:\dir\subdir\Test\TestComponent.cshtml) - Column
ComponentAttribute - - Title - - AttributeStructure.DoubleQuotes
HtmlContent - (120:2,23 [4] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (120:2,23 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Date
ComponentAttribute - (137:2,40 [4] x:\dir\subdir\Test\TestComponent.cshtml) - FieldName - FieldName - AttributeStructure.DoubleQuotes
HtmlContent - (137:2,40 [4] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (137:2,40 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Date
ComponentAttribute - - Format - - AttributeStructure.DoubleQuotes
HtmlContent - (151:2,54 [1] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (151:2,54 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Html - d
ComponentAttribute - - Width - - AttributeStructure.DoubleQuotes
HtmlContent - (161:2,64 [5] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (161:2,64 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - 10rem
HtmlContent - (170:2,73 [6] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (170:2,73 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
ComponentTypeArgument - (13:0,13 [15] x:\dir\subdir\Test\TestComponent.cshtml) - TItem
LazyIntermediateToken - (13:0,13 [15] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - WeatherForecast
ComponentAttribute - - Items - - AttributeStructure.DoubleQuotes
CSharpExpression - (37:0,37 [33] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (39:0,39 [30] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - Array.Empty<WeatherForecast>()
HtmlContent - (203:4,7 [2] x:\dir\subdir\Test\TestComponent.cshtml)
LazyIntermediateToken - (203:4,7 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
NamespaceDeclaration - - __Blazor.Test.TestComponent
ClassDeclaration - - internal static - TypeInference - -
ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateColumn_0
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Source Location: (13:0,13 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|WeatherForecast|
Generated Location: (908:25,13 [15] )
|WeatherForecast|

Source Location: (39:0,39 [30] x:\dir\subdir\Test\TestComponent.cshtml)
|Array.Empty<WeatherForecast>()|
Generated Location: (1120:34,39 [30] )
|Array.Empty<WeatherForecast>()|

Loading

0 comments on commit 966311e

Please sign in to comment.