Remove Redirect writers

This commit is contained in:
Ajay Bhargav Baaskaran 2017-05-05 12:50:17 -07:00
parent d3e37f20ce
commit b44d59ca36
20 changed files with 114 additions and 790 deletions

View File

@ -1,212 +0,0 @@
// 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.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
{
internal class RedirectedRuntimeBasicWriter : RuntimeBasicWriter
{
private readonly string _textWriter;
public RedirectedRuntimeBasicWriter(string textWriter)
{
_textWriter = textWriter;
}
public override string WriteCSharpExpressionMethod { get; set; } = "WriteTo";
public override string WriteHtmlContentMethod { get; set; } = "WriteLiteralTo";
public override string BeginWriteAttributeMethod { get; set; } = "BeginWriteAttributeTo";
public override string EndWriteAttributeMethod { get; set; } = "EndWriteAttributeTo";
public override string WriteAttributeValueMethod { get; set; } = "WriteAttributeValueTo";
public override void WriteCSharpExpression(CSharpRenderingContext context, CSharpExpressionIRNode node)
{
IDisposable linePragmaScope = null;
if (node.Source != null)
{
linePragmaScope = context.Writer.BuildLinePragma(node.Source.Value);
var offset = WriteCSharpExpressionMethod.Length + "(".Length + _textWriter.Length + ", ".Length;
context.Writer.WritePadding(offset, node.Source, context);
}
context.Writer.WriteStartMethodInvocation(WriteCSharpExpressionMethod);
context.Writer.Write(_textWriter);
context.Writer.WriteParameterSeparator();
for (var i = 0; i < node.Children.Count; i++)
{
if (node.Children[i] is RazorIRToken token && token.IsCSharp)
{
context.Writer.Write(token.Content);
}
else
{
// There may be something else inside the expression like a Template or another extension node.
context.RenderNode(node.Children[i]);
}
}
context.Writer.WriteEndMethodInvocation();
linePragmaScope?.Dispose();
}
public override void WriteHtmlContent(CSharpRenderingContext context, HtmlContentIRNode node)
{
const int MaxStringLiteralLength = 1024;
var builder = new StringBuilder();
for (var i = 0; i < node.Children.Count; i++)
{
if (node.Children[i] is RazorIRToken token && token.IsHtml)
{
builder.Append(token.Content);
}
}
var content = builder.ToString();
var charactersConsumed = 0;
// Render the string in pieces to avoid Roslyn OOM exceptions at compile time: https://github.com/aspnet/External/issues/54
while (charactersConsumed < content.Length)
{
string textToRender;
if (content.Length <= MaxStringLiteralLength)
{
textToRender = content;
}
else
{
var charactersToSubstring = Math.Min(MaxStringLiteralLength, content.Length - charactersConsumed);
textToRender = content.Substring(charactersConsumed, charactersToSubstring);
}
context.Writer
.WriteStartMethodInvocation(WriteHtmlContentMethod)
.Write(_textWriter)
.WriteParameterSeparator()
.WriteStringLiteral(textToRender)
.WriteEndMethodInvocation();
charactersConsumed += textToRender.Length;
}
}
public override void WriteHtmlAttribute(CSharpRenderingContext context, HtmlAttributeIRNode node)
{
var valuePieceCount = node
.Children
.Count(child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode);
var prefixLocation = node.Source.Value.AbsoluteIndex;
var suffixLocation = node.Source.Value.AbsoluteIndex + node.Source.Value.Length - node.Suffix.Length;
context.Writer
.WriteStartMethodInvocation(BeginWriteAttributeMethod)
.Write(_textWriter)
.WriteParameterSeparator()
.WriteStringLiteral(node.Name)
.WriteParameterSeparator()
.WriteStringLiteral(node.Prefix)
.WriteParameterSeparator()
.Write(prefixLocation.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator()
.WriteStringLiteral(node.Suffix)
.WriteParameterSeparator()
.Write(suffixLocation.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator()
.Write(valuePieceCount.ToString(CultureInfo.InvariantCulture))
.WriteEndMethodInvocation();
context.RenderChildren(node);
context.Writer
.WriteStartMethodInvocation(EndWriteAttributeMethod)
.Write(_textWriter)
.WriteEndMethodInvocation();
}
public override void WriteHtmlAttributeValue(CSharpRenderingContext context, HtmlAttributeValueIRNode node)
{
var prefixLocation = node.Source.Value.AbsoluteIndex;
var valueLocation = node.Source.Value.AbsoluteIndex + node.Prefix.Length;
var valueLength = node.Source.Value.Length;
context.Writer
.WriteStartMethodInvocation(WriteAttributeValueMethod)
.Write(_textWriter)
.WriteParameterSeparator()
.WriteStringLiteral(node.Prefix)
.WriteParameterSeparator()
.Write(prefixLocation.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator()
.WriteStringLiteral(node.Content)
.WriteParameterSeparator()
.Write(valueLocation.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator()
.Write(valueLength.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator()
.WriteBooleanLiteral(true)
.WriteEndMethodInvocation();
}
public override void WriteCSharpAttributeValue(CSharpRenderingContext context, CSharpAttributeValueIRNode node)
{
const string ValueWriterName = "__razor_attribute_value_writer";
var expressionValue = node.Children.FirstOrDefault() as CSharpExpressionIRNode;
var linePragma = expressionValue != null ? context.Writer.BuildLinePragma(node.Source.Value) : null;
var prefixLocation = node.Source.Value.AbsoluteIndex;
var valueLocation = node.Source.Value.AbsoluteIndex + node.Prefix.Length;
var valueLength = node.Source.Value.Length - node.Prefix.Length;
context.Writer
.WriteStartMethodInvocation(WriteAttributeValueMethod)
.Write(_textWriter)
.WriteParameterSeparator()
.WriteStringLiteral(node.Prefix)
.WriteParameterSeparator()
.Write(prefixLocation.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator();
if (expressionValue != null)
{
Debug.Assert(node.Children.Count == 1);
RenderExpressionInline(context, expressionValue);
}
else
{
// Not an expression; need to buffer the result.
context.Writer.WriteStartNewObject(TemplateTypeName);
using (context.Push(new RedirectedRuntimeBasicWriter(ValueWriterName)))
using (context.Writer.BuildAsyncLambda(endLine: false, parameterNames: ValueWriterName))
{
context.RenderChildren(node);
}
context.Writer.WriteEndMethodInvocation(false);
}
context.Writer
.WriteParameterSeparator()
.Write(valueLocation.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator()
.Write(valueLength.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator()
.WriteBooleanLiteral(false)
.WriteEndMethodInvocation();
linePragma?.Dispose();
}
}
}

View File

@ -1,59 +0,0 @@
// 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.CodeGeneration
{
internal class RedirectedRuntimeTagHelperWriter : RuntimeTagHelperWriter
{
private readonly string _textWriter;
public RedirectedRuntimeTagHelperWriter(string textWriter)
{
_textWriter = textWriter;
}
public override string WriteTagHelperOutputMethod { get; set; } = "WriteTo";
public override void WriteExecuteTagHelpers(CSharpRenderingContext context, ExecuteTagHelpersIRNode node)
{
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);
}
}
}

View File

@ -22,6 +22,10 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
public virtual string WriteAttributeValueMethod { get; set; } = "WriteAttributeValue";
public virtual string PushWriterMethod { get; set; } = "PushWriter";
public virtual string PopWriterMethod { get; set; } = "PopWriter";
public string TemplateTypeName { get; set; } = "Microsoft.AspNetCore.Mvc.Razor.HelperResult";
public override void WriteChecksum(CSharpRenderingContext context, ChecksumIRNode node)
@ -216,10 +220,13 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
// Not an expression; need to buffer the result.
context.Writer.WriteStartNewObject(TemplateTypeName);
using (context.Push(new RedirectedRuntimeBasicWriter(ValueWriterName)))
using (context.Writer.BuildAsyncLambda(endLine: false, parameterNames: ValueWriterName))
{
context.Writer.WriteMethodInvocation(PushWriterMethod, ValueWriterName);
context.RenderChildren(node);
context.Writer.WriteMethodInvocation(PopWriterMethod);
}
context.Writer.WriteEndMethodInvocation(false);

View File

@ -9,9 +9,15 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
internal class TemplateTargetExtension : ITemplateTargetExtension
{
public static readonly string DefaultTemplateTypeName = "Microsoft.AspNetCore.Mvc.Razor.HelperResult";
public static readonly string DefaultPushWriterMethod = "PushWriter";
public static readonly string DefaultPopWriterMethod = "PopWriter";
public string TemplateTypeName { get; set; } = DefaultTemplateTypeName;
public string PushWriterMethod { get; set; } = DefaultPushWriterMethod;
public string PopWriterMethod { get; set; } = DefaultPopWriterMethod;
public void WriteTemplate(CSharpRenderingContext context, TemplateIRNode node)
{
const string ItemParameterName = "item";
@ -21,21 +27,20 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
.Write(ItemParameterName).Write(" => ")
.WriteStartNewObject(TemplateTypeName);
IDisposable basicWriterScope = null;
IDisposable tagHelperWriterScope = null;
if (!context.Options.DesignTimeMode)
{
basicWriterScope = context.Push(new RedirectedRuntimeBasicWriter(TemplateWriterName));
tagHelperWriterScope = context.Push(new RedirectedRuntimeTagHelperWriter(TemplateWriterName));
}
using (context.Writer.BuildAsyncLambda(endLine: false, parameterNames: TemplateWriterName))
{
context.RenderChildren(node);
}
if (!context.Options.DesignTimeMode)
{
context.Writer.WriteMethodInvocation(PushWriterMethod, TemplateWriterName);
}
basicWriterScope?.Dispose();
tagHelperWriterScope?.Dispose();
context.RenderChildren(node);
if (!context.Options.DesignTimeMode)
{
context.Writer.WriteMethodInvocation(PopWriterMethod);
}
}
context.Writer.WriteEndMethodInvocation(endLine: false);
}

View File

@ -1,414 +0,0 @@
// 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 System.Linq;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
{
public class RedirectedRuntimeBasicWriterTest
{
[Fact]
public void WriteCSharpExpression_Runtime_SkipsLinePragma_WithoutSource()
{
// Arrange
var writer = new RedirectedRuntimeBasicWriter("test_writer")
{
WriteCSharpExpressionMethod = "Test",
};
var context = new CSharpRenderingContext()
{
Options = RazorParserOptions.CreateDefaultOptions(),
Writer = new Legacy.CSharpCodeWriter(),
};
var node = new CSharpExpressionIRNode();
var builder = RazorIRBuilder.Create(node);
builder.Add(new RazorIRToken()
{
Content = "i++",
Kind = RazorIRToken.TokenKind.CSharp,
});
// Act
writer.WriteCSharpExpression(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"Test(test_writer, i++);
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteCSharpExpression_Runtime_WritesLinePragma_WithSource()
{
// Arrange
var writer = new RedirectedRuntimeBasicWriter("test_writer")
{
WriteCSharpExpressionMethod = "Test",
};
var context = new CSharpRenderingContext()
{
Options = RazorParserOptions.CreateDefaultOptions(),
Writer = new Legacy.CSharpCodeWriter(),
};
var node = new CSharpExpressionIRNode()
{
Source = new SourceSpan("test.cshtml", 0, 0, 0, 3),
};
var builder = RazorIRBuilder.Create(node);
builder.Add(new RazorIRToken()
{
Content = "i++",
Kind = RazorIRToken.TokenKind.CSharp,
});
// Act
writer.WriteCSharpExpression(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"#line 1 ""test.cshtml""
Test(test_writer, i++);
#line default
#line hidden
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteCSharpExpression_Runtime_WithExtensionNode_WritesPadding()
{
// Arrange
var writer = new RedirectedRuntimeBasicWriter("test_writer")
{
WriteCSharpExpressionMethod = "Test",
};
var context = new CSharpRenderingContext()
{
Options = RazorParserOptions.CreateDefaultOptions(),
Writer = new Legacy.CSharpCodeWriter(),
};
var node = new CSharpExpressionIRNode();
var builder = RazorIRBuilder.Create(node);
builder.Add(new RazorIRToken()
{
Content = "i",
Kind = RazorIRToken.TokenKind.CSharp,
});
builder.Add(new MyExtensionIRNode());
builder.Add(new RazorIRToken()
{
Content = "++",
Kind = RazorIRToken.TokenKind.CSharp,
});
context.RenderNode = (n) => Assert.IsType<MyExtensionIRNode>(n);
// Act
writer.WriteCSharpExpression(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"Test(test_writer, i++);
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteCSharpExpression_Runtime_WithSource_WritesPadding()
{
// Arrange
var writer = new RedirectedRuntimeBasicWriter("test_writer")
{
WriteCSharpExpressionMethod = "Test",
};
var sourceDocument = TestRazorSourceDocument.Create(" @i++");
var context = new CSharpRenderingContext()
{
Options = RazorParserOptions.CreateDefaultOptions(),
CodeDocument = RazorCodeDocument.Create(sourceDocument),
Writer = new Legacy.CSharpCodeWriter(),
};
var node = new CSharpExpressionIRNode()
{
Source = new SourceSpan("test.cshtml", 24, 0, 24, 3),
};
var builder = RazorIRBuilder.Create(node);
builder.Add(new RazorIRToken()
{
Content = "i",
Kind = RazorIRToken.TokenKind.CSharp,
});
builder.Add(new MyExtensionIRNode());
builder.Add(new RazorIRToken()
{
Content = "++",
Kind = RazorIRToken.TokenKind.CSharp,
});
context.RenderNode = (n) => Assert.IsType<MyExtensionIRNode>(n);
// Act
writer.WriteCSharpExpression(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"#line 1 ""test.cshtml""
Test(test_writer, i++);
#line default
#line hidden
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteHtmlContent_RendersContentCorrectly()
{
var writer = new RedirectedRuntimeBasicWriter("test_writer");
var context = new CSharpRenderingContext()
{
Writer = new Legacy.CSharpCodeWriter(),
Options = RazorParserOptions.CreateDefaultOptions(),
};
var node = new HtmlContentIRNode();
node.Children.Add(new RazorIRToken()
{
Content = "SomeContent",
Kind = RazorIRToken.TokenKind.Html,
Parent = node
});
// Act
writer.WriteHtmlContent(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"WriteLiteralTo(test_writer, ""SomeContent"");
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteHtmlContent_LargeStringLiteral_UsesMultipleWrites()
{
var writer = new RedirectedRuntimeBasicWriter("test_writer");
var context = new CSharpRenderingContext()
{
Writer = new Legacy.CSharpCodeWriter(),
Options = RazorParserOptions.CreateDefaultOptions(),
};
var node = new HtmlContentIRNode();
node.Children.Add(new RazorIRToken()
{
Content = new string('*', 2000),
Kind = RazorIRToken.TokenKind.Html,
Parent = node
});
// Act
writer.WriteHtmlContent(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(string.Format(
@"WriteLiteralTo(test_writer, @""{0}"");
WriteLiteralTo(test_writer, @""{1}"");
", new string('*', 1024), new string('*', 976)),
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteHtmlAttribute_RendersCorrectly()
{
var writer = new RedirectedRuntimeBasicWriter("test_writer");
var context = GetCSharpRenderingContext(writer);
var content = "<input checked=\"hello-world @false\" />";
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument);
var node = irDocument.Children.OfType<HtmlAttributeIRNode>().Single();
// Act
writer.WriteHtmlAttribute(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"BeginWriteAttributeTo(test_writer, ""checked"", "" checked=\"""", 6, ""\"""", 34, 2);
Render Children
EndWriteAttributeTo(test_writer);
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteHtmlAttributeValue_RendersCorrectly()
{
var writer = new RedirectedRuntimeBasicWriter("test_writer");
var context = GetCSharpRenderingContext(writer);
var content = "<input checked=\"hello-world @false\" />";
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument);
var node = irDocument.Children.OfType<HtmlAttributeIRNode>().Single().Children[0] as HtmlAttributeValueIRNode;
// Act
writer.WriteHtmlAttributeValue(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"WriteAttributeValueTo(test_writer, """", 16, ""hello-world"", 16, 11, true);
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteCSharpAttributeValue_RendersCorrectly()
{
var writer = new RedirectedRuntimeBasicWriter("test_writer");
var context = GetCSharpRenderingContext(writer);
var content = "<input checked=\"hello-world @false\" />";
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument);
var node = irDocument.Children.OfType<HtmlAttributeIRNode>().Single().Children[1] as CSharpAttributeValueIRNode;
// Act
writer.WriteCSharpAttributeValue(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"#line 1 ""test.cshtml""
WriteAttributeValueTo(test_writer, "" "", 27, false, 28, 6, false);
#line default
#line hidden
",
csharp,
ignoreLineEndingDifferences: true);
}
[Fact]
public void WriteCSharpAttributeValue_NonExpression_BuffersResult()
{
var writer = new RedirectedRuntimeBasicWriter("test_writer");
var context = GetCSharpRenderingContext(writer);
var content = "<input checked=\"hello-world @if(@true){ }\" />";
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument);
var node = irDocument.Children.OfType<HtmlAttributeIRNode>().Single().Children[1] as CSharpAttributeValueIRNode;
// Act
writer.WriteCSharpAttributeValue(context, node);
// Assert
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"WriteAttributeValueTo(test_writer, "" "", 27, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {
Render Children
}
), 28, 13, false);
",
csharp,
ignoreLineEndingDifferences: true);
}
private static CSharpRenderingContext GetCSharpRenderingContext(BasicWriter writer)
{
var options = RazorParserOptions.CreateDefaultOptions();
var codeWriter = new Legacy.CSharpCodeWriter();
var context = new CSharpRenderingContext()
{
Writer = codeWriter,
Options = options,
BasicWriter = writer,
RenderChildren = n =>
{
codeWriter.WriteLine("Render Children");
}
};
return context;
}
private static DocumentIRNode Lower(RazorCodeDocument codeDocument)
{
var engine = RazorEngine.Create();
return Lower(codeDocument, engine);
}
private static DocumentIRNode Lower(RazorCodeDocument codeDocument, RazorEngine engine)
{
for (var i = 0; i < engine.Phases.Count; i++)
{
var phase = engine.Phases[i];
phase.Execute(codeDocument);
if (phase is IRazorIRLoweringPhase)
{
break;
}
}
var irDocument = codeDocument.GetIRDocument();
Assert.NotNull(irDocument);
return irDocument;
}
private class MyExtensionIRNode : ExtensionIRNode
{
public override IList<RazorIRNode> Children => throw new NotImplementedException();
public override RazorIRNode Parent { get; set; }
public override SourceSpan? Source { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override void Accept(RazorIRNodeVisitor visitor)
{
throw new NotImplementedException();
}
public override void WriteNode(RuntimeTarget target, CSharpRenderingContext context)
{
throw new NotImplementedException();
}
}
}
}

View File

@ -1,46 +0,0 @@
// 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;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
{
public class RedirectedRuntimeTagHelperWriterTest
{
[Fact]
public void WriteExecuteTagHelpers_Runtime_RendersWithRedirectWriter()
{
// Arrange
var writer = new RedirectedRuntimeTagHelperWriter("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);
}
}
}

View File

@ -589,7 +589,9 @@ WriteAttributeValue("" "", 27, false, 28, 6, false);
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"WriteAttributeValue("" "", 27, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {
PushWriter(__razor_attribute_value_writer);
Render Children
PopWriter();
}
), 28, 13, false);
",

View File

@ -80,7 +80,9 @@ AddHtmlAttributeValue("" "", 27, false, 28, 6, false);
var csharp = context.Writer.Builder.ToString();
Assert.Equal(
@"AddHtmlAttributeValue("" "", 27, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {
PushWriter(__razor_attribute_value_writer);
Render Children
PopWriter();
}
), 28, 13, false);
",

View File

@ -18,6 +18,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
var extension = new TemplateTargetExtension()
{
TemplateTypeName = "global::TestTemplate",
PushWriterMethod = "TestPushWriter",
PopWriterMethod = "TestPopWriter"
};
var context = new CSharpRenderingContext()
@ -31,10 +33,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
context.RenderChildren = (n) =>
{
Assert.Same(node, n);
Assert.IsType<RedirectedRuntimeBasicWriter>(context.BasicWriter);
context.Writer.Write(" var s = \"Inside\"");
context.Writer.WriteLine(" var s = \"Inside\"");
};
// Act
@ -42,7 +41,9 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
// Assert
var expected = @"item => new global::TestTemplate(async(__razor_template_writer) => {
TestPushWriter(__razor_template_writer);
var s = ""Inside""
TestPopWriter();
}
)";

View File

@ -408,6 +408,7 @@ __TestNamespace_PTagHelper.Age = ("My age is this long.".Length);
WriteLiteral("\r\n ");
#line 34 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ComplexTagHelpers.cshtml"
Write(someMethod(item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
PushWriter(__razor_template_writer);
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "test", async() => {
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, "test", async() => {
}
@ -445,8 +446,9 @@ __TestNamespace_PTagHelper.Age = 123;
{
await __tagHelperExecutionContext.SetOutputContentAsync();
}
WriteTo(__razor_template_writer, __tagHelperExecutionContext.Output);
Write(__tagHelperExecutionContext.Output);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
PopWriter();
}
)));

View File

@ -62,13 +62,14 @@ WriteAttributeValue(" ", 232, ch, 233, 3, false);
WriteLiteral(" />\r\n <p");
BeginWriteAttribute("class", " class=\"", 248, "\"", 281, 1);
WriteAttributeValue("", 256, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {
PushWriter(__razor_attribute_value_writer);
#line 10 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml"
if(cls != null) {
#line default
#line hidden
#line 10 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes.cshtml"
WriteTo(__razor_attribute_value_writer, cls);
Write(cls);
#line default
#line hidden
@ -77,6 +78,7 @@ WriteTo(__razor_attribute_value_writer, cls);
#line default
#line hidden
PopWriter();
}
), 256, 25, false);
EndWriteAttribute();

View File

@ -57,13 +57,14 @@ AddHtmlAttributeValue(" ", 57, DateTime.Now, 58, 13, false);
__tagHelperExecutionContext.Add(__TestNamespace_InputTagHelper);
BeginAddHtmlAttributeValues(__tagHelperExecutionContext, "unbound", 2, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
AddHtmlAttributeValue("", 95, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {
PushWriter(__razor_attribute_value_writer);
#line 5 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
if (true) {
#line default
#line hidden
#line 5 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
WriteTo(__razor_attribute_value_writer, string.Empty);
Write(string.Empty);
#line default
#line hidden
@ -73,7 +74,7 @@ WriteTo(__razor_attribute_value_writer, string.Empty);
#line default
#line hidden
#line 5 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
WriteTo(__razor_attribute_value_writer, false);
Write(false);
#line default
#line hidden
@ -82,6 +83,7 @@ WriteTo(__razor_attribute_value_writer, string.Empty);
#line default
#line hidden
PopWriter();
}
), 95, 44, false);
AddHtmlAttributeValue(" ", 139, "suffix", 140, 7, true);
@ -180,13 +182,14 @@ AddHtmlAttributeValue("", 347, long.MinValue, 347, 14, false);
#line default
#line hidden
AddHtmlAttributeValue(" ", 361, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {
PushWriter(__razor_attribute_value_writer);
#line 10 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
if (true) {
#line default
#line hidden
#line 10 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
WriteTo(__razor_attribute_value_writer, string.Empty);
Write(string.Empty);
#line default
#line hidden
@ -196,7 +199,7 @@ AddHtmlAttributeValue("", 347, long.MinValue, 347, 14, false);
#line default
#line hidden
#line 10 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
WriteTo(__razor_attribute_value_writer, false);
Write(false);
#line default
#line hidden
@ -205,6 +208,7 @@ AddHtmlAttributeValue("", 347, long.MinValue, 347, 14, false);
#line default
#line hidden
PopWriter();
}
), 362, 44, false);
#line 10 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
@ -260,13 +264,14 @@ AddHtmlAttributeValue(" ", 490, int.MaxValue, 491, 13, false);
__tagHelperExecutionContext.Add(__TestNamespace_InputTagHelper);
BeginAddHtmlAttributeValues(__tagHelperExecutionContext, "unbound", 1, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
AddHtmlAttributeValue("", 528, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {
PushWriter(__razor_attribute_value_writer);
#line 14 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
if (true) {
#line default
#line hidden
#line 14 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
WriteTo(__razor_attribute_value_writer, string.Empty);
Write(string.Empty);
#line default
#line hidden
@ -276,7 +281,7 @@ WriteTo(__razor_attribute_value_writer, string.Empty);
#line default
#line hidden
#line 14 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DynamicAttributeTagHelpers.cshtml"
WriteTo(__razor_attribute_value_writer, false);
Write(false);
#line default
#line hidden
@ -285,6 +290,7 @@ WriteTo(__razor_attribute_value_writer, string.Empty);
#line default
#line hidden
PopWriter();
}
), 528, 44, false);
EndAddHtmlAttributeValues(__tagHelperExecutionContext);

View File

@ -12,7 +12,9 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
WriteLiteral("<div>");
#line 1 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpressionWithMarkup.cshtml"
Write(item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, "</div>");
PushWriter(__razor_template_writer);
WriteLiteral("</div>");
PopWriter();
}
));

View File

@ -14,13 +14,14 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
WriteLiteral("(string link) {\r\n <a");
BeginWriteAttribute("href", " href=\"", 36, "\"", 93, 1);
WriteAttributeValue("", 43, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {
PushWriter(__razor_attribute_value_writer);
#line 2 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks.cshtml"
if(link != null) {
#line default
#line hidden
#line 2 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks.cshtml"
WriteTo(__razor_attribute_value_writer, link);
Write(link);
#line default
#line hidden
@ -29,12 +30,13 @@ WriteTo(__razor_attribute_value_writer, link);
#line default
#line hidden
WriteLiteralTo(__razor_attribute_value_writer, "#");
WriteLiteral("#");
#line 2 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks.cshtml"
}
#line default
#line hidden
PopWriter();
}
), 43, 50, false);
EndWriteAttribute();

View File

@ -17,7 +17,9 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
#line default
#line hidden
item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, "<p>Bar</p>");
PushWriter(__razor_template_writer);
WriteLiteral("<p>Bar</p>");
PopWriter();
}
)
#line 3 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Instrumented.cshtml"

View File

@ -41,13 +41,15 @@ WriteAttributeValue(" ", 121, thing, 122, 6, false);
#line default
#line hidden
item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, "<span>");
PushWriter(__razor_template_writer);
WriteLiteral("<span>");
#line 16 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections.cshtml"
WriteTo(__razor_template_writer, item);
Write(item);
#line default
#line hidden
WriteLiteralTo(__razor_template_writer, "</span>");
WriteLiteral("</span>");
PopWriter();
}
)
#line 16 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections.cshtml"

View File

@ -45,6 +45,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
#line default
#line hidden
item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
PushWriter(__razor_template_writer);
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("div", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "test", async() => {
WriteLiteral("<h3>");
#line 16 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/TagHelpersWithTemplate.cshtml"
@ -77,8 +78,9 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
{
await __tagHelperExecutionContext.SetOutputContentAsync();
}
WriteTo(__razor_template_writer, __tagHelperExecutionContext.Output);
Write(__tagHelperExecutionContext.Output);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
PopWriter();
}
)
#line 16 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/TagHelpersWithTemplate.cshtml"

View File

@ -17,13 +17,15 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
#line default
#line hidden
item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, "This works ");
PushWriter(__razor_template_writer);
WriteLiteral("This works ");
#line 12 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
WriteTo(__razor_template_writer, item);
Write(item);
#line default
#line hidden
WriteLiteralTo(__razor_template_writer, "!");
WriteLiteral("!");
PopWriter();
}
)
#line 12 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
@ -45,15 +47,17 @@ Write(foo(""));
#line default
#line hidden
item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, "<p");
BeginWriteAttributeTo(__razor_template_writer, "class", " class=\"", 411, "\"", 424, 1);
PushWriter(__razor_template_writer);
WriteLiteral("<p");
BeginWriteAttribute("class", " class=\"", 411, "\"", 424, 1);
#line 17 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
WriteAttributeValueTo(__razor_template_writer, "", 419, item, 419, 5, false);
WriteAttributeValue("", 419, item, 419, 5, false);
#line default
#line hidden
EndWriteAttributeTo(__razor_template_writer);
WriteLiteralTo(__razor_template_writer, ">Hello</p>");
EndWriteAttribute();
WriteLiteral(">Hello</p>");
PopWriter();
}
)
#line 17 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
@ -70,13 +74,15 @@ Write(bar("myclass"));
WriteLiteral("\r\n<ul>\r\n");
#line 22 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
Write(Repeat(10, item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, "<li>Item #");
PushWriter(__razor_template_writer);
WriteLiteral("<li>Item #");
#line 22 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
WriteTo(__razor_template_writer, item);
Write(item);
#line default
#line hidden
WriteLiteralTo(__razor_template_writer, "</li>");
WriteLiteral("</li>");
PopWriter();
}
)));
@ -86,13 +92,15 @@ WriteTo(__razor_template_writer, item);
#line 26 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
Write(Repeat(10,
item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, " This is line#");
PushWriter(__razor_template_writer);
WriteLiteral(" This is line#");
#line 27 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
WriteTo(__razor_template_writer, item);
Write(item);
#line default
#line hidden
WriteLiteralTo(__razor_template_writer, " of markup<br/>\r\n");
WriteLiteral(" of markup<br/>\r\n");
PopWriter();
}
)));
@ -102,13 +110,15 @@ WriteTo(__razor_template_writer, item);
#line 32 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
Write(Repeat(10,
item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, ": This is line#");
PushWriter(__razor_template_writer);
WriteLiteral(": This is line#");
#line 33 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
WriteTo(__razor_template_writer, item);
Write(item);
#line default
#line hidden
WriteLiteralTo(__razor_template_writer, " of markup<br />\r\n");
WriteLiteral(" of markup<br />\r\n");
PopWriter();
}
)));
@ -118,13 +128,15 @@ WriteTo(__razor_template_writer, item);
#line 38 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
Write(Repeat(10,
item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, ":: This is line#");
PushWriter(__razor_template_writer);
WriteLiteral(":: This is line#");
#line 39 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
WriteTo(__razor_template_writer, item);
Write(item);
#line default
#line hidden
WriteLiteralTo(__razor_template_writer, " of markup<br />\r\n");
WriteLiteral(" of markup<br />\r\n");
PopWriter();
}
)));
@ -133,20 +145,22 @@ WriteTo(__razor_template_writer, item);
WriteLiteral("\r\n</p>\r\n\r\n\r\n<ul>\r\n ");
#line 45 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
Write(Repeat(10, item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
WriteLiteralTo(__razor_template_writer, "<li>\r\n Item #");
PushWriter(__razor_template_writer);
WriteLiteral("<li>\r\n Item #");
#line 46 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
WriteTo(__razor_template_writer, item);
Write(item);
#line default
#line hidden
WriteLiteralTo(__razor_template_writer, "\r\n");
WriteLiteral("\r\n");
#line 47 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Templates.cshtml"
var parent = item;
#line default
#line hidden
WriteLiteralTo(__razor_template_writer, " <ul>\r\n <li>Child Items... ?</li>\r\n");
WriteLiteralTo(__razor_template_writer, " </ul>\r\n </li>");
WriteLiteral(" <ul>\r\n <li>Child Items... ?</li>\r\n");
WriteLiteral(" </ul>\r\n </li>");
PopWriter();
}
)));

View File

@ -45,6 +45,8 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
__tagHelperExecutionContext.Add(__TestNamespace_PTagHelper);
BeginAddHtmlAttributeValues(__tagHelperExecutionContext, "class", 1, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
AddHtmlAttributeValue("", 109, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {
PushWriter(__razor_attribute_value_writer);
PopWriter();
}
), 109, 6, false);
EndAddHtmlAttributeValues(__tagHelperExecutionContext);

View File

@ -98,9 +98,11 @@ __InputTagHelper.BarProp = DateTime.Now;
BeginContext(217, 29, false);
#line 9 "TestFiles/IntegrationTests/InstrumentationPassIntegrationTest/BasicTest.cshtml"
Write(Foo(item => new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_template_writer) => {
PushWriter(__razor_template_writer);
BeginContext(222, 24, true);
WriteLiteralTo(__razor_template_writer, "<span>Hello world</span>");
WriteLiteral("<span>Hello world</span>");
EndContext();
PopWriter();
}
)));