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_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(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();
        }
    }