From ed04f3ebb8a43f586a4b8aa79dd2a965b0232289 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 29 Apr 2019 16:16:05 +0100 Subject: [PATCH] 'key' directive attribute for components (dotnet/aspnetcore-tooling#508) \n\nCommit migrated from https://github.com/dotnet/aspnetcore-tooling/commit/0803d3bbed3e7a5b17e4e167ea953d263bbae4b9 --- .../CodeGeneration/DefaultDocumentWriter.cs | 5 + .../CodeGeneration/IntermediateNodeWriter.cs | 5 + .../src/ComponentResources.Designer.cs | 9 + .../src/ComponentResources.resx | 3 + .../ComponentDesignTimeNodeWriter.cs | 59 ++++++- .../Components/ComponentKeyLoweringPass.cs | 76 ++++++++ .../src/Components/ComponentMetadata.cs | 8 + .../src/Components/ComponentNodeWriter.cs | 14 ++ .../Components/ComponentRuntimeNodeWriter.cs | 54 +++++- .../src/Components/ComponentsApi.cs | 2 + .../TagHelperDescriptorExtensions.cs | 12 ++ .../Intermediate/ComponentIntermediateNode.cs | 2 + .../Intermediate/IntermediateNodeVisitor.cs | 5 + .../MarkupElementIntermediateNode.cs | 3 + .../Intermediate/SetKeyIntermediateNode.cs | 42 +++++ .../src/RazorProjectEngine.cs | 1 + .../ComponentCodeGenerationTestBase.cs | 162 ++++++++++++++++++ .../test/RazorProjectEngineTest.cs | 1 + .../TestComponent.codegen.cs | 56 ++++++ .../Component_WithKey/TestComponent.ir.txt | 30 ++++ .../TestComponent.mappings.txt | 14 ++ .../TestComponent.codegen.cs | 47 +++++ .../TestComponent.ir.txt | 31 ++++ .../TestComponent.mappings.txt | 5 + .../Element_WithKey/TestComponent.codegen.cs | 44 +++++ .../Element_WithKey/TestComponent.ir.txt | 32 ++++ .../TestComponent.mappings.txt | 14 ++ .../TestComponent.codegen.cs | 56 ++++++ .../TestComponent.ir.txt | 30 ++++ .../TestComponent.mappings.txt | 23 +++ .../TestComponent.codegen.cs | 72 ++++++++ .../TestComponent.ir.txt | 28 +++ .../TestComponent.mappings.txt | 24 +++ .../TestComponent.codegen.cs | 73 ++++++++ .../TestComponent.ir.txt | 29 ++++ .../TestComponent.mappings.txt | 19 ++ .../TestComponent.codegen.cs | 41 +++++ .../Component_WithKey/TestComponent.ir.txt | 19 ++ .../TestComponent.mappings.txt | 14 ++ .../TestComponent.codegen.cs | 37 ++++ .../TestComponent.ir.txt | 18 ++ .../TestComponent.mappings.txt | 5 + .../Element_WithKey/TestComponent.codegen.cs | 42 +++++ .../Element_WithKey/TestComponent.ir.txt | 21 +++ .../TestComponent.mappings.txt | 14 ++ .../TestComponent.codegen.cs | 52 ++++++ .../TestComponent.ir.txt | 19 ++ .../TestComponent.mappings.txt | 18 ++ .../TestComponent.codegen.cs | 48 ++++++ .../TestComponent.ir.txt | 17 ++ .../TestComponent.mappings.txt | 14 ++ .../TestComponent.codegen.cs | 59 +++++++ .../TestComponent.ir.txt | 18 ++ .../TestComponent.mappings.txt | 14 ++ .../src/CompilerFeatures.cs | 1 + .../src/KeyTagHelperDescriptorProvider.cs | 77 +++++++++ .../KeyTagHelperDescriptorProviderTest.cs | 88 ++++++++++ .../IntermediateNodeWriter.cs | 5 + .../RenderTree/RenderTreeBuilder.cs | 4 + 59 files changed, 1733 insertions(+), 2 deletions(-) create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentKeyLoweringPass.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/SetKeyIntermediateNode.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.ir.txt create mode 100644 src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt create mode 100644 src/Razor/Microsoft.CodeAnalysis.Razor/src/KeyTagHelperDescriptorProvider.cs create mode 100644 src/Razor/Microsoft.CodeAnalysis.Razor/test/KeyTagHelperDescriptorProviderTest.cs 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 d6fb6742da..294304dd18 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/DefaultDocumentWriter.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/DefaultDocumentWriter.cs @@ -297,6 +297,11 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration Context.NodeWriter.WriteReferenceCapture(Context, node); } + public override void VisitSetKey(SetKeyIntermediateNode node) + { + Context.NodeWriter.WriteSetKey(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 c8a3c6659a..d4e49066f9 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/IntermediateNodeWriter.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/IntermediateNodeWriter.cs @@ -64,6 +64,11 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration throw new NotSupportedException("This writer does not support components."); } + public virtual void WriteSetKey(CodeRenderingContext context, SetKeyIntermediateNode 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.Designer.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.Designer.cs index 5d4e39e752..10af5b8063 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.Designer.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.Designer.cs @@ -168,6 +168,15 @@ namespace Microsoft.AspNetCore.Razor.Language { } } + /// + /// Looks up a localized string similar to Ensures that the component or element will be preserved across renders if (and only if) the supplied key value matches.. + /// + internal static string KeyTagHelper_Documentation { + get { + return ResourceManager.GetString("KeyTagHelper_Documentation", resourceCulture); + } + } + /// /// Looks up a localized string similar to Declares a layout type for the current document.. /// diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx index 4a27c934ae..48b636ec27 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx @@ -153,6 +153,9 @@ TypeName + + Ensures that the component or element will be preserved across renders if (and only if) the supplied key value matches. + Declares a layout type for the current document. 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 f18235f463..9b38d73700 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs @@ -314,6 +314,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components // builder.OpenComponent(0); // builder.AddAttribute(1, "Foo", ...); // builder.AddAttribute(2, "ChildContent", ...); + // builder.SetKey(someValue); // builder.AddElementCapture(3, (__value) => _field = __value); // builder.CloseComponent(); foreach (var typeArgument in node.TypeArguments) @@ -347,6 +348,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Components }); } + foreach (var setKey in node.SetKeys) + { + context.RenderNode(setKey); + } + foreach (var capture in node.Captures) { context.RenderNode(capture); @@ -362,7 +368,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Components var attributes = node.Attributes.ToList(); var childContents = node.ChildContents.ToList(); var captures = node.Captures.ToList(); - var remaining = attributes.Count + childContents.Count + captures.Count; + var setKeys = node.SetKeys.ToList(); + var remaining = attributes.Count + childContents.Count + captures.Count + setKeys.Count; context.CodeWriter.Write(node.TypeInferenceNode.FullTypeName); context.CodeWriter.Write("."); @@ -406,6 +413,20 @@ namespace Microsoft.AspNetCore.Razor.Language.Components } } + for (var i = 0; i < setKeys.Count; i++) + { + context.CodeWriter.Write("-1"); + context.CodeWriter.Write(", "); + + WriteSetKeyInnards(context, setKeys[i]); + + remaining--; + if (remaining > 0) + { + context.CodeWriter.Write(", "); + } + } + for (var i = 0; i < captures.Count; i++) { context.CodeWriter.Write("-1"); @@ -717,6 +738,42 @@ namespace Microsoft.AspNetCore.Razor.Language.Components _scopeStack.CloseScope(context); } + public override void WriteSetKey(CodeRenderingContext context, SetKeyIntermediateNode node) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (node == null) + { + throw new ArgumentNullException(nameof(node)); + } + + // Looks like: + // + // builder.SetKey(_keyValue); + + var codeWriter = context.CodeWriter; + + codeWriter + .WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.SetKey}"); + WriteSetKeyInnards(context, node); + codeWriter.WriteEndMethodInvocation(); + } + + private void WriteSetKeyInnards(CodeRenderingContext context, SetKeyIntermediateNode node) + { + WriteCSharpCode(context, new CSharpCodeIntermediateNode + { + Source = node.Source, + Children = + { + node.KeyValueToken + } + }); + } + public override void WriteReferenceCapture(CodeRenderingContext context, ReferenceCaptureIntermediateNode node) { if (context == null) diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentKeyLoweringPass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentKeyLoweringPass.cs new file mode 100644 index 0000000000..7dad9740d5 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentKeyLoweringPass.cs @@ -0,0 +1,76 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Razor.Language.Intermediate; + +namespace Microsoft.AspNetCore.Razor.Language.Components +{ + internal class ComponentKeyLoweringPass : 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 @namespace = documentNode.FindPrimaryNamespace(); + var @class = documentNode.FindPrimaryClass(); + if (@namespace == null || @class == null) + { + // Nothing to do, bail. We can't function without the standard structure. + return; + } + + var references = documentNode.FindDescendantReferences(); + for (var i = 0; i < references.Count; i++) + { + var reference = references[i]; + var node = (TagHelperPropertyIntermediateNode)reference.Node; + + if (node.TagHelper.IsKeyTagHelper()) + { + reference.Replace(RewriteUsage(reference.Parent, node)); + } + } + } + + private IntermediateNode RewriteUsage(IntermediateNode parent, TagHelperPropertyIntermediateNode node) + { + // If we can't get a nonempty attribute value, do nothing because there will + // already be a diagnostic for empty values + var keyValueToken = DetermineKeyValueToken(node); + if (keyValueToken == null) + { + return node; + } + + return new SetKeyIntermediateNode(keyValueToken); + } + + private IntermediateToken DetermineKeyValueToken(TagHelperPropertyIntermediateNode attributeNode) + { + IntermediateToken foundToken = null; + + if (attributeNode.Children.Count == 1) + { + if (attributeNode.Children[0] is IntermediateToken token) + { + foundToken = token; + } + else if (attributeNode.Children[0] is CSharpExpressionIntermediateNode csharpNode) + { + if (csharpNode.Children.Count == 1) + { + foundToken = csharpNode.Children[0] as IntermediateToken; + } + } + } + + return !string.IsNullOrWhiteSpace(foundToken?.Content) ? foundToken : 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 17966db799..f57daad348 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentMetadata.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentMetadata.cs @@ -23,6 +23,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components tagHelperKind == ChildContent.TagHelperKind || tagHelperKind == EventHandler.TagHelperKind || tagHelperKind == Bind.TagHelperKind || + tagHelperKind == Key.TagHelperKind || tagHelperKind == Ref.TagHelperKind; } @@ -116,6 +117,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Components public readonly static string TagHelperKind = "Components.EventHandler"; } + public static class Key + { + public readonly static string TagHelperKind = "Components.Key"; + + 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 0629f7dc69..ca8704fef0 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs @@ -160,6 +160,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Components index++; } + foreach (var setKey in node.Component.SetKeys) + { + context.CodeWriter.WriteStartInstanceMethodInvocation("builder", ComponentsApi.RenderTreeBuilder.SetKey); + context.CodeWriter.Write(parameters[index].parameterName); + context.CodeWriter.WriteEndMethodInvocation(); + + index++; + } + foreach (var capture in node.Component.Captures) { context.CodeWriter.WriteStartInstanceMethodInvocation("builder", capture.IsComponentCapture ? ComponentsApi.RenderTreeBuilder.AddComponentReferenceCapture : ComponentsApi.RenderTreeBuilder.AddElementReferenceCapture); @@ -200,6 +209,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Components p.Add(($"__seq{p.Count}", typeName, $"__arg{p.Count}")); } + foreach (var capture in node.Component.SetKeys) + { + p.Add(($"__seq{p.Count}", "object", $"__arg{p.Count}")); + } + foreach (var capture in node.Component.Captures) { // The capture type name should already contain the global:: prefix. 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 83d1c2941f..a3224213a9 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs @@ -190,6 +190,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Components context.RenderNode(attribute); } + foreach (var setKey in node.SetKeys) + { + context.RenderNode(setKey); + } + foreach (var capture in node.Captures) { context.RenderNode(capture); @@ -317,6 +322,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components // builder.OpenComponent(0); // builder.AddAttribute(1, "Foo", ...); // builder.AddAttribute(2, "ChildContent", ...); + // builder.SetKey(someValue); // builder.AddElementCapture(3, (__value) => _field = __value); // builder.CloseComponent(); @@ -344,6 +350,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Components context.RenderNode(childContent); } + foreach (var setKey in node.SetKeys) + { + context.RenderNode(setKey); + } + foreach (var capture in node.Captures) { context.RenderNode(capture); @@ -366,7 +377,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Components var attributes = node.Attributes.ToList(); var childContents = node.ChildContents.ToList(); var captures = node.Captures.ToList(); - var remaining = attributes.Count + childContents.Count + captures.Count; + var setKeys = node.SetKeys.ToList(); + var remaining = attributes.Count + childContents.Count + captures.Count + setKeys.Count; context.CodeWriter.Write(node.TypeInferenceNode.FullTypeName); context.CodeWriter.Write("."); @@ -410,6 +422,20 @@ namespace Microsoft.AspNetCore.Razor.Language.Components } } + for (var i = 0; i < setKeys.Count; i++) + { + context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write(", "); + + WriteSetKeyInnards(context, setKeys[i]); + + remaining--; + if (remaining > 0) + { + context.CodeWriter.Write(", "); + } + } + for (var i = 0; i < captures.Count; i++) { context.CodeWriter.Write((_sourceSequence++).ToString()); @@ -651,6 +677,32 @@ namespace Microsoft.AspNetCore.Razor.Language.Components _scopeStack.CloseScope(context); } + public override void WriteSetKey(CodeRenderingContext context, SetKeyIntermediateNode node) + { + // Looks like: + // + // builder.SetKey(_keyValue); + + var codeWriter = context.CodeWriter; + + codeWriter + .WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.SetKey}"); + WriteSetKeyInnards(context, node); + codeWriter.WriteEndMethodInvocation(); + } + + private void WriteSetKeyInnards(CodeRenderingContext context, SetKeyIntermediateNode node) + { + WriteCSharpCode(context, new CSharpCodeIntermediateNode + { + Source = node.Source, + Children = + { + node.KeyValueToken + } + }); + } + public override void WriteReferenceCapture(CodeRenderingContext context, ReferenceCaptureIntermediateNode node) { // Looks like: 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 59db7873dd..858dd7169b 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentsApi.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentsApi.cs @@ -87,6 +87,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Components public static readonly string GetFrames = nameof(GetFrames); public static readonly string ChildContent = nameof(ChildContent); + + public static readonly string SetKey = nameof(SetKey); } public static class RuntimeHelpers 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 1bbd8d8ace..8d16b94f9d 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/TagHelperDescriptorExtensions.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/TagHelperDescriptorExtensions.cs @@ -139,6 +139,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Components string.Equals(ComponentMetadata.EventHandler.TagHelperKind, kind); } + public static bool IsKeyTagHelper(this TagHelperDescriptor tagHelper) + { + if (tagHelper == null) + { + throw new ArgumentNullException(nameof(tagHelper)); + } + + return + tagHelper.Metadata.TryGetValue(ComponentMetadata.SpecialKindKey, out var kind) && + string.Equals(ComponentMetadata.Key.TagHelperKind, kind); + } + public static bool IsRefTagHelper(this TagHelperDescriptor tagHelper) { if (tagHelper == null) 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 f3cb7feea0..7b623a0fe9 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentIntermediateNode.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/ComponentIntermediateNode.cs @@ -16,6 +16,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public IEnumerable Captures => Children.OfType(); + public IEnumerable SetKeys => 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/IntermediateNodeVisitor.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeVisitor.cs index af4c6c41af..134294394d 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeVisitor.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/IntermediateNodeVisitor.cs @@ -168,5 +168,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate { VisitDefault(node); } + + public virtual void VisitSetKey(SetKeyIntermediateNode 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 7ea2b95882..bf70855bc3 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/MarkupElementIntermediateNode.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/MarkupElementIntermediateNode.cs @@ -14,10 +14,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate public IEnumerable Captures => Children.OfType(); + public IEnumerable SetKeys => Children.OfType(); + public IEnumerable Body => Children.Where(c => { return c as HtmlAttributeIntermediateNode == null && + c as SetKeyIntermediateNode == null && c as ReferenceCaptureIntermediateNode == null; }); diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/SetKeyIntermediateNode.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/SetKeyIntermediateNode.cs new file mode 100644 index 0000000000..507f89c863 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/SetKeyIntermediateNode.cs @@ -0,0 +1,42 @@ +// 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 SetKeyIntermediateNode : IntermediateNode + { + public SetKeyIntermediateNode(IntermediateToken keyValueToken) + { + KeyValueToken = keyValueToken ?? throw new ArgumentNullException(nameof(keyValueToken)); + Source = KeyValueToken.Source; + } + + public override IntermediateNodeCollection Children => IntermediateNodeCollection.ReadOnly; + + public IntermediateToken KeyValueToken { get; } + + public override void Accept(IntermediateNodeVisitor visitor) + { + if (visitor == null) + { + throw new ArgumentNullException(nameof(visitor)); + } + + visitor.VisitSetKey(this); + } + + public override void FormatNode(IntermediateNodeFormatter formatter) + { + if (formatter == null) + { + throw new ArgumentNullException(nameof(formatter)); + } + + formatter.WriteContent(KeyValueToken.Content); + + formatter.WriteProperty(nameof(KeyValueToken), KeyValueToken.Content); + } + } +} diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngine.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngine.cs index 82ca3509a8..cdc6b9ff4a 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngine.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngine.cs @@ -226,6 +226,7 @@ namespace Microsoft.AspNetCore.Razor.Language builder.Features.Add(new ComponentLoweringPass()); builder.Features.Add(new ComponentScriptTagPass()); builder.Features.Add(new ComponentEventHandlerLoweringPass()); + builder.Features.Add(new ComponentKeyLoweringPass()); builder.Features.Add(new ComponentReferenceCaptureLoweringPass()); builder.Features.Add(new ComponentBindLoweringPass()); builder.Features.Add(new ComponentTemplateDiagnosticPass()); 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 7f76f8cdd4..7cbc74266f 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs @@ -2724,6 +2724,68 @@ namespace Test CompileToAssembly(generated); } + [Fact] + public void GenericComponent_WithKey() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class MyComponent : ComponentBase + { + [Parameter] TItem Item { get; set; } + } +} +")); + + // Act + var generated = CompileToCSharp(@" + + +@functions { + private object _someKey = new object(); +} +"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + + [Fact] + public void GenericComponent_WithKey_TypeInference() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class MyComponent : ComponentBase + { + [Parameter] TItem Item { get; set; } + } +} +")); + + // Act + var generated = CompileToCSharp(@" + + +@functions { + private object _someKey = new object(); +} +"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + [Fact] public void GenericComponent_WithComponentRef() { @@ -2831,6 +2893,106 @@ namespace Test.Shared #endregion + #region Key + + [Fact] + public void Element_WithKey() + { + // Arrange/Act + var generated = CompileToCSharp(@" +Hello + +@functions { + private object someObject = new object(); +} +"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + + [Fact] + public void Element_WithKey_AndOtherAttributes() + { + // Arrange/Act + var generated = CompileToCSharp(@" + + +@functions { + private object someObject = new object(); + + [Parameter] protected int Min { get; set; } + } +"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + + [Fact] + public void Component_WithKey() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class MyComponent : ComponentBase + { + } +} +")); + + // Arrange/Act + var generated = CompileToCSharp(@" + + +@functions { + private DateTime someDate = DateTime.Now; +} +"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + + [Fact] + public void Component_WithKey_WithChildContent() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using Microsoft.AspNetCore.Components; + +namespace Test +{ + public class MyComponent : ComponentBase + { + } +} +")); + + // Arrange/Act + var generated = CompileToCSharp(@" + + Some further content + +"); + + // 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 65600a9b88..9a5673a70b 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorProjectEngineTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorProjectEngineTest.cs @@ -52,6 +52,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Test 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_WithKey/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/TestComponent.codegen.cs new file mode 100644 index 0000000000..b3049fa6f9 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/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 = ""; + __o = ""; + builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment)((builder2) => { + } + )); + builder.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + someDate.Day + +#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 DateTime someDate = DateTime.Now; + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/TestComponent.ir.txt new file mode 100644 index 0000000000..6b4cf2695b --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/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 [74] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - - ParamBefore - AttributeStructure.DoubleQuotes + HtmlContent - (26:0,26 [6] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (26:0,26 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before + SetKey - (39:0,39 [12] x:\dir\subdir\Test\TestComponent.cshtml) - someDate.Day + ComponentAttribute - - ParamAfter - AttributeStructure.DoubleQuotes + HtmlContent - (65:0,65 [5] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (65:0,65 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after + HtmlContent - (74:0,74 [4] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (74:0,74 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n + HtmlContent - (140:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (140:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (90:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (90:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private DateTime someDate = DateTime.Now;\n diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/TestComponent.mappings.txt new file mode 100644 index 0000000000..c1f44c953c --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey/TestComponent.mappings.txt @@ -0,0 +1,14 @@ +Source Location: (39:0,39 [12] x:\dir\subdir\Test\TestComponent.cshtml) +|someDate.Day| +Generated Location: (1108:30,39 [12] ) +|someDate.Day| + +Source Location: (90:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) +| + private DateTime someDate = DateTime.Now; +| +Generated Location: (1467:47,12 [49] ) +| + private DateTime someDate = DateTime.Now; +| + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.codegen.cs new file mode 100644 index 0000000000..014af5ca83 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.codegen.cs @@ -0,0 +1,47 @@ +// +#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.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment)((builder2) => { + } + )); + builder.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + 123 + 456 + +#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 + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.ir.txt new file mode 100644 index 0000000000..7540550b11 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/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 + ComponentChildContent - - ChildContent - context + HtmlContent - (44:0,44 [11] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (44:0,44 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n Some + MarkupElement - (55:1,9 [16] x:\dir\subdir\Test\TestComponent.cshtml) - el + HtmlContent - (59:1,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (59:1,13 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Html - further + HtmlContent - (71:1,25 [10] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (71:1,25 [10] x:\dir\subdir\Test\TestComponent.cshtml) - Html - content\n + SetKey - (18:0,18 [9] x:\dir\subdir\Test\TestComponent.cshtml) - 123 + 456 + ComponentAttribute - - SomeProp - AttributeStructure.DoubleQuotes + HtmlContent - (39:0,39 [3] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (39:0,39 [3] x:\dir\subdir\Test\TestComponent.cshtml) - Html - val + HtmlContent - (95:2,14 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (95:2,14 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.mappings.txt new file mode 100644 index 0000000000..e508dba546 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (18:0,18 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|123 + 456| +Generated Location: (1064:29,18 [9] ) +|123 + 456| + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.codegen.cs new file mode 100644 index 0000000000..445881ed56 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/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.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + someObject + +#line default +#line hidden +#nullable disable + ); + } + #pragma warning restore 1998 +#nullable restore +#line 3 "x:\dir\subdir\Test\TestComponent.cshtml" + + private object someObject = new object(); + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.ir.txt new file mode 100644 index 0000000000..5761655406 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.ir.txt @@ -0,0 +1,32 @@ +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 [83] x:\dir\subdir\Test\TestComponent.cshtml) - elem + HtmlContent - (71:0,71 [5] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (71:0,71 [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 + SetKey - (36:0,36 [10] x:\dir\subdir\Test\TestComponent.cshtml) - someObject + HtmlAttribute - - attributeafter=" - " + HtmlAttributeValue - (64:0,64 [5] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (64:0,64 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after + HtmlContent - (83:0,83 [4] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (83:0,83 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n + HtmlContent - (149:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (149:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (99:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (99:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private object someObject = new object();\n diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.mappings.txt new file mode 100644 index 0000000000..eb409186f8 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey/TestComponent.mappings.txt @@ -0,0 +1,14 @@ +Source Location: (36:0,36 [10] x:\dir\subdir\Test\TestComponent.cshtml) +|someObject| +Generated Location: (908:25,36 [10] ) +|someObject| + +Source Location: (99:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) +| + private object someObject = new object(); +| +Generated Location: (1117:35,12 [49] ) +| + private object someObject = new object(); +| + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.codegen.cs new file mode 100644 index 0000000000..897386b74a --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/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 = +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Min + +#line default +#line hidden +#nullable disable + ; + builder.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + someObject + +#line default +#line hidden +#nullable disable + ); + } + #pragma warning restore 1998 +#nullable restore +#line 3 "x:\dir\subdir\Test\TestComponent.cshtml" + + private object someObject = new object(); + + [Parameter] protected int Min { get; set; } + + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.ir.txt new file mode 100644 index 0000000000..55b45fa3e4 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/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 + MarkupElement - (0:0,0 [62] x:\dir\subdir\Test\TestComponent.cshtml) - input + HtmlAttribute - - type=" - " + HtmlAttributeValue - (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - text + HtmlAttribute - - data-slider-min=" - " + CSharpExpressionAttributeValue - (36:0,36 [4] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (37:0,37 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - Min + SetKey - (48:0,48 [10] x:\dir\subdir\Test\TestComponent.cshtml) - someObject + HtmlContent - (62:0,62 [4] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (62:0,62 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n + HtmlContent - (191:6,5 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (191:6,5 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (78:2,12 [112] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (78:2,12 [112] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private object someObject = new object();\n\n [Parameter] protected int Min { get; set; }\n diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.mappings.txt new file mode 100644 index 0000000000..aa3e3e4fdc --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.mappings.txt @@ -0,0 +1,23 @@ +Source Location: (37:0,37 [3] x:\dir\subdir\Test\TestComponent.cshtml) +|Min| +Generated Location: (900:25,37 [3] ) +|Min| + +Source Location: (48:0,48 [10] x:\dir\subdir\Test\TestComponent.cshtml) +|someObject| +Generated Location: (1117:34,48 [10] ) +|someObject| + +Source Location: (78:2,12 [112] x:\dir\subdir\Test\TestComponent.cshtml) +| + private object someObject = new object(); + + [Parameter] protected int Min { get; set; } + | +Generated Location: (1326:44,12 [112] ) +| + private object someObject = new object(); + + [Parameter] protected int Min { get; set; } + | + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs new file mode 100644 index 0000000000..709829ce9a --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs @@ -0,0 +1,72 @@ +// +#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 = typeof( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + int + +#line default +#line hidden +#nullable disable + ); + __o = Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + 3 + +#line default +#line hidden +#nullable disable + ); + builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment)((builder2) => { + } + )); + builder.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + _someKey + +#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 object _someKey = new object(); + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.ir.txt new file mode 100644 index 0000000000..4738739183 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.ir.txt @@ -0,0 +1,28 @@ +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 [49] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentTypeArgument - (19:0,19 [3] x:\dir\subdir\Test\TestComponent.cshtml) - TItem + IntermediateToken - (19:0,19 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - int + ComponentAttribute - (29:0,29 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Item - AttributeStructure.DoubleQuotes + IntermediateToken - (29:0,29 [1] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 3 + SetKey - (37:0,37 [8] x:\dir\subdir\Test\TestComponent.cshtml) - _someKey + HtmlContent - (49:0,49 [4] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (49:0,49 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n + HtmlContent - (113:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (113:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (65:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (65:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private object _someKey = new object();\n diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt new file mode 100644 index 0000000000..2a8f37b34e --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt @@ -0,0 +1,24 @@ +Source Location: (19:0,19 [3] x:\dir\subdir\Test\TestComponent.cshtml) +|int| +Generated Location: (889:25,19 [3] ) +|int| + +Source Location: (29:0,29 [1] x:\dir\subdir\Test\TestComponent.cshtml) +|3| +Generated Location: (1141:34,29 [1] ) +|3| + +Source Location: (37:0,37 [8] x:\dir\subdir\Test\TestComponent.cshtml) +|_someKey| +Generated Location: (1497:46,37 [8] ) +|_someKey| + +Source Location: (65:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) +| + private object _someKey = new object(); +| +Generated Location: (1854:63,12 [47] ) +| + private object _someKey = new object(); +| + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs new file mode 100644 index 0000000000..1ee445b21c --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/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" + 3 + +#line default +#line hidden +#nullable disable + , -1, +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + _someKey + +#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 object _someKey = new object(); + +#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, TItem __arg0, int __seq1, object __arg1) + { + builder.OpenComponent>(seq); + builder.AddAttribute(__seq0, "Item", __arg0); + builder.SetKey(__arg1); + builder.CloseComponent(); + } + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.ir.txt new file mode 100644 index 0000000000..3b5cc52c25 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.ir.txt @@ -0,0 +1,29 @@ +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 [39] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (19:0,19 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Item - AttributeStructure.DoubleQuotes + IntermediateToken - (19:0,19 [1] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 3 + SetKey - (27:0,27 [8] x:\dir\subdir\Test\TestComponent.cshtml) - _someKey + HtmlContent - (39:0,39 [4] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (39:0,39 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n + HtmlContent - (103:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (103:4,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (55:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (55:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private object _someKey = new object();\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/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt new file mode 100644 index 0000000000..474623cead --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt @@ -0,0 +1,19 @@ +Source Location: (19:0,19 [1] x:\dir\subdir\Test\TestComponent.cshtml) +|3| +Generated Location: (955:25,19 [1] ) +|3| + +Source Location: (27:0,27 [8] x:\dir\subdir\Test\TestComponent.cshtml) +|_someKey| +Generated Location: (1125:33,27 [8] ) +|_someKey| + +Source Location: (55:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) +| + private object _someKey = new object(); +| +Generated Location: (1482:50,12 [47] ) +| + private object _someKey = new object(); +| + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.codegen.cs new file mode 100644 index 0000000000..0a8803d967 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/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, "ParamBefore", "before"); + builder.AddAttribute(2, "ParamAfter", "after"); + builder.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + someDate.Day + +#line default +#line hidden +#nullable disable + ); + builder.CloseComponent(); + } + #pragma warning restore 1998 +#nullable restore +#line 3 "x:\dir\subdir\Test\TestComponent.cshtml" + + private DateTime someDate = DateTime.Now; + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.ir.txt new file mode 100644 index 0000000000..021fc0aead --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/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 [74] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - - ParamBefore - AttributeStructure.DoubleQuotes + HtmlContent - (26:0,26 [6] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (26:0,26 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - before + SetKey - (39:0,39 [12] x:\dir\subdir\Test\TestComponent.cshtml) - someDate.Day + ComponentAttribute - - ParamAfter - AttributeStructure.DoubleQuotes + HtmlContent - (65:0,65 [5] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (65:0,65 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after + CSharpCode - (90:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (90:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private DateTime someDate = DateTime.Now;\n diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.mappings.txt new file mode 100644 index 0000000000..bdca049e18 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey/TestComponent.mappings.txt @@ -0,0 +1,14 @@ +Source Location: (39:0,39 [12] x:\dir\subdir\Test\TestComponent.cshtml) +|someDate.Day| +Generated Location: (824:21,39 [12] ) +|someDate.Day| + +Source Location: (90:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) +| + private DateTime someDate = DateTime.Now; +| +Generated Location: (1074:32,12 [49] ) +| + private DateTime someDate = DateTime.Now; +| + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.codegen.cs new file mode 100644 index 0000000000..17c3ae4e46 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.codegen.cs @@ -0,0 +1,37 @@ +// +#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, "SomeProp", "val"); + builder.AddAttribute(2, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment)((builder2) => { + builder2.AddMarkupContent(3, "\r\n Some "); + builder2.AddMarkupContent(4, "further content\r\n"); + } + )); + builder.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + 123 + 456 + +#line default +#line hidden +#nullable disable + ); + builder.CloseComponent(); + } + #pragma warning restore 1998 + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.ir.txt new file mode 100644 index 0000000000..d5cee0071c --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.ir.txt @@ -0,0 +1,18 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [14] ) - System + UsingDirective - (18:2,1 [34] ) - System.Collections.Generic + UsingDirective - (53:3,1 [19] ) - System.Linq + UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks + UsingDirective - (104:5,1 [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 + ComponentChildContent - - ChildContent - context + HtmlContent - (44:0,44 [11] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (44:0,44 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n Some + MarkupBlock - - further content\n + SetKey - (18:0,18 [9] x:\dir\subdir\Test\TestComponent.cshtml) - 123 + 456 + ComponentAttribute - - SomeProp - AttributeStructure.DoubleQuotes + HtmlContent - (39:0,39 [3] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (39:0,39 [3] x:\dir\subdir\Test\TestComponent.cshtml) - Html - val diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.mappings.txt new file mode 100644 index 0000000000..d41eee6ea6 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Component_WithKey_WithChildContent/TestComponent.mappings.txt @@ -0,0 +1,5 @@ +Source Location: (18:0,18 [9] x:\dir\subdir\Test\TestComponent.cshtml) +|123 + 456| +Generated Location: (1029:27,18 [9] ) +|123 + 456| + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.codegen.cs new file mode 100644 index 0000000000..fd9d0844f6 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/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.AddAttribute(2, "attributeafter", "after"); + builder.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + someObject + +#line default +#line hidden +#nullable disable + ); + builder.AddContent(3, "Hello"); + builder.CloseElement(); + } + #pragma warning restore 1998 +#nullable restore +#line 3 "x:\dir\subdir\Test\TestComponent.cshtml" + + private object someObject = new object(); + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.ir.txt new file mode 100644 index 0000000000..5c5902d95a --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.ir.txt @@ -0,0 +1,21 @@ +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 [83] x:\dir\subdir\Test\TestComponent.cshtml) - elem + HtmlContent - (71:0,71 [5] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (71:0,71 [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 + SetKey - (36:0,36 [10] x:\dir\subdir\Test\TestComponent.cshtml) - someObject + HtmlAttribute - - attributeafter=" - " + HtmlAttributeValue - (64:0,64 [5] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (64:0,64 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - after + CSharpCode - (99:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (99:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private object someObject = new object();\n diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.mappings.txt new file mode 100644 index 0000000000..0a63f5d85d --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey/TestComponent.mappings.txt @@ -0,0 +1,14 @@ +Source Location: (36:0,36 [10] x:\dir\subdir\Test\TestComponent.cshtml) +|someObject| +Generated Location: (817:21,36 [10] ) +|someObject| + +Source Location: (99:2,12 [49] x:\dir\subdir\Test\TestComponent.cshtml) +| + private object someObject = new object(); +| +Generated Location: (1108:33,12 [49] ) +| + private object someObject = new object(); +| + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.codegen.cs new file mode 100644 index 0000000000..176ad7f171 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.codegen.cs @@ -0,0 +1,52 @@ +// +#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, "input"); + builder.AddAttribute(1, "type", "text"); + builder.AddAttribute(2, "data-slider-min", +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + Min + +#line default +#line hidden +#nullable disable + ); + builder.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + someObject + +#line default +#line hidden +#nullable disable + ); + builder.CloseElement(); + } + #pragma warning restore 1998 +#nullable restore +#line 3 "x:\dir\subdir\Test\TestComponent.cshtml" + + private object someObject = new object(); + + [Parameter] protected int Min { get; set; } + + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.ir.txt new file mode 100644 index 0000000000..c4b3b00270 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/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 + MarkupElement - (0:0,0 [62] x:\dir\subdir\Test\TestComponent.cshtml) - input + HtmlAttribute - - type=" - " + HtmlAttributeValue - (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (13:0,13 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - text + HtmlAttribute - - data-slider-min=" - " + CSharpExpressionAttributeValue - (36:0,36 [4] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (37:0,37 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - Min + SetKey - (48:0,48 [10] x:\dir\subdir\Test\TestComponent.cshtml) - someObject + CSharpCode - (78:2,12 [112] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (78:2,12 [112] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private object someObject = new object();\n\n [Parameter] protected int Min { get; set; }\n diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.mappings.txt new file mode 100644 index 0000000000..7530b38835 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/Element_WithKey_AndOtherAttributes/TestComponent.mappings.txt @@ -0,0 +1,18 @@ +Source Location: (48:0,48 [10] x:\dir\subdir\Test\TestComponent.cshtml) +|someObject| +Generated Location: (987:29,48 [10] ) +|someObject| + +Source Location: (78:2,12 [112] x:\dir\subdir\Test\TestComponent.cshtml) +| + private object someObject = new object(); + + [Parameter] protected int Min { get; set; } + | +Generated Location: (1233:40,12 [112] ) +| + private object someObject = new object(); + + [Parameter] protected int Min { get; set; } + | + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs new file mode 100644 index 0000000000..7afcd337b5 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.codegen.cs @@ -0,0 +1,48 @@ +// +#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, "Item", Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + 3 + +#line default +#line hidden +#nullable disable + )); + builder.SetKey( +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + _someKey + +#line default +#line hidden +#nullable disable + ); + builder.CloseComponent(); + } + #pragma warning restore 1998 +#nullable restore +#line 3 "x:\dir\subdir\Test\TestComponent.cshtml" + + private object _someKey = new object(); + +#line default +#line hidden +#nullable disable + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.ir.txt new file mode 100644 index 0000000000..f3c2f8e143 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.ir.txt @@ -0,0 +1,17 @@ +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 [49] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentTypeArgument - (19:0,19 [3] x:\dir\subdir\Test\TestComponent.cshtml) - TItem + IntermediateToken - (19:0,19 [3] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - int + ComponentAttribute - (29:0,29 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Item - AttributeStructure.DoubleQuotes + IntermediateToken - (29:0,29 [1] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 3 + SetKey - (37:0,37 [8] x:\dir\subdir\Test\TestComponent.cshtml) - _someKey + CSharpCode - (65:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (65:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private object _someKey = new object();\n diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt new file mode 100644 index 0000000000..508332c609 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey/TestComponent.mappings.txt @@ -0,0 +1,14 @@ +Source Location: (37:0,37 [8] x:\dir\subdir\Test\TestComponent.cshtml) +|_someKey| +Generated Location: (980:28,37 [8] ) +|_someKey| + +Source Location: (65:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) +| + private object _someKey = new object(); +| +Generated Location: (1226:39,12 [47] ) +| + private object _someKey = new object(); +| + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.codegen.cs new file mode 100644 index 0000000000..6e8d31af45 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/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" + 3 + +#line default +#line hidden +#nullable disable + , 2, +#nullable restore +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + _someKey + +#line default +#line hidden +#nullable disable + ); + } + #pragma warning restore 1998 +#nullable restore +#line 3 "x:\dir\subdir\Test\TestComponent.cshtml" + + private object _someKey = new object(); + +#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, TItem __arg0, int __seq1, object __arg1) + { + builder.OpenComponent>(seq); + builder.AddAttribute(__seq0, "Item", __arg0); + builder.SetKey(__arg1); + builder.CloseComponent(); + } + } +} +#pragma warning restore 1591 diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.ir.txt new file mode 100644 index 0000000000..35285b1a16 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.ir.txt @@ -0,0 +1,18 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [14] ) - System + UsingDirective - (18:2,1 [34] ) - System.Collections.Generic + UsingDirective - (53:3,1 [19] ) - System.Linq + UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks + UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components + ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Components.ComponentBase - + MethodDeclaration - - protected override - void - BuildRenderTree + Component - (0:0,0 [39] x:\dir\subdir\Test\TestComponent.cshtml) - MyComponent + ComponentAttribute - (19:0,19 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Item - AttributeStructure.DoubleQuotes + IntermediateToken - (19:0,19 [1] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - 3 + SetKey - (27:0,27 [8] x:\dir\subdir\Test\TestComponent.cshtml) - _someKey + CSharpCode - (55:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (55:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private object _someKey = new object();\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/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt new file mode 100644 index 0000000000..0873889778 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/GenericComponent_WithKey_TypeInference/TestComponent.mappings.txt @@ -0,0 +1,14 @@ +Source Location: (27:0,27 [8] x:\dir\subdir\Test\TestComponent.cshtml) +|_someKey| +Generated Location: (854:26,27 [8] ) +|_someKey| + +Source Location: (55:2,12 [47] x:\dir\subdir\Test\TestComponent.cshtml) +| + private object _someKey = new object(); +| +Generated Location: (1061:36,12 [47] ) +| + private object _someKey = new object(); +| + diff --git a/src/Razor/Microsoft.CodeAnalysis.Razor/src/CompilerFeatures.cs b/src/Razor/Microsoft.CodeAnalysis.Razor/src/CompilerFeatures.cs index b42e6b5cc8..b555832cc8 100644 --- a/src/Razor/Microsoft.CodeAnalysis.Razor/src/CompilerFeatures.cs +++ b/src/Razor/Microsoft.CodeAnalysis.Razor/src/CompilerFeatures.cs @@ -28,6 +28,7 @@ namespace Microsoft.CodeAnalysis.Razor builder.Features.Add(new ComponentTagHelperDescriptorProvider()); builder.Features.Add(new EventHandlerTagHelperDescriptorProvider()); builder.Features.Add(new RefTagHelperDescriptorProvider()); + builder.Features.Add(new KeyTagHelperDescriptorProvider()); builder.Features.Add(new DefaultTypeNameFeature()); } diff --git a/src/Razor/Microsoft.CodeAnalysis.Razor/src/KeyTagHelperDescriptorProvider.cs b/src/Razor/Microsoft.CodeAnalysis.Razor/src/KeyTagHelperDescriptorProvider.cs new file mode 100644 index 0000000000..7ea05126be --- /dev/null +++ b/src/Razor/Microsoft.CodeAnalysis.Razor/src/KeyTagHelperDescriptorProvider.cs @@ -0,0 +1,77 @@ +// 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 KeyTagHelperDescriptorProvider : ITagHelperDescriptorProvider + { + // Run after the component tag helper provider + public int Order { get; set; } = 1000; + + 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 renderTreeBuilderType = compilation.GetTypeByMetadataName(ComponentsApi.RenderTreeBuilder.FullTypeName); + if (renderTreeBuilderType == 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(CreateKeyTagHelper()); + } + + private TagHelperDescriptor CreateKeyTagHelper() + { + var builder = TagHelperDescriptorBuilder.Create(ComponentMetadata.Key.TagHelperKind, "Key", ComponentsApi.AssemblyName); + builder.Documentation = ComponentResources.KeyTagHelper_Documentation; + + builder.Metadata.Add(ComponentMetadata.SpecialKindKey, ComponentMetadata.Key.TagHelperKind); + builder.Metadata.Add(TagHelperMetadata.Common.ClassifyAttributesOnly, bool.TrueString); + builder.Metadata[TagHelperMetadata.Runtime.Name] = ComponentMetadata.Key.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.Key"); + + builder.TagMatchingRule(rule => + { + rule.TagName = "*"; + rule.Attribute(attribute => + { + attribute.Name = "key"; + }); + }); + + builder.BindAttribute(attribute => + { + attribute.Documentation = ComponentResources.KeyTagHelper_Documentation; + attribute.Name = "key"; + + // 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("Key"); + attribute.TypeName = typeof(object).FullName; + }); + + return builder.Build(); + } + } +} diff --git a/src/Razor/Microsoft.CodeAnalysis.Razor/test/KeyTagHelperDescriptorProviderTest.cs b/src/Razor/Microsoft.CodeAnalysis.Razor/test/KeyTagHelperDescriptorProviderTest.cs new file mode 100644 index 0000000000..ae9288bd19 --- /dev/null +++ b/src/Razor/Microsoft.CodeAnalysis.Razor/test/KeyTagHelperDescriptorProviderTest.cs @@ -0,0 +1,88 @@ +// 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 KeyTagHelperDescriptorProviderTest : TagHelperDescriptorProviderTestBase + { + [Fact] + public void Execute_CreatesDescriptor() + { + // Arrange + var context = TagHelperDescriptorProviderContext.Create(); + context.SetCompilation(BaseCompilation); + + var provider = new KeyTagHelperDescriptorProvider(); + + // Act + provider.Execute(context); + + // Assert + var matches = context.Results.Where(result => result.IsKeyTagHelper()); + var item = Assert.Single(matches); + + Assert.Empty(item.AllowedChildTags); + Assert.Null(item.TagOutputHint); + Assert.Empty(item.Diagnostics); + Assert.False(item.HasErrors); + Assert.Equal(ComponentMetadata.Key.TagHelperKind, item.Kind); + Assert.Equal(bool.TrueString, item.Metadata[TagHelperMetadata.Common.ClassifyAttributesOnly]); + Assert.Equal(ComponentMetadata.Key.RuntimeName, item.Metadata[TagHelperMetadata.Runtime.Name]); + Assert.False(item.IsDefaultKind()); + Assert.False(item.KindUsesDefaultTagHelperRuntime()); + + Assert.Equal( + "Ensures that the component or element will be preserved across renders if (and only if) the supplied key value matches.", + item.Documentation); + + Assert.Equal("Microsoft.AspNetCore.Components", item.AssemblyName); + Assert.Equal("Key", item.Name); + Assert.Equal("Microsoft.AspNetCore.Components.Key", item.DisplayName); + Assert.Equal("Microsoft.AspNetCore.Components.Key", item.GetTypeName()); + + // The tag matching rule for a key is just the attribute name "key" + 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("key", requiredAttribute.DisplayName); + Assert.Equal("key", 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.Key.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( + "Ensures that the component or element will be preserved across renders if (and only if) the supplied key value matches.", + attribute.Documentation); + + Assert.Equal("key", attribute.Name); + Assert.Equal("Key", attribute.GetPropertyName()); + Assert.Equal("object Microsoft.AspNetCore.Components.Key.Key", 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.Common/Language/IntegrationTests/IntermediateNodeWriter.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntermediateNodeWriter.cs index 4ae07f5e8d..c83dbb7c79 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntermediateNodeWriter.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/IntermediateNodeWriter.cs @@ -168,6 +168,11 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests WriteContentNode(node, node.IdentifierToken?.Content); } + public override void VisitSetKey(SetKeyIntermediateNode node) + { + WriteContentNode(node, node.KeyValueToken?.Content); + } + void IExtensionIntermediateNodeVisitor.VisitExtension(RouteAttributeExtensionNode node) { WriteContentNode(node, node.Template); 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 e07c337a4d..2dfaac26cf 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 @@ -103,5 +103,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree public void AddComponentReferenceCapture(int sequence, Action componentReferenceCaptureAction) { } + + public void SetKey(object key) + { + } } } \ No newline at end of file