Add support for generic-typed components (#1417)
* Add the ability to discover generic types/properties * Add @typeparam directive Adds the ability to declare a generic-typed component using Razor. * Add a 'type parameter' property to generic components * Adds the ability to consume generic-typed components
This commit is contained in:
parent
b99d805bc0
commit
354752cf16
|
|
@ -311,6 +311,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
BoundAttribute = valueAttribute, // Might be null if it doesn't match a component attribute
|
||||
PropertyName = valueAttribute?.GetPropertyName(),
|
||||
TagHelper = valueAttribute == null ? null : node.TagHelper,
|
||||
TypeName = valueAttribute?.IsWeaklyTyped() == false ? valueAttribute.TypeName : null,
|
||||
};
|
||||
|
||||
valueNode.Children.Clear();
|
||||
|
|
@ -326,6 +327,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
BoundAttribute = changeAttribute, // Might be null if it doesn't match a component attribute
|
||||
PropertyName = changeAttribute?.GetPropertyName(),
|
||||
TagHelper = changeAttribute == null ? null : node.TagHelper,
|
||||
TypeName = changeAttribute?.IsWeaklyTyped() == false ? changeAttribute.TypeName : null,
|
||||
};
|
||||
|
||||
changeNode.Children.Clear();
|
||||
|
|
|
|||
|
|
@ -343,6 +343,11 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
foreach (var typeArgument in node.TypeArguments)
|
||||
{
|
||||
context.RenderNode(typeArgument);
|
||||
}
|
||||
|
||||
foreach (var attribute in node.Attributes)
|
||||
{
|
||||
context.RenderNode(attribute);
|
||||
|
|
@ -363,7 +368,10 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
// Consider what would happen if the user's cursor was inside the element. At
|
||||
// design -time we want to render an empty lambda to provide proper scoping
|
||||
// for any code that the user types.
|
||||
context.RenderNode(new ComponentChildContentIntermediateNode());
|
||||
context.RenderNode(new ComponentChildContentIntermediateNode()
|
||||
{
|
||||
TypeName = BlazorApi.RenderFragment.FullTypeName,
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var capture in node.Captures)
|
||||
|
|
@ -425,7 +433,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
context.CodeWriter.Write(DesignTimeVariable);
|
||||
context.CodeWriter.Write(" = ");
|
||||
context.CodeWriter.Write("new ");
|
||||
context.CodeWriter.Write(node.BoundAttribute.TypeName);
|
||||
context.CodeWriter.Write(node.TypeName);
|
||||
context.CodeWriter.Write("(");
|
||||
context.CodeWriter.WriteLine();
|
||||
|
||||
|
|
@ -448,7 +456,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
{
|
||||
context.CodeWriter.Write(BlazorApi.RuntimeHelpers.TypeCheck);
|
||||
context.CodeWriter.Write("<");
|
||||
context.CodeWriter.Write(node.BoundAttribute.TypeName);
|
||||
context.CodeWriter.Write(node.TypeName);
|
||||
context.CodeWriter.Write(">");
|
||||
context.CodeWriter.Write("(");
|
||||
}
|
||||
|
|
@ -504,6 +512,41 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
_scopeStack.CloseScope(context);
|
||||
}
|
||||
|
||||
public override void WriteComponentTypeArgument(CodeRenderingContext context, ComponentTypeArgumentExtensionNode node)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
// At design type we want write the equivalent of:
|
||||
//
|
||||
// __o = typeof(TItem);
|
||||
context.CodeWriter.Write(DesignTimeVariable);
|
||||
context.CodeWriter.Write(" = ");
|
||||
context.CodeWriter.Write("typeof(");
|
||||
|
||||
var tokens = GetCSharpTokens(node);
|
||||
for (var i = 0; i < tokens.Count; i++)
|
||||
{
|
||||
WriteCSharpToken(context, tokens[i]);
|
||||
}
|
||||
|
||||
context.CodeWriter.Write(");");
|
||||
context.CodeWriter.WriteLine();
|
||||
|
||||
IReadOnlyList<IntermediateToken> GetCSharpTokens(ComponentTypeArgumentExtensionNode arg)
|
||||
{
|
||||
// We generally expect all children to be CSharp, this is here just in case.
|
||||
return arg.FindDescendantNodes<IntermediateToken>().Where(t => t.IsCSharp).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteTemplate(CodeRenderingContext context, TemplateIntermediateNode node)
|
||||
{
|
||||
if (context == null)
|
||||
|
|
|
|||
|
|
@ -263,5 +263,23 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
childContent2.AttributeName,
|
||||
component2.TagName);
|
||||
}
|
||||
|
||||
public static readonly RazorDiagnosticDescriptor GenericComponentMissingTypeArgument =
|
||||
new RazorDiagnosticDescriptor(
|
||||
"BL10000",
|
||||
() => "The component '{0}' is missing required type arguments. Specify the missing types using the attributes: {1}.",
|
||||
RazorDiagnosticSeverity.Error);
|
||||
|
||||
public static RazorDiagnostic Create_GenericComponentMissingTypeArgument(
|
||||
SourceSpan? source,
|
||||
ComponentExtensionNode component,
|
||||
IEnumerable<BoundAttributeDescriptor> attributes)
|
||||
{
|
||||
Debug.Assert(component.Component.IsGenericTypedComponent());
|
||||
|
||||
var attributesText = string.Join(", ", attributes.Select(a => $"'{a.Name}'"));
|
||||
return RazorDiagnostic.Create(GenericComponentMissingTypeArgument, source ?? SourceSpan.Undefined, component.TagName, attributesText);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
InjectDirective.Register(builder);
|
||||
LayoutDirective.Register(builder);
|
||||
PageDirective.Register(builder);
|
||||
TypeParamDirective.Register(builder);
|
||||
|
||||
builder.Features.Remove(builder.Features.OfType<IImportProjectFeature>().Single());
|
||||
builder.Features.Add(new BlazorImportProjectFeature());
|
||||
|
|
@ -82,6 +83,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
builder.Features.Add(new RefLoweringPass());
|
||||
builder.Features.Add(new BindLoweringPass());
|
||||
builder.Features.Add(new TemplateDiagnosticPass());
|
||||
builder.Features.Add(new GenericComponentPass());
|
||||
builder.Features.Add(new ChildContentDiagnosticPass());
|
||||
builder.Features.Add(new HtmlBlockPass());
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
public static readonly string RuntimeName = "Blazor.IComponent";
|
||||
|
||||
public readonly static string TagHelperKind = "Blazor.Component";
|
||||
|
||||
public readonly static string GenericTypedKey = "Blazor.GenericTyped";
|
||||
|
||||
public readonly static string TypeParameterKey = "Blazor.TypeParameter";
|
||||
}
|
||||
|
||||
public static class EventHandler
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
|
||||
public abstract void WriteComponentChildContent(CodeRenderingContext context, ComponentChildContentIntermediateNode node);
|
||||
|
||||
public abstract void WriteComponentTypeArgument(CodeRenderingContext context, ComponentTypeArgumentExtensionNode node);
|
||||
|
||||
public abstract void WriteHtmlElement(CodeRenderingContext context, HtmlElementIntermediateNode node);
|
||||
|
||||
public abstract void WriteHtmlBlock(CodeRenderingContext context, HtmlBlockIntermediateNode node);
|
||||
|
|
|
|||
|
|
@ -307,6 +307,9 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
context.CodeWriter.Write(");");
|
||||
context.CodeWriter.WriteLine();
|
||||
|
||||
// We can skip type arguments during runtime codegen, they are handled in the
|
||||
// type/parameter declarations.
|
||||
|
||||
foreach (var attribute in node.Attributes)
|
||||
{
|
||||
context.RenderNode(attribute);
|
||||
|
|
@ -322,7 +325,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
context.RenderNode(capture);
|
||||
}
|
||||
|
||||
// builder.OpenComponent<TComponent>(42);
|
||||
// builder.CloseComponent();
|
||||
context.CodeWriter.Write(_scopeStack.BuilderVarName);
|
||||
context.CodeWriter.Write(".");
|
||||
context.CodeWriter.Write(BlazorApi.RenderTreeBuilder.CloseComponent);
|
||||
|
|
@ -376,7 +379,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
(node.BoundAttribute?.IsChildContentProperty() ?? false))
|
||||
{
|
||||
context.CodeWriter.Write("new ");
|
||||
context.CodeWriter.Write(node.BoundAttribute.TypeName);
|
||||
context.CodeWriter.Write(node.TypeName);
|
||||
context.CodeWriter.Write("(");
|
||||
|
||||
for (var i = 0; i < tokens.Count; i++)
|
||||
|
|
@ -392,7 +395,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
{
|
||||
context.CodeWriter.Write(BlazorApi.RuntimeHelpers.TypeCheck);
|
||||
context.CodeWriter.Write("<");
|
||||
context.CodeWriter.Write(node.BoundAttribute.TypeName);
|
||||
context.CodeWriter.Write(node.TypeName);
|
||||
context.CodeWriter.Write(">");
|
||||
context.CodeWriter.Write("(");
|
||||
}
|
||||
|
|
@ -454,6 +457,12 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
_scopeStack.CloseScope(context);
|
||||
}
|
||||
|
||||
public override void WriteComponentTypeArgument(CodeRenderingContext context, ComponentTypeArgumentExtensionNode node)
|
||||
{
|
||||
// We can skip type arguments during runtime codegen, they are handled in the
|
||||
// type/parameter declarations.
|
||||
}
|
||||
|
||||
public override void WriteTemplate(CodeRenderingContext context, TemplateIntermediateNode node)
|
||||
{
|
||||
if (context == null)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
|
@ -49,6 +49,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
PropertyName = propertyNode.BoundAttribute.GetPropertyName();
|
||||
Source = propertyNode.Source;
|
||||
TagHelper = propertyNode.TagHelper;
|
||||
TypeName = propertyNode.BoundAttribute.IsWeaklyTyped() ? null : propertyNode.BoundAttribute.TypeName;
|
||||
|
||||
for (var i = 0; i < propertyNode.Children.Count; i++)
|
||||
{
|
||||
|
|
@ -74,6 +75,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
PropertyName = attributeNode.BoundAttribute.GetPropertyName();
|
||||
Source = attributeNode.Source;
|
||||
TagHelper = attributeNode.TagHelper;
|
||||
TypeName = attributeNode.BoundAttribute.IsWeaklyTyped() ? null : attributeNode.BoundAttribute.TypeName;
|
||||
|
||||
for (var i = 0; i < attributeNode.Children.Count; i++)
|
||||
{
|
||||
|
|
@ -98,6 +100,8 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
|
||||
public TagHelperDescriptor TagHelper { get; set; }
|
||||
|
||||
public string TypeName { get; set; }
|
||||
|
||||
public override void Accept(IntermediateNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
|
||||
public string ParameterName { get; set; } = "context";
|
||||
|
||||
public string TypeName => BoundAttribute?.TypeName == null ? BlazorApi.RenderFragment.FullTypeName : BoundAttribute.TypeName;
|
||||
public string TypeName { get; set; }
|
||||
|
||||
public override void Accept(IntermediateNodeVisitor visitor)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
|
@ -91,6 +92,19 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
@class.Modifiers.Clear();
|
||||
@class.Modifiers.Add("public");
|
||||
|
||||
var documentNode = codeDocument.GetDocumentIntermediateNode();
|
||||
var typeParamReferences = documentNode.FindDirectiveReferences(TypeParamDirective.Directive);
|
||||
for (var i = 0; i < typeParamReferences.Count; i++)
|
||||
{
|
||||
var typeParamNode = (DirectiveIntermediateNode)typeParamReferences[i].Node;
|
||||
if (typeParamNode.HasDiagnostics)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@class.TypeParameters.Add(new TypeParameter() { ParameterName = typeParamNode.Tokens.First().Content, });
|
||||
}
|
||||
|
||||
method.ReturnType = "void";
|
||||
method.MethodName = BlazorApi.BlazorComponent.BuildRenderTree;
|
||||
method.Modifiers.Clear();
|
||||
|
|
|
|||
|
|
@ -23,9 +23,11 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
|
||||
public TagHelperDescriptor Component { get; set; }
|
||||
|
||||
public string TagName { get; set; }
|
||||
public IEnumerable<ComponentTypeArgumentExtensionNode> TypeArguments => Children.OfType<ComponentTypeArgumentExtensionNode>();
|
||||
|
||||
public string TypeName => Component?.GetTypeName();
|
||||
public string TagName { get; set; }
|
||||
|
||||
public string TypeName { get; set; }
|
||||
|
||||
public override void Accept(IntermediateNodeVisitor visitor)
|
||||
{
|
||||
|
|
@ -76,6 +78,13 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
builder.Append("=\"...\"");
|
||||
}
|
||||
|
||||
foreach (var typeArgument in TypeArguments)
|
||||
{
|
||||
builder.Append(" ");
|
||||
builder.Append(typeArgument.TypeParameterName);
|
||||
builder.Append("=\"...\"");
|
||||
}
|
||||
|
||||
builder.Append(">");
|
||||
builder.Append(ChildContents.Any() ? "..." : string.Empty);
|
||||
builder.Append("</");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Blazor.Shared;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
|
@ -70,6 +69,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
Component = tagHelper,
|
||||
Source = node.Source,
|
||||
TagName = node.TagName,
|
||||
TypeName = tagHelper.GetTypeName(),
|
||||
};
|
||||
|
||||
for (var i = 0; i < node.Diagnostics.Count; i++)
|
||||
|
|
@ -214,6 +214,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
{
|
||||
BoundAttribute = attribute,
|
||||
Source = source,
|
||||
TypeName = attribute?.TypeName ?? BlazorApi.RenderFragment.FullTypeName,
|
||||
};
|
||||
|
||||
// There are two cases here:
|
||||
|
|
@ -332,7 +333,21 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
// Each 'tag helper property' belongs to a specific tag helper. We want to handle
|
||||
// the cases for components, but leave others alone. This allows our other passes
|
||||
// to handle those cases.
|
||||
_children.Add(node.TagHelper.IsComponentTagHelper() ? (IntermediateNode)new ComponentAttributeExtensionNode(node) : node);
|
||||
if (!node.TagHelper.IsComponentTagHelper())
|
||||
{
|
||||
_children.Add(node);
|
||||
return;
|
||||
}
|
||||
|
||||
// Another special case here - this might be a type argument. These don't represent 'real' parameters
|
||||
// that get passed to the component, it needs special code generation support.
|
||||
if (node.TagHelper.IsGenericTypedComponent() && node.BoundAttribute.IsTypeParameterProperty())
|
||||
{
|
||||
_children.Add(new ComponentTypeArgumentExtensionNode(node));
|
||||
return;
|
||||
}
|
||||
|
||||
_children.Add(new ComponentAttributeExtensionNode(node));
|
||||
}
|
||||
|
||||
public override void VisitDefault(IntermediateNode node)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Blazor.Shared;
|
||||
|
|
@ -95,6 +96,20 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
// Razor ITagHelper runtime.
|
||||
builder.Metadata[TagHelperMetadata.Runtime.Name] = BlazorMetadata.Component.RuntimeName;
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
builder.Metadata[BlazorMetadata.Component.GenericTypedKey] = bool.TrueString;
|
||||
|
||||
for (var i = 0; i < type.TypeArguments.Length; i++)
|
||||
{
|
||||
var typeParameter = type.TypeArguments[i] as ITypeParameterSymbol;
|
||||
if (typeParameter != null)
|
||||
{
|
||||
CreateTypeParameterProperty(builder, typeParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var xml = type.GetDocumentationCommentXml();
|
||||
if (!string.IsNullOrEmpty(xml))
|
||||
{
|
||||
|
|
@ -111,33 +126,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
continue;
|
||||
}
|
||||
|
||||
builder.BindAttribute(pb =>
|
||||
{
|
||||
pb.Name = property.property.Name;
|
||||
pb.TypeName = property.property.Type.ToDisplayString(FullNameTypeDisplayFormat);
|
||||
pb.SetPropertyName(property.property.Name);
|
||||
|
||||
if (property.kind == PropertyKind.Enum)
|
||||
{
|
||||
pb.IsEnum = true;
|
||||
}
|
||||
|
||||
if (property.kind == PropertyKind.ChildContent)
|
||||
{
|
||||
pb.Metadata.Add(BlazorMetadata.Component.ChildContentKey, bool.TrueString);
|
||||
}
|
||||
|
||||
if (property.kind == PropertyKind.Delegate)
|
||||
{
|
||||
pb.Metadata.Add(BlazorMetadata.Component.DelegateSignatureKey, bool.TrueString);
|
||||
}
|
||||
|
||||
xml = property.property.GetDocumentationCommentXml();
|
||||
if (!string.IsNullOrEmpty(xml))
|
||||
{
|
||||
pb.Documentation = xml;
|
||||
}
|
||||
});
|
||||
CreateProperty(builder, property.property, property.kind);
|
||||
}
|
||||
|
||||
var descriptor = builder.Build();
|
||||
|
|
@ -145,6 +134,97 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
return descriptor;
|
||||
}
|
||||
|
||||
private void CreateProperty(TagHelperDescriptorBuilder builder, IPropertySymbol property, PropertyKind kind)
|
||||
{
|
||||
builder.BindAttribute(pb =>
|
||||
{
|
||||
pb.Name = property.Name;
|
||||
pb.TypeName = property.Type.ToDisplayString(FullNameTypeDisplayFormat);
|
||||
pb.SetPropertyName(property.Name);
|
||||
|
||||
if (kind == PropertyKind.Enum)
|
||||
{
|
||||
pb.IsEnum = true;
|
||||
}
|
||||
|
||||
if (kind == PropertyKind.ChildContent)
|
||||
{
|
||||
pb.Metadata.Add(BlazorMetadata.Component.ChildContentKey, bool.TrueString);
|
||||
}
|
||||
|
||||
if (kind == PropertyKind.Delegate)
|
||||
{
|
||||
pb.Metadata.Add(BlazorMetadata.Component.DelegateSignatureKey, bool.TrueString);
|
||||
}
|
||||
|
||||
if (HasTypeParameter(property.Type))
|
||||
{
|
||||
pb.Metadata.Add(BlazorMetadata.Component.GenericTypedKey, bool.TrueString);
|
||||
}
|
||||
|
||||
var xml = property.GetDocumentationCommentXml();
|
||||
if (!string.IsNullOrEmpty(xml))
|
||||
{
|
||||
pb.Documentation = xml;
|
||||
}
|
||||
});
|
||||
|
||||
bool HasTypeParameter(ITypeSymbol type)
|
||||
{
|
||||
if (type is ITypeParameterSymbol)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// We need to check for cases like:
|
||||
// [Parameter] List<T> MyProperty { get; set; }
|
||||
// AND
|
||||
// [Parameter] List<string> MyProperty { get; set; }
|
||||
//
|
||||
// We need to inspect the type arguments to tell the difference between a property that
|
||||
// uses the containing class' type parameter(s) and a vanilla usage of generic types like
|
||||
// List<> and Dictionary<,>
|
||||
//
|
||||
// Since we need to handle cases like RenderFragment<List<T>>, this check must be recursive.
|
||||
if (type is INamedTypeSymbol namedType && namedType.IsGenericType)
|
||||
{
|
||||
var typeArguments = namedType.TypeArguments;
|
||||
for (var i = 0; i < typeArguments.Length; i++)
|
||||
{
|
||||
if (HasTypeParameter(typeArguments[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Another case to handle - if the type being inspected is a nested type
|
||||
// inside a generic containing class. The common usage for this would be a case
|
||||
// where a generic templated component defines a 'context' nested class.
|
||||
if (namedType.ContainingType != null && HasTypeParameter(namedType.ContainingType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateTypeParameterProperty(TagHelperDescriptorBuilder builder, ITypeSymbol typeParameter)
|
||||
{
|
||||
builder.BindAttribute(pb =>
|
||||
{
|
||||
pb.DisplayName = typeParameter.Name;
|
||||
pb.Name = typeParameter.Name;
|
||||
pb.TypeName = typeof(Type).FullName;
|
||||
pb.SetPropertyName(typeParameter.Name);
|
||||
|
||||
pb.Metadata[BlazorMetadata.Component.TypeParameterKey] = bool.TrueString;
|
||||
|
||||
pb.Documentation = string.Format(Resources.ComponentTypeParameter_Documentation, typeParameter.Name, builder.Name);
|
||||
});
|
||||
}
|
||||
|
||||
private TagHelperDescriptor CreateChildContentDescriptor(BlazorSymbols symbols, TagHelperDescriptor component, BoundAttributeDescriptor attribute)
|
||||
{
|
||||
var typeName = component.GetTypeName() + "." + attribute.Name;
|
||||
|
|
@ -396,7 +476,6 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
return
|
||||
symbol.DeclaredAccessibility == Accessibility.Public &&
|
||||
!symbol.IsAbstract &&
|
||||
!symbol.IsGenericType &&
|
||||
symbol.AllInterfaces.Contains(_symbols.IComponent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||
{
|
||||
internal class ComponentTypeArgumentExtensionNode : ExtensionIntermediateNode
|
||||
{
|
||||
public ComponentTypeArgumentExtensionNode(TagHelperPropertyIntermediateNode propertyNode)
|
||||
{
|
||||
if (propertyNode == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyNode));
|
||||
}
|
||||
|
||||
BoundAttribute = propertyNode.BoundAttribute;
|
||||
Source = propertyNode.Source;
|
||||
TagHelper = propertyNode.TagHelper;
|
||||
|
||||
for (var i = 0; i < propertyNode.Children.Count; i++)
|
||||
{
|
||||
Children.Add(propertyNode.Children[i]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < propertyNode.Diagnostics.Count; i++)
|
||||
{
|
||||
Diagnostics.Add(propertyNode.Diagnostics[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public override IntermediateNodeCollection Children { get; } = new IntermediateNodeCollection();
|
||||
|
||||
public BoundAttributeDescriptor BoundAttribute { get; set; }
|
||||
|
||||
public string TypeParameterName => BoundAttribute.Name;
|
||||
|
||||
public TagHelperDescriptor TagHelper { get; set; }
|
||||
|
||||
public override void Accept(IntermediateNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(visitor));
|
||||
}
|
||||
|
||||
AcceptExtensionNode<ComponentTypeArgumentExtensionNode>(this, visitor);
|
||||
}
|
||||
|
||||
public override void WriteNode(CodeTarget target, CodeRenderingContext context)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(target));
|
||||
}
|
||||
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var writer = (BlazorNodeWriter)context.NodeWriter;
|
||||
writer.WriteComponentTypeArgument(context, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||
{
|
||||
// This pass:
|
||||
// 1. Adds diagnostics for missing generic type arguments
|
||||
// 2. Rewrites the type name of the component to substitute generic type arguments
|
||||
// 3. Rewrites the type names of parameters/child content to substitute generic type arguments
|
||||
internal class GenericComponentPass : IntermediateNodePassBase, IRazorOptimizationPass
|
||||
{
|
||||
// Runs after components/eventhandlers/ref/bind/templates. We want to validate every component
|
||||
// and it's usage of ChildContent.
|
||||
public override int Order => 160;
|
||||
|
||||
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||
{
|
||||
var visitor = new Visitor();
|
||||
visitor.Visit(documentNode);
|
||||
}
|
||||
|
||||
|
||||
private class Visitor : IntermediateNodeWalker, IExtensionIntermediateNodeVisitor<ComponentExtensionNode>
|
||||
{
|
||||
public void VisitExtension(ComponentExtensionNode node)
|
||||
{
|
||||
if (node.Component.IsGenericTypedComponent())
|
||||
{
|
||||
// Not generic, ignore.
|
||||
Process(node);
|
||||
}
|
||||
|
||||
base.VisitDefault(node);
|
||||
}
|
||||
|
||||
private void Process(ComponentExtensionNode node)
|
||||
{
|
||||
// First collect all of the information we have about each type parameter
|
||||
var bindings = new Dictionary<string, GenericTypeNameRewriter.Binding>();
|
||||
foreach (var attribute in node.Component.GetTypeParameters())
|
||||
{
|
||||
bindings.Add(attribute.Name, new GenericTypeNameRewriter.Binding() { Attribute = attribute, });
|
||||
}
|
||||
|
||||
foreach (var typeArgumentNode in node.TypeArguments)
|
||||
{
|
||||
var binding = bindings[typeArgumentNode.TypeParameterName];
|
||||
binding.Node = typeArgumentNode;
|
||||
binding.Content = GetContent(typeArgumentNode);
|
||||
}
|
||||
|
||||
// Right now we don't have type inference, so all type arguments are required.
|
||||
var missing = new List<BoundAttributeDescriptor>();
|
||||
foreach (var binding in bindings)
|
||||
{
|
||||
if (binding.Value.Node == null || string.IsNullOrWhiteSpace(binding.Value.Content))
|
||||
{
|
||||
missing.Add(binding.Value.Attribute);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing.Count > 0)
|
||||
{
|
||||
// We add our own error for this because its likely the user will see other errors due
|
||||
// to incorrect codegen without the types. Our errors message will pretty clearly indicate
|
||||
// what to do, whereas the other errors might be confusing.
|
||||
node.Diagnostics.Add(BlazorDiagnosticFactory.Create_GenericComponentMissingTypeArgument(node.Source, node, missing));
|
||||
}
|
||||
|
||||
var rewriter = new GenericTypeNameRewriter(bindings);
|
||||
|
||||
// Rewrite the component type name
|
||||
node.TypeName = RewriteTypeName(rewriter, node.TypeName);
|
||||
|
||||
foreach (var attribute in node.Attributes)
|
||||
{
|
||||
if (attribute.BoundAttribute?.IsGenericTypedProperty() ?? false && attribute.TypeName != null)
|
||||
{
|
||||
// If we know the type name, then replace any generic type parameter inside it with
|
||||
// the known types.
|
||||
attribute.TypeName = RewriteTypeName(rewriter, attribute.TypeName);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var childContent in node.ChildContents)
|
||||
{
|
||||
if (childContent.BoundAttribute?.IsGenericTypedProperty() ?? false && childContent.TypeName != null)
|
||||
{
|
||||
// If we know the type name, then replace any generic type parameter inside it with
|
||||
// the known types.
|
||||
childContent.TypeName = RewriteTypeName(rewriter, childContent.TypeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string RewriteTypeName(GenericTypeNameRewriter rewriter, string typeName)
|
||||
{
|
||||
var parsed = SyntaxFactory.ParseTypeName(typeName);
|
||||
var rewritten = (TypeSyntax)rewriter.Visit(parsed);
|
||||
return rewritten.ToFullString();
|
||||
}
|
||||
|
||||
private string GetContent(ComponentTypeArgumentExtensionNode node)
|
||||
{
|
||||
return string.Join(string.Empty, node.FindDescendantNodes<IntermediateToken>().Where(t => t.IsCSharp).Select(t => t.Content));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||
{
|
||||
internal class GenericTypeNameRewriter : CSharpSyntaxRewriter
|
||||
{
|
||||
private readonly Dictionary<string, Binding> _bindings;
|
||||
|
||||
public GenericTypeNameRewriter(Dictionary<string, Binding> bindings)
|
||||
{
|
||||
_bindings = bindings;
|
||||
}
|
||||
|
||||
public override SyntaxNode Visit(SyntaxNode node)
|
||||
{
|
||||
// We can handle a single IdentifierNameSyntax at the top level (like 'TItem)
|
||||
// OR a GenericNameSyntax recursively (like `List<T>`)
|
||||
if (node is IdentifierNameSyntax identifier && !(identifier.Parent is QualifiedNameSyntax))
|
||||
{
|
||||
if (_bindings.TryGetValue(identifier.Identifier.Text, out var binding))
|
||||
{
|
||||
// If we don't have a valid replacement, use object. This will make the code at least reasonable
|
||||
// compared to leaving the type parameter in place.
|
||||
//
|
||||
// We add our own diagnostics for missing/invalid type parameters anyway.
|
||||
var replacement = binding?.Content == null ? typeof(object).FullName : binding.Content;
|
||||
return identifier.Update(SyntaxFactory.Identifier(replacement));
|
||||
}
|
||||
}
|
||||
|
||||
return base.Visit(node);
|
||||
}
|
||||
|
||||
public override SyntaxNode VisitGenericName(GenericNameSyntax node)
|
||||
{
|
||||
var args = node.TypeArgumentList.Arguments;
|
||||
for (var i = 0; i < args.Count; i++)
|
||||
{
|
||||
var typeArgument = args[i];
|
||||
args = args.Replace(typeArgument, (TypeSyntax)Visit(typeArgument));
|
||||
}
|
||||
|
||||
return node.WithTypeArgumentList(node.TypeArgumentList.WithArguments(args));
|
||||
}
|
||||
|
||||
public class Binding
|
||||
{
|
||||
public BoundAttributeDescriptor Attribute { get; set; }
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public ComponentTypeArgumentExtensionNode Node { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -114,6 +114,15 @@ namespace Microsoft.AspNetCore.Blazor.Razor {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Specifies the type of the type parameter {0} for the {1} component..
|
||||
/// </summary>
|
||||
internal static string ComponentTypeParameter_Documentation {
|
||||
get {
|
||||
return ResourceManager.GetString("ComponentTypeParameter_Documentation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sets the '{0}' attribute to the provided string or delegate value. A delegate value should be of type '{1}'..
|
||||
/// </summary>
|
||||
|
|
@ -221,5 +230,32 @@ namespace Microsoft.AspNetCore.Blazor.Razor {
|
|||
return ResourceManager.GetString("RefTagHelper_Documentation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Declares a generic type parameter for the generated component class..
|
||||
/// </summary>
|
||||
internal static string TypeParamDirective_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("TypeParamDirective_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The name of the type parameter..
|
||||
/// </summary>
|
||||
internal static string TypeParamDirective_Token_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("TypeParamDirective_Token_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to type parameter.
|
||||
/// </summary>
|
||||
internal static string TypeParamDirective_Token_Name {
|
||||
get {
|
||||
return ResourceManager.GetString("TypeParamDirective_Token_Name", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,9 @@
|
|||
<data name="ChildContentParameterName_Documentation" xml:space="preserve">
|
||||
<value>Specifies the parameter name for the '{0}' lambda expression.</value>
|
||||
</data>
|
||||
<data name="ComponentTypeParameter_Documentation" xml:space="preserve">
|
||||
<value>Specifies the type of the type parameter {0} for the {1} component.</value>
|
||||
</data>
|
||||
<data name="EventHandlerTagHelper_Documentation" xml:space="preserve">
|
||||
<value>Sets the '{0}' attribute to the provided string or delegate value. A delegate value should be of type '{1}'.</value>
|
||||
</data>
|
||||
|
|
@ -171,4 +174,13 @@
|
|||
<data name="RefTagHelper_Documentation" xml:space="preserve">
|
||||
<value>Populates the specified field or property with a reference to the element or component.</value>
|
||||
</data>
|
||||
<data name="TypeParamDirective_Description" xml:space="preserve">
|
||||
<value>Declares a generic type parameter for the generated component class.</value>
|
||||
</data>
|
||||
<data name="TypeParamDirective_Token_Description" xml:space="preserve">
|
||||
<value>The name of the type parameter.</value>
|
||||
</data>
|
||||
<data name="TypeParamDirective_Token_Name" xml:space="preserve">
|
||||
<value>type parameter</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -22,6 +22,30 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
string.Equals(value, bool.TrueString);
|
||||
}
|
||||
|
||||
public static bool IsGenericTypedProperty(this BoundAttributeDescriptor attribute)
|
||||
{
|
||||
if (attribute == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(attribute));
|
||||
}
|
||||
|
||||
return
|
||||
attribute.Metadata.TryGetValue(BlazorMetadata.Component.GenericTypedKey, out var value) &&
|
||||
string.Equals(value, bool.TrueString);
|
||||
}
|
||||
|
||||
public static bool IsTypeParameterProperty(this BoundAttributeDescriptor attribute)
|
||||
{
|
||||
if (attribute == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(attribute));
|
||||
}
|
||||
|
||||
return
|
||||
attribute.Metadata.TryGetValue(BlazorMetadata.Component.TypeParameterKey, out var value) &&
|
||||
string.Equals(value, bool.TrueString);
|
||||
}
|
||||
|
||||
public static bool IsWeaklyTyped(this BoundAttributeDescriptor attribute)
|
||||
{
|
||||
if (attribute == null)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,19 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
string.Equals(bool.TrueString, fallback);
|
||||
}
|
||||
|
||||
public static bool IsGenericTypedComponent(this TagHelperDescriptor tagHelper)
|
||||
{
|
||||
if (tagHelper == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tagHelper));
|
||||
}
|
||||
|
||||
return
|
||||
IsComponentTagHelper(tagHelper) &&
|
||||
tagHelper.Metadata.TryGetValue(BlazorMetadata.Component.GenericTypedKey, out var value) &&
|
||||
string.Equals(bool.TrueString, value);
|
||||
}
|
||||
|
||||
public static bool IsInputElementBindTagHelper(this TagHelperDescriptor tagHelper)
|
||||
{
|
||||
if (tagHelper == null)
|
||||
|
|
@ -160,5 +173,27 @@ namespace Microsoft.AspNetCore.Blazor.Razor
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the set of component attributes that represent generic type parameters of the component type.
|
||||
/// </summary>
|
||||
/// <param name="tagHelper">The <see cref="TagHelperDescriptor"/>.</param>
|
||||
/// <returns>The type parameter attributes</returns>
|
||||
public static IEnumerable<BoundAttributeDescriptor> GetTypeParameters(this TagHelperDescriptor tagHelper)
|
||||
{
|
||||
if (tagHelper == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tagHelper));
|
||||
}
|
||||
|
||||
for (var i = 0; i < tagHelper.BoundAttributes.Count; i++)
|
||||
{
|
||||
var attribute = tagHelper.BoundAttributes[i];
|
||||
if (attribute.IsTypeParameterProperty())
|
||||
{
|
||||
yield return attribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||
{
|
||||
internal class TypeParamDirective
|
||||
{
|
||||
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
|
||||
"typeparam",
|
||||
DirectiveKind.SingleLine,
|
||||
builder =>
|
||||
{
|
||||
builder.AddMemberToken(Resources.TypeParamDirective_Token_Name, Resources.TypeParamDirective_Token_Description);
|
||||
builder.Usage = DirectiveUsage.FileScopedMultipleOccurring;
|
||||
builder.Description = Resources.TypeParamDirective_Description;
|
||||
});
|
||||
|
||||
public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder builder)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(builder));
|
||||
}
|
||||
|
||||
builder.AddDirective(Directive);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,8 +11,8 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
|||
internal override bool UseTwoPhaseCompilation => true;
|
||||
|
||||
public CodeGenerationTestBase()
|
||||
: base(generateBaselines: false)
|
||||
{
|
||||
GenerateBaselines = true;
|
||||
}
|
||||
|
||||
#region Basics
|
||||
|
|
@ -81,6 +81,36 @@ namespace Test
|
|||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComponentWithTypeParameters()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@using Microsoft.AspNetCore.Blazor;
|
||||
@typeparam TItem1
|
||||
@typeparam TItem2
|
||||
|
||||
<h1>Item1</h1>
|
||||
@foreach (var item2 in Items2)
|
||||
{
|
||||
<p>
|
||||
@ChildContent(item2);
|
||||
</p>
|
||||
}
|
||||
@functions {
|
||||
[Parameter] TItem1 Item1 { get; set; }
|
||||
[Parameter] List<TItem2> Items2 { get; set; }
|
||||
[Parameter] RenderFragment<TItem2> ChildContent { get; set; }
|
||||
}");
|
||||
|
||||
// Assert
|
||||
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
|
||||
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
|
||||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChildComponent_WithExplicitStringParameter()
|
||||
{
|
||||
|
|
@ -1199,6 +1229,146 @@ namespace Test
|
|||
|
||||
#endregion
|
||||
|
||||
#region Generics
|
||||
|
||||
[Fact]
|
||||
public void ChildComponent_Generic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<TItem> : BlazorComponent
|
||||
{
|
||||
[Parameter] TItem Item { get; set; }
|
||||
}
|
||||
}
|
||||
"));
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MyComponent TItem=string Item=""@(""hi"")""/>");
|
||||
|
||||
// Assert
|
||||
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
|
||||
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
|
||||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChildComponent_GenericBind()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<TItem> : BlazorComponent
|
||||
{
|
||||
[Parameter]
|
||||
TItem Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
Action<TItem> ValueChanged { get; set; }
|
||||
}
|
||||
}
|
||||
"));
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MyComponent TItem=string bind-Item=Value/>
|
||||
@functions {
|
||||
string Value;
|
||||
}");
|
||||
|
||||
// Assert
|
||||
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
|
||||
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
|
||||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChildComponent_GenericChildContent()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using Microsoft.AspNetCore.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<TItem> : BlazorComponent
|
||||
{
|
||||
[Parameter] TItem Item { get; set; }
|
||||
|
||||
[Parameter] RenderFragment<TItem> ChildContent { get; set; }
|
||||
}
|
||||
}
|
||||
"));
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MyComponent TItem=string Item=""@(""hi"")"">
|
||||
<div>@context.ToLower()</div>
|
||||
</MyComponent>");
|
||||
|
||||
// Assert
|
||||
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
|
||||
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
|
||||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChildComponent_MultipleGenerics()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(Parse(@"
|
||||
using Microsoft.AspNetCore.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<TItem1, TItem2> : BlazorComponent
|
||||
{
|
||||
[Parameter] TItem1 Item { get; set; }
|
||||
|
||||
[Parameter] RenderFragment<TItem1> ChildContent { get; set; }
|
||||
|
||||
[Parameter] RenderFragment<Context> AnotherChildContent { get; set; }
|
||||
|
||||
public class Context
|
||||
{
|
||||
public TItem2 Item { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
"));
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MyComponent TItem1=string TItem2=int Item=""@(""hi"")"">
|
||||
<ChildContent><div>@context.ToLower()</div></ChildContent>
|
||||
<AnotherChildContent Context=""item"">
|
||||
@System.Math.Max(0, item.Item);
|
||||
</AnotherChildContent>
|
||||
</MyComponent>");
|
||||
|
||||
// Assert
|
||||
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
|
||||
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
|
||||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ref
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1335,7 +1505,7 @@ namespace Test
|
|||
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
|
||||
CompileToAssembly(generated);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void RazorTemplate_NonGeneric_InImplicitExpression()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
|
|
@ -85,5 +85,43 @@ namespace Test.AnotherNamespace
|
|||
var bindings = result.CodeDocument.GetTagHelperContext();
|
||||
Assert.Single(bindings.TagHelpers, t => t.Name == "Microsoft.AspNetCore.Blazor.Routing.NavLink");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComponentDiscovery_CanFindComponent_WithTypeParameter()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var result = CompileToCSharp("UniqueName.cshtml", @"
|
||||
@addTagHelper *, TestAssembly
|
||||
@typeparam TItem
|
||||
@functions {
|
||||
[Parameter] TItem Item { get; set; }
|
||||
}");
|
||||
|
||||
// Assert
|
||||
var bindings = result.CodeDocument.GetTagHelperContext();
|
||||
Assert.Single(bindings.TagHelpers, t => t.Name == "Test.UniqueName<TItem>");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComponentDiscovery_CanFindComponent_WithMultipleTypeParameters()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
var result = CompileToCSharp("UniqueName.cshtml", @"
|
||||
@addTagHelper *, TestAssembly
|
||||
@typeparam TItem1
|
||||
@typeparam TItem2
|
||||
@typeparam TItem3
|
||||
@functions {
|
||||
[Parameter] TItem1 Item { get; set; }
|
||||
}");
|
||||
|
||||
// Assert
|
||||
var bindings = result.CodeDocument.GetTagHelperContext();
|
||||
Assert.Single(bindings.TagHelpers, t => t.Name == "Test.UniqueName<TItem1, TItem2, TItem3>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,190 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Blazor.Razor;
|
||||
using Microsoft.AspNetCore.Blazor.RenderTree;
|
||||
using Microsoft.AspNetCore.Blazor.Test.Helpers;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Build.Test
|
||||
{
|
||||
public class GenericComponentRazorIntegrationTest : RazorIntegrationTestBase
|
||||
{
|
||||
private readonly CSharpSyntaxTree GenericContextComponent = Parse(@"
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
using Microsoft.AspNetCore.Blazor.RenderTree;
|
||||
namespace Test
|
||||
{
|
||||
public class GenericContext<TItem> : BlazorComponent
|
||||
{
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
var items = (IReadOnlyList<TItem>)Items ?? Array.Empty<TItem>();
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
builder.AddContent(i, ChildContent, new Context() { Index = i, Item = items[i], });
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
List<TItem> Items { get; set; }
|
||||
|
||||
[Parameter]
|
||||
RenderFragment<Context> ChildContent { get; set; }
|
||||
|
||||
public class Context
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public TItem Item { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
");
|
||||
|
||||
private readonly CSharpSyntaxTree MultipleGenericParameterComponent = Parse(@"
|
||||
using Microsoft.AspNetCore.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
using Microsoft.AspNetCore.Blazor.RenderTree;
|
||||
namespace Test
|
||||
{
|
||||
public class MultipleGenericParameter<TItem1, TItem2, TItem3> : BlazorComponent
|
||||
{
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, Item1);
|
||||
builder.AddContent(1, Item2);
|
||||
builder.AddContent(2, Item3);
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
TItem1 Item1 { get; set; }
|
||||
|
||||
[Parameter]
|
||||
TItem2 Item2 { get; set; }
|
||||
|
||||
[Parameter]
|
||||
TItem3 Item3 { get; set; }
|
||||
}
|
||||
}
|
||||
");
|
||||
|
||||
internal override bool UseTwoPhaseCompilation => true;
|
||||
|
||||
[Fact]
|
||||
public void Render_GenericComponent_WithChildContent()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(GenericContextComponent);
|
||||
|
||||
var component = CompileToComponent(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<GenericContext TItem=int Items=""@(new List<int>() { 1, 2, })"">
|
||||
<div>@(context.Item * context.Index)</div>
|
||||
</GenericContext>");
|
||||
|
||||
// Act
|
||||
var frames = GetRenderTree(component);
|
||||
|
||||
// Assert
|
||||
var genericComponentType = component.GetType().Assembly.DefinedTypes
|
||||
.Where(t => t.Name == "GenericContext`1")
|
||||
.Single()
|
||||
.MakeGenericType(typeof(int));
|
||||
|
||||
Assert.Collection(
|
||||
frames,
|
||||
frame => AssertFrame.Component(frame, genericComponentType.FullName, 3, 0),
|
||||
frame => AssertFrame.Attribute(frame, "Items", typeof(List<int>), 1),
|
||||
frame => AssertFrame.Attribute(frame, RenderTreeBuilder.ChildContent, 2),
|
||||
frame => AssertFrame.Whitespace(frame, 3),
|
||||
frame => AssertFrame.Element(frame, "div", 2, 4),
|
||||
frame => AssertFrame.Text(frame, "0", 5),
|
||||
frame => AssertFrame.Whitespace(frame, 6),
|
||||
frame => AssertFrame.Whitespace(frame, 3),
|
||||
frame => AssertFrame.Element(frame, "div", 2, 4),
|
||||
frame => AssertFrame.Text(frame, "2", 5),
|
||||
frame => AssertFrame.Whitespace(frame, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_GenericComponent_MultipleParameters_WithChildContent()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(MultipleGenericParameterComponent);
|
||||
|
||||
var component = CompileToComponent(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MultipleGenericParameter
|
||||
TItem1=""int""
|
||||
TItem2=""string""
|
||||
TItem3=long
|
||||
Item1=3
|
||||
Item2=""@(""FOO"")""
|
||||
Item3=39L/>");
|
||||
|
||||
// Act
|
||||
var frames = GetRenderTree(component);
|
||||
|
||||
// Assert
|
||||
var genericComponentType = component.GetType().Assembly.DefinedTypes
|
||||
.Where(t => t.Name == "MultipleGenericParameter`3")
|
||||
.Single()
|
||||
.MakeGenericType(typeof(int), typeof(string), typeof(long));
|
||||
|
||||
Assert.Collection(
|
||||
frames,
|
||||
frame => AssertFrame.Component(frame, genericComponentType.FullName, 4, 0),
|
||||
frame => AssertFrame.Attribute(frame, "Item1", 3, 1),
|
||||
frame => AssertFrame.Attribute(frame, "Item2", "FOO", 2),
|
||||
frame => AssertFrame.Attribute(frame, "Item3", 39L, 3),
|
||||
frame => AssertFrame.Text(frame, "3", 0),
|
||||
frame => AssertFrame.Text(frame, "FOO", 1),
|
||||
frame => AssertFrame.Text(frame, "39", 2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenericComponent_WithoutAnyTypeParameters_TriggersDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(GenericContextComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<GenericContext />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.GenericComponentMissingTypeArgument.Id, diagnostic.Id);
|
||||
Assert.Equal(
|
||||
"The component 'GenericContext' is missing required type arguments. Specify the missing types using the attributes: 'TItem'.",
|
||||
diagnostic.GetMessage());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenericComponent_WithMissingTypeParameters_TriggersDiagnostic()
|
||||
{
|
||||
// Arrange
|
||||
AdditionalSyntaxTrees.Add(MultipleGenericParameterComponent);
|
||||
|
||||
// Act
|
||||
var generated = CompileToCSharp(@"
|
||||
@addTagHelper *, TestAssembly
|
||||
<MultipleGenericParameter TItem1=int />");
|
||||
|
||||
// Assert
|
||||
var diagnostic = Assert.Single(generated.Diagnostics);
|
||||
Assert.Same(BlazorDiagnosticFactory.GenericComponentMissingTypeArgument.Id, diagnostic.Id);
|
||||
Assert.Equal(
|
||||
"The component 'MultipleGenericParameter' is missing required type arguments. " +
|
||||
"Specify the missing types using the attributes: 'TItem2', 'TItem3'.",
|
||||
diagnostic.GetMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
|||
IExtensionIntermediateNodeVisitor<ComponentExtensionNode>,
|
||||
IExtensionIntermediateNodeVisitor<ComponentAttributeExtensionNode>,
|
||||
IExtensionIntermediateNodeVisitor<ComponentChildContentIntermediateNode>,
|
||||
IExtensionIntermediateNodeVisitor<ComponentTypeArgumentExtensionNode>,
|
||||
IExtensionIntermediateNodeVisitor<RouteAttributeExtensionNode>,
|
||||
IExtensionIntermediateNodeVisitor<RefExtensionNode>
|
||||
{
|
||||
|
|
@ -291,6 +292,11 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
|||
WriteContentNode(node, node.AttributeName);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<ComponentTypeArgumentExtensionNode>.VisitExtension(ComponentTypeArgumentExtensionNode node)
|
||||
{
|
||||
WriteContentNode(node, node.TypeParameterName);
|
||||
}
|
||||
|
||||
void IExtensionIntermediateNodeVisitor<RouteAttributeExtensionNode>.VisitExtension(RouteAttributeExtensionNode node)
|
||||
{
|
||||
WriteContentNode(node, node.Template);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
|
@ -17,9 +17,14 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
|||
{
|
||||
private static readonly AsyncLocal<string> _directoryPath = new AsyncLocal<string>();
|
||||
|
||||
protected RazorBaselineIntegrationTestBase()
|
||||
protected RazorBaselineIntegrationTestBase(bool? generateBaselines = null)
|
||||
{
|
||||
TestProjectRoot = TestProject.GetProjectDirectory(GetType());
|
||||
|
||||
if (generateBaselines.HasValue)
|
||||
{
|
||||
GenerateBaselines = generateBaselines.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Used by the test framework to set the directory for test files.
|
||||
|
|
@ -30,9 +35,9 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
|||
}
|
||||
|
||||
#if GENERATE_BASELINES
|
||||
protected bool GenerateBaselines { get; set; } = true;
|
||||
protected bool GenerateBaselines { get; } = true;
|
||||
#else
|
||||
protected bool GenerateBaselines { get; set; } = false;
|
||||
protected bool GenerateBaselines { get; } = false;
|
||||
#endif
|
||||
|
||||
protected string TestProjectRoot { get; }
|
||||
|
|
@ -47,6 +52,12 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
|||
// Force consistent paths since they are going to be recorded in files.
|
||||
internal override string WorkingDirectory => ArbitraryWindowsPath;
|
||||
|
||||
[Fact]
|
||||
public void GenerateBaselinesMustBeFalse()
|
||||
{
|
||||
Assert.False(GenerateBaselines, "GenerateBaselines should be set back to false before you check in!");
|
||||
}
|
||||
|
||||
protected void AssertDocumentNodeMatchesBaseline(RazorCodeDocument codeDocument)
|
||||
{
|
||||
var document = codeDocument.GetDocumentIntermediateNode();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
// <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.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::System.Object __typeHelper = "*, TestAssembly";
|
||||
}
|
||||
))();
|
||||
}
|
||||
#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.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
__o = typeof(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
string
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
);
|
||||
__o = Microsoft.AspNetCore.Blazor.Components.RuntimeHelpers.TypeCheck<string>(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
"hi"
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
);
|
||||
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
|
||||
}
|
||||
));
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
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 [33] ) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [44] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
DesignTimeDirective -
|
||||
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
|
||||
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
|
||||
ComponentExtensionNode - (31:1,0 [42] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - Test.MyComponent<string>
|
||||
ComponentTypeArgumentExtensionNode - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem
|
||||
IntermediateToken - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - string
|
||||
ComponentAttributeExtensionNode - (63:1,32 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Item - Item
|
||||
CSharpExpression - (64:1,33 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (65:1,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "hi"
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|*, TestAssembly|
|
||||
Generated Location: (559:16,38 [15] )
|
||||
|*, TestAssembly|
|
||||
|
||||
Source Location: (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|string|
|
||||
Generated Location: (1083:30,19 [6] )
|
||||
|string|
|
||||
|
||||
Source Location: (65:1,34 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|"hi"|
|
||||
Generated Location: (1315:37,34 [4] )
|
||||
|"hi"|
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// <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.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::System.Object __typeHelper = "*, TestAssembly";
|
||||
}
|
||||
))();
|
||||
}
|
||||
#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.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
__o = typeof(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
string
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
);
|
||||
__o = Microsoft.AspNetCore.Blazor.Components.BindMethods.GetValue(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
Value
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
);
|
||||
__o = Microsoft.AspNetCore.Blazor.Components.BindMethods.SetValueHandler(__value => Value = __value, Value);
|
||||
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
|
||||
}
|
||||
));
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
|
||||
string Value;
|
||||
|
||||
#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 [33] ) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [44] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
DesignTimeDirective -
|
||||
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
|
||||
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
|
||||
ComponentExtensionNode - (31:1,0 [43] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - Test.MyComponent<string>
|
||||
ComponentTypeArgumentExtensionNode - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem
|
||||
IntermediateToken - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - string
|
||||
ComponentAttributeExtensionNode - (67:1,36 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Item -
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - Microsoft.AspNetCore.Blazor.Components.BindMethods.GetValue(
|
||||
IntermediateToken - (67:1,36 [5] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - Value
|
||||
IntermediateToken - - CSharp - )
|
||||
ComponentAttributeExtensionNode - (67:1,36 [5] x:\dir\subdir\Test\TestComponent.cshtml) - ItemChanged -
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - Microsoft.AspNetCore.Blazor.Components.BindMethods.SetValueHandler(__value => Value = __value, Value)
|
||||
HtmlContent - (74:1,43 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (74:1,43 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpCode - (88:2,12 [21] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (88:2,12 [21] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n string Value;\n
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|*, TestAssembly|
|
||||
Generated Location: (559:16,38 [15] )
|
||||
|*, TestAssembly|
|
||||
|
||||
Source Location: (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|string|
|
||||
Generated Location: (1083:30,19 [6] )
|
||||
|string|
|
||||
|
||||
Source Location: (67:1,36 [5] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|Value|
|
||||
Generated Location: (1305:37,36 [5] )
|
||||
|Value|
|
||||
|
||||
Source Location: (88:2,12 [21] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|
|
||||
string Value;
|
||||
|
|
||||
Generated Location: (1740:49,12 [21] )
|
||||
|
|
||||
string Value;
|
||||
|
|
||||
|
||||
|
|
@ -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.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::System.Object __typeHelper = "*, TestAssembly";
|
||||
}
|
||||
))();
|
||||
}
|
||||
#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.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
__o = typeof(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
string
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
);
|
||||
__o = Microsoft.AspNetCore.Blazor.Components.RuntimeHelpers.TypeCheck<string>(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
"hi"
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
);
|
||||
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment<string>)((context) => (builder2) => {
|
||||
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
__o = context.ToLower();
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
));
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
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 [33] ) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [44] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
DesignTimeDirective -
|
||||
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
|
||||
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
|
||||
ComponentExtensionNode - (31:1,0 [90] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - Test.MyComponent<string>
|
||||
ComponentChildContent - - ChildContent
|
||||
HtmlContent - (72:1,41 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (72:1,41 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
HtmlElement - (76:2,2 [29] x:\dir\subdir\Test\TestComponent.cshtml) - div
|
||||
CSharpExpression - (82:2,8 [17] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (82:2,8 [17] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - context.ToLower()
|
||||
HtmlContent - (105:2,31 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (105:2,31 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
ComponentTypeArgumentExtensionNode - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem
|
||||
IntermediateToken - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - string
|
||||
ComponentAttributeExtensionNode - (63:1,32 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Item - Item
|
||||
CSharpExpression - (64:1,33 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (65:1,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "hi"
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|*, TestAssembly|
|
||||
Generated Location: (559:16,38 [15] )
|
||||
|*, TestAssembly|
|
||||
|
||||
Source Location: (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|string|
|
||||
Generated Location: (1083:30,19 [6] )
|
||||
|string|
|
||||
|
||||
Source Location: (65:1,34 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|"hi"|
|
||||
Generated Location: (1315:37,34 [4] )
|
||||
|"hi"|
|
||||
|
||||
Source Location: (82:2,8 [17] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|context.ToLower()|
|
||||
Generated Location: (1563:44,8 [17] )
|
||||
|context.ToLower()|
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// <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.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::System.Object __typeHelper = "*, TestAssembly";
|
||||
}
|
||||
))();
|
||||
}
|
||||
#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.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
__o = typeof(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
string
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
);
|
||||
__o = typeof(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
int
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
);
|
||||
__o = Microsoft.AspNetCore.Blazor.Components.RuntimeHelpers.TypeCheck<string>(
|
||||
#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
"hi"
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
);
|
||||
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment<string>)((context) => (builder2) => {
|
||||
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
__o = context.ToLower();
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
));
|
||||
builder.AddAttribute(-1, "AnotherChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment<Test.MyComponent<string, int>.Context>)((item) => (builder2) => {
|
||||
#line 5 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
__o = System.Math.Max(0, item.Item);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
));
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
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 [33] ) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [44] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
DesignTimeDirective -
|
||||
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
|
||||
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
|
||||
ComponentExtensionNode - (31:1,0 [228] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - Test.MyComponent<string, int>
|
||||
ComponentChildContent - (88:2,2 [58] x:\dir\subdir\Test\TestComponent.cshtml) - ChildContent
|
||||
HtmlElement - (102:2,16 [29] x:\dir\subdir\Test\TestComponent.cshtml) - div
|
||||
CSharpExpression - (108:2,22 [17] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (108:2,22 [17] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - context.ToLower()
|
||||
ComponentChildContent - (148:3,0 [95] x:\dir\subdir\Test\TestComponent.cshtml) - AnotherChildContent
|
||||
HtmlContent - (184:3,36 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (184:3,36 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpExpression - (189:4,3 [29] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (189:4,3 [29] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - System.Math.Max(0, item.Item)
|
||||
HtmlContent - (218:4,32 [3] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (218:4,32 [3] x:\dir\subdir\Test\TestComponent.cshtml) - Html - ;\n
|
||||
ComponentTypeArgumentExtensionNode - (51:1,20 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem1
|
||||
IntermediateToken - (51:1,20 [6] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - string
|
||||
ComponentTypeArgumentExtensionNode - (65:1,34 [3] x:\dir\subdir\Test\TestComponent.cshtml) - TItem2
|
||||
IntermediateToken - (65:1,34 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - int
|
||||
ComponentAttributeExtensionNode - (75:1,44 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Item - Item
|
||||
CSharpExpression - (76:1,45 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (77:1,46 [4] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "hi"
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|*, TestAssembly|
|
||||
Generated Location: (559:16,38 [15] )
|
||||
|*, TestAssembly|
|
||||
|
||||
Source Location: (51:1,20 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|string|
|
||||
Generated Location: (1084:30,20 [6] )
|
||||
|string|
|
||||
|
||||
Source Location: (65:1,34 [3] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|int|
|
||||
Generated Location: (1251:37,34 [3] )
|
||||
|int|
|
||||
|
||||
Source Location: (77:1,46 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|"hi"|
|
||||
Generated Location: (1492:44,46 [4] )
|
||||
|"hi"|
|
||||
|
||||
Source Location: (108:2,22 [17] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|context.ToLower()|
|
||||
Generated Location: (1754:51,22 [17] )
|
||||
|context.ToLower()|
|
||||
|
||||
Source Location: (189:4,3 [29] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|System.Math.Max(0, item.Item)|
|
||||
Generated Location: (2065:59,6 [29] )
|
||||
|System.Math.Max(0, item.Item)|
|
||||
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// <auto-generated/>
|
||||
#pragma warning disable 1591
|
||||
namespace Test
|
||||
{
|
||||
#line hidden
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
using Microsoft.AspNetCore.Blazor;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent<TItem1, TItem2> : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 219
|
||||
private void __RazorDirectiveTokenHelpers__() {
|
||||
((System.Action)(() => {
|
||||
global::System.Object TItem1 = null;
|
||||
}
|
||||
))();
|
||||
((System.Action)(() => {
|
||||
global::System.Object TItem2 = null;
|
||||
}
|
||||
))();
|
||||
}
|
||||
#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.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
#line 6 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
foreach (var item2 in Items2)
|
||||
{
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 9 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
__o = ChildContent(item2);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 10 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#line 12 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
|
||||
[Parameter] TItem1 Item1 { get; set; }
|
||||
[Parameter] List<TItem2> Items2 { get; set; }
|
||||
[Parameter] RenderFragment<TItem2> ChildContent { get; set; }
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
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 - (1:0,1 [34] x:\dir\subdir\Test\TestComponent.cshtml) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [44] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
DesignTimeDirective -
|
||||
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
|
||||
DirectiveToken - (14:0,14 [9] ) - "*, Test"
|
||||
DirectiveToken - (48:1,11 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem1
|
||||
DirectiveToken - (67:2,11 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem2
|
||||
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 - (35:0,35 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (35:0,35 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
HtmlContent - (75:3,0 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (75:3,0 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
HtmlElement - (77:4,0 [14] x:\dir\subdir\Test\TestComponent.cshtml) - h1
|
||||
HtmlContent - (81:4,4 [5] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (81:4,4 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Item1
|
||||
HtmlContent - (91:4,14 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (91:4,14 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpCode - (94:5,1 [38] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (94:5,1 [38] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - foreach (var item2 in Items2)\n{\n
|
||||
HtmlElement - (132:7,4 [40] x:\dir\subdir\Test\TestComponent.cshtml) - p
|
||||
HtmlContent - (135:7,7 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (135:7,7 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpExpression - (142:8,5 [19] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (142:8,5 [19] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ChildContent(item2)
|
||||
HtmlContent - (161:8,24 [7] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (161:8,24 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Html - ;\n
|
||||
CSharpCode - (172:9,8 [3] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (172:9,8 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n}
|
||||
HtmlContent - (175:10,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (175:10,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpCode - (189:11,12 [164] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (189:11,12 [164] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n [Parameter] TItem1 Item1 { get; set; }\n [Parameter] List<TItem2> Items2 { get; set; }\n [Parameter] RenderFragment<TItem2> ChildContent { get; set; }\n
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
Source Location: (1:0,1 [34] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|using Microsoft.AspNetCore.Blazor;|
|
||||
Generated Location: (257:10,0 [34] )
|
||||
|using Microsoft.AspNetCore.Blazor;|
|
||||
|
||||
Source Location: (48:1,11 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|TItem1|
|
||||
Generated Location: (637:20,22 [6] )
|
||||
|TItem1|
|
||||
|
||||
Source Location: (67:2,11 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|TItem2|
|
||||
Generated Location: (735:24,22 [6] )
|
||||
|TItem2|
|
||||
|
||||
Source Location: (94:5,1 [38] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|foreach (var item2 in Items2)
|
||||
{
|
||||
|
|
||||
Generated Location: (1211:37,1 [38] )
|
||||
|foreach (var item2 in Items2)
|
||||
{
|
||||
|
|
||||
|
||||
Source Location: (142:8,5 [19] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|ChildContent(item2)|
|
||||
Generated Location: (1339:44,6 [19] )
|
||||
|ChildContent(item2)|
|
||||
|
||||
Source Location: (172:9,8 [3] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|
|
||||
}|
|
||||
Generated Location: (1452:49,8 [3] )
|
||||
|
|
||||
}|
|
||||
|
||||
Source Location: (189:11,12 [164] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|
|
||||
[Parameter] TItem1 Item1 { get; set; }
|
||||
[Parameter] List<TItem2> Items2 { get; set; }
|
||||
[Parameter] RenderFragment<TItem2> ChildContent { get; set; }
|
||||
|
|
||||
Generated Location: (1601:57,12 [164] )
|
||||
|
|
||||
[Parameter] TItem1 Item1 { get; set; }
|
||||
[Parameter] List<TItem2> Items2 { get; set; }
|
||||
[Parameter] RenderFragment<TItem2> ChildContent { get; set; }
|
||||
|
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// <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.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
builder.OpenComponent<Test.MyComponent<string>>(0);
|
||||
builder.AddAttribute(1, "Item", Microsoft.AspNetCore.Blazor.Components.RuntimeHelpers.TypeCheck<string>("hi"));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
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 [35] ) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [46] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
MethodDeclaration - - protected override - void - BuildRenderTree
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
|
||||
ComponentExtensionNode - (31:1,0 [42] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - Test.MyComponent<string>
|
||||
ComponentTypeArgumentExtensionNode - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem
|
||||
IntermediateToken - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - string
|
||||
ComponentAttributeExtensionNode - (63:1,32 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Item - Item
|
||||
CSharpExpression - (64:1,33 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (65:1,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "hi"
|
||||
|
|
@ -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.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
builder.OpenComponent<Test.MyComponent<string>>(0);
|
||||
builder.AddAttribute(1, "Item", Microsoft.AspNetCore.Blazor.Components.BindMethods.GetValue(Value));
|
||||
builder.AddAttribute(2, "ItemChanged", Microsoft.AspNetCore.Blazor.Components.BindMethods.SetValueHandler(__value => Value = __value, Value));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
|
||||
string Value;
|
||||
|
||||
#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 [35] ) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [46] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
MethodDeclaration - - protected override - void - BuildRenderTree
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
|
||||
ComponentExtensionNode - (31:1,0 [43] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - Test.MyComponent<string>
|
||||
ComponentTypeArgumentExtensionNode - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem
|
||||
IntermediateToken - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - string
|
||||
ComponentAttributeExtensionNode - (67:1,36 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Item -
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - Microsoft.AspNetCore.Blazor.Components.BindMethods.GetValue(
|
||||
IntermediateToken - (67:1,36 [5] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - Value
|
||||
IntermediateToken - - CSharp - )
|
||||
ComponentAttributeExtensionNode - (67:1,36 [5] x:\dir\subdir\Test\TestComponent.cshtml) - ItemChanged -
|
||||
CSharpExpression -
|
||||
IntermediateToken - - CSharp - Microsoft.AspNetCore.Blazor.Components.BindMethods.SetValueHandler(__value => Value = __value, Value)
|
||||
CSharpCode - (88:2,12 [21] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (88:2,12 [21] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n string Value;\n
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
Source Location: (88:2,12 [21] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|
|
||||
string Value;
|
||||
|
|
||||
Generated Location: (1087:24,12 [21] )
|
||||
|
|
||||
string Value;
|
||||
|
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// <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.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
builder.OpenComponent<Test.MyComponent<string>>(0);
|
||||
builder.AddAttribute(1, "Item", Microsoft.AspNetCore.Blazor.Components.RuntimeHelpers.TypeCheck<string>("hi"));
|
||||
builder.AddAttribute(2, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment<string>)((context) => (builder2) => {
|
||||
builder2.AddContent(3, "\n ");
|
||||
builder2.OpenElement(4, "div");
|
||||
builder2.AddContent(5, context.ToLower());
|
||||
builder2.CloseElement();
|
||||
builder2.AddContent(6, "\n");
|
||||
}
|
||||
));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
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 [35] ) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [46] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
MethodDeclaration - - protected override - void - BuildRenderTree
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
|
||||
ComponentExtensionNode - (31:1,0 [90] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - Test.MyComponent<string>
|
||||
ComponentChildContent - - ChildContent
|
||||
HtmlContent - (72:1,41 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (72:1,41 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
HtmlElement - (76:2,2 [29] x:\dir\subdir\Test\TestComponent.cshtml) - div
|
||||
CSharpExpression - (82:2,8 [17] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (82:2,8 [17] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - context.ToLower()
|
||||
HtmlContent - (105:2,31 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (105:2,31 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
ComponentTypeArgumentExtensionNode - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem
|
||||
IntermediateToken - (50:1,19 [6] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - string
|
||||
ComponentAttributeExtensionNode - (63:1,32 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Item - Item
|
||||
CSharpExpression - (64:1,33 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (65:1,34 [4] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "hi"
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// <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.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
builder.OpenComponent<Test.MyComponent<string, int>>(0);
|
||||
builder.AddAttribute(1, "Item", Microsoft.AspNetCore.Blazor.Components.RuntimeHelpers.TypeCheck<string>("hi"));
|
||||
builder.AddAttribute(2, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment<string>)((context) => (builder2) => {
|
||||
builder2.OpenElement(3, "div");
|
||||
builder2.AddContent(4, context.ToLower());
|
||||
builder2.CloseElement();
|
||||
}
|
||||
));
|
||||
builder.AddAttribute(5, "AnotherChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment<Test.MyComponent<string, int>.Context>)((item) => (builder2) => {
|
||||
builder2.AddContent(6, "\n ");
|
||||
builder2.AddContent(7, System.Math.Max(0, item.Item));
|
||||
builder2.AddContent(8, ";\n");
|
||||
}
|
||||
));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
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 [35] ) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [46] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
MethodDeclaration - - protected override - void - BuildRenderTree
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
|
||||
ComponentExtensionNode - (31:1,0 [228] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent - Test.MyComponent<string, int>
|
||||
ComponentChildContent - (88:2,2 [58] x:\dir\subdir\Test\TestComponent.cshtml) - ChildContent
|
||||
HtmlElement - (102:2,16 [29] x:\dir\subdir\Test\TestComponent.cshtml) - div
|
||||
CSharpExpression - (108:2,22 [17] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (108:2,22 [17] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - context.ToLower()
|
||||
ComponentChildContent - (148:3,0 [95] x:\dir\subdir\Test\TestComponent.cshtml) - AnotherChildContent
|
||||
HtmlContent - (184:3,36 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (184:3,36 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpExpression - (189:4,3 [29] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (189:4,3 [29] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - System.Math.Max(0, item.Item)
|
||||
HtmlContent - (218:4,32 [3] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (218:4,32 [3] x:\dir\subdir\Test\TestComponent.cshtml) - Html - ;\n
|
||||
ComponentTypeArgumentExtensionNode - (51:1,20 [6] x:\dir\subdir\Test\TestComponent.cshtml) - TItem1
|
||||
IntermediateToken - (51:1,20 [6] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - string
|
||||
ComponentTypeArgumentExtensionNode - (65:1,34 [3] x:\dir\subdir\Test\TestComponent.cshtml) - TItem2
|
||||
IntermediateToken - (65:1,34 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - int
|
||||
ComponentAttributeExtensionNode - (75:1,44 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Item - Item
|
||||
CSharpExpression - (76:1,45 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (77:1,46 [4] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "hi"
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// <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.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
public class TestComponent<TItem1, TItem2> : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
|
||||
{
|
||||
base.BuildRenderTree(builder);
|
||||
builder.AddMarkupContent(0, "<h1>Item1</h1>\n");
|
||||
#line 6 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
foreach (var item2 in Items2)
|
||||
{
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
builder.AddContent(1, " ");
|
||||
builder.OpenElement(2, "p");
|
||||
builder.AddContent(3, "\n ");
|
||||
builder.AddContent(4, ChildContent(item2));
|
||||
builder.AddContent(5, ";\n ");
|
||||
builder.CloseElement();
|
||||
builder.AddContent(6, "\n");
|
||||
#line 11 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
#line 12 "x:\dir\subdir\Test\TestComponent.cshtml"
|
||||
|
||||
[Parameter] TItem1 Item1 { get; set; }
|
||||
[Parameter] List<TItem2> Items2 { get; set; }
|
||||
[Parameter] RenderFragment<TItem2> ChildContent { get; set; }
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
#pragma warning restore 1591
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
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 - (1:0,1 [36] x:\dir\subdir\Test\TestComponent.cshtml) - Microsoft.AspNetCore.Blazor
|
||||
UsingDirective - (140:6,1 [46] ) - Microsoft.AspNetCore.Blazor.Components
|
||||
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
|
||||
MethodDeclaration - - protected override - void - BuildRenderTree
|
||||
CSharpCode -
|
||||
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
|
||||
HtmlBlock - - <h1>Item1</h1>\n
|
||||
CSharpCode - (94:5,1 [34] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (94:5,1 [34] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - foreach (var item2 in Items2)\n{\n
|
||||
HtmlContent - (128:7,0 [4] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (128:7,0 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html -
|
||||
HtmlElement - (132:7,4 [40] x:\dir\subdir\Test\TestComponent.cshtml) - p
|
||||
HtmlContent - (135:7,7 [6] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (135:7,7 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpExpression - (142:8,5 [19] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (142:8,5 [19] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ChildContent(item2)
|
||||
HtmlContent - (161:8,24 [7] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (161:8,24 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Html - ;\n
|
||||
HtmlContent - (172:9,8 [2] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (172:9,8 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
|
||||
CSharpCode - (174:10,0 [3] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (174:10,0 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - }\n
|
||||
CSharpCode - (189:11,12 [164] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
IntermediateToken - (189:11,12 [164] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n [Parameter] TItem1 Item1 { get; set; }\n [Parameter] List<TItem2> Items2 { get; set; }\n [Parameter] RenderFragment<TItem2> ChildContent { get; set; }\n
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
Source Location: (94:5,1 [34] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|foreach (var item2 in Items2)
|
||||
{
|
||||
|
|
||||
Generated Location: (731:20,1 [34] )
|
||||
|foreach (var item2 in Items2)
|
||||
{
|
||||
|
|
||||
|
||||
Source Location: (174:10,0 [3] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|}
|
||||
|
|
||||
Generated Location: (1163:34,0 [3] )
|
||||
|}
|
||||
|
|
||||
|
||||
Source Location: (189:11,12 [164] x:\dir\subdir\Test\TestComponent.cshtml)
|
||||
|
|
||||
[Parameter] TItem1 Item1 { get; set; }
|
||||
[Parameter] List<TItem2> Items2 { get; set; }
|
||||
[Parameter] RenderFragment<TItem2> ChildContent { get; set; }
|
||||
|
|
||||
Generated Location: (1310:41,12 [164] )
|
||||
|
|
||||
[Parameter] TItem1 Item1 { get; set; }
|
||||
[Parameter] List<TItem2> Items2 { get; set; }
|
||||
[Parameter] RenderFragment<TItem2> ChildContent { get; set; }
|
||||
|
|
||||
|
||||
|
|
@ -124,6 +124,73 @@ namespace Test
|
|||
kvp => { Assert.Equal(TagHelperMetadata.Common.PropertyName, kvp.Key); Assert.Equal("MyProperty", kvp.Value); });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Excecute_FindsIComponentType_CreatesDescriptor_Generic()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
var compilation = BaseCompilation.AddSyntaxTrees(Parse(@"
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<T> : IComponent
|
||||
{
|
||||
public void Init(RenderHandle renderHandle) { }
|
||||
|
||||
public void SetParameters(ParameterCollection parameters) { }
|
||||
|
||||
[Parameter]
|
||||
private string MyProperty { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
"));
|
||||
|
||||
Assert.Empty(compilation.GetDiagnostics());
|
||||
|
||||
var context = TagHelperDescriptorProviderContext.Create();
|
||||
context.SetCompilation(compilation);
|
||||
|
||||
var provider = new ComponentTagHelperDescriptorProvider();
|
||||
|
||||
// Act
|
||||
provider.Execute(context);
|
||||
|
||||
// Assert
|
||||
var components = ExcludeBuiltInComponents(context);
|
||||
var component = Assert.Single(components);
|
||||
|
||||
Assert.Equal("TestAssembly", component.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>", component.Name);
|
||||
Assert.Equal("Test.MyComponent<T>", component.DisplayName);
|
||||
Assert.Equal("Test.MyComponent<T>", component.GetTypeName());
|
||||
|
||||
Assert.True(component.IsGenericTypedComponent());
|
||||
|
||||
var rule = Assert.Single(component.TagMatchingRules);
|
||||
Assert.Equal("MyComponent", rule.TagName);
|
||||
|
||||
Assert.Collection(
|
||||
component.BoundAttributes.OrderBy(a => a.Name),
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("MyProperty", a.Name);
|
||||
Assert.Equal("MyProperty", a.GetPropertyName());
|
||||
Assert.Equal("string Test.MyComponent<T>.MyProperty", a.DisplayName);
|
||||
Assert.Equal("System.String", a.TypeName);
|
||||
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("T", a.Name);
|
||||
Assert.Equal("T", a.GetPropertyName());
|
||||
Assert.Equal("T", a.DisplayName);
|
||||
Assert.Equal("System.Type", a.TypeName);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Excecute_FindsBlazorComponentType_CreatesDescriptor()
|
||||
{
|
||||
|
|
@ -263,6 +330,142 @@ namespace Test
|
|||
Assert.False(attribute.IsStringProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Excecute_GenericProperty_CreatesDescriptor()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
var compilation = BaseCompilation.AddSyntaxTrees(Parse(@"
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<T> : BlazorComponent
|
||||
{
|
||||
[Parameter]
|
||||
T MyProperty { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
"));
|
||||
|
||||
Assert.Empty(compilation.GetDiagnostics());
|
||||
|
||||
var context = TagHelperDescriptorProviderContext.Create();
|
||||
context.SetCompilation(compilation);
|
||||
|
||||
var provider = new ComponentTagHelperDescriptorProvider();
|
||||
|
||||
// Act
|
||||
provider.Execute(context);
|
||||
|
||||
// Assert
|
||||
var components = ExcludeBuiltInComponents(context);
|
||||
var component = Assert.Single(components);
|
||||
|
||||
Assert.Equal("TestAssembly", component.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>", component.Name);
|
||||
|
||||
Assert.Collection(
|
||||
component.BoundAttributes.OrderBy(a => a.Name),
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("MyProperty", a.Name);
|
||||
Assert.Equal("MyProperty", a.GetPropertyName());
|
||||
Assert.Equal("T Test.MyComponent<T>.MyProperty", a.DisplayName);
|
||||
Assert.Equal("T", a.TypeName);
|
||||
Assert.True(a.IsGenericTypedProperty());
|
||||
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("T", a.Name);
|
||||
Assert.Equal("T", a.GetPropertyName());
|
||||
Assert.Equal("T", a.DisplayName);
|
||||
Assert.Equal("System.Type", a.TypeName);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Excecute_MultipleGenerics_CreatesDescriptor()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
var compilation = BaseCompilation.AddSyntaxTrees(Parse(@"
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<T, U, V> : BlazorComponent
|
||||
{
|
||||
[Parameter]
|
||||
T MyProperty1 { get; set; }
|
||||
|
||||
[Parameter]
|
||||
U MyProperty2 { get; set; }
|
||||
|
||||
[Parameter]
|
||||
V MyProperty3 { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
"));
|
||||
|
||||
Assert.Empty(compilation.GetDiagnostics());
|
||||
|
||||
var context = TagHelperDescriptorProviderContext.Create();
|
||||
context.SetCompilation(compilation);
|
||||
|
||||
var provider = new ComponentTagHelperDescriptorProvider();
|
||||
|
||||
// Act
|
||||
provider.Execute(context);
|
||||
|
||||
// Assert
|
||||
var components = ExcludeBuiltInComponents(context);
|
||||
var component = Assert.Single(components);
|
||||
|
||||
Assert.Equal("TestAssembly", component.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T, U, V>", component.Name);
|
||||
|
||||
Assert.Collection(
|
||||
component.BoundAttributes.OrderBy(a => a.Name),
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("MyProperty1", a.Name);
|
||||
Assert.Equal("T", a.TypeName);
|
||||
Assert.True(a.IsGenericTypedProperty());
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("MyProperty2", a.Name);
|
||||
Assert.Equal("U", a.TypeName);
|
||||
Assert.True(a.IsGenericTypedProperty());
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("MyProperty3", a.Name);
|
||||
Assert.Equal("V", a.TypeName);
|
||||
Assert.True(a.IsGenericTypedProperty());
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("T", a.Name);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("U", a.Name);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("V", a.Name);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_DelegateProperty_CreatesDescriptor()
|
||||
{
|
||||
|
|
@ -313,6 +516,68 @@ namespace Test
|
|||
Assert.False(attribute.IsChildContentProperty());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_DelegateProperty_CreatesDescriptor_Generic()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
var compilation = BaseCompilation.AddSyntaxTrees(Parse(@"
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<T> : BlazorComponent
|
||||
{
|
||||
[Parameter]
|
||||
Action<T> OnClick { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
"));
|
||||
|
||||
Assert.Empty(compilation.GetDiagnostics());
|
||||
|
||||
var context = TagHelperDescriptorProviderContext.Create();
|
||||
context.SetCompilation(compilation);
|
||||
|
||||
var provider = new ComponentTagHelperDescriptorProvider();
|
||||
|
||||
// Act
|
||||
provider.Execute(context);
|
||||
|
||||
// Assert
|
||||
var components = ExcludeBuiltInComponents(context);
|
||||
var component = Assert.Single(components);
|
||||
|
||||
Assert.Equal("TestAssembly", component.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>", component.Name);
|
||||
|
||||
Assert.Collection(
|
||||
component.BoundAttributes.OrderBy(a => a.Name),
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("OnClick", a.Name);
|
||||
Assert.Equal("System.Action<T>", a.TypeName);
|
||||
Assert.False(a.HasIndexer);
|
||||
Assert.False(a.IsBooleanProperty);
|
||||
Assert.False(a.IsEnum);
|
||||
Assert.False(a.IsStringProperty);
|
||||
Assert.True(a.IsDelegateProperty());
|
||||
Assert.False(a.IsChildContentProperty());
|
||||
Assert.True(a.IsGenericTypedProperty());
|
||||
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("T", a.Name);
|
||||
Assert.Equal("T", a.GetPropertyName());
|
||||
Assert.Equal("T", a.DisplayName);
|
||||
Assert.Equal("System.Type", a.TypeName);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_RenderFragmentProperty_CreatesDescriptors()
|
||||
{
|
||||
|
|
@ -418,6 +683,7 @@ namespace Test
|
|||
Assert.False(attribute.IsDelegateProperty()); // We treat RenderFragment as separate from generalized delegates
|
||||
Assert.True(attribute.IsChildContentProperty());
|
||||
Assert.True(attribute.IsParameterizedChildContentProperty());
|
||||
Assert.False(attribute.IsGenericTypedProperty());
|
||||
|
||||
var childContent = Assert.Single(components, c => c.IsChildContentTagHelper());
|
||||
|
||||
|
|
@ -431,6 +697,313 @@ namespace Test
|
|||
Assert.Equal("Specifies the parameter name for the 'ChildContent2' lambda expression.", contextAttribute.Documentation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_RenderFragmentGenericProperty_CreatesDescriptor()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
var compilation = BaseCompilation.AddSyntaxTrees(Parse(@"
|
||||
using Microsoft.AspNetCore.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<T> : BlazorComponent
|
||||
{
|
||||
[Parameter]
|
||||
RenderFragment<T> ChildContent2 { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
"));
|
||||
|
||||
Assert.Empty(compilation.GetDiagnostics());
|
||||
|
||||
var context = TagHelperDescriptorProviderContext.Create();
|
||||
context.SetCompilation(compilation);
|
||||
|
||||
var provider = new ComponentTagHelperDescriptorProvider();
|
||||
|
||||
// Act
|
||||
provider.Execute(context);
|
||||
|
||||
// Assert
|
||||
var components = ExcludeBuiltInComponents(context);
|
||||
var component = Assert.Single(components, c => c.IsComponentTagHelper());
|
||||
|
||||
Assert.Equal("TestAssembly", component.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>", component.Name);
|
||||
|
||||
Assert.Collection(
|
||||
component.BoundAttributes.OrderBy(a => a.Name),
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("ChildContent2", a.Name);
|
||||
Assert.Equal("Microsoft.AspNetCore.Blazor.RenderFragment<T>", a.TypeName);
|
||||
|
||||
Assert.False(a.HasIndexer);
|
||||
Assert.False(a.IsBooleanProperty);
|
||||
Assert.False(a.IsEnum);
|
||||
Assert.False(a.IsStringProperty);
|
||||
Assert.False(a.IsDelegateProperty()); // We treat RenderFragment as separate from generalized delegates
|
||||
Assert.True(a.IsChildContentProperty());
|
||||
Assert.True(a.IsParameterizedChildContentProperty());
|
||||
Assert.True(a.IsGenericTypedProperty());
|
||||
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("T", a.Name);
|
||||
Assert.Equal("T", a.GetPropertyName());
|
||||
Assert.Equal("T", a.DisplayName);
|
||||
Assert.Equal("System.Type", a.TypeName);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
});
|
||||
|
||||
var childContent = Assert.Single(components, c => c.IsChildContentTagHelper());
|
||||
|
||||
Assert.Equal("TestAssembly", childContent.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>.ChildContent2", childContent.Name);
|
||||
|
||||
// A RenderFragment<T> tag helper has a parameter to allow you to set the lambda parameter name.
|
||||
var contextAttribute = Assert.Single(childContent.BoundAttributes);
|
||||
Assert.Equal("Context", contextAttribute.Name);
|
||||
Assert.Equal("System.String", contextAttribute.TypeName);
|
||||
Assert.Equal("Specifies the parameter name for the 'ChildContent2' lambda expression.", contextAttribute.Documentation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_RenderFragmentClosedGenericListProperty_CreatesDescriptor()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
var compilation = BaseCompilation.AddSyntaxTrees(Parse(@"
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<T> : BlazorComponent
|
||||
{
|
||||
[Parameter]
|
||||
RenderFragment<List<string>> ChildContent2 { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
"));
|
||||
|
||||
Assert.Empty(compilation.GetDiagnostics());
|
||||
|
||||
var context = TagHelperDescriptorProviderContext.Create();
|
||||
context.SetCompilation(compilation);
|
||||
|
||||
var provider = new ComponentTagHelperDescriptorProvider();
|
||||
|
||||
// Act
|
||||
provider.Execute(context);
|
||||
|
||||
// Assert
|
||||
var components = ExcludeBuiltInComponents(context);
|
||||
var component = Assert.Single(components, c => c.IsComponentTagHelper());
|
||||
|
||||
Assert.Equal("TestAssembly", component.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>", component.Name);
|
||||
|
||||
Assert.Collection(
|
||||
component.BoundAttributes.OrderBy(a => a.Name),
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("ChildContent2", a.Name);
|
||||
Assert.Equal("Microsoft.AspNetCore.Blazor.RenderFragment<System.Collections.Generic.List<System.String>>", a.TypeName);
|
||||
|
||||
Assert.False(a.HasIndexer);
|
||||
Assert.False(a.IsBooleanProperty);
|
||||
Assert.False(a.IsEnum);
|
||||
Assert.False(a.IsStringProperty);
|
||||
Assert.False(a.IsDelegateProperty()); // We treat RenderFragment as separate from generalized delegates
|
||||
Assert.True(a.IsChildContentProperty());
|
||||
Assert.True(a.IsParameterizedChildContentProperty());
|
||||
Assert.False(a.IsGenericTypedProperty());
|
||||
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("T", a.Name);
|
||||
Assert.Equal("T", a.GetPropertyName());
|
||||
Assert.Equal("T", a.DisplayName);
|
||||
Assert.Equal("System.Type", a.TypeName);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
});
|
||||
|
||||
var childContent = Assert.Single(components, c => c.IsChildContentTagHelper());
|
||||
|
||||
Assert.Equal("TestAssembly", childContent.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>.ChildContent2", childContent.Name);
|
||||
|
||||
// A RenderFragment<T> tag helper has a parameter to allow you to set the lambda parameter name.
|
||||
var contextAttribute = Assert.Single(childContent.BoundAttributes);
|
||||
Assert.Equal("Context", contextAttribute.Name);
|
||||
Assert.Equal("System.String", contextAttribute.TypeName);
|
||||
Assert.Equal("Specifies the parameter name for the 'ChildContent2' lambda expression.", contextAttribute.Documentation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_RenderFragmentGenericListProperty_CreatesDescriptor()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
var compilation = BaseCompilation.AddSyntaxTrees(Parse(@"
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<T> : BlazorComponent
|
||||
{
|
||||
[Parameter]
|
||||
RenderFragment<List<T>> ChildContent2 { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
"));
|
||||
|
||||
Assert.Empty(compilation.GetDiagnostics());
|
||||
|
||||
var context = TagHelperDescriptorProviderContext.Create();
|
||||
context.SetCompilation(compilation);
|
||||
|
||||
var provider = new ComponentTagHelperDescriptorProvider();
|
||||
|
||||
// Act
|
||||
provider.Execute(context);
|
||||
|
||||
// Assert
|
||||
var components = ExcludeBuiltInComponents(context);
|
||||
var component = Assert.Single(components, c => c.IsComponentTagHelper());
|
||||
|
||||
Assert.Equal("TestAssembly", component.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>", component.Name);
|
||||
|
||||
Assert.Collection(
|
||||
component.BoundAttributes.OrderBy(a => a.Name),
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("ChildContent2", a.Name);
|
||||
Assert.Equal("Microsoft.AspNetCore.Blazor.RenderFragment<System.Collections.Generic.List<T>>", a.TypeName);
|
||||
|
||||
Assert.False(a.HasIndexer);
|
||||
Assert.False(a.IsBooleanProperty);
|
||||
Assert.False(a.IsEnum);
|
||||
Assert.False(a.IsStringProperty);
|
||||
Assert.False(a.IsDelegateProperty()); // We treat RenderFragment as separate from generalized delegates
|
||||
Assert.True(a.IsChildContentProperty());
|
||||
Assert.True(a.IsParameterizedChildContentProperty());
|
||||
Assert.True(a.IsGenericTypedProperty());
|
||||
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("T", a.Name);
|
||||
Assert.Equal("T", a.GetPropertyName());
|
||||
Assert.Equal("T", a.DisplayName);
|
||||
Assert.Equal("System.Type", a.TypeName);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
});
|
||||
|
||||
var childContent = Assert.Single(components, c => c.IsChildContentTagHelper());
|
||||
|
||||
Assert.Equal("TestAssembly", childContent.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>.ChildContent2", childContent.Name);
|
||||
|
||||
// A RenderFragment<T> tag helper has a parameter to allow you to set the lambda parameter name.
|
||||
var contextAttribute = Assert.Single(childContent.BoundAttributes);
|
||||
Assert.Equal("Context", contextAttribute.Name);
|
||||
Assert.Equal("System.String", contextAttribute.TypeName);
|
||||
Assert.Equal("Specifies the parameter name for the 'ChildContent2' lambda expression.", contextAttribute.Documentation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_RenderFragmentGenericContextProperty_CreatesDescriptor()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
var compilation = BaseCompilation.AddSyntaxTrees(Parse(@"
|
||||
using Microsoft.AspNetCore.Blazor;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
public class MyComponent<T> : BlazorComponent
|
||||
{
|
||||
[Parameter]
|
||||
RenderFragment<Context> ChildContent2 { get; set; }
|
||||
|
||||
public class Context
|
||||
{
|
||||
public T Item { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"));
|
||||
|
||||
Assert.Empty(compilation.GetDiagnostics());
|
||||
|
||||
var context = TagHelperDescriptorProviderContext.Create();
|
||||
context.SetCompilation(compilation);
|
||||
|
||||
var provider = new ComponentTagHelperDescriptorProvider();
|
||||
|
||||
// Act
|
||||
provider.Execute(context);
|
||||
|
||||
// Assert
|
||||
var components = ExcludeBuiltInComponents(context);
|
||||
var component = Assert.Single(components, c => c.IsComponentTagHelper());
|
||||
|
||||
Assert.Equal("TestAssembly", component.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>", component.Name);
|
||||
|
||||
Assert.Collection(
|
||||
component.BoundAttributes.OrderBy(a => a.Name),
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("ChildContent2", a.Name);
|
||||
Assert.Equal("Microsoft.AspNetCore.Blazor.RenderFragment<Test.MyComponent<T>.Context>", a.TypeName);
|
||||
|
||||
Assert.False(a.HasIndexer);
|
||||
Assert.False(a.IsBooleanProperty);
|
||||
Assert.False(a.IsEnum);
|
||||
Assert.False(a.IsStringProperty);
|
||||
Assert.False(a.IsDelegateProperty()); // We treat RenderFragment as separate from generalized delegates
|
||||
Assert.True(a.IsChildContentProperty());
|
||||
Assert.True(a.IsParameterizedChildContentProperty());
|
||||
Assert.True(a.IsGenericTypedProperty());
|
||||
|
||||
},
|
||||
a =>
|
||||
{
|
||||
Assert.Equal("T", a.Name);
|
||||
Assert.Equal("T", a.GetPropertyName());
|
||||
Assert.Equal("T", a.DisplayName);
|
||||
Assert.Equal("System.Type", a.TypeName);
|
||||
Assert.True(a.IsTypeParameterProperty());
|
||||
});
|
||||
|
||||
var childContent = Assert.Single(components, c => c.IsChildContentTagHelper());
|
||||
|
||||
Assert.Equal("TestAssembly", childContent.AssemblyName);
|
||||
Assert.Equal("Test.MyComponent<T>.ChildContent2", childContent.Name);
|
||||
|
||||
// A RenderFragment<T> tag helper has a parameter to allow you to set the lambda parameter name.
|
||||
var contextAttribute = Assert.Single(childContent.BoundAttributes);
|
||||
Assert.Equal("Context", contextAttribute.Name);
|
||||
Assert.Equal("System.String", contextAttribute.TypeName);
|
||||
Assert.Equal("Specifies the parameter name for the 'ChildContent2' lambda expression.", contextAttribute.Documentation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_MultipleRenderFragmentProperties_CreatesDescriptor()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Razor
|
||||
{
|
||||
public class GenericTypeNameRewriterTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("TItem2", "Type2")]
|
||||
|
||||
// Unspecified argument -> System.Object
|
||||
[InlineData("TItem3", "System.Object")]
|
||||
|
||||
// Not a type parameter
|
||||
[InlineData("TItem4", "TItem4")]
|
||||
|
||||
// In a qualified name, not a type parameter
|
||||
[InlineData("TItem1.TItem2", "TItem1.TItem2")]
|
||||
|
||||
// Type parameters can't have type parameters
|
||||
[InlineData("TItem1.TItem2<TItem1, TItem2, TItem3>", "TItem1.TItem2<Type1, Type2, System.Object>")]
|
||||
[InlineData("TItem2<TItem1<TItem3>, System.TItem2, RenderFragment<List<TItem1>>", "TItem2<TItem1<System.Object>, System.TItem2, RenderFragment<List<Type1>>")]
|
||||
public void GenericTypeNameRewriter_CanReplaceTypeParametersWithTypeArguments(string original, string expected)
|
||||
{
|
||||
// Arrange
|
||||
var visitor = new GenericTypeNameRewriter(new Dictionary<string, GenericTypeNameRewriter.Binding>()
|
||||
{
|
||||
{ "TItem1", new GenericTypeNameRewriter.Binding(){ Content = "Type1", } },
|
||||
{ "TItem2", new GenericTypeNameRewriter.Binding(){ Content = "Type2", } },
|
||||
{ "TItem3", new GenericTypeNameRewriter.Binding(){ Content = null, } },
|
||||
});
|
||||
|
||||
var parsed = SyntaxFactory.ParseTypeName(original);
|
||||
|
||||
// Act
|
||||
var actual = visitor.Visit(parsed);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, actual.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<TemplatedTable Items="@Items">
|
||||
<TemplatedTable Items="@Items" TItem="Item">
|
||||
<Header><tr><th>Col1</th><th>Col2</th><th>Col3</th></tr></Header>
|
||||
<Footer>
|
||||
@if (ShowFooter)
|
||||
|
|
@ -14,12 +14,19 @@
|
|||
Toggle: <input type="checkbox" bind="ShowFooter" id="toggle"/>
|
||||
|
||||
@functions {
|
||||
List<TemplatedTable.Item> Items { get; } = new List<TemplatedTable.Item>()
|
||||
List<Item> Items { get; } = new List<Item>()
|
||||
{
|
||||
new TemplatedTable.Item(){ Col1 = "a0", Col2 = "b0", Col3 = "c0", },
|
||||
new TemplatedTable.Item(){ Col1 = "a1", Col2 = "b1", Col3 = "c1", },
|
||||
new TemplatedTable.Item(){ Col1 = "a2", Col2 = "b2", Col3 = "c2", },
|
||||
new Item(){ Col1 = "a0", Col2 = "b0", Col3 = "c0", },
|
||||
new Item(){ Col1 = "a1", Col2 = "b1", Col3 = "c1", },
|
||||
new Item(){ Col1 = "a2", Col2 = "b2", Col3 = "c2", },
|
||||
};
|
||||
|
||||
bool ShowFooter;
|
||||
|
||||
public class Item
|
||||
{
|
||||
public string Col1 { get; set; }
|
||||
public string Col2 { get; set; }
|
||||
public string Col3 { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
@typeparam TItem
|
||||
|
||||
<ol>
|
||||
@{
|
||||
var index = 1;
|
||||
|
|
@ -9,7 +11,7 @@
|
|||
</ol>
|
||||
|
||||
@functions{
|
||||
[Parameter] IEnumerable<string> Items { get; set; }
|
||||
[Parameter] IEnumerable<TItem> Items { get; set; }
|
||||
|
||||
[Parameter] RenderFragment<Context> Template { get; set; }
|
||||
|
||||
|
|
@ -17,6 +19,6 @@
|
|||
{
|
||||
public int Index { get; set; }
|
||||
|
||||
public string Item { get; set; }
|
||||
public TItem Item { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<div id="codeblocktemplate">
|
||||
@{
|
||||
RenderFragment<OrderedList.Context> template = (context) => @<li>#@context.Index - @context.Item.ToLower()</li>;
|
||||
RenderFragment<OrderedList<string>.Context> template = (context) => @<li>#@context.Index - @context.Item.ToLower()</li>;
|
||||
}
|
||||
<OrderedList Items="@items" Template="@template" />
|
||||
<OrderedList Items="@items" Template="@template" TItem="string"/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
@typeparam TItem
|
||||
<table>
|
||||
@if (Header != null)
|
||||
{
|
||||
|
|
@ -24,18 +25,11 @@
|
|||
RenderFragment Header { get; set; }
|
||||
|
||||
[Parameter]
|
||||
RenderFragment<Item> ItemTemplate { get; set; }
|
||||
RenderFragment<TItem> ItemTemplate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
RenderFragment Footer { get; set; }
|
||||
|
||||
[Parameter]
|
||||
IReadOnlyList<Item> Items { get; set; }
|
||||
|
||||
public class Item
|
||||
{
|
||||
public string Col1 { get; set; }
|
||||
public string Col2 { get; set; }
|
||||
public string Col3 { get; set; }
|
||||
}
|
||||
IReadOnlyList<TItem> Items { get; set; }
|
||||
}
|
||||
Loading…
Reference in New Issue