Skip to content
This repository has been archived by the owner on Dec 19, 2018. It is now read-only.

Commit

Permalink
Moved ExecuteTagHelpersIRNode from renderer to writer
Browse files Browse the repository at this point in the history
  • Loading branch information
ajaybhargavb committed Apr 6, 2017
1 parent 0481cc6 commit 0228fd2
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public TagHelperWriterScope Push(TagHelperWriter writer)
throw new ArgumentNullException(nameof(writer));
}

var scope = new TagHelperWriterScope(this, BasicWriter);
var scope = new TagHelperWriterScope(this, TagHelperWriter);
TagHelperWriter = writer;
return scope;
}
Expand Down Expand Up @@ -131,9 +131,9 @@ public void Dispose()
public struct TagHelperWriterScope : IDisposable
{
private readonly CSharpRenderingContext _context;
private readonly BasicWriter _writer;
private readonly TagHelperWriter _writer;

public TagHelperWriterScope(CSharpRenderingContext context, BasicWriter writer)
public TagHelperWriterScope(CSharpRenderingContext context, TagHelperWriter writer)
{
if (context == null)
{
Expand All @@ -151,7 +151,7 @@ public TagHelperWriterScope(CSharpRenderingContext context, BasicWriter writer)

public void Dispose()
{
_context.BasicWriter = _writer;
_context.TagHelperWriter = _writer;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
Context.TagHelperWriter.WriteCreateTagHelper(Context, node);
}

public override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
{
Context.TagHelperWriter.WriteExecuteTagHelpers(Context, node);
}

public override void VisitDefault(RazorIRNode node)
{
// This is a temporary bridge to the renderer, which allows us to move functionality piecemeal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public override void WriteCreateTagHelper(CSharpRenderingContext context, Create

public override void WriteExecuteTagHelpers(CSharpRenderingContext context, ExecuteTagHelpersIRNode node)
{
throw new NotImplementedException();
// Do nothing
}

public override void WriteInitializeTagHelperStructure(CSharpRenderingContext context, InitializeTagHelperStructureIRNode node)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// 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.Evolution.Intermediate;

namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
{
internal class RedirectedTagHelperWriter : TagHelperWriter
{
private readonly TagHelperWriter _previous;
private readonly string _textWriter;

public RedirectedTagHelperWriter(TagHelperWriter previous, string textWriter)
{
_previous = previous;
_textWriter = textWriter;
}

public string ExecutionContextVariableName { get; set; } = "__tagHelperExecutionContext";

public string ExecutionContextOutputPropertyName { get; set; } = "Output";

public string ExecutionContextSetOutputContentAsyncMethodName { get; set; } = "SetOutputContentAsync";

public string RunnerVariableName { get; set; } = "__tagHelperRunner";

public string RunnerRunAsyncMethodName { get; set; } = "RunAsync";

public string ScopeManagerVariableName { get; set; } = "__tagHelperScopeManager";

public string ScopeManagerEndMethodName { get; set; } = "End";

public string TagHelperOutputIsContentModifiedPropertyName { get; set; } = "IsContentModified";

public string WriteTagHelperOutputMethod { get; set; } = "WriteTo";

public override void WriteAddTagHelperHtmlAttribute(CSharpRenderingContext context, AddTagHelperHtmlAttributeIRNode node)
{
_previous.WriteAddTagHelperHtmlAttribute(context, node);
}

public override void WriteCreateTagHelper(CSharpRenderingContext context, CreateTagHelperIRNode node)
{
_previous.WriteCreateTagHelper(context, node);
}

public override void WriteDeclareTagHelperFields(CSharpRenderingContext context, DeclareTagHelperFieldsIRNode node)
{
_previous.WriteDeclareTagHelperFields(context, node);
}

public override void WriteExecuteTagHelpers(CSharpRenderingContext context, ExecuteTagHelpersIRNode node)
{
if (context.Options.DesignTimeMode)
{
_previous.WriteExecuteTagHelpers(context, node);
return;
}

context.Writer
.Write("await ")
.WriteStartInstanceMethodInvocation(
RunnerVariableName,
RunnerRunAsyncMethodName)
.Write(ExecutionContextVariableName)
.WriteEndMethodInvocation();

var tagHelperOutputAccessor = $"{ExecutionContextVariableName}.{ExecutionContextOutputPropertyName}";

context.Writer
.Write("if (!")
.Write(tagHelperOutputAccessor)
.Write(".")
.Write(TagHelperOutputIsContentModifiedPropertyName)
.WriteLine(")");

using (context.Writer.BuildScope())
{
context.Writer
.Write("await ")
.WriteInstanceMethodInvocation(
ExecutionContextVariableName,
ExecutionContextSetOutputContentAsyncMethodName);
}

context.Writer
.WriteStartMethodInvocation(WriteTagHelperOutputMethod)
.Write(_textWriter)
.WriteParameterSeparator()
.Write(tagHelperOutputAccessor)
.WriteEndMethodInvocation()
.WriteStartAssignment(ExecutionContextVariableName)
.WriteInstanceMethodInvocation(
ScopeManagerVariableName,
ScopeManagerEndMethodName);
}

public override void WriteInitializeTagHelperStructure(CSharpRenderingContext context, InitializeTagHelperStructureIRNode node)
{
_previous.WriteInitializeTagHelperStructure(context, node);
}

public override void WriteSetTagHelperProperty(CSharpRenderingContext context, SetTagHelperPropertyIRNode node)
{
_previous.WriteSetTagHelperProperty(context, node);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -456,46 +456,6 @@ public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
.WriteEndMethodInvocation();
}

public override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
{
Context.Writer
.Write("await ")
.WriteStartInstanceMethodInvocation(
"__tagHelperRunner" /* ORIGINAL: RunnerVariableName */,
"RunAsync" /* ORIGINAL: RunnerRunAsyncMethodName */)
.Write("__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */)
.WriteEndMethodInvocation();

var executionContextVariableName = "__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */;
var executionContextOutputPropertyName = "Output" /* ORIGINAL: ExecutionContextOutputPropertyName */;
var tagHelperOutputAccessor = $"{executionContextVariableName}.{executionContextOutputPropertyName}";

Context.Writer
.Write("if (!")
.Write(tagHelperOutputAccessor)
.Write(".")
.Write("IsContentModified" /* ORIGINAL: TagHelperOutputIsContentModifiedPropertyName */)
.WriteLine(")");

using (Context.Writer.BuildScope())
{
Context.Writer
.Write("await ")
.WriteInstanceMethodInvocation(
executionContextVariableName,
"SetOutputContentAsync" /* ORIGINAL: ExecutionContextSetOutputContentAsyncMethodName */);
}

Context.Writer
.Write(Context.RenderingConventions.StartWriteMethod)
.Write(tagHelperOutputAccessor)
.WriteEndMethodInvocation()
.WriteStartAssignment(executionContextVariableName)
.WriteInstanceMethodInvocation(
"__tagHelperScopeManager" /* ORIGINAL: ScopeManagerVariableName */,
"End" /* ORIGINAL: ScopeManagerEndMethodName */);
}

public override void VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
{
Context.Writer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,24 @@ public class RuntimeTagHelperWriter : TagHelperWriter

public string ExecutionContextAddMethodName { get; set; } = "Add";

public string ExecutionContextOutputPropertyName { get; set; } = "Output";

public string ExecutionContextSetOutputContentAsyncMethodName { get; set; } = "SetOutputContentAsync";

public string RunnerTypeName { get; set; } = "global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner";

public string RunnerVariableName { get; set; } = "__tagHelperRunner";

public string RunnerRunAsyncMethodName { get; set; } = "RunAsync";

public string ScopeManagerTypeName { get; set; } = "global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager";

public string ScopeManagerVariableName { get; set; } = "__tagHelperScopeManager";

public string ScopeManagerBeginMethodName { get; set; } = "Begin";

public string ScopeManagerEndMethodName { get; set; } = "End";

public string StartTagHelperWritingScopeMethodName { get; set; } = "StartTagHelperWritingScope";

public string EndTagHelperWritingScopeMethodName { get; set; } = "EndTagHelperWritingScope";
Expand All @@ -34,6 +42,10 @@ public class RuntimeTagHelperWriter : TagHelperWriter

public string CreateTagHelperMethodName { get; set; } = "CreateTagHelper";

public string TagHelperOutputIsContentModifiedPropertyName { get; set; } = "IsContentModified";

public string WriteTagHelperOutputMethod { get; set; } = "Write";

public override void WriteDeclareTagHelperFields(CSharpRenderingContext context, DeclareTagHelperFieldsIRNode node)
{
context.Writer.WriteLineHiddenDirective();
Expand Down Expand Up @@ -137,7 +149,40 @@ public override void WriteCreateTagHelper(CSharpRenderingContext context, Create

public override void WriteExecuteTagHelpers(CSharpRenderingContext context, ExecuteTagHelpersIRNode node)
{
throw new NotImplementedException();
context.Writer
.Write("await ")
.WriteStartInstanceMethodInvocation(
RunnerVariableName,
RunnerRunAsyncMethodName)
.Write(ExecutionContextVariableName)
.WriteEndMethodInvocation();

var tagHelperOutputAccessor = $"{ExecutionContextVariableName}.{ExecutionContextOutputPropertyName}";

context.Writer
.Write("if (!")
.Write(tagHelperOutputAccessor)
.Write(".")
.Write(TagHelperOutputIsContentModifiedPropertyName)
.WriteLine(")");

using (context.Writer.BuildScope())
{
context.Writer
.Write("await ")
.WriteInstanceMethodInvocation(
ExecutionContextVariableName,
ExecutionContextSetOutputContentAsyncMethodName);
}

context.Writer
.WriteStartMethodInvocation(WriteTagHelperOutputMethod)
.Write(tagHelperOutputAccessor)
.WriteEndMethodInvocation()
.WriteStartAssignment(ExecutionContextVariableName)
.WriteInstanceMethodInvocation(
ScopeManagerVariableName,
ScopeManagerEndMethodName);
}

public override void WriteInitializeTagHelperStructure(CSharpRenderingContext context, InitializeTagHelperStructureIRNode node)
Expand Down Expand Up @@ -167,6 +212,7 @@ public override void WriteInitializeTagHelperStructure(CSharpRenderingContext co
context.RenderingConventions = new CSharpRenderingConventions(context.Writer);

using (context.Push(new RuntimeBasicWriter()))
using (context.Push(new RuntimeTagHelperWriter()))
{
using (context.Writer.BuildAsyncLambda(endLine: false))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public void WriteTemplate(CSharpRenderingContext context, TemplateIRNode node)
context.RenderingConventions = new CSharpRedirectRenderingConventions(TemplateWriterName, context.Writer);

using (context.Push(new RedirectedBasicWriter(context.BasicWriter, TemplateWriterName)))
using (context.Push(new RedirectedTagHelperWriter(context.TagHelperWriter, TemplateWriterName)))
{
using (context.Writer.BuildAsyncLambda(endLine: false, parameterNames: TemplateWriterName))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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 System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
using Xunit;

namespace Microsoft.AspNetCore.Razor.Evolution.CodeGeneration
{
public class RedirectedTagHelperWriterTest
{
// In design time this will not include the 'text writer' parameter.
[Fact]
public void WriteExecuteTagHelpers_DesignTime_DoesNormalWrite()
{
// Arrange
var writer = new RedirectedTagHelperWriter(new DesignTimeTagHelperWriter(), "test_writer")
{
WriteTagHelperOutputMethod = "Test",
};

var context = new CSharpRenderingContext()
{
Options = RazorParserOptions.CreateDefaultOptions(),
Writer = new Legacy.CSharpCodeWriter(),
};

context.Options.DesignTimeMode = true;

var node = new ExecuteTagHelpersIRNode();

// Act
writer.WriteExecuteTagHelpers(context, node);

// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Empty(csharp);
}

[Fact]
public void WriteExecuteTagHelpers_Runtime_RendersWithRedirectWriter()
{
// Arrange
var writer = new RedirectedTagHelperWriter(new RuntimeTagHelperWriter(), "test_writer")
{
WriteTagHelperOutputMethod = "Test",
};

var context = new CSharpRenderingContext()
{
Options = RazorParserOptions.CreateDefaultOptions(),
Writer = new Legacy.CSharpCodeWriter(),
};

var node = new ExecuteTagHelpersIRNode();

// Act
writer.WriteExecuteTagHelpers(context, node);

// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
if (!__tagHelperExecutionContext.Output.IsContentModified)
{
await __tagHelperExecutionContext.SetOutputContentAsync();
}
Test(test_writer, __tagHelperExecutionContext.Output);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
",
csharp,
ignoreLineEndingDifferences: true);
}
}
}
Loading

0 comments on commit 0228fd2

Please sign in to comment.