aspnetcore/src/Microsoft.AspNetCore.Razor..../CodeGeneration/RuntimeBasicWriter.cs

147 lines
5.0 KiB
C#

// 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.Text;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
{
public class RuntimeBasicWriter : BasicWriter
{
public string WriteCSharpExpressionMethod { get; set; } = "Write";
public string WriteHtmlContentMethod { get; set; } = "WriteLiteral";
public override void WriteCSharpExpression(CSharpRenderingContext context, CSharpExpressionIRNode node)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}
IDisposable linePragmaScope = null;
if (node.Source != null)
{
linePragmaScope = context.Writer.BuildLinePragma(node.Source.Value);
context.Writer.WritePadding(WriteCSharpExpressionMethod.Length + 1, node.Source, context);
}
context.Writer.WriteStartMethodInvocation(WriteCSharpExpressionMethod);
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 WriteCSharpStatement(CSharpRenderingContext context, CSharpStatementIRNode node)
{
var isWhitespaceStatement = true;
for (var i = 0; i < node.Children.Count; i++)
{
var token = node.Children[i] as RazorIRToken;
if (token == null || !string.IsNullOrWhiteSpace(token.Content))
{
isWhitespaceStatement = false;
break;
}
}
if (isWhitespaceStatement)
{
return;
}
IDisposable linePragmaScope = null;
if (node.Source != null)
{
linePragmaScope = context.Writer.BuildLinePragma(node.Source.Value);
context.Writer.WritePadding(0, node.Source.Value, context);
}
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 statement like an extension node.
context.RenderNode(node.Children[i]);
}
}
if (linePragmaScope == null)
{
context.Writer.WriteLine();
}
linePragmaScope?.Dispose();
}
public override void WriteHtmlAttribute(CSharpRenderingContext context, HtmlAttributeIRNode node)
{
throw new NotImplementedException();
}
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)
.WriteStringLiteral(textToRender)
.WriteEndMethodInvocation();
charactersConsumed += textToRender.Length;
}
}
}
}