diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/DefaultDocumentWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/DefaultDocumentWriter.cs
index e665bbc024..fcae6150cb 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/DefaultDocumentWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/DefaultDocumentWriter.cs
@@ -304,6 +304,11 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
Context.NodeWriter.WriteSetKey(Context, node);
}
+ public override void VisitSplat(SplatIntermediateNode node)
+ {
+ Context.NodeWriter.WriteSplat(Context, node);
+ }
+
public override void VisitDefault(IntermediateNode node)
{
Context.RenderChildren(node);
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/IntermediateNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/IntermediateNodeWriter.cs
index d4e49066f9..5d6d116fc6 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/IntermediateNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/IntermediateNodeWriter.cs
@@ -69,6 +69,11 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
throw new NotSupportedException("This writer does not support components.");
}
+ public virtual void WriteSplat(CodeRenderingContext context, SplatIntermediateNode node)
+ {
+ throw new NotSupportedException("This writer does not support components.");
+ }
+
public abstract void BeginWriterScope(CodeRenderingContext context, string writer);
public abstract void EndWriterScope(CodeRenderingContext context);
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx
index 8b9c27a0de..178f1bb59b 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx
@@ -195,6 +195,9 @@
Populates the specified field or property with a reference to the element or component.
+
+ Merges a collection of attributes into the current element or component.
+
Declares a generic type parameter for the generated component class.
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
index 9b38d73700..7885d47f8e 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
@@ -317,14 +317,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// builder.SetKey(someValue);
// builder.AddElementCapture(3, (__value) => _field = __value);
// builder.CloseComponent();
+
foreach (var typeArgument in node.TypeArguments)
{
context.RenderNode(typeArgument);
}
- foreach (var attribute in node.Attributes)
+ // We need to preserve order for attibutes and attribute splats since the ordering
+ // has a semantic effect.
+
+ foreach (var child in node.Children)
{
- context.RenderNode(attribute);
+ if (child is ComponentAttributeIntermediateNode attribute)
+ {
+ context.RenderNode(attribute);
+ }
+ else if (child is SplatIntermediateNode splat)
+ {
+ context.RenderNode(splat);
+ }
}
if (node.ChildContents.Any())
@@ -365,7 +376,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// to that method. We pass in all of the attribute values + the sequence numbers.
//
// __Blazor.MyComponent.TypeInference.CreateMyComponent_0(builder, 0, 1, ..., 2, ..., 3, ....);
- var attributes = node.Attributes.ToList();
+
+ // Preserve order of attributes + splats
+ var attributes = node.Children.Where(s =>
+ {
+ return s is ComponentAttributeIntermediateNode || s is SplatIntermediateNode;
+ }).ToList();
var childContents = node.ChildContents.ToList();
var captures = node.Captures.ToList();
var setKeys = node.SetKeys.ToList();
@@ -390,7 +406,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// Don't type check generics, since we can't actually write the type name.
// The type checking with happen anyway since we defined a method and we're generating
// a call to it.
- WriteComponentAttributeInnards(context, attributes[i], canTypeCheck: false);
+ if (attributes[i] is ComponentAttributeIntermediateNode attribute)
+ {
+ WriteComponentAttributeInnards(context, attribute, canTypeCheck: false);
+ }
+ else if (attributes[i] is SplatIntermediateNode splat)
+ {
+ WriteSplatInnards(context, splat, canTypeCheck: false);
+ }
remaining--;
if (remaining > 0)
@@ -630,13 +653,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
bool NeedsTypeCheck(ComponentAttributeIntermediateNode n)
{
return n.BoundAttribute != null && !n.BoundAttribute.IsWeaklyTyped();
- }
+ }
+ }
- IReadOnlyList GetCSharpTokens(ComponentAttributeIntermediateNode attribute)
- {
- // We generally expect all children to be CSharp, this is here just in case.
- return attribute.FindDescendantNodes().Where(t => t.IsCSharp).ToArray();
- }
+ private IReadOnlyList GetCSharpTokens(IntermediateNode node)
+ {
+ // We generally expect all children to be CSharp, this is here just in case.
+ return node.FindDescendantNodes().Where(t => t.IsCSharp).ToArray();
}
public override void WriteComponentChildContent(CodeRenderingContext context, ComponentChildContentIntermediateNode node)
@@ -774,6 +797,54 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
});
}
+ public override void WriteSplat(CodeRenderingContext context, SplatIntermediateNode node)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ if (node == null)
+ {
+ throw new ArgumentNullException(nameof(node));
+ }
+
+ // Looks like:
+ //
+ // builder.AddMultipleAttributes(2, ...);
+ context.CodeWriter.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddMultipleAttributes}");
+ context.CodeWriter.Write("-1");
+ context.CodeWriter.WriteParameterSeparator();
+
+ WriteSplatInnards(context, node, canTypeCheck: true);
+
+ context.CodeWriter.WriteEndMethodInvocation();
+ }
+
+ private void WriteSplatInnards(CodeRenderingContext context, SplatIntermediateNode node, bool canTypeCheck)
+ {
+ var tokens = GetCSharpTokens(node);
+
+ if (canTypeCheck)
+ {
+ context.CodeWriter.Write(ComponentsApi.RuntimeHelpers.TypeCheck);
+ context.CodeWriter.Write("<");
+ context.CodeWriter.Write(ComponentsApi.AddMultipleAttributesTypeFullName);
+ context.CodeWriter.Write(">");
+ context.CodeWriter.Write("(");
+ }
+
+ for (var i = 0; i < tokens.Count; i++)
+ {
+ WriteCSharpToken(context, tokens[i]);
+ }
+
+ if (canTypeCheck)
+ {
+ context.CodeWriter.Write(")");
+ }
+ }
+
public override void WriteReferenceCapture(CodeRenderingContext context, ReferenceCaptureIntermediateNode node)
{
if (context == null)
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentMetadata.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentMetadata.cs
index 217ae776e6..4c6db3048e 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentMetadata.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentMetadata.cs
@@ -17,16 +17,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
public static readonly string ImportsFileName = "_Imports.razor";
- public static bool IsComponentTagHelperKind(string tagHelperKind)
- {
- return tagHelperKind == Component.TagHelperKind ||
- tagHelperKind == ChildContent.TagHelperKind ||
- tagHelperKind == EventHandler.TagHelperKind ||
- tagHelperKind == Bind.TagHelperKind ||
- tagHelperKind == Key.TagHelperKind ||
- tagHelperKind == Ref.TagHelperKind;
- }
-
public static string MangleClassName(string className)
{
if (string.IsNullOrEmpty(className))
@@ -131,6 +121,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
public static readonly string RuntimeName = "Components.None";
}
+ public static class Splat
+ {
+ public readonly static string TagHelperKind = "Components.Splat";
+
+ public static readonly string RuntimeName = "Components.None";
+ }
+
public static class Ref
{
public readonly static string TagHelperKind = "Components.Ref";
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs
index ca8704fef0..a10cdba86d 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs
@@ -130,19 +130,33 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
context.CodeWriter.WriteLine();
var index = 0;
- foreach (var attribute in node.Component.Attributes)
+
+ // Preserve order of attributes and splat.
+ foreach (var child in node.Component.Children)
{
- context.CodeWriter.WriteStartInstanceMethodInvocation("builder", ComponentsApi.RenderTreeBuilder.AddAttribute);
- context.CodeWriter.Write(parameters[index].seqName);
- context.CodeWriter.Write(", ");
+ if (child is ComponentAttributeIntermediateNode attribute)
+ {
+ context.CodeWriter.WriteStartInstanceMethodInvocation("builder", ComponentsApi.RenderTreeBuilder.AddAttribute);
+ context.CodeWriter.Write(parameters[index].seqName);
+ context.CodeWriter.Write(", ");
- context.CodeWriter.Write($"\"{attribute.AttributeName}\"");
- context.CodeWriter.Write(", ");
+ context.CodeWriter.Write($"\"{attribute.AttributeName}\"");
+ context.CodeWriter.Write(", ");
- context.CodeWriter.Write(parameters[index].parameterName);
- context.CodeWriter.WriteEndMethodInvocation();
+ context.CodeWriter.Write(parameters[index].parameterName);
+ context.CodeWriter.WriteEndMethodInvocation();
+ index++;
+ }
+ else if (child is SplatIntermediateNode)
+ {
+ context.CodeWriter.WriteStartInstanceMethodInvocation("builder", ComponentsApi.RenderTreeBuilder.AddMultipleAttributes);
+ context.CodeWriter.Write(parameters[index].seqName);
+ context.CodeWriter.Write(", ");
- index++;
+ context.CodeWriter.Write(parameters[index].parameterName);
+ context.CodeWriter.WriteEndMethodInvocation();
+ index++;
+ }
}
foreach (var childContent in node.Component.ChildContents)
@@ -189,14 +203,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
List<(string seqName, string typeName, string parameterName)> GetParameterDeclarations()
{
var p = new List<(string seqName, string typeName, string parameterName)>();
- foreach (var attribute in node.Component.Attributes)
+
+ // Preserve order between attributes and splats
+ foreach (var child in node.Component.Children)
{
- var typeName = attribute.TypeName;
- if (attribute.BoundAttribute != null && !attribute.BoundAttribute.IsGenericTypedProperty())
+ if (child is ComponentAttributeIntermediateNode attribute)
{
- typeName = "global::" + typeName;
+ var typeName = attribute.TypeName;
+ if (attribute.BoundAttribute != null && !attribute.BoundAttribute.IsGenericTypedProperty())
+ {
+ typeName = "global::" + typeName;
+ }
+ p.Add(($"__seq{p.Count}", typeName, $"__arg{p.Count}"));
+ }
+ else if (child is SplatIntermediateNode splat)
+ {
+ var typeName = ComponentsApi.AddMultipleAttributesTypeFullName;
+ p.Add(($"__seq{p.Count}", typeName, $"__arg{p.Count}"));
}
- p.Add(($"__seq{p.Count}", typeName, $"__arg{p.Count}"));
}
foreach (var childContent in node.Component.ChildContents)
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs
index 2330b1adfe..418aa160f5 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs
@@ -184,10 +184,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
.WriteStringLiteral(node.TagName)
.WriteEndMethodInvocation();
- // Render Attributes before creating the scope.
- foreach (var attribute in node.Attributes)
+ // Render attributes and splats (in order) before creating the scope.
+ foreach (var child in node.Children)
{
- context.RenderNode(attribute);
+ if (child is HtmlAttributeIntermediateNode attribute)
+ {
+ context.RenderNode(attribute);
+ }
+ else if (child is SplatIntermediateNode splat)
+ {
+ context.RenderNode(splat);
+ }
}
foreach (var setKey in node.SetKeys)
@@ -348,9 +355,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// We can skip type arguments during runtime codegen, they are handled in the
// type/parameter declarations.
- foreach (var attribute in node.Attributes)
+ // Preserve order of attributes and splats
+ foreach (var child in node.Children)
{
- context.RenderNode(attribute);
+ if (child is ComponentAttributeIntermediateNode attribute)
+ {
+ context.RenderNode(attribute);
+ }
+ else if (child is SplatIntermediateNode splat)
+ {
+ context.RenderNode(splat);
+ }
}
foreach (var childContent in node.ChildContents)
@@ -382,7 +397,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// to that method. We pass in all of the attribute values + the sequence numbers.
//
// __Blazor.MyComponent.TypeInference.CreateMyComponent_0(builder, 0, 1, ..., 2, ..., 3, ...);
- var attributes = node.Attributes.ToList();
+
+ // Preserve order of attributes and splats
+ var attributes = node.Children.Where(n =>
+ {
+ return n is ComponentAttributeIntermediateNode || n is SplatIntermediateNode;
+ }).ToList();
var childContents = node.ChildContents.ToList();
var captures = node.Captures.ToList();
var setKeys = node.SetKeys.ToList();
@@ -407,7 +427,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// Don't type check generics, since we can't actually write the type name.
// The type checking with happen anyway since we defined a method and we're generating
// a call to it.
- WriteComponentAttributeInnards(context, attributes[i], canTypeCheck: false);
+ if (attributes[i] is ComponentAttributeIntermediateNode attribute)
+ {
+ WriteComponentAttributeInnards(context, attribute, canTypeCheck: false);
+ }
+ else if (attributes[i] is SplatIntermediateNode splat)
+ {
+ WriteSplatInnards(context, splat, canTypeCheck: false);
+ }
remaining--;
if (remaining > 0)
@@ -429,7 +456,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
context.CodeWriter.Write(", ");
}
}
-
+
for (var i = 0; i < setKeys.Count; i++)
{
context.CodeWriter.Write((_sourceSequence++).ToString());
@@ -597,12 +624,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
}
}
- IReadOnlyList GetCSharpTokens(ComponentAttributeIntermediateNode attribute)
- {
- // We generally expect all children to be CSharp, this is here just in case.
- return attribute.FindDescendantNodes().Where(t => t.IsCSharp).ToArray();
- }
-
IReadOnlyList GetHtmlTokens(HtmlContentIntermediateNode html)
{
// We generally expect all children to be HTML, this is here just in case.
@@ -615,6 +636,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
}
}
+ private IReadOnlyList GetCSharpTokens(IntermediateNode node)
+ {
+ // We generally expect all children to be CSharp, this is here just in case.
+ return node.FindDescendantNodes().Where(t => t.IsCSharp).ToArray();
+ }
+
public override void WriteComponentChildContent(CodeRenderingContext context, ComponentChildContentIntermediateNode node)
{
if (context == null)
@@ -711,6 +738,54 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
});
}
+ public override void WriteSplat(CodeRenderingContext context, SplatIntermediateNode node)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ if (node == null)
+ {
+ throw new ArgumentNullException(nameof(node));
+ }
+
+ // Looks like:
+ //
+ // builder.AddMultipleAttributes(2, ...);
+ context.CodeWriter.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddMultipleAttributes}");
+ context.CodeWriter.Write((_sourceSequence++).ToString());
+ context.CodeWriter.WriteParameterSeparator();
+
+ WriteSplatInnards(context, node, canTypeCheck: true);
+
+ context.CodeWriter.WriteEndMethodInvocation();
+ }
+
+ private void WriteSplatInnards(CodeRenderingContext context, SplatIntermediateNode node, bool canTypeCheck)
+ {
+ var tokens = GetCSharpTokens(node);
+
+ if (canTypeCheck)
+ {
+ context.CodeWriter.Write(ComponentsApi.RuntimeHelpers.TypeCheck);
+ context.CodeWriter.Write("<");
+ context.CodeWriter.Write(ComponentsApi.AddMultipleAttributesTypeFullName);
+ context.CodeWriter.Write(">");
+ context.CodeWriter.Write("(");
+ }
+
+ for (var i = 0; i < tokens.Count; i++)
+ {
+ WriteCSharpToken(context, tokens[i]);
+ }
+
+ if (canTypeCheck)
+ {
+ context.CodeWriter.Write(")");
+ }
+ }
+
public override void WriteReferenceCapture(CodeRenderingContext context, ReferenceCaptureIntermediateNode node)
{
// Looks like:
@@ -759,7 +834,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
});
}
}
-
+
private void WriteAttribute(CodeRenderingContext context, string key, IList value)
{
BeginWriteAttribute(context.CodeWriter, key);
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentSplatLoweringPass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentSplatLoweringPass.cs
new file mode 100644
index 0000000000..a1d7ed5cf9
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentSplatLoweringPass.cs
@@ -0,0 +1,52 @@
+// 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 System.Linq;
+using Microsoft.AspNetCore.Razor.Language.Intermediate;
+
+namespace Microsoft.AspNetCore.Razor.Language.Components
+{
+ internal class ComponentSplatLoweringPass : ComponentIntermediateNodePassBase, IRazorOptimizationPass
+ {
+ // Run after component lowering pass
+ public override int Order => 50;
+
+ protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
+ {
+ if (!IsComponentDocument(documentNode))
+ {
+ return;
+ }
+
+ var references = documentNode.FindDescendantReferences();
+ var parents = new HashSet();
+ for (var i = 0; i < references.Count; i++)
+ {
+ parents.Add(references[i].Parent);
+ }
+
+ for (var i = 0; i < references.Count; i++)
+ {
+ var reference = references[i];
+ var node = (TagHelperDirectiveAttributeIntermediateNode)reference.Node;
+ if (node.TagHelper.IsSplatTagHelper())
+ {
+ reference.Replace(RewriteUsage(reference.Parent, node));
+ }
+ }
+ }
+
+ private IntermediateNode RewriteUsage(IntermediateNode parent, TagHelperDirectiveAttributeIntermediateNode node)
+ {
+ var result = new SplatIntermediateNode()
+ {
+ Source = node.Source,
+ };
+
+ result.Children.AddRange(node.FindDescendantNodes().Where(t => t.IsCSharp));
+ result.Diagnostics.AddRange(node.Diagnostics);
+ return result;
+ }
+ }
+}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentsApi.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentsApi.cs
index 45f99abb3b..94d7895fe6 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentsApi.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentsApi.cs
@@ -9,6 +9,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
{
public static readonly string AssemblyName = "Microsoft.AspNetCore.Components";
+ public static readonly string AddMultipleAttributesTypeFullName = "global::System.Collections.Generic.IEnumerable>";
+
public static class ComponentBase
{
public static readonly string Namespace = "Microsoft.AspNetCore.Components";
@@ -78,6 +80,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
public static readonly string AddAttribute = nameof(AddAttribute);
+ public static readonly string AddMultipleAttributes = nameof(AddMultipleAttributes);
+
public static readonly string AddElementReferenceCapture = nameof(AddElementReferenceCapture);
public static readonly string AddComponentReferenceCapture = nameof(AddComponentReferenceCapture);
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/TagHelperDescriptorExtensions.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/TagHelperDescriptorExtensions.cs
index 6cb9f26bc6..6ea32c7171 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/TagHelperDescriptorExtensions.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/TagHelperDescriptorExtensions.cs
@@ -9,6 +9,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
{
internal static class TagHelperDescriptorExtensions
{
+ public static bool IsAnyComponentDocumentTagHelper(this TagHelperDescriptor tagHelper)
+ {
+ if (tagHelper == null)
+ {
+ throw new ArgumentNullException(nameof(tagHelper));
+ }
+
+ return tagHelper.IsComponentTagHelper() || tagHelper.Metadata.ContainsKey(ComponentMetadata.SpecialKindKey);
+ }
+
public static bool IsBindTagHelper(this TagHelperDescriptor tagHelper)
{
if (tagHelper == null)
@@ -153,6 +163,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
string.Equals(ComponentMetadata.Key.TagHelperKind, kind);
}
+ public static bool IsSplatTagHelper(this TagHelperDescriptor tagHelper)
+ {
+ if (tagHelper == null)
+ {
+ throw new ArgumentNullException(nameof(tagHelper));
+ }
+
+ return
+ tagHelper.Metadata.TryGetValue(ComponentMetadata.SpecialKindKey, out var kind) &&
+ string.Equals(ComponentMetadata.Splat.TagHelperKind, kind);
+ }
+
public static bool IsRefTagHelper(this TagHelperDescriptor tagHelper)
{
if (tagHelper == null)
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperBinderPhase.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperBinderPhase.cs
index 788b22c597..e9982aa2c5 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperBinderPhase.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperBinderPhase.cs
@@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.Razor.Language
public TagHelperDirectiveVisitor(IReadOnlyList tagHelpers)
{
// We don't want to consider components in a view document.
- _tagHelpers = tagHelpers.Where(t => !ComponentMetadata.IsComponentTagHelperKind(t.Kind)).ToList();
+ _tagHelpers = tagHelpers.Where(t => !t.IsAnyComponentDocumentTagHelper()).ToList();
}
public override string TagHelperPrefix => _tagHelperPrefix;
@@ -232,7 +232,7 @@ namespace Microsoft.AspNetCore.Razor.Language
_filePath = filePath;
// We don't want to consider non-component tag helpers in a component document.
- _tagHelpers = tagHelpers.Where(t => ComponentMetadata.IsComponentTagHelperKind(t.Kind) && !IsTagHelperFromMangledClass(t)).ToList();
+ _tagHelpers = tagHelpers.Where(t => t.IsAnyComponentDocumentTagHelper() && !IsTagHelperFromMangledClass(t)).ToList();
for (var i = 0; i < _tagHelpers.Count; i++)
{
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentIntermediateNode.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentIntermediateNode.cs
index 7b623a0fe9..cfe7c3a276 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentIntermediateNode.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentIntermediateNode.cs
@@ -4,9 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
-using Microsoft.AspNetCore.Razor.Language.Components;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
@@ -18,6 +15,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
public IEnumerable SetKeys => Children.OfType();
+ public IEnumerable Splats => Children.OfType();
+
public IEnumerable ChildContents => Children.OfType();
public override IntermediateNodeCollection Children { get; } = new IntermediateNodeCollection();
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentTypeInferenceMethodIntermediateNode.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentTypeInferenceMethodIntermediateNode.cs
index 97829bbcbc..35340f0172 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentTypeInferenceMethodIntermediateNode.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentTypeInferenceMethodIntermediateNode.cs
@@ -2,8 +2,6 @@
// 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.CodeGeneration;
-using Microsoft.AspNetCore.Razor.Language.Components;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeCollection.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeCollection.cs
index 4c50fa1240..409dddad30 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeCollection.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeCollection.cs
@@ -59,6 +59,33 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
_inner.Add(item);
}
+ public void AddRange(IEnumerable items)
+ {
+ if (items == null)
+ {
+ throw new ArgumentNullException(nameof(items));
+ }
+
+ foreach (var item in items)
+ {
+ _inner.Add(item);
+ }
+ }
+
+ public void AddRange(IntermediateNodeCollection items)
+ {
+ if (items == null)
+ {
+ throw new ArgumentNullException(nameof(items));
+ }
+
+ var count = items.Count;
+ for (var i = 0; i < count; i++)
+ {
+ _inner.Add(items[i]);
+ }
+ }
+
public void Clear()
{
_inner.Clear();
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeVisitor.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeVisitor.cs
index 1489e23002..6aa7ba085c 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeVisitor.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeVisitor.cs
@@ -183,5 +183,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
VisitDefault(node);
}
+
+ public virtual void VisitSplat(SplatIntermediateNode node)
+ {
+ VisitDefault(node);
+ }
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/MarkupElementIntermediateNode.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/MarkupElementIntermediateNode.cs
index bf70855bc3..db29186789 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/MarkupElementIntermediateNode.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/MarkupElementIntermediateNode.cs
@@ -20,6 +20,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
return
c as HtmlAttributeIntermediateNode == null &&
+ c as SplatIntermediateNode == null &&
c as SetKeyIntermediateNode == null &&
c as ReferenceCaptureIntermediateNode == null;
});
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/SplatIntermediateNode.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/SplatIntermediateNode.cs
new file mode 100644
index 0000000000..1a64be2d5a
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/SplatIntermediateNode.cs
@@ -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;
+
+namespace Microsoft.AspNetCore.Razor.Language.Intermediate
+{
+ public sealed class SplatIntermediateNode : IntermediateNode
+ {
+ public override IntermediateNodeCollection Children { get; } = new IntermediateNodeCollection();
+
+ public override void Accept(IntermediateNodeVisitor visitor)
+ {
+ if (visitor == null)
+ {
+ throw new ArgumentNullException(nameof(visitor));
+ }
+
+ visitor.VisitSplat(this);
+ }
+
+ public override void FormatNode(IntermediateNodeFormatter formatter)
+ {
+ if (formatter == null)
+ {
+ throw new ArgumentNullException(nameof(formatter));
+ }
+
+ // No properties => do nothing
+ }
+ }
+}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorDiagnosticCollection.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorDiagnosticCollection.cs
index 46f35ac3e0..71464ad304 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorDiagnosticCollection.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorDiagnosticCollection.cs
@@ -52,6 +52,16 @@ namespace Microsoft.AspNetCore.Razor.Language
_inner.Add(item);
}
+ public void AddRange(RazorDiagnosticCollection items)
+ {
+ if (items == null)
+ {
+ throw new ArgumentNullException(nameof(items));
+ }
+
+ _inner.AddRange(items);
+ }
+
public void Clear()
{
_inner.Clear();
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngine.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngine.cs
index 9ae6652fe7..07729dcd25 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngine.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngine.cs
@@ -231,6 +231,7 @@ namespace Microsoft.AspNetCore.Razor.Language
builder.Features.Add(new ComponentEventHandlerLoweringPass());
builder.Features.Add(new ComponentKeyLoweringPass());
builder.Features.Add(new ComponentReferenceCaptureLoweringPass());
+ builder.Features.Add(new ComponentSplatLoweringPass());
builder.Features.Add(new ComponentBindLoweringPass());
builder.Features.Add(new ComponentTemplateDiagnosticPass());
builder.Features.Add(new ComponentGenericTypePass());
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs
index e46a5808d6..5b17860cd3 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs
@@ -3200,6 +3200,185 @@ namespace Test
#endregion
+ #region Splat
+
+ [Fact]
+ public void Element_WithSplat()
+ {
+ // Arrange/Act
+ var generated = CompileToCSharp(@"
+Hello
+
+@code {
+ private Dictionary someAttributes = new Dictionary();
+}
+");
+
+ // Assert
+ AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
+ AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
+ CompileToAssembly(generated);
+ }
+
+ [Fact]
+ public void Element_WithSplat_ImplicitExpression()
+ {
+ // Arrange/Act
+ var generated = CompileToCSharp(@"
+Hello
+
+@code {
+ private Dictionary someAttributes = new Dictionary();
+}
+");
+
+ // Assert
+ AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
+ AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
+ CompileToAssembly(generated);
+ }
+
+ [Fact]
+ public void Element_WithSplat_ExplicitExpression()
+ {
+ // Arrange/Act
+ var generated = CompileToCSharp(@"
+Hello
+
+@code {
+ private Dictionary someAttributes = new Dictionary();
+}
+");
+
+ // Assert
+ AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
+ AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
+ CompileToAssembly(generated);
+ }
+
+ [Fact]
+ public void Component_WithSplat()
+ {
+ // Arrange
+ AdditionalSyntaxTrees.Add(Parse(@"
+using Microsoft.AspNetCore.Components;
+
+namespace Test
+{
+ public class MyComponent : ComponentBase
+ {
+ }
+}
+"));
+
+ // Arrange/Act
+ var generated = CompileToCSharp(@"
+
+
+@code {
+ private Dictionary someAttributes = new Dictionary();
+}
+");
+
+ // Assert
+ AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
+ AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
+ CompileToAssembly(generated);
+ }
+
+ [Fact]
+ public void Component_WithSplat_ImplicitExpression()
+ {
+ // Arrange
+ AdditionalSyntaxTrees.Add(Parse(@"
+using Microsoft.AspNetCore.Components;
+
+namespace Test
+{
+ public class MyComponent : ComponentBase
+ {
+ }
+}
+"));
+
+ // Arrange/Act
+ var generated = CompileToCSharp(@"
+
+
+@code {
+ private Dictionary someAttributes = new Dictionary();
+}
+");
+
+ // Assert
+ AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
+ AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
+ CompileToAssembly(generated);
+ }
+
+ [Fact]
+ public void Component_WithSplat_ExplicitExpression()
+ {
+ // Arrange
+ AdditionalSyntaxTrees.Add(Parse(@"
+using Microsoft.AspNetCore.Components;
+
+namespace Test
+{
+ public class MyComponent : ComponentBase
+ {
+ }
+}
+"));
+
+ // Arrange/Act
+ var generated = CompileToCSharp(@"
+
+
+@code {
+ private Dictionary someAttributes = new Dictionary();
+}
+");
+
+ // Assert
+ AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
+ AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
+ CompileToAssembly(generated);
+ }
+
+ [Fact]
+ public void Component_WithSplat_GenericTypeInference()
+ {
+ // Arrange
+ AdditionalSyntaxTrees.Add(Parse(@"
+using Microsoft.AspNetCore.Components;
+
+namespace Test
+{
+ public class MyComponent : ComponentBase
+ {
+ [Parameter] T Value { get; set;}
+ }
+}
+"));
+
+ // Arrange/Act
+ var generated = CompileToCSharp(@"
+
+
+@code {
+ private Dictionary someAttributes = new Dictionary();
+}
+");
+
+ // Assert
+ AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
+ AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
+ CompileToAssembly(generated);
+ }
+
+ #endregion
+
#region Ref
[Fact]
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorProjectEngineTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorProjectEngineTest.cs
index 8a7ac84c04..576c3cc448 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorProjectEngineTest.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorProjectEngineTest.cs
@@ -62,6 +62,7 @@ namespace Microsoft.AspNetCore.Razor.Language
feature => Assert.IsType(feature),
feature => Assert.IsType(feature),
feature => Assert.IsType(feature),
+ feature => Assert.IsType(feature),
feature => Assert.IsType(feature),
feature => Assert.IsType(feature),
feature => Assert.IsType(feature),
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat/TestComponent.codegen.cs
new file mode 100644
index 0000000000..0d4169fba6
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat/TestComponent.codegen.cs
@@ -0,0 +1,56 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ __o = "";
+ builder.AddMultipleAttributes(-1, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ __o = "";
+ builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment)((builder2) => {
+ }
+ ));
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+__o = typeof(MyComponent);
+
+#line default
+#line hidden
+#nullable disable
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat/TestComponent.ir.txt
new file mode 100644
index 0000000000..75b0855ba8
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat/TestComponent.ir.txt
@@ -0,0 +1,31 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning disable 0414
+ CSharpCode -
+ IntermediateToken - - CSharp - private static System.Object __o = null;
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning restore 0414
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ Component - (0:0,0 [92] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
+ ComponentAttribute - - AttributeBefore - AttributeStructure.DoubleQuotes
+ HtmlContent - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (51:0,51 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (51:0,51 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ ComponentAttribute - - AttributeAfter - AttributeStructure.DoubleQuotes
+ HtmlContent - (83:0,83 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (83:0,83 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ HtmlContent - (92:0,92 [4] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (92:0,92 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
+ HtmlContent - (197:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (197:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (103:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (103:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat/TestComponent.mappings.txt
new file mode 100644
index 0000000000..f41e1dd4b4
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat/TestComponent.mappings.txt
@@ -0,0 +1,14 @@
+Source Location: (51:0,51 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+|someAttributes|
+Generated Location: (1135:26,51 [14] )
+|someAttributes|
+
+Source Location: (103:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1666:47,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..043027af8e
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,56 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ __o = "";
+ builder.AddMultipleAttributes(-1, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ __o = "";
+ builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment)((builder2) => {
+ }
+ ));
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+__o = typeof(MyComponent);
+
+#line default
+#line hidden
+#nullable disable
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..2c052ccece
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,31 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning disable 0414
+ CSharpCode -
+ IntermediateToken - - CSharp - private static System.Object __o = null;
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning restore 0414
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ Component - (0:0,0 [95] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
+ ComponentAttribute - - AttributeBefore - AttributeStructure.DoubleQuotes
+ HtmlContent - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (51:0,51 [17] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (53:0,53 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ ComponentAttribute - - AttributeAfter - AttributeStructure.DoubleQuotes
+ HtmlContent - (86:0,86 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (86:0,86 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ HtmlContent - (95:0,95 [4] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (95:0,95 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
+ HtmlContent - (200:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (200:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..d001b6cf92
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,14 @@
+Source Location: (53:0,53 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+|someAttributes|
+Generated Location: (1137:26,53 [14] )
+|someAttributes|
+
+Source Location: (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1668:47,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs
new file mode 100644
index 0000000000..9e861da4c2
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs
@@ -0,0 +1,73 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ __Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0(builder, -1, -1,
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ 18
+
+#line default
+#line hidden
+#nullable disable
+ , -1,
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ );
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+__o = typeof(MyComponent<>);
+
+#line default
+#line hidden
+#nullable disable
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+namespace __Blazor.Test.TestComponent
+{
+ #line hidden
+ internal static class TypeInference
+ {
+ public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, int seq, int __seq0, T __arg0, int __seq1, global::System.Collections.Generic.IEnumerable> __arg1)
+ {
+ builder.OpenComponent>(seq);
+ builder.AddAttribute(__seq0, "Value", __arg0);
+ builder.AddMultipleAttributes(__seq1, __arg1);
+ builder.CloseComponent();
+ }
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.ir.txt
new file mode 100644
index 0000000000..dcd6ec48af
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.ir.txt
@@ -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 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning disable 0414
+ CSharpCode -
+ IntermediateToken - - CSharp - private static System.Object __o = null;
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning restore 0414
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ Component - (0:0,0 [58] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
+ ComponentAttribute - (20:0,20 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Value - AttributeStructure.DoubleQuotes
+ IntermediateToken - (20:0,20 [2] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 18
+ Splat - (37:0,37 [17] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (39:0,39 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlContent - (58:0,58 [4] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (58:0,58 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
+ HtmlContent - (163:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (163:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (69:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (69:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
+ NamespaceDeclaration - - __Blazor.Test.TestComponent
+ ClassDeclaration - - internal static - TypeInference - -
+ ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateMyComponent_0
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt
new file mode 100644
index 0000000000..bb471b72f2
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt
@@ -0,0 +1,19 @@
+Source Location: (20:0,20 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+|18|
+Generated Location: (956:25,20 [2] )
+|18|
+
+Source Location: (39:0,39 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+|someAttributes|
+Generated Location: (1139:33,39 [14] )
+|someAttributes|
+
+Source Location: (69:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1497:50,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..72eef6602a
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,56 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ __o = "";
+ builder.AddMultipleAttributes(-1, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ __o = "";
+ builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment)((builder2) => {
+ }
+ ));
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+__o = typeof(MyComponent);
+
+#line default
+#line hidden
+#nullable disable
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..5413c22919
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,31 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning disable 0414
+ CSharpCode -
+ IntermediateToken - - CSharp - private static System.Object __o = null;
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning restore 0414
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ Component - (0:0,0 [93] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
+ ComponentAttribute - - AttributeBefore - AttributeStructure.DoubleQuotes
+ HtmlContent - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (51:0,51 [15] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (52:0,52 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ ComponentAttribute - - AttributeAfter - AttributeStructure.DoubleQuotes
+ HtmlContent - (84:0,84 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (84:0,84 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ HtmlContent - (93:0,93 [4] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (93:0,93 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
+ HtmlContent - (198:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (198:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (104:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (104:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..37bc7bc713
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,14 @@
+Source Location: (52:0,52 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+|someAttributes|
+Generated Location: (1136:26,52 [14] )
+|someAttributes|
+
+Source Location: (104:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1667:47,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat/TestComponent.codegen.cs
new file mode 100644
index 0000000000..425b0783a4
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat/TestComponent.codegen.cs
@@ -0,0 +1,44 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.AddMultipleAttributes(-1, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat/TestComponent.ir.txt
new file mode 100644
index 0000000000..4a7fee9ede
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat/TestComponent.ir.txt
@@ -0,0 +1,33 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ 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
+ MarkupElement - (0:0,0 [95] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (83:0,83 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (83:0,83 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (44:0,44 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (44:0,44 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ HtmlAttributeValue - (76:0,76 [5] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (76:0,76 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ HtmlContent - (95:0,95 [4] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (95:0,95 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
+ HtmlContent - (200:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (200:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat/TestComponent.mappings.txt
new file mode 100644
index 0000000000..7aa265e6be
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat/TestComponent.mappings.txt
@@ -0,0 +1,14 @@
+Source Location: (44:0,44 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+|someAttributes|
+Generated Location: (1105:25,44 [14] )
+|someAttributes|
+
+Source Location: (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1314:35,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..76a517831b
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.codegen.cs
@@ -0,0 +1,53 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ __o =
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ;
+ __o =
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ "after"
+
+#line default
+#line hidden
+#nullable disable
+ ;
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..a75a687119
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.ir.txt
@@ -0,0 +1,34 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ 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
+ MarkupElement - (0:0,0 [103] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (91:0,91 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (91:0,91 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ HtmlAttribute - (44:0,44 [17] x:\dir\subdir\Test\TestComponent.cshtml) - -
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - (46:0,46 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ CSharpExpressionAttributeValue - (79:0,79 [10] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (81:0,81 [7] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "after"
+ HtmlContent - (103:0,103 [4] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (103:0,103 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
+ HtmlContent - (208:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (208:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (114:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (114:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..945fbb3ba8
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.mappings.txt
@@ -0,0 +1,19 @@
+Source Location: (46:0,46 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+|someAttributes|
+Generated Location: (909:25,46 [14] )
+|someAttributes|
+
+Source Location: (81:0,81 [7] x:\dir\subdir\Test\TestComponent.cshtml)
+|"after"|
+Generated Location: (1161:34,81 [7] )
+|"after"|
+
+Source Location: (114:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1361:44,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..412b7925a6
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.codegen.cs
@@ -0,0 +1,53 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ __o =
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ;
+ __o =
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ "after"
+
+#line default
+#line hidden
+#nullable disable
+ ;
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..9102ec0b57
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.ir.txt
@@ -0,0 +1,34 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ 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
+ MarkupElement - (0:0,0 [101] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (89:0,89 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (89:0,89 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ HtmlAttribute - (44:0,44 [15] x:\dir\subdir\Test\TestComponent.cshtml) - -
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - (45:0,45 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ CSharpExpressionAttributeValue - (77:0,77 [10] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (79:0,79 [7] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "after"
+ HtmlContent - (101:0,101 [4] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (101:0,101 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
+ HtmlContent - (206:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (206:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (112:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (112:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..50bff77584
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.mappings.txt
@@ -0,0 +1,19 @@
+Source Location: (45:0,45 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+|someAttributes|
+Generated Location: (908:25,45 [14] )
+|someAttributes|
+
+Source Location: (79:0,79 [7] x:\dir\subdir\Test\TestComponent.cshtml)
+|"after"|
+Generated Location: (1158:34,79 [7] )
+|"after"|
+
+Source Location: (112:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1358:44,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..834d985403
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,44 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.AddMultipleAttributes(-1, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..26b987b602
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,33 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ 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
+ MarkupElement - (0:0,0 [98] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (86:0,86 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (86:0,86 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (44:0,44 [17] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (46:0,46 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ HtmlAttributeValue - (79:0,79 [5] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (79:0,79 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ HtmlContent - (98:0,98 [4] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (98:0,98 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
+ HtmlContent - (203:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (203:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (109:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (109:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..fe05732372
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,14 @@
+Source Location: (46:0,46 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+|someAttributes|
+Generated Location: (1107:25,46 [14] )
+|someAttributes|
+
+Source Location: (109:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1316:35,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..5e89ad26c1
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,44 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.AddMultipleAttributes(-1, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..c0246900dd
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,33 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ 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
+ MarkupElement - (0:0,0 [96] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (84:0,84 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (84:0,84 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (44:0,44 [15] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (45:0,45 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ HtmlAttributeValue - (77:0,77 [5] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (77:0,77 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ HtmlContent - (96:0,96 [4] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (96:0,96 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n
+ HtmlContent - (201:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (201:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (107:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (107:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..93a63203a3
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,14 @@
+Source Location: (45:0,45 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+|someAttributes|
+Generated Location: (1106:25,45 [14] )
+|someAttributes|
+
+Source Location: (107:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1315:35,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat/TestComponent.codegen.cs
new file mode 100644
index 0000000000..afcd1b2eaa
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat/TestComponent.codegen.cs
@@ -0,0 +1,41 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.OpenComponent(0);
+ builder.AddAttribute(1, "AttributeBefore", "before");
+ builder.AddMultipleAttributes(2, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ builder.AddAttribute(3, "AttributeAfter", "after");
+ builder.CloseComponent();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat/TestComponent.ir.txt
new file mode 100644
index 0000000000..30826c2804
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat/TestComponent.ir.txt
@@ -0,0 +1,20 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ Component - (0:0,0 [92] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
+ ComponentAttribute - - AttributeBefore - AttributeStructure.DoubleQuotes
+ HtmlContent - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (51:0,51 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (51:0,51 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ ComponentAttribute - - AttributeAfter - AttributeStructure.DoubleQuotes
+ HtmlContent - (83:0,83 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (83:0,83 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ CSharpCode - (103:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (103:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat/TestComponent.mappings.txt
new file mode 100644
index 0000000000..98281f7763
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (103:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1280:32,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..22260c859d
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,41 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.OpenComponent(0);
+ builder.AddAttribute(1, "AttributeBefore", "before");
+ builder.AddMultipleAttributes(2, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ builder.AddAttribute(3, "AttributeAfter", "after");
+ builder.CloseComponent();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..a26f802577
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,20 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ Component - (0:0,0 [95] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
+ ComponentAttribute - - AttributeBefore - AttributeStructure.DoubleQuotes
+ HtmlContent - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (51:0,51 [17] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (53:0,53 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ ComponentAttribute - - AttributeAfter - AttributeStructure.DoubleQuotes
+ HtmlContent - (86:0,86 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (86:0,86 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ CSharpCode - (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..5086704541
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ExplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1282:32,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs
new file mode 100644
index 0000000000..f9fa516a04
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.codegen.cs
@@ -0,0 +1,59 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ __Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0(builder, 0, 1,
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ 18
+
+#line default
+#line hidden
+#nullable disable
+ , 2,
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ );
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+namespace __Blazor.Test.TestComponent
+{
+ #line hidden
+ internal static class TypeInference
+ {
+ public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, int seq, int __seq0, T __arg0, int __seq1, global::System.Collections.Generic.IEnumerable> __arg1)
+ {
+ builder.OpenComponent>(seq);
+ builder.AddAttribute(__seq0, "Value", __arg0);
+ builder.AddMultipleAttributes(__seq1, __arg1);
+ builder.CloseComponent();
+ }
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.ir.txt
new file mode 100644
index 0000000000..286bcc16d5
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.ir.txt
@@ -0,0 +1,19 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ Component - (0:0,0 [58] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
+ ComponentAttribute - (20:0,20 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Value - AttributeStructure.DoubleQuotes
+ IntermediateToken - (20:0,20 [2] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 18
+ Splat - (37:0,37 [17] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (39:0,39 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ CSharpCode - (69:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (69:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
+ NamespaceDeclaration - - __Blazor.Test.TestComponent
+ ClassDeclaration - - internal static - TypeInference - -
+ ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateMyComponent_0
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt
new file mode 100644
index 0000000000..d5113c101d
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_GenericTypeInference/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (69:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1076:36,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_Generic_TypeInferenceBug/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_Generic_TypeInferenceBug/TestComponent.codegen.cs
new file mode 100644
index 0000000000..65e14caddc
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_Generic_TypeInferenceBug/TestComponent.codegen.cs
@@ -0,0 +1,59 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ __Blazor.Test.TestComponent.TypeInference.CreateMyComponent_0(builder, 0, 1,
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ 18
+
+#line default
+#line hidden
+#nullable disable
+ , 2,
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ );
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private IReadOnlyDictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+namespace __Blazor.Test.TestComponent
+{
+ #line hidden
+ internal static class TypeInference
+ {
+ public static void CreateMyComponent_0(global::Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, int seq, int __seq0, T __arg0, int __seq1, System.Collections.Generic.IEnumerable> __arg1)
+ {
+ builder.OpenComponent>(seq);
+ builder.AddAttribute(__seq0, "Value", __arg0);
+ builder.AddMultipleAttributes(__seq1, __arg1);
+ builder.CloseComponent();
+ }
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_Generic_TypeInferenceBug/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_Generic_TypeInferenceBug/TestComponent.ir.txt
new file mode 100644
index 0000000000..02f4391879
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_Generic_TypeInferenceBug/TestComponent.ir.txt
@@ -0,0 +1,20 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ Component - (0:0,0 [58] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
+ ComponentAttribute - (20:0,20 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Value - AttributeStructure.DoubleQuotes
+ IntermediateToken - (20:0,20 [2] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 18
+ ComponentAttribute - (37:0,37 [17] x:\dir\subdir\Test\TestComponent.cshtml) - - AttributeStructure.DoubleQuotes
+ CSharpExpression - (38:0,38 [16] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (39:0,39 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ CSharpCode - (69:2,7 [102] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (69:2,7 [102] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private IReadOnlyDictionary someAttributes = new Dictionary();\n
+ NamespaceDeclaration - - __Blazor.Test.TestComponent
+ ClassDeclaration - - internal static - TypeInference - -
+ ComponentTypeInferenceMethod - - __Blazor.Test.TestComponent.TypeInference - CreateMyComponent_0
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_Generic_TypeInferenceBug/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_Generic_TypeInferenceBug/TestComponent.mappings.txt
new file mode 100644
index 0000000000..20a61bad48
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_Generic_TypeInferenceBug/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (69:2,7 [102] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private IReadOnlyDictionary someAttributes = new Dictionary();
+|
+Generated Location: (1076:36,7 [102] )
+|
+ private IReadOnlyDictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..231cd3080e
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,41 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.OpenComponent(0);
+ builder.AddAttribute(1, "AttributeBefore", "before");
+ builder.AddMultipleAttributes(2, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ builder.AddAttribute(3, "AttributeAfter", "after");
+ builder.CloseComponent();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..328956d3b4
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,20 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ Component - (0:0,0 [93] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent
+ ComponentAttribute - - AttributeBefore - AttributeStructure.DoubleQuotes
+ HtmlContent - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (30:0,30 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (51:0,51 [15] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (52:0,52 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ ComponentAttribute - - AttributeAfter - AttributeStructure.DoubleQuotes
+ HtmlContent - (84:0,84 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (84:0,84 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ CSharpCode - (104:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (104:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..5bf6f2a952
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithSplat_ImplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (104:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1281:32,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat/TestComponent.codegen.cs
new file mode 100644
index 0000000000..dc1c1a70c9
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat/TestComponent.codegen.cs
@@ -0,0 +1,42 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.OpenElement(0, "elem");
+ builder.AddAttribute(1, "attributebefore", "before");
+ builder.AddMultipleAttributes(2, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ builder.AddAttribute(3, "attributeafter", "after");
+ builder.AddContent(4, "Hello");
+ builder.CloseElement();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat/TestComponent.ir.txt
new file mode 100644
index 0000000000..3d2bb8827d
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat/TestComponent.ir.txt
@@ -0,0 +1,22 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ MarkupElement - (0:0,0 [95] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (83:0,83 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (83:0,83 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (44:0,44 [14] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (44:0,44 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ HtmlAttributeValue - (76:0,76 [5] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (76:0,76 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ CSharpCode - (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat/TestComponent.mappings.txt
new file mode 100644
index 0000000000..e8700cac0c
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (106:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1304:33,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..45d0f576fa
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.codegen.cs
@@ -0,0 +1,50 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.OpenElement(0, "elem");
+ builder.AddAttribute(1, "attributebefore", "before");
+ builder.AddMultipleAttributes(2,
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ );
+ builder.AddAttribute(3, "attributeafter",
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ "after"
+
+#line default
+#line hidden
+#nullable disable
+ );
+ builder.AddContent(4, "Hello");
+ builder.CloseElement();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..bc5492667f
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.ir.txt
@@ -0,0 +1,23 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ MarkupElement - (0:0,0 [103] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (91:0,91 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (91:0,91 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ HtmlAttribute - (44:0,44 [17] x:\dir\subdir\Test\TestComponent.cshtml) - -
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - (46:0,46 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ CSharpExpressionAttributeValue - (79:0,79 [10] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (81:0,81 [7] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "after"
+ CSharpCode - (114:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (114:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..34c0a6c91b
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatExplictExpression/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (114:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1352:41,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..4f0ffe54ea
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.codegen.cs
@@ -0,0 +1,50 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.OpenElement(0, "elem");
+ builder.AddAttribute(1, "attributebefore", "before");
+ builder.AddMultipleAttributes(2,
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ );
+ builder.AddAttribute(3, "attributeafter",
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ "after"
+
+#line default
+#line hidden
+#nullable disable
+ );
+ builder.AddContent(4, "Hello");
+ builder.CloseElement();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..7337ac5168
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.ir.txt
@@ -0,0 +1,23 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ MarkupElement - (0:0,0 [101] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (89:0,89 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (89:0,89 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ HtmlAttribute - (44:0,44 [15] x:\dir\subdir\Test\TestComponent.cshtml) - -
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - (45:0,45 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ CSharpExpressionAttributeValue - (77:0,77 [10] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (79:0,79 [7] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - "after"
+ CSharpCode - (112:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (112:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..7c434c273a
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplatImplictExpression/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (112:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1349:41,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..93ef6b1df5
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,42 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.OpenElement(0, "elem");
+ builder.AddAttribute(1, "attributebefore", "before");
+ builder.AddMultipleAttributes(2, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ builder.AddAttribute(3, "attributeafter", "after");
+ builder.AddContent(4, "Hello");
+ builder.CloseElement();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..9b36e0b4c1
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,22 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ MarkupElement - (0:0,0 [98] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (86:0,86 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (86:0,86 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (44:0,44 [17] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (46:0,46 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ HtmlAttributeValue - (79:0,79 [5] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (79:0,79 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ CSharpCode - (109:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (109:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..6159a4bd7e
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ExplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (109:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1306:33,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..5ea9a1cef2
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,42 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
+ {
+ builder.OpenElement(0, "elem");
+ builder.AddAttribute(1, "attributebefore", "before");
+ builder.AddMultipleAttributes(2, Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck>>(
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ someAttributes
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ builder.AddAttribute(3, "attributeafter", "after");
+ builder.AddContent(4, "Hello");
+ builder.CloseElement();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ private Dictionary someAttributes = new Dictionary();
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..e028cc8181
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,22 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ MarkupElement - (0:0,0 [96] x:\dir\subdir\Test\TestComponent.cshtml) - elem
+ HtmlContent - (84:0,84 [5] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (84:0,84 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello
+ HtmlAttribute - - attributebefore=" - "
+ HtmlAttributeValue - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (23:0,23 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before
+ Splat - (44:0,44 [15] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (45:0,45 [14] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - someAttributes
+ HtmlAttribute - - attributeafter=" - "
+ HtmlAttributeValue - (77:0,77 [5] x:\dir\subdir\Test\TestComponent.cshtml) -
+ IntermediateToken - (77:0,77 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after
+ CSharpCode - (107:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (107:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Dictionary someAttributes = new Dictionary();\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..9dc859d5fb
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithSplat_ImplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,9 @@
+Source Location: (107:2,7 [93] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+Generated Location: (1305:33,7 [93] )
+|
+ private Dictionary someAttributes = new Dictionary();
+|
+
diff --git a/src/Razor/Microsoft.CodeAnalysis.Razor/src/CompilerFeatures.cs b/src/Razor/Microsoft.CodeAnalysis.Razor/src/CompilerFeatures.cs
index b555832cc8..a9ea37b7ec 100644
--- a/src/Razor/Microsoft.CodeAnalysis.Razor/src/CompilerFeatures.cs
+++ b/src/Razor/Microsoft.CodeAnalysis.Razor/src/CompilerFeatures.cs
@@ -29,6 +29,7 @@ namespace Microsoft.CodeAnalysis.Razor
builder.Features.Add(new EventHandlerTagHelperDescriptorProvider());
builder.Features.Add(new RefTagHelperDescriptorProvider());
builder.Features.Add(new KeyTagHelperDescriptorProvider());
+ builder.Features.Add(new SplatTagHelperDescriptorProvider());
builder.Features.Add(new DefaultTypeNameFeature());
}
diff --git a/src/Razor/Microsoft.CodeAnalysis.Razor/src/SplatTagHelperDescriptorProvider.cs b/src/Razor/Microsoft.CodeAnalysis.Razor/src/SplatTagHelperDescriptorProvider.cs
new file mode 100644
index 0000000000..86aa7a78e3
--- /dev/null
+++ b/src/Razor/Microsoft.CodeAnalysis.Razor/src/SplatTagHelperDescriptorProvider.cs
@@ -0,0 +1,79 @@
+// 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.Components;
+
+namespace Microsoft.CodeAnalysis.Razor
+{
+ internal class SplatTagHelperDescriptorProvider : ITagHelperDescriptorProvider
+ {
+ // Order doesn't matter
+ public int Order { get; set; }
+
+ public RazorEngine Engine { get; set; }
+
+ public void Execute(TagHelperDescriptorProviderContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ var compilation = context.GetCompilation();
+ if (compilation == null)
+ {
+ return;
+ }
+
+ var renderTreeBuilder = compilation.GetTypeByMetadataName(ComponentsApi.RenderTreeBuilder.FullTypeName);
+ if (renderTreeBuilder == null)
+ {
+ // If we can't find RenderTreeBuilder, then just bail. We won't be able to compile the
+ // generated code anyway.
+ return;
+ }
+
+ context.Results.Add(CreateSplatTagHelper());
+ }
+
+ private TagHelperDescriptor CreateSplatTagHelper()
+ {
+ var builder = TagHelperDescriptorBuilder.Create(ComponentMetadata.Splat.TagHelperKind, "Attributes", ComponentsApi.AssemblyName);
+ builder.Documentation = ComponentResources.SplatTagHelper_Documentation;
+
+ builder.Metadata.Add(ComponentMetadata.SpecialKindKey, ComponentMetadata.Splat.TagHelperKind);
+ builder.Metadata.Add(TagHelperMetadata.Common.ClassifyAttributesOnly, bool.TrueString);
+ builder.Metadata[TagHelperMetadata.Runtime.Name] = ComponentMetadata.Splat.RuntimeName;
+
+ // WTE has a bug in 15.7p1 where a Tag Helper without a display-name that looks like
+ // a C# property will crash trying to create the tooltips.
+ builder.SetTypeName("Microsoft.AspNetCore.Components.Attributes");
+
+ builder.TagMatchingRule(rule =>
+ {
+ rule.TagName = "*";
+ rule.Attribute(attribute =>
+ {
+ attribute.Name = "@attributes";
+ attribute.Metadata[ComponentMetadata.Common.DirectiveAttribute] = bool.TrueString;
+ });
+ });
+
+ builder.BindAttribute(attribute =>
+ {
+ attribute.Documentation = ComponentResources.SplatTagHelper_Documentation;
+ attribute.Name = "@attributes";
+
+ // WTE has a bug 15.7p1 where a Tag Helper without a display-name that looks like
+ // a C# property will crash trying to create the tooltips.
+ attribute.SetPropertyName("Attributes");
+ attribute.TypeName = typeof(object).FullName;
+ attribute.Metadata[ComponentMetadata.Common.DirectiveAttribute] = bool.TrueString;
+ });
+
+ return builder.Build();
+ }
+ }
+}
diff --git a/src/Razor/Microsoft.CodeAnalysis.Razor/test/SplatTagHelperDescriptorProviderTest.cs b/src/Razor/Microsoft.CodeAnalysis.Razor/test/SplatTagHelperDescriptorProviderTest.cs
new file mode 100644
index 0000000000..c07c95a2aa
--- /dev/null
+++ b/src/Razor/Microsoft.CodeAnalysis.Razor/test/SplatTagHelperDescriptorProviderTest.cs
@@ -0,0 +1,87 @@
+// 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.Linq;
+using Microsoft.AspNetCore.Razor.Language;
+using Microsoft.AspNetCore.Razor.Language.Components;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Razor
+{
+ public class SplatTagHelperDescriptorProviderTest : TagHelperDescriptorProviderTestBase
+ {
+ [Fact]
+ public void Execute_CreatesDescriptor()
+ {
+ // Arrange
+ var context = TagHelperDescriptorProviderContext.Create();
+ context.SetCompilation(BaseCompilation);
+
+ var provider = new SplatTagHelperDescriptorProvider();
+
+ // Act
+ provider.Execute(context);
+
+ // Assert
+ var matches = context.Results.Where(result => result.IsSplatTagHelper());
+ var item = Assert.Single(matches);
+
+ Assert.Empty(item.AllowedChildTags);
+ Assert.Null(item.TagOutputHint);
+ Assert.Empty(item.Diagnostics);
+ Assert.False(item.HasErrors);
+ Assert.Equal(ComponentMetadata.Splat.TagHelperKind, item.Kind);
+ Assert.Equal(bool.TrueString, item.Metadata[TagHelperMetadata.Common.ClassifyAttributesOnly]);
+ Assert.Equal(ComponentMetadata.Splat.RuntimeName, item.Metadata[TagHelperMetadata.Runtime.Name]);
+ Assert.False(item.IsDefaultKind());
+ Assert.False(item.KindUsesDefaultTagHelperRuntime());
+
+ Assert.Equal(
+ "Merges a collection of attributes into the current element or component.",
+ item.Documentation);
+
+ Assert.Equal("Microsoft.AspNetCore.Components", item.AssemblyName);
+ Assert.Equal("Attributes", item.Name);
+ Assert.Equal("Microsoft.AspNetCore.Components.Attributes", item.DisplayName);
+ Assert.Equal("Microsoft.AspNetCore.Components.Attributes", item.GetTypeName());
+
+ var rule = Assert.Single(item.TagMatchingRules);
+ Assert.Empty(rule.Diagnostics);
+ Assert.False(rule.HasErrors);
+ Assert.Null(rule.ParentTag);
+ Assert.Equal("*", rule.TagName);
+ Assert.Equal(TagStructure.Unspecified, rule.TagStructure);
+
+ var requiredAttribute = Assert.Single(rule.Attributes);
+ Assert.Empty(requiredAttribute.Diagnostics);
+ Assert.Equal("@attributes", requiredAttribute.DisplayName);
+ Assert.Equal("@attributes", requiredAttribute.Name);
+ Assert.Equal(RequiredAttributeDescriptor.NameComparisonMode.FullMatch, requiredAttribute.NameComparison);
+ Assert.Null(requiredAttribute.Value);
+ Assert.Equal(RequiredAttributeDescriptor.ValueComparisonMode.None, requiredAttribute.ValueComparison);
+
+ var attribute = Assert.Single(item.BoundAttributes);
+ Assert.Empty(attribute.Diagnostics);
+ Assert.False(attribute.HasErrors);
+ Assert.Equal(ComponentMetadata.Splat.TagHelperKind, attribute.Kind);
+ Assert.False(attribute.IsDefaultKind());
+ Assert.False(attribute.HasIndexer);
+ Assert.Null(attribute.IndexerNamePrefix);
+ Assert.Null(attribute.IndexerTypeName);
+ Assert.False(attribute.IsIndexerBooleanProperty);
+ Assert.False(attribute.IsIndexerStringProperty);
+
+ Assert.Equal(
+ "Merges a collection of attributes into the current element or component.",
+ attribute.Documentation);
+
+ Assert.Equal("@attributes", attribute.Name);
+ Assert.Equal("Attributes", attribute.GetPropertyName());
+ Assert.Equal("object Microsoft.AspNetCore.Components.Attributes.Attributes", attribute.DisplayName);
+ Assert.Equal("System.Object", attribute.TypeName);
+ Assert.False(attribute.IsStringProperty);
+ Assert.False(attribute.IsBooleanProperty);
+ Assert.False(attribute.IsEnum);
+ }
+ }
+}
diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.ComponentShim/Microsoft.AspNetCore.Components/RenderTree/RenderTreeBuilder.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.ComponentShim/Microsoft.AspNetCore.Components/RenderTree/RenderTreeBuilder.cs
index 2dace410eb..98d8a0bdb4 100644
--- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.ComponentShim/Microsoft.AspNetCore.Components/RenderTree/RenderTreeBuilder.cs
+++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.ComponentShim/Microsoft.AspNetCore.Components/RenderTree/RenderTreeBuilder.cs
@@ -84,6 +84,10 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{
}
+ public void AddMultipleAttributes(int sequence, IEnumerable> attributes)
+ {
+ }
+
public void OpenComponent(int sequence) where TComponent : IComponent
{
}