зеркало из https://github.com/dotnet/razor.git
Components that accept bind-Something can request SomethingExpression (#213)
* In binding to components, automatically supply FooExpression when requested * Fix tests * CR feedback
This commit is contained in:
Родитель
3f822a03cd
Коммит
ca9de74f4e
|
@ -24,6 +24,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
public readonly static string ValueAttribute = "Blazor.Bind.ValueAttribute";
|
||||
|
||||
public readonly static string ChangeAttribute = "Blazor.Bind.ChangeAttribute";
|
||||
|
||||
public readonly static string ExpressionAttribute = "Blazor.Bind.ExpressionAttribute";
|
||||
}
|
||||
|
||||
public static class ChildContent
|
||||
|
|
|
@ -148,11 +148,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
{
|
||||
// Bind works similarly to a macro, it always expands to code that the user could have written.
|
||||
//
|
||||
// For the nodes that are related to the bind-attribute rewrite them to look like a pair of
|
||||
// For the nodes that are related to the bind-attribute rewrite them to look like a set of
|
||||
// 'normal' HTML attributes similar to the following transformation.
|
||||
//
|
||||
// Input: <MyComponent bind-Value="@currentCount" />
|
||||
// Output: <MyComponent Value ="...<get the value>..." ValueChanged ="... <set the value>..." />
|
||||
// Output: <MyComponent Value ="...<get the value>..." ValueChanged ="... <set the value>..." ValueExpression ="() => ...<get the value>..." />
|
||||
//
|
||||
// This means that the expression that appears inside of 'bind' must be an LValue or else
|
||||
// there will be errors. In general the errors that come from C# in this case are good enough
|
||||
|
@ -171,8 +171,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
node.AttributeName,
|
||||
out var valueAttributeName,
|
||||
out var changeAttributeName,
|
||||
out var expressionAttributeName,
|
||||
out var valueAttribute,
|
||||
out var changeAttribute))
|
||||
out var changeAttribute,
|
||||
out var expressionAttribute))
|
||||
{
|
||||
// Skip anything we can't understand. It's important that we don't crash, that will bring down
|
||||
// the build.
|
||||
|
@ -340,7 +342,32 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
changeNode.Children[0].Children.Add(changeExpressionTokens[i]);
|
||||
}
|
||||
|
||||
return new[] { valueNode, changeNode };
|
||||
// Finally, also emit a node for the "Expression" attribute, but only if the target
|
||||
// component is defined to accept one
|
||||
ComponentAttributeIntermediateNode expressionNode = null;
|
||||
if (expressionAttribute != null)
|
||||
{
|
||||
expressionNode = new ComponentAttributeIntermediateNode(node)
|
||||
{
|
||||
AttributeName = expressionAttributeName,
|
||||
BoundAttribute = expressionAttribute,
|
||||
PropertyName = expressionAttribute.GetPropertyName(),
|
||||
TagHelper = node.TagHelper,
|
||||
TypeName = expressionAttribute.IsWeaklyTyped() ? null : expressionAttribute.TypeName,
|
||||
};
|
||||
|
||||
expressionNode.Children.Clear();
|
||||
expressionNode.Children.Add(new CSharpExpressionIntermediateNode());
|
||||
expressionNode.Children[0].Children.Add(new IntermediateToken()
|
||||
{
|
||||
Content = $"() => {original.Content}",
|
||||
Kind = TokenKind.CSharp
|
||||
});
|
||||
}
|
||||
|
||||
return expressionNode == null
|
||||
? new[] { valueNode, changeNode }
|
||||
: new[] { valueNode, changeNode, expressionNode };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -394,11 +421,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
string attributeName,
|
||||
out string valueAttributeName,
|
||||
out string changeAttributeName,
|
||||
out string expressionAttributeName,
|
||||
out BoundAttributeDescriptor valueAttribute,
|
||||
out BoundAttributeDescriptor changeAttribute)
|
||||
out BoundAttributeDescriptor changeAttribute,
|
||||
out BoundAttributeDescriptor expressionAttribute)
|
||||
{
|
||||
valueAttribute = null;
|
||||
changeAttribute = null;
|
||||
expressionAttribute = null;
|
||||
expressionAttributeName = null;
|
||||
|
||||
// Even though some of our 'bind' tag helpers specify the attribute names, they
|
||||
// should still satisfy one of the valid syntaxes.
|
||||
|
@ -415,6 +446,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
// We expect 1 bind tag helper per-node.
|
||||
valueAttributeName = node.TagHelper.GetValueAttributeName() ?? valueAttributeName;
|
||||
changeAttributeName = node.TagHelper.GetChangeAttributeName() ?? changeAttributeName;
|
||||
expressionAttributeName = node.TagHelper.GetExpressionAttributeName() ?? expressionAttributeName;
|
||||
|
||||
// We expect 0-1 components per-node.
|
||||
var componentTagHelper = (parent as ComponentIntermediateNode)?.Component;
|
||||
|
@ -437,6 +469,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
changeAttributeName = valueAttributeName + "Changed";
|
||||
}
|
||||
|
||||
// Likewise for the expression attribute
|
||||
if (expressionAttributeName == null)
|
||||
{
|
||||
expressionAttributeName = valueAttributeName + "Expression";
|
||||
}
|
||||
|
||||
for (var i = 0; i < componentTagHelper.BoundAttributes.Count; i++)
|
||||
{
|
||||
var attribute = componentTagHelper.BoundAttributes[i];
|
||||
|
@ -450,6 +488,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
{
|
||||
changeAttribute = attribute;
|
||||
}
|
||||
|
||||
if (string.Equals(expressionAttributeName, attribute.Name))
|
||||
{
|
||||
expressionAttribute = attribute;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -95,6 +95,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
return result;
|
||||
}
|
||||
|
||||
public static string GetExpressionAttributeName(this TagHelperDescriptor tagHelper)
|
||||
{
|
||||
if (tagHelper == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tagHelper));
|
||||
}
|
||||
|
||||
tagHelper.Metadata.TryGetValue(BlazorMetadata.Bind.ExpressionAttribute, out var result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool IsChildContentTagHelper(this TagHelperDescriptor tagHelper)
|
||||
{
|
||||
if (tagHelper == null)
|
||||
|
|
|
@ -351,6 +351,8 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
//
|
||||
// The easiest way to figure this out without a lot of backtracking is to look for `FooChanged` and then
|
||||
// try to find a matching "Foo".
|
||||
//
|
||||
// We also look for a corresponding FooExpression attribute, though its presence is optional.
|
||||
for (var i = 0; i < tagHelper.BoundAttributes.Count; i++)
|
||||
{
|
||||
var changeAttribute = tagHelper.BoundAttributes[i];
|
||||
|
@ -360,12 +362,25 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
}
|
||||
|
||||
BoundAttributeDescriptor valueAttribute = null;
|
||||
BoundAttributeDescriptor expressionAttribute = null;
|
||||
var valueAttributeName = changeAttribute.Name.Substring(0, changeAttribute.Name.Length - "Changed".Length);
|
||||
var expressionAttributeName = valueAttributeName + "Expression";
|
||||
for (var j = 0; j < tagHelper.BoundAttributes.Count; j++)
|
||||
{
|
||||
if (tagHelper.BoundAttributes[j].Name == valueAttributeName && !tagHelper.BoundAttributes[j].IsDelegateProperty())
|
||||
{
|
||||
valueAttribute = tagHelper.BoundAttributes[j];
|
||||
|
||||
}
|
||||
|
||||
if (tagHelper.BoundAttributes[j].Name == expressionAttributeName)
|
||||
{
|
||||
expressionAttribute = tagHelper.BoundAttributes[j];
|
||||
}
|
||||
|
||||
if (valueAttribute != null && expressionAttribute != null)
|
||||
{
|
||||
// We found both, so we can stop looking now
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -388,6 +403,11 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
builder.Metadata[BlazorMetadata.Bind.ValueAttribute] = valueAttribute.Name;
|
||||
builder.Metadata[BlazorMetadata.Bind.ChangeAttribute] = changeAttribute.Name;
|
||||
|
||||
if (expressionAttribute != null)
|
||||
{
|
||||
builder.Metadata[BlazorMetadata.Bind.ExpressionAttribute] = expressionAttribute.Name;
|
||||
}
|
||||
|
||||
// WTE has a bug 15.7p1 where a Tag Helper without a display-name that looks like
|
||||
// a C# property will crash trying to create the toolips.
|
||||
builder.SetTypeName(tagHelper.GetTypeName());
|
||||
|
|
|
@ -428,6 +428,122 @@ namespace Test
|
|||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BindToComponent_SpecifiesValueAndExpression()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent : ComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
int Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
Action<int> ValueChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
Expression<Func<int>> ValueExpression { get; set; }
|
||||
}
|
||||
}"));
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MyComponent bind-Value=""ParentValue"" />
|
||||
@functions {
|
||||
public int ParentValue { get; set; } = 42;
|
||||
}");
|
||||
|
||||
// Assert
|
||||
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
|
||||
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
|
||||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BindToComponent_SpecifiesValueAndExpression_TypeChecked()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent : ComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
int Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
Action<int> ValueChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
Expression<Func<string>> ValueExpression { get; set; }
|
||||
}
|
||||
}"));
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MyComponent bind-Value=""ParentValue"" />
|
||||
@functions {
|
||||
public int ParentValue { get; set; } = 42;
|
||||
}");
|
||||
|
||||
var assembly = CompileToAssembly(generated, throwOnFailure: false);
|
||||
// This has some errors
|
||||
Assert.Collection(
|
||||
assembly.Diagnostics.OrderBy(d => d.Id),
|
||||
d => Assert.Equal("CS0029", d.Id),
|
||||
d => Assert.Equal("CS1662", d.Id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BindToComponent_SpecifiesValueAndExpression_Generic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<T> : ComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
T SomeParam { get; set; }
|
||||
|
||||
[Parameter]
|
||||
Action<T> SomeParamChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
Expression<Func<T>> SomeParamExpression { get; set; }
|
||||
}
|
||||
}"));
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MyComponent bind-SomeParam=""ParentValue"" />
|
||||
@functions {
|
||||
public DateTime ParentValue { get; set; } = DateTime.Now;
|
||||
}");
|
||||
|
||||
// Assert
|
||||
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
|
||||
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
|
||||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BindToElement_WritesAttributes()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// <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 class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
global::System.Object __typeHelper = "*, TestAssembly";
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
))();
|
||||
}
|
||||
#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(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
__o = Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck<System.Int32>(Microsoft.AspNetCore.Components.BindMethods.GetValue(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
ParentValue
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
));
|
||||
__o = new System.Action<System.Int32>(
|
||||
__value => ParentValue = __value);
|
||||
__o = Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck<System.Linq.Expressions.Expression<System.Func<System.Int32>>>(() => ParentValue);
|
||||
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment)((builder2) => {
|
||||
}
|
||||
));
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
|
||||
public int ParentValue { get; set; } = 42;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
|
@ -0,0 +1,39 @@
|
|||
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 - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
|
||||
DesignTimeDirective -
|
||||
DirectiveToken - (14:0,14 [36] ) - "*, Microsoft.AspNetCore.Components"
|
||||
DirectiveToken - (14:0,14 [9] ) - "*, Test"
|
||||
DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly
|
||||
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
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
|
||||
HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
Component - (31:1,0 [40] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
|
||||
ComponentAttribute - (56:1,25 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindMethods.GetValue(
|
||||
IntermediateToken - (56:1,25 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
|
||||
IntermediateToken - - CSharp - )
|
||||
ComponentAttribute - (56:1,25 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - __value => ParentValue = __value
|
||||
ComponentAttribute - (56:1,25 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueExpression - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - () => ParentValue
|
||||
HtmlContent - (71:1,40 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (71:1,40 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpCode - (85:2,12 [50] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (85:2,12 [50] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n
|
|
@ -0,0 +1,19 @@
|
|||
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|*, TestAssembly|
|
||||
Generated Location: (554:16,38 [15] )
|
||||
|*, TestAssembly|
|
||||
|
||||
Source Location: (56:1,25 [11] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|ParentValue|
|
||||
Generated Location: (1236:33,25 [11] )
|
||||
|ParentValue|
|
||||
|
||||
Source Location: (85:2,12 [50] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|
|
||||
public int ParentValue { get; set; } = 42;
|
||||
|
|
||||
Generated Location: (1819:47,12 [50] )
|
||||
|
|
||||
public int ParentValue { get; set; } = 42;
|
||||
|
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
// <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 class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
global::System.Object __typeHelper = "*, TestAssembly";
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
))();
|
||||
}
|
||||
#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(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
__Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0(builder, -1, -1, Microsoft.AspNetCore.Components.BindMethods.GetValue(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
ParentValue
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
), -1,
|
||||
__value => ParentValue = __value, -1, () => ParentValue);
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
|
||||
public DateTime ParentValue { get; set; } = DateTime.Now;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
namespace __Blazor.Test.TestComponent
|
||||
{
|
||||
#line hidden
|
||||
internal static class TypeInference
|
||||
{
|
||||
public static void CreateMyComponent_0<T>(global::Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, int seq, int __seq0, T __arg0, int __seq1, global::System.Action<T> __arg1, int __seq2, global::System.Linq.Expressions.Expression<global::System.Func<T>> __arg2)
|
||||
{
|
||||
builder.OpenComponent<global::Test.MyComponent<T>>(seq);
|
||||
builder.AddAttribute(__seq0, "SomeParam", __arg0);
|
||||
builder.AddAttribute(__seq1, "SomeParamChanged", __arg1);
|
||||
builder.AddAttribute(__seq2, "SomeParamExpression", __arg2);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
|
@ -0,0 +1,42 @@
|
|||
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 - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
|
||||
DesignTimeDirective -
|
||||
DirectiveToken - (14:0,14 [36] ) - "*, Microsoft.AspNetCore.Components"
|
||||
DirectiveToken - (14:0,14 [9] ) - "*, Test"
|
||||
DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly
|
||||
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
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
|
||||
HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
Component - (31:1,0 [44] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
|
||||
ComponentAttribute - (60:1,29 [11] x:\dir\subdir\Test\TestComponent.cshtml) - SomeParam - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindMethods.GetValue(
|
||||
IntermediateToken - (60:1,29 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
|
||||
IntermediateToken - - CSharp - )
|
||||
ComponentAttribute - (60:1,29 [11] x:\dir\subdir\Test\TestComponent.cshtml) - SomeParamChanged - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - __value => ParentValue = __value
|
||||
ComponentAttribute - (60:1,29 [11] x:\dir\subdir\Test\TestComponent.cshtml) - SomeParamExpression - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - () => ParentValue
|
||||
HtmlContent - (75:1,44 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (75:1,44 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpCode - (89:2,12 [65] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (89:2,12 [65] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public DateTime ParentValue { get; set; } = DateTime.Now;\n
|
||||
NamespaceDeclaration - - __Blazor.Test.TestComponent
|
||||
ClassDeclaration - - internal static - TypeInference - -
|
||||
ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateMyComponent_0
|
|
@ -0,0 +1,19 @@
|
|||
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|*, TestAssembly|
|
||||
Generated Location: (554:16,38 [15] )
|
||||
|*, TestAssembly|
|
||||
|
||||
Source Location: (60:1,29 [11] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|ParentValue|
|
||||
Generated Location: (1242:33,29 [11] )
|
||||
|ParentValue|
|
||||
|
||||
Source Location: (89:2,12 [65] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|
|
||||
public DateTime ParentValue { get; set; } = DateTime.Now;
|
||||
|
|
||||
Generated Location: (1490:42,12 [65] )
|
||||
|
|
||||
public DateTime ParentValue { get; set; } = DateTime.Now;
|
||||
|
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// <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 class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
builder.OpenComponent<Test.MyComponent>(0);
|
||||
builder.AddAttribute(1, "Value", Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck<System.Int32>(Microsoft.AspNetCore.Components.BindMethods.GetValue(ParentValue)));
|
||||
builder.AddAttribute(2, "ValueChanged", new System.Action<System.Int32>(__value => ParentValue = __value));
|
||||
builder.AddAttribute(3, "ValueExpression", Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck<System.Linq.Expressions.Expression<System.Func<System.Int32>>>(() => ParentValue));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
|
||||
public int ParentValue { get; set; } = 42;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
|
@ -0,0 +1,25 @@
|
|||
Document -
|
||||
NamespaceDeclaration - - Test
|
||||
UsingDirective - (3:1,1 [14] ) - System
|
||||
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
|
||||
UsingDirective - (53:3,1 [19] ) - System.Linq
|
||||
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
|
||||
UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
|
||||
MethodDeclaration - - protected override - void - BuildRenderTree
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
|
||||
Component - (31:1,0 [40] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
|
||||
ComponentAttribute - (56:1,25 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Value - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindMethods.GetValue(
|
||||
IntermediateToken - (56:1,25 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
|
||||
IntermediateToken - - CSharp - )
|
||||
ComponentAttribute - (56:1,25 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueChanged - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - __value => ParentValue = __value
|
||||
ComponentAttribute - (56:1,25 [11] x:\dir\subdir\Test\TestComponent.cshtml) - ValueExpression - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - () => ParentValue
|
||||
CSharpCode - (85:2,12 [50] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (85:2,12 [50] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public int ParentValue { get; set; } = 42;\n
|
|
@ -0,0 +1,9 @@
|
|||
Source Location: (85:2,12 [50] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|
|
||||
public int ParentValue { get; set; } = 42;
|
||||
|
|
||||
Generated Location: (1261:24,12 [50] )
|
||||
|
|
||||
public int ParentValue { get; set; } = 42;
|
||||
|
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// <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 class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
__Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0(builder, 0, 1, Microsoft.AspNetCore.Components.BindMethods.GetValue(ParentValue), 2, __value => ParentValue = __value, 3, () => ParentValue);
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
|
||||
public DateTime ParentValue { get; set; } = DateTime.Now;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
namespace __Blazor.Test.TestComponent
|
||||
{
|
||||
#line hidden
|
||||
internal static class TypeInference
|
||||
{
|
||||
public static void CreateMyComponent_0<T>(global::Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, int seq, int __seq0, T __arg0, int __seq1, global::System.Action<T> __arg1, int __seq2, global::System.Linq.Expressions.Expression<global::System.Func<T>> __arg2)
|
||||
{
|
||||
builder.OpenComponent<global::Test.MyComponent<T>>(seq);
|
||||
builder.AddAttribute(__seq0, "SomeParam", __arg0);
|
||||
builder.AddAttribute(__seq1, "SomeParamChanged", __arg1);
|
||||
builder.AddAttribute(__seq2, "SomeParamExpression", __arg2);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
|
@ -0,0 +1,28 @@
|
|||
Document -
|
||||
NamespaceDeclaration - - Test
|
||||
UsingDirective - (3:1,1 [14] ) - System
|
||||
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
|
||||
UsingDirective - (53:3,1 [19] ) - System.Linq
|
||||
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
|
||||
UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
|
||||
MethodDeclaration - - protected override - void - BuildRenderTree
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
|
||||
Component - (31:1,0 [44] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
|
||||
ComponentAttribute - (60:1,29 [11] x:\dir\subdir\Test\TestComponent.cshtml) - SomeParam - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindMethods.GetValue(
|
||||
IntermediateToken - (60:1,29 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
|
||||
IntermediateToken - - CSharp - )
|
||||
ComponentAttribute - (60:1,29 [11] x:\dir\subdir\Test\TestComponent.cshtml) - SomeParamChanged - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - __value => ParentValue = __value
|
||||
ComponentAttribute - (60:1,29 [11] x:\dir\subdir\Test\TestComponent.cshtml) - SomeParamExpression - AttributeStructure.DoubleQuotes
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - () => ParentValue
|
||||
CSharpCode - (89:2,12 [65] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (89:2,12 [65] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public DateTime ParentValue { get; set; } = DateTime.Now;\n
|
||||
NamespaceDeclaration - - __Blazor.Test.TestComponent
|
||||
ClassDeclaration - - internal static - TypeInference - -
|
||||
ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateMyComponent_0
|
|
@ -0,0 +1,9 @@
|
|||
Source Location: (89:2,12 [65] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|
|
||||
public DateTime ParentValue { get; set; } = DateTime.Now;
|
||||
|
|
||||
Generated Location: (878:20,12 [65] )
|
||||
|
|
||||
public DateTime ParentValue { get; set; } = DateTime.Now;
|
||||
|
|
||||
|
|
@ -36,6 +36,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
|||
{
|
||||
typeof(System.Runtime.AssemblyTargetedPatchBandAttribute).Assembly, // System.Runtime
|
||||
typeof(Enumerable).Assembly, // Other .NET fundamental types
|
||||
typeof(System.Linq.Expressions.Expression).Assembly,
|
||||
typeof(ComponentBase).Assembly,
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
// Arrange
|
||||
var compilation = BaseCompilation.AddSyntaxTrees(Parse(@"
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Test
|
||||
|
@ -31,6 +32,9 @@ namespace Test
|
|||
|
||||
[Parameter]
|
||||
Action<string> MyPropertyChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
Expression<Func<string>> MyPropertyExpression { get; set; }
|
||||
}
|
||||
}
|
||||
"));
|
||||
|
@ -69,6 +73,7 @@ namespace Test
|
|||
|
||||
Assert.Equal("MyProperty", bind.Metadata[BlazorMetadata.Bind.ValueAttribute]);
|
||||
Assert.Equal("MyPropertyChanged", bind.Metadata[BlazorMetadata.Bind.ChangeAttribute]);
|
||||
Assert.Equal("MyPropertyExpression", bind.Metadata[BlazorMetadata.Bind.ExpressionAttribute]);
|
||||
|
||||
Assert.Equal(
|
||||
"Binds the provided expression to the 'MyProperty' property and a change event " +
|
||||
|
|
Загрузка…
Ссылка в новой задаче