public void WriteTagHelperBody_Runtime_RendersCorrectly_UsesTagNameAndModeFromContext()
        {
            // Arrange
            var extension = new DefaultTagHelperTargetExtension();
            var context   = TestCodeRenderingContext.CreateRuntime();

            var tagHelperNode = new TagHelperIntermediateNode();
            var node          = new DefaultTagHelperBodyIntermediateNode()
            {
                Children =
                {
                    new CSharpExpressionIntermediateNode(),
                },
                TagMode = TagMode.SelfClosing,
                TagName = "p",
            };

            tagHelperNode.Children.Add(node);
            Push(context, tagHelperNode);

            // Act
            extension.WriteTagHelperBody(context, node);

            // Assert
            var csharp = context.CodeWriter.GenerateCode();

            Assert.Equal(
                @"__tagHelperExecutionContext = __tagHelperScopeManager.Begin(""p"", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, ""test"", async() => {
    Render Children
}
);
",
                csharp,
                ignoreLineEndingDifferences: true);
        }
        public void WriteTagHelperBody_DesignTime_WritesChildren()
        {
            // Arrange
            var extension = new DefaultTagHelperTargetExtension();
            var context   = TestCodeRenderingContext.CreateDesignTime();

            var tagHelperNode = new TagHelperIntermediateNode();
            var node          = new DefaultTagHelperBodyIntermediateNode()
            {
                Children =
                {
                    new CSharpExpressionIntermediateNode(),
                }
            };

            tagHelperNode.Children.Add(node);
            Push(context, tagHelperNode);

            // Act
            extension.WriteTagHelperBody(context, node);

            // Assert
            var csharp = context.CodeWriter.GenerateCode();

            Assert.Equal(
                @"Render Children
",
                csharp,
                ignoreLineEndingDifferences: true);
        }
        public void WriteTagHelperBody(CodeRenderingContext context, DefaultTagHelperBodyIntermediateNode node)
        {
            if (context.Parent as TagHelperIntermediateNode == null)
            {
                var message = Resources.FormatIntermediateNodes_InvalidParentNode(node.GetType(), typeof(TagHelperIntermediateNode));
                throw new InvalidOperationException(message);
            }

            if (context.Options.DesignTime)
            {
                context.RenderChildren(node);
            }
            else
            {
                // Call into the tag helper scope manager to start a new tag helper scope.
                // Also capture the value as the current execution context.
                context.CodeWriter
                .WriteStartAssignment(ExecutionContextVariableName)
                .WriteStartInstanceMethodInvocation(
                    ScopeManagerVariableName,
                    ScopeManagerBeginMethodName);

                // Assign a unique ID for this instance of the source HTML tag. This must be unique
                // per call site, e.g. if the tag is on the view twice, there should be two IDs.
                var uniqueId = (string)context.Items[CodeRenderingContext.SuppressUniqueIds];
                if (uniqueId == null)
                {
                    uniqueId = GetDeterministicId(context);
                }

                context.CodeWriter.WriteStringLiteral(node.TagName)
                .WriteParameterSeparator()
                .Write(TagModeTypeName)
                .Write(".")
                .Write(node.TagMode.ToString())
                .WriteParameterSeparator()
                .WriteStringLiteral(uniqueId)
                .WriteParameterSeparator();

                using (context.CodeWriter.BuildAsyncLambda())
                {
                    // We remove and redirect writers so TagHelper authors can retrieve content.
                    context.RenderChildren(node, new RuntimeNodeWriter());
                }

                context.CodeWriter.WriteEndMethodInvocation();
            }
        }