From ff40124594b58b17988d50841175430a4b73d1a9 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Thu, 6 Jul 2017 19:02:48 -0700 Subject: [PATCH] Convert most of CodeWriter into extensions We don't really want to ship what we have as a contract. As an emergency measure we are making it into internal extension methods so we can have a do-over in 2.1. --- ...oft.AspNetCore.Mvc.Razor.Extensions.csproj | 6 + .../CodeGeneration/CodeWriter.cs | 749 ++---------------- .../CodeGeneration/CodeWriterExtensions.cs | 642 +++++++++++++++ .../Properties/Resources.Designer.cs | 14 + .../Resources.resx | 3 + .../InjectTargetExtensionTest.cs | 4 +- .../CodeGeneration/CSharpCodeWriterTest.cs | 29 +- .../DesignTimeNodeWriterTest.cs | 28 +- .../LiteralRuntimeNodeWriterTest.cs | 2 +- .../CodeGeneration/RuntimeNodeWriterTest.cs | 36 +- ...elperHtmlAttributeRuntimeNodeWriterTest.cs | 6 +- .../DefaultTagHelperTargetExtensionTest.cs | 50 +- .../DesignTimeDirectiveTargetExtensionTest.cs | 12 +- ...reallocatedAttributeTargetExtensionTest.cs | 14 +- .../Extensions/SectionTargetExtensionTest.cs | 4 +- .../Extensions/TemplateTargetExtensionTest.cs | 2 +- 16 files changed, 833 insertions(+), 768 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriterExtensions.cs diff --git a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj index cb81e717aa..6298ff78bc 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Razor.Extensions/Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj @@ -10,6 +10,12 @@ aspnetcore;aspnetcoremvc;cshtml;razor + + + Shared\CodeWriterExtensions.cs + + + diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriter.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriter.cs index 8f78f1f92e..5b44fbc7fc 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriter.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriter.cs @@ -2,104 +2,135 @@ // 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.Diagnostics; -using System.Globalization; -using System.Linq; using System.Text; namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration { public sealed class CodeWriter { - private const string InstanceMethodFormat = "{0}.{1}"; - - private static readonly char[] CStyleStringLiteralEscapeChars = { - '\r', - '\t', - '\"', - '\'', - '\\', - '\0', - '\n', - '\u2028', - '\u2029', - }; - private static readonly char[] NewLineCharacters = { '\r', '\n' }; - private string _cache = string.Empty; - private bool _dirty; + private readonly StringBuilder _builder; + + private string _newLine; private int _absoluteIndex; private int _currentLineIndex; private int _currentLineCharacterIndex; - internal StringBuilder Builder { get; } = new StringBuilder(); + public CodeWriter() + { + NewLine = Environment.NewLine; + _builder = new StringBuilder(); + } public int CurrentIndent { get; set; } - public bool IsAfterNewLine { get; private set; } + public int Length => _builder.Length; - public string NewLine { get; set; } = Environment.NewLine; + public string NewLine + { + get => _newLine; + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (value != "\r\n" && value != "\n") + { + throw new ArgumentException(Resources.FormatCodeWriter_InvalidNewLine(value), nameof(value)); + } + + _newLine = value; + } + } public SourceLocation Location => new SourceLocation(_absoluteIndex, _currentLineIndex, _currentLineCharacterIndex); + public char this[int index] + { + get + { + if (index < 0 || index >= _builder.Length) + { + throw new IndexOutOfRangeException(nameof(index)); + } + + return _builder[index]; + } + } + // Internal for testing. internal CodeWriter Indent(int size) { - if (IsAfterNewLine) + if (Length == 0 || this[Length - 1] == '\n') { - Builder.Append(' ', size); + _builder.Append(' ', size); _currentLineCharacterIndex += size; _absoluteIndex += size; - - _dirty = true; - IsAfterNewLine = false; } return this; } - public CodeWriter Write(string data) + public CodeWriter Write(string value) { - if (data == null) + if (value == null) { - return this; + throw new ArgumentNullException(nameof(value)); } - return Write(data, 0, data.Length); + return Write(value, 0, value.Length); } - public CodeWriter Write(string data, int index, int count) + public CodeWriter Write(string value, int startIndex, int count) { - if (data == null || count == 0) + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (startIndex < 0) + { + throw new ArgumentOutOfRangeException(nameof(startIndex)); + } + + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count)); + } + + if (startIndex > value.Length - count) + { + throw new ArgumentOutOfRangeException(nameof(startIndex)); + } + + if (count == 0) { return this; } Indent(CurrentIndent); - Builder.Append(data, index, count); - - _dirty = true; - IsAfterNewLine = false; + _builder.Append(value, startIndex, count); _absoluteIndex += count; // The data string might contain a partial newline where the previously // written string has part of the newline. - var i = index; + var i = startIndex; int? trailingPartStart = null; if ( // Check the last character of the previous write operation. - Builder.Length - count - 1 >= 0 && - Builder[Builder.Length - count - 1] == '\r' && + _builder.Length - count - 1 >= 0 && + _builder[_builder.Length - count - 1] == '\r' && // Check the first character of the current write operation. - Builder[Builder.Length - count] == '\n') + _builder[_builder.Length - count] == '\n') { // This is newline that's spread across two writes. Skip the first character of the // current write operation. @@ -112,7 +143,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration // Iterate the string, stopping at each occurrence of a newline character. This lets us count the // newline occurrences and keep the index of the last one. - while ((i = data.IndexOfAny(NewLineCharacters, i)) >= 0) + while ((i = value.IndexOfAny(NewLineCharacters, i)) >= 0) { // Newline found. _currentLineIndex++; @@ -123,8 +154,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration // We might have stopped at a \r, so check if it's followed by \n and then advance the index to // start the next search after it. if (count > i && - data[i - 1] == '\r' && - data[i] == '\n') + value[i - 1] == '\r' && + value[i] == '\n') { i++; } @@ -149,638 +180,28 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration public CodeWriter WriteLine() { - Builder.Append(NewLine); + _builder.Append(NewLine); _currentLineIndex++; _currentLineCharacterIndex = 0; _absoluteIndex += NewLine.Length; - _dirty = true; - IsAfterNewLine = true; - return this; } - public CodeWriter WriteLine(string data) + public CodeWriter WriteLine(string value) { - return Write(data).WriteLine(); + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + return Write(value).WriteLine(); } public string GenerateCode() { - if (_dirty) - { - _cache = Builder.ToString(); - _dirty = false; - } - - return _cache; - } - - public CodeWriter WritePadding(int offset, SourceSpan? span, CodeRenderingContext context) - { - if (span == null) - { - return this; - } - - var basePadding = CalculatePadding(); - var resolvedPadding = Math.Max(basePadding - offset, 0); - - if (context.Options.IndentWithTabs) - { - // Avoid writing directly to the StringBuilder here, that will throw off the manual indexing - // done by the base class. - var tabs = resolvedPadding / context.Options.IndentSize; - for (var i = 0; i < tabs; i++) - { - Write("\t"); - } - - var spaces = resolvedPadding % context.Options.IndentSize; - for (var i = 0; i < spaces; i++) - { - Write(" "); - } - } - else - { - for (var i = 0; i < resolvedPadding; i++) - { - Write(" "); - } - } - - return this; - - int CalculatePadding() - { - var spaceCount = 0; - for (var i = span.Value.AbsoluteIndex - 1; i >= 0; i--) - { - var @char = context.SourceDocument[i]; - if (@char == '\n' || @char == '\r') - { - break; - } - else if (@char == '\t') - { - spaceCount += context.Options.IndentSize; - } - else - { - spaceCount++; - } - } - - return spaceCount; - } - } - - public CodeWriter WriteVariableDeclaration(string type, string name, string value) - { - Write(type).Write(" ").Write(name); - if (!string.IsNullOrEmpty(value)) - { - Write(" = ").Write(value); - } - else - { - Write(" = null"); - } - - WriteLine(";"); - - return this; - } - - public CodeWriter WriteBooleanLiteral(bool value) - { - return Write(value.ToString().ToLowerInvariant()); - } - - public CodeWriter WriteStartAssignment(string name) - { - return Write(name).Write(" = "); - } - - public CodeWriter WriteParameterSeparator() - { - return Write(", "); - } - - public CodeWriter WriteStartNewObject(string typeName) - { - return Write("new ").Write(typeName).Write("("); - } - - public CodeWriter WriteStringLiteral(string literal) - { - if (literal.Length >= 256 && literal.Length <= 1500 && literal.IndexOf('\0') == -1) - { - WriteVerbatimStringLiteral(literal); - } - else - { - WriteCStyleStringLiteral(literal); - } - - return this; - } - - public CodeWriter WriteUsing(string name) - { - return WriteUsing(name, endLine: true); - } - - public CodeWriter WriteUsing(string name, bool endLine) - { - Write("using "); - Write(name); - - if (endLine) - { - WriteLine(";"); - } - - return this; - } - - /// - /// Writes a #line pragma directive for the line number at the specified . - /// - /// The location to generate the line pragma for. - /// The file to generate the line pragma for. - /// The current instance of . - public CodeWriter WriteLineNumberDirective(SourceSpan location, string file) - { - if (location.FilePath != null) - { - file = location.FilePath; - } - - if (Builder.Length >= NewLine.Length && !IsAfterNewLine) - { - WriteLine(); - } - - var lineNumberAsString = (location.LineIndex + 1).ToString(CultureInfo.InvariantCulture); - return Write("#line ").Write(lineNumberAsString).Write(" \"").Write(file).WriteLine("\""); - } - - public CodeWriter WriteStartMethodInvocation(string methodName) - { - Write(methodName); - - return Write("("); - } - - public CodeWriter WriteEndMethodInvocation() - { - return WriteEndMethodInvocation(endLine: true); - } - - public CodeWriter WriteEndMethodInvocation(bool endLine) - { - Write(")"); - if (endLine) - { - WriteLine(";"); - } - - return this; - } - - // Writes a method invocation for the given instance name. - public CodeWriter WriteInstanceMethodInvocation( - string instanceName, - string methodName, - params string[] parameters) - { - if (instanceName == null) - { - throw new ArgumentNullException(nameof(instanceName)); - } - - if (methodName == null) - { - throw new ArgumentNullException(nameof(methodName)); - } - - return WriteInstanceMethodInvocation(instanceName, methodName, endLine: true, parameters: parameters); - } - - // Writes a method invocation for the given instance name. - public CodeWriter WriteInstanceMethodInvocation( - string instanceName, - string methodName, - bool endLine, - params string[] parameters) - { - if (instanceName == null) - { - throw new ArgumentNullException(nameof(instanceName)); - } - - if (methodName == null) - { - throw new ArgumentNullException(nameof(methodName)); - } - - return WriteMethodInvocation( - string.Format(CultureInfo.InvariantCulture, InstanceMethodFormat, instanceName, methodName), - endLine, - parameters); - } - - public CodeWriter WriteStartInstanceMethodInvocation(string instanceName, string methodName) - { - if (instanceName == null) - { - throw new ArgumentNullException(nameof(instanceName)); - } - - if (methodName == null) - { - throw new ArgumentNullException(nameof(methodName)); - } - - return WriteStartMethodInvocation( - string.Format(CultureInfo.InvariantCulture, InstanceMethodFormat, instanceName, methodName)); - } - - public CodeWriter WriteField(IList modifiers, string typeName, string fieldName) - { - if (modifiers == null) - { - throw new ArgumentNullException(nameof(modifiers)); - } - - if (typeName == null) - { - throw new ArgumentNullException(nameof(typeName)); - } - - if (fieldName == null) - { - throw new ArgumentNullException(nameof(fieldName)); - } - - for (var i = 0; i < modifiers.Count; i++) - { - Write(modifiers[i]); - Write(" "); - } - - Write(typeName); - Write(" "); - Write(fieldName); - Write(";"); - WriteLine(); - - return this; - } - - public CodeWriter WriteMethodInvocation(string methodName, params string[] parameters) - { - return WriteMethodInvocation(methodName, endLine: true, parameters: parameters); - } - - public CodeWriter WriteMethodInvocation(string methodName, bool endLine, params string[] parameters) - { - return WriteStartMethodInvocation(methodName) - .Write(string.Join(", ", parameters)) - .WriteEndMethodInvocation(endLine); - } - - public CodeWriter WriteAutoPropertyDeclaration(IList modifiers, string typeName, string propertyName) - { - if (modifiers == null) - { - throw new ArgumentNullException(nameof(modifiers)); - } - - if (typeName == null) - { - throw new ArgumentNullException(nameof(typeName)); - } - - if (propertyName == null) - { - throw new ArgumentNullException(nameof(propertyName)); - } - - for (var i = 0; i < modifiers.Count; i++) - { - Write(modifiers[i]); - Write(" "); - } - - Write(typeName); - Write(" "); - Write(propertyName); - Write(" { get; set; }"); - WriteLine(); - - return this; - } - - public CSharpCodeWritingScope BuildScope() - { - return new CSharpCodeWritingScope(this); - } - - public CSharpCodeWritingScope BuildLambda(params string[] parameterNames) - { - return BuildLambda(async: false, parameterNames: parameterNames); - } - - public CSharpCodeWritingScope BuildAsyncLambda(params string[] parameterNames) - { - return BuildLambda(async: true, parameterNames: parameterNames); - } - - private CSharpCodeWritingScope BuildLambda(bool async, string[] parameterNames) - { - if (async) - { - Write("async"); - } - - Write("(").Write(string.Join(", ", parameterNames)).Write(") => "); - - var scope = new CSharpCodeWritingScope(this); - - return scope; - } - - public CSharpCodeWritingScope BuildNamespace(string name) - { - Write("namespace ").WriteLine(name); - - return new CSharpCodeWritingScope(this); - } - - public CSharpCodeWritingScope BuildClassDeclaration( - IList modifiers, - string name, - string baseType, - IEnumerable interfaces) - { - for (var i = 0; i < modifiers.Count; i++) - { - Write(modifiers[i]); - Write(" "); - } - - Write("class "); - Write(name); - - var hasBaseType = !string.IsNullOrEmpty(baseType); - var hasInterfaces = interfaces != null && interfaces.Count() > 0; - - if (hasBaseType || hasInterfaces) - { - Write(" : "); - - if (hasBaseType) - { - Write(baseType); - - if (hasInterfaces) - { - WriteParameterSeparator(); - } - } - - if (hasInterfaces) - { - Write(string.Join(", ", interfaces)); - } - } - - WriteLine(); - - return new CSharpCodeWritingScope(this); - } - - public CSharpCodeWritingScope BuildMethodDeclaration( - string accessibility, - string returnType, - string name, - IEnumerable> parameters) - { - Write(accessibility) - .Write(" ") - .Write(returnType) - .Write(" ") - .Write(name) - .Write("(") - .Write(string.Join(", ", parameters.Select(p => p.Key + " " + p.Value))) - .WriteLine(")"); - - return new CSharpCodeWritingScope(this); - } - - public IDisposable BuildLinePragma(SourceSpan? span) - { - if (string.IsNullOrEmpty(span?.FilePath)) - { - // Can't build a valid line pragma without a file path. - return NullDisposable.Default; - } - - return new LinePragmaWriter(this, span.Value); - } - - private void WriteVerbatimStringLiteral(string literal) - { - Write("@\""); - - // We need to find the index of each '"' (double-quote) to escape it. - var start = 0; - int end; - while ((end = literal.IndexOf('\"', start)) > -1) - { - Write(literal, start, end - start); - - Write("\"\""); - - start = end + 1; - } - - Debug.Assert(end == -1); // We've hit all of the double-quotes. - - // Write the remainder after the last double-quote. - Write(literal, start, literal.Length - start); - - Write("\""); - } - - private void WriteCStyleStringLiteral(string literal) - { - // From CSharpCodeGenerator.QuoteSnippetStringCStyle in CodeDOM - Write("\""); - - // We need to find the index of each escapable character to escape it. - var start = 0; - int end; - while ((end = literal.IndexOfAny(CStyleStringLiteralEscapeChars, start)) > -1) - { - Write(literal, start, end - start); - - switch (literal[end]) - { - case '\r': - Write("\\r"); - break; - case '\t': - Write("\\t"); - break; - case '\"': - Write("\\\""); - break; - case '\'': - Write("\\\'"); - break; - case '\\': - Write("\\\\"); - break; - case '\0': - Write("\\\0"); - break; - case '\n': - Write("\\n"); - break; - case '\u2028': - case '\u2029': - Write("\\u"); - Write(((int)literal[end]).ToString("X4", CultureInfo.InvariantCulture)); - break; - default: - Debug.Assert(false, "Unknown escape character."); - break; - } - - start = end + 1; - } - - Debug.Assert(end == -1); // We've hit all of chars that need escaping. - - // Write the remainder after the last escaped char. - Write(literal, start, literal.Length - start); - - Write("\""); - } - - public struct CSharpCodeWritingScope : IDisposable - { - private CodeWriter _writer; - private bool _autoSpace; - private int _tabSize; - private int _startIndent; - - public CSharpCodeWritingScope(CodeWriter writer, int tabSize = 4, bool autoSpace = true) - { - _writer = writer; - _autoSpace = true; - _tabSize = tabSize; - _startIndent = -1; // Set in WriteStartScope - - WriteStartScope(); - } - - public void Dispose() - { - WriteEndScope(); - } - - private void WriteStartScope() - { - TryAutoSpace(" "); - - _writer.WriteLine("{"); - _writer.CurrentIndent += _tabSize; - _startIndent = _writer.CurrentIndent; - } - - private void WriteEndScope() - { - TryAutoSpace(_writer.NewLine); - - // Ensure the scope hasn't been modified - if (_writer.CurrentIndent == _startIndent) - { - _writer.CurrentIndent -= _tabSize; - } - - _writer.WriteLine("}"); - } - - private void TryAutoSpace(string spaceCharacter) - { - if (_autoSpace && - _writer.Builder.Length > 0 && - !char.IsWhiteSpace(_writer.Builder[_writer.Builder.Length - 1])) - { - _writer.Write(spaceCharacter); - } - } - } - - private class LinePragmaWriter : IDisposable - { - private readonly CodeWriter _writer; - private readonly int _startIndent; - - public LinePragmaWriter(CodeWriter writer, SourceSpan documentLocation) - { - if (writer == null) - { - throw new ArgumentNullException(nameof(writer)); - } - - _writer = writer; - _startIndent = _writer.CurrentIndent; - _writer.CurrentIndent = 0; - _writer.WriteLineNumberDirective(documentLocation, documentLocation.FilePath); - } - - public void Dispose() - { - // Need to add an additional line at the end IF there wasn't one already written. - // This is needed to work with the C# editor's handling of #line ... - var builder = _writer.Builder; - var endsWithNewline = builder.Length > 0 && builder[builder.Length - 1] == '\n'; - - // Always write at least 1 empty line to potentially separate code from pragmas. - _writer.WriteLine(); - - // Check if the previous empty line wasn't enough to separate code from pragmas. - if (!endsWithNewline) - { - _writer.WriteLine(); - } - - _writer - .WriteLine("#line default") - .WriteLine("#line hidden"); - - _writer.CurrentIndent = _startIndent; - } - } - - private class NullDisposable : IDisposable - { - public static readonly NullDisposable Default = new NullDisposable(); - - private NullDisposable() - { - } - - public void Dispose() - { - } + return _builder.ToString(); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriterExtensions.cs b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriterExtensions.cs new file mode 100644 index 0000000000..7d8c846ca2 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Language/CodeGeneration/CodeWriterExtensions.cs @@ -0,0 +1,642 @@ +// 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.Diagnostics; +using System.Globalization; +using System.Linq; + +namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration +{ + internal static class CodeWriterExtensions + { + private const string InstanceMethodFormat = "{0}.{1}"; + + private static readonly char[] CStyleStringLiteralEscapeChars = + { + '\r', + '\t', + '\"', + '\'', + '\\', + '\0', + '\n', + '\u2028', + '\u2029', + }; + + public static bool IsAtBeginningOfLine(this CodeWriter writer) + { + return writer.Length == 0 || writer[writer.Length - 1] == '\n'; + } + + public static CodeWriter WritePadding(this CodeWriter writer, int offset, SourceSpan? span, CodeRenderingContext context) + { + if (span == null) + { + return writer; + } + + var basePadding = CalculatePadding(); + var resolvedPadding = Math.Max(basePadding - offset, 0); + + if (context.Options.IndentWithTabs) + { + // Avoid writing directly to the StringBuilder here, that will throw off the manual indexing + // done by the base class. + var tabs = resolvedPadding / context.Options.IndentSize; + for (var i = 0; i < tabs; i++) + { + writer.Write("\t"); + } + + var spaces = resolvedPadding % context.Options.IndentSize; + for (var i = 0; i < spaces; i++) + { + writer.Write(" "); + } + } + else + { + for (var i = 0; i < resolvedPadding; i++) + { + writer.Write(" "); + } + } + + return writer; + + int CalculatePadding() + { + var spaceCount = 0; + for (var i = span.Value.AbsoluteIndex - 1; i >= 0; i--) + { + var @char = context.SourceDocument[i]; + if (@char == '\n' || @char == '\r') + { + break; + } + else if (@char == '\t') + { + spaceCount += context.Options.IndentSize; + } + else + { + spaceCount++; + } + } + + return spaceCount; + } + } + + public static CodeWriter WriteVariableDeclaration(this CodeWriter writer, string type, string name, string value) + { + writer.Write(type).Write(" ").Write(name); + if (!string.IsNullOrEmpty(value)) + { + writer.Write(" = ").Write(value); + } + else + { + writer.Write(" = null"); + } + + writer.WriteLine(";"); + + return writer; + } + + public static CodeWriter WriteBooleanLiteral(this CodeWriter writer, bool value) + { + return writer.Write(value.ToString().ToLowerInvariant()); + } + + public static CodeWriter WriteStartAssignment(this CodeWriter writer, string name) + { + return writer.Write(name).Write(" = "); + } + + public static CodeWriter WriteParameterSeparator(this CodeWriter writer) + { + return writer.Write(", "); + } + + public static CodeWriter WriteStartNewObject(this CodeWriter writer, string typeName) + { + return writer.Write("new ").Write(typeName).Write("("); + } + + public static CodeWriter WriteStringLiteral(this CodeWriter writer, string literal) + { + if (literal.Length >= 256 && literal.Length <= 1500 && literal.IndexOf('\0') == -1) + { + WriteVerbatimStringLiteral(writer, literal); + } + else + { + WriteCStyleStringLiteral(writer, literal); + } + + return writer; + } + + public static CodeWriter WriteUsing(this CodeWriter writer, string name) + { + return WriteUsing(writer, name, endLine: true); + } + + public static CodeWriter WriteUsing(this CodeWriter writer, string name, bool endLine) + { + writer.Write("using "); + writer.Write(name); + + if (endLine) + { + writer.WriteLine(";"); + } + + return writer; + } + + public static CodeWriter WriteLineNumberDirective(this CodeWriter writer, SourceSpan span) + { + if (writer.Length >= writer.NewLine.Length && !IsAtBeginningOfLine(writer)) + { + writer.WriteLine(); + } + + var lineNumberAsString = (span.LineIndex + 1).ToString(CultureInfo.InvariantCulture); + return writer.Write("#line ").Write(lineNumberAsString).Write(" \"").Write(span.FilePath).WriteLine("\""); + } + + public static CodeWriter WriteStartMethodInvocation(this CodeWriter writer, string methodName) + { + writer.Write(methodName); + + return writer.Write("("); + } + + public static CodeWriter WriteEndMethodInvocation(this CodeWriter writer) + { + return WriteEndMethodInvocation(writer, endLine: true); + } + + public static CodeWriter WriteEndMethodInvocation(this CodeWriter writer, bool endLine) + { + writer.Write(")"); + if (endLine) + { + writer.WriteLine(";"); + } + + return writer; + } + + // Writes a method invocation for the given instance name. + public static CodeWriter WriteInstanceMethodInvocation( + this CodeWriter writer, + string instanceName, + string methodName, + params string[] parameters) + { + if (instanceName == null) + { + throw new ArgumentNullException(nameof(instanceName)); + } + + if (methodName == null) + { + throw new ArgumentNullException(nameof(methodName)); + } + + return WriteInstanceMethodInvocation(writer, instanceName, methodName, endLine: true, parameters: parameters); + } + + // Writes a method invocation for the given instance name. + public static CodeWriter WriteInstanceMethodInvocation( + this CodeWriter writer, + string instanceName, + string methodName, + bool endLine, + params string[] parameters) + { + if (instanceName == null) + { + throw new ArgumentNullException(nameof(instanceName)); + } + + if (methodName == null) + { + throw new ArgumentNullException(nameof(methodName)); + } + + return WriteMethodInvocation( + writer, + string.Format(CultureInfo.InvariantCulture, InstanceMethodFormat, instanceName, methodName), + endLine, + parameters); + } + + public static CodeWriter WriteStartInstanceMethodInvocation(this CodeWriter writer, string instanceName, string methodName) + { + if (instanceName == null) + { + throw new ArgumentNullException(nameof(instanceName)); + } + + if (methodName == null) + { + throw new ArgumentNullException(nameof(methodName)); + } + + return WriteStartMethodInvocation( + writer, + string.Format(CultureInfo.InvariantCulture, InstanceMethodFormat, instanceName, methodName)); + } + + public static CodeWriter WriteField(this CodeWriter writer, IList modifiers, string typeName, string fieldName) + { + if (modifiers == null) + { + throw new ArgumentNullException(nameof(modifiers)); + } + + if (typeName == null) + { + throw new ArgumentNullException(nameof(typeName)); + } + + if (fieldName == null) + { + throw new ArgumentNullException(nameof(fieldName)); + } + + for (var i = 0; i < modifiers.Count; i++) + { + writer.Write(modifiers[i]); + writer.Write(" "); + } + + writer.Write(typeName); + writer.Write(" "); + writer.Write(fieldName); + writer.Write(";"); + writer.WriteLine(); + + return writer; + } + + public static CodeWriter WriteMethodInvocation(this CodeWriter writer, string methodName, params string[] parameters) + { + return WriteMethodInvocation(writer, methodName, endLine: true, parameters: parameters); + } + + public static CodeWriter WriteMethodInvocation(this CodeWriter writer, string methodName, bool endLine, params string[] parameters) + { + return + WriteStartMethodInvocation(writer, methodName) + .Write(string.Join(", ", parameters)) + .WriteEndMethodInvocation(endLine); + } + + public static CodeWriter WriteAutoPropertyDeclaration(this CodeWriter writer, IList modifiers, string typeName, string propertyName) + { + if (modifiers == null) + { + throw new ArgumentNullException(nameof(modifiers)); + } + + if (typeName == null) + { + throw new ArgumentNullException(nameof(typeName)); + } + + if (propertyName == null) + { + throw new ArgumentNullException(nameof(propertyName)); + } + + for (var i = 0; i < modifiers.Count; i++) + { + writer.Write(modifiers[i]); + writer.Write(" "); + } + + writer.Write(typeName); + writer.Write(" "); + writer.Write(propertyName); + writer.Write(" { get; set; }"); + writer.WriteLine(); + + return writer; + } + + public static CSharpCodeWritingScope BuildScope(this CodeWriter writer) + { + return new CSharpCodeWritingScope(writer); + } + + public static CSharpCodeWritingScope BuildLambda(this CodeWriter writer, params string[] parameterNames) + { + return BuildLambda(writer, async: false, parameterNames: parameterNames); + } + + public static CSharpCodeWritingScope BuildAsyncLambda(this CodeWriter writer, params string[] parameterNames) + { + return BuildLambda(writer, async: true, parameterNames: parameterNames); + } + + private static CSharpCodeWritingScope BuildLambda(CodeWriter writer, bool async, string[] parameterNames) + { + if (async) + { + writer.Write("async"); + } + + writer.Write("(").Write(string.Join(", ", parameterNames)).Write(") => "); + + var scope = new CSharpCodeWritingScope(writer); + + return scope; + } + + public static CSharpCodeWritingScope BuildNamespace(this CodeWriter writer, string name) + { + writer.Write("namespace ").WriteLine(name); + + return new CSharpCodeWritingScope(writer); + } + + public static CSharpCodeWritingScope BuildClassDeclaration( + this CodeWriter writer, + IList modifiers, + string name, + string baseType, + IEnumerable interfaces) + { + for (var i = 0; i < modifiers.Count; i++) + { + writer.Write(modifiers[i]); + writer.Write(" "); + } + + writer.Write("class "); + writer.Write(name); + + var hasBaseType = !string.IsNullOrEmpty(baseType); + var hasInterfaces = interfaces != null && interfaces.Count() > 0; + + if (hasBaseType || hasInterfaces) + { + writer.Write(" : "); + + if (hasBaseType) + { + writer.Write(baseType); + + if (hasInterfaces) + { + WriteParameterSeparator(writer); + } + } + + if (hasInterfaces) + { + writer.Write(string.Join(", ", interfaces)); + } + } + + writer.WriteLine(); + + return new CSharpCodeWritingScope(writer); + } + + public static CSharpCodeWritingScope BuildMethodDeclaration( + this CodeWriter writer, + string accessibility, + string returnType, + string name, + IEnumerable> parameters) + { + writer.Write(accessibility) + .Write(" ") + .Write(returnType) + .Write(" ") + .Write(name) + .Write("(") + .Write(string.Join(", ", parameters.Select(p => p.Key + " " + p.Value))) + .WriteLine(")"); + + return new CSharpCodeWritingScope(writer); + } + + public static IDisposable BuildLinePragma(this CodeWriter writer, SourceSpan? span) + { + if (string.IsNullOrEmpty(span?.FilePath)) + { + // Can't build a valid line pragma without a file path. + return NullDisposable.Default; + } + + return new LinePragmaWriter(writer, span.Value); + } + + private static void WriteVerbatimStringLiteral(CodeWriter writer, string literal) + { + writer.Write("@\""); + + // We need to suppress indenting during the writing of the string's content. A + // verbatim string literal could contain newlines that don't get escaped. + var indent = writer.CurrentIndent; + writer.CurrentIndent = 0; + + // We need to find the index of each '"' (double-quote) to escape it. + var start = 0; + int end; + while ((end = literal.IndexOf('\"', start)) > -1) + { + writer.Write(literal, start, end - start); + + writer.Write("\"\""); + + start = end + 1; + } + + Debug.Assert(end == -1); // We've hit all of the double-quotes. + + // Write the remainder after the last double-quote. + writer.Write(literal, start, literal.Length - start); + + writer.Write("\""); + + writer.CurrentIndent = indent; + } + + private static void WriteCStyleStringLiteral(CodeWriter writer, string literal) + { + // From CSharpCodeGenerator.QuoteSnippetStringCStyle in CodeDOM + writer.Write("\""); + + // We need to find the index of each escapable character to escape it. + var start = 0; + int end; + while ((end = literal.IndexOfAny(CStyleStringLiteralEscapeChars, start)) > -1) + { + writer.Write(literal, start, end - start); + + switch (literal[end]) + { + case '\r': + writer.Write("\\r"); + break; + case '\t': + writer.Write("\\t"); + break; + case '\"': + writer.Write("\\\""); + break; + case '\'': + writer.Write("\\\'"); + break; + case '\\': + writer.Write("\\\\"); + break; + case '\0': + writer.Write("\\\0"); + break; + case '\n': + writer.Write("\\n"); + break; + case '\u2028': + case '\u2029': + writer.Write("\\u"); + writer.Write(((int)literal[end]).ToString("X4", CultureInfo.InvariantCulture)); + break; + default: + Debug.Assert(false, "Unknown escape character."); + break; + } + + start = end + 1; + } + + Debug.Assert(end == -1); // We've hit all of chars that need escaping. + + // Write the remainder after the last escaped char. + writer.Write(literal, start, literal.Length - start); + + writer.Write("\""); + } + + public struct CSharpCodeWritingScope : IDisposable + { + private CodeWriter _writer; + private bool _autoSpace; + private int _tabSize; + private int _startIndent; + + public CSharpCodeWritingScope(CodeWriter writer, int tabSize = 4, bool autoSpace = true) + { + _writer = writer; + _autoSpace = true; + _tabSize = tabSize; + _startIndent = -1; // Set in WriteStartScope + + WriteStartScope(); + } + + public void Dispose() + { + WriteEndScope(); + } + + private void WriteStartScope() + { + TryAutoSpace(" "); + + _writer.WriteLine("{"); + _writer.CurrentIndent += _tabSize; + _startIndent = _writer.CurrentIndent; + } + + private void WriteEndScope() + { + TryAutoSpace(_writer.NewLine); + + // Ensure the scope hasn't been modified + if (_writer.CurrentIndent == _startIndent) + { + _writer.CurrentIndent -= _tabSize; + } + + _writer.WriteLine("}"); + } + + private void TryAutoSpace(string spaceCharacter) + { + if (_autoSpace && + _writer.Length > 0 && + !char.IsWhiteSpace(_writer[_writer.Length - 1])) + { + _writer.Write(spaceCharacter); + } + } + } + + private class LinePragmaWriter : IDisposable + { + private readonly CodeWriter _writer; + private readonly int _startIndent; + + public LinePragmaWriter(CodeWriter writer, SourceSpan span) + { + if (writer == null) + { + throw new ArgumentNullException(nameof(writer)); + } + + _writer = writer; + _startIndent = _writer.CurrentIndent; + _writer.CurrentIndent = 0; + WriteLineNumberDirective(writer, span); + } + + public void Dispose() + { + // Need to add an additional line at the end IF there wasn't one already written. + // This is needed to work with the C# editor's handling of #line ... + var endsWithNewline = _writer.Length > 0 && _writer[_writer.Length - 1] == '\n'; + + // Always write at least 1 empty line to potentially separate code from pragmas. + _writer.WriteLine(); + + // Check if the previous empty line wasn't enough to separate code from pragmas. + if (!endsWithNewline) + { + _writer.WriteLine(); + } + + _writer + .WriteLine("#line default") + .WriteLine("#line hidden"); + + _writer.CurrentIndent = _startIndent; + } + } + + private class NullDisposable : IDisposable + { + public static readonly NullDisposable Default = new NullDisposable(); + + private NullDisposable() + { + } + + public void Dispose() + { + } + } + } +} diff --git a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs index 89a137d0f8..5ad23f1a9a 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs @@ -598,6 +598,20 @@ namespace Microsoft.AspNetCore.Razor.Language internal static string FormatIntermediateNodes_InvalidParentNode(object p0, object p1) => string.Format(CultureInfo.CurrentCulture, GetString("IntermediateNodes_InvalidParentNode"), p0, p1); + /// + /// Invalid newline sequence '{0}'. Support newline sequences are '\r\n' and '\n'. + /// + internal static string CodeWriter_InvalidNewLine + { + get => GetString("CodeWriter_InvalidNewLine"); + } + + /// + /// Invalid newline sequence '{0}'. Support newline sequences are '\r\n' and '\n'. + /// + internal static string FormatCodeWriter_InvalidNewLine(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("CodeWriter_InvalidNewLine"), p0); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx index 15d914463d..b40cb967a9 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx +++ b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx @@ -243,4 +243,7 @@ The '{0}' node type can only be used as a direct child of a '{1}' node. + + Invalid newline sequence '{0}'. Support newline sequences are '\r\n' and '\n'. + \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/InjectTargetExtensionTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/InjectTargetExtensionTest.cs index 352c958c71..ec36da6564 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/InjectTargetExtensionTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/InjectTargetExtensionTest.cs @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions Assert.Equal( "[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]" + Environment.NewLine + "public PropertyType PropertyName { get; private set; }" + Environment.NewLine, - context.CodeWriter.Builder.ToString()); + context.CodeWriter.GenerateCode()); } [Fact] @@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions "public PropertyType PropertyName { get; private set; }" + Environment.NewLine + Environment.NewLine + "#line default" + Environment.NewLine + "#line hidden" + Environment.NewLine, - context.CodeWriter.Builder.ToString()); + context.CodeWriter.GenerateCode()); } } } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/CSharpCodeWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/CSharpCodeWriterTest.cs index fdd149a742..e0bfa57ca1 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/CSharpCodeWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/CSharpCodeWriterTest.cs @@ -263,38 +263,17 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration } [Fact] - public void WriteLineNumberDirective_UsesFilePath_WhenFileInSourceLocationIsNull() + public void WriteLineNumberDirective_UsesFilePath_FromSourceLocation() { // Arrange var filePath = "some-path"; + var mappingLocation = new SourceSpan(filePath, 10, 4, 3, 9); + var writer = new CodeWriter(); var expected = $"#line 5 \"{filePath}\"" + writer.NewLine; - var sourceLocation = new SourceLocation(10, 4, 3); - var mappingLocation = new SourceSpan(sourceLocation, 9); // Act - writer.WriteLineNumberDirective(mappingLocation, filePath); - var code = writer.GenerateCode(); - - // Assert - Assert.Equal(expected, code); - } - - [Theory] - [InlineData("")] - [InlineData("source-location-file-path")] - public void WriteLineNumberDirective_UsesSourceLocationFilePath_IfAvailable( - string sourceLocationFilePath) - { - // Arrange - var filePath = "some-path"; - var writer = new CodeWriter(); - var expected = $"#line 5 \"{sourceLocationFilePath}\"" + writer.NewLine; - var sourceLocation = new SourceLocation(sourceLocationFilePath, 10, 4, 3); - var mappingLocation = new SourceSpan(sourceLocation, 9); - - // Act - writer.WriteLineNumberDirective(mappingLocation, filePath); + writer.WriteLineNumberDirective(mappingLocation); var code = writer.GenerateCode(); // Assert diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeNodeWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeNodeWriterTest.cs index 56033fe8a8..2769dd39d6 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeNodeWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/DesignTimeNodeWriterTest.cs @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration writer.WriteUsingDirective(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"using System; ", @@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration // Assert var mapping = Assert.Single(((DefaultCodeRenderingContext)context).SourceMappings); Assert.Equal(expectedSourceMapping, mapping); - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" using System; @@ -88,7 +88,7 @@ using System; writer.WriteCSharpExpression(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__o = i++; ", @@ -118,7 +118,7 @@ using System; writer.WriteCSharpExpression(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" __o = i++; @@ -155,7 +155,7 @@ __o = i++; writer.WriteCSharpExpression(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__o = iRender Children ++; @@ -192,7 +192,7 @@ __o = i++; writer.WriteCSharpExpression(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" __o = iRender Children @@ -224,7 +224,7 @@ __o = i++; writer.WriteCSharpCode(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Empty(csharp); } @@ -250,7 +250,7 @@ __o = i++; writer.WriteCSharpCode(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @" ", @@ -277,7 +277,7 @@ __o = i++; writer.WriteCSharpCode(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"if (true) { } ", @@ -307,7 +307,7 @@ __o = i++; writer.WriteCSharpCode(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" if (true) { } @@ -341,7 +341,7 @@ if (true) { } writer.WriteCSharpCode(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" if (true) { } @@ -370,7 +370,7 @@ if (true) { } writer.WriteCSharpExpressionAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" __o = false; @@ -398,7 +398,7 @@ if (true) { } writer.WriteCSharpCodeAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" if(@true){ } @@ -426,7 +426,7 @@ if (true) { } writer.WriteCSharpCodeAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" if(@true){ diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/LiteralRuntimeNodeWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/LiteralRuntimeNodeWriterTest.cs index 81dbad980e..be55c8e1a8 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/LiteralRuntimeNodeWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/LiteralRuntimeNodeWriterTest.cs @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration writer.WriteCSharpExpression(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" WriteLiteral(i++); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeNodeWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeNodeWriterTest.cs index fe6ca63021..751e600c9e 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeNodeWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/RuntimeNodeWriterTest.cs @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration writer.WriteUsingDirective(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"using System; ", @@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration writer.WriteUsingDirective(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" using System; @@ -88,7 +88,7 @@ using System; writer.WriteCSharpExpression(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"Test(i++); ", @@ -122,7 +122,7 @@ using System; writer.WriteCSharpExpression(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" Test(i++); @@ -163,7 +163,7 @@ Test(i++); writer.WriteCSharpExpression(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"Test(iRender Children ++); @@ -204,7 +204,7 @@ Test(i++); writer.WriteCSharpExpression(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" Test(iRender Children @@ -237,7 +237,7 @@ Test(i++); writer.WriteCSharpCode(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Empty(csharp); } @@ -261,7 +261,7 @@ Test(i++); writer.WriteCSharpCode(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"if (true) { } ", @@ -292,7 +292,7 @@ Test(i++); writer.WriteCSharpCode(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" if (true) { } @@ -327,7 +327,7 @@ if (true) { } writer.WriteCSharpCode(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" if (true) { } @@ -358,7 +358,7 @@ if (true) { } writer.WriteHtmlContent(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"WriteLiteral(""SomeContent""); ", @@ -385,7 +385,7 @@ if (true) { } writer.WriteHtmlContent(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal(string.Format( @"WriteLiteral(@""{0}""); WriteLiteral(@""{1}""); @@ -411,7 +411,7 @@ WriteLiteral(@""{1}""); writer.WriteHtmlAttribute(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"BeginWriteAttribute(""checked"", "" checked=\"""", 6, ""\"""", 34, 2); Render Children @@ -439,7 +439,7 @@ EndWriteAttribute(); writer.WriteHtmlAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"WriteAttributeValue("""", 16, ""hello-world"", 16, 11, true); ", @@ -464,7 +464,7 @@ EndWriteAttribute(); writer.WriteCSharpExpressionAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" WriteAttributeValue("" "", 27, false, 28, 6, false); @@ -494,7 +494,7 @@ WriteAttributeValue("" "", 27, false, 28, 6, false); writer.WriteCSharpCodeAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"WriteAttributeValue("" "", 27, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => { PushWriter(__razor_attribute_value_writer); @@ -525,7 +525,7 @@ WriteAttributeValue("" "", 27, false, 28, 6, false); writer.BeginWriterScope(context, "MyWriter"); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"TestPushWriter(MyWriter); ", @@ -547,7 +547,7 @@ WriteAttributeValue("" "", 27, false, 28, 6, false); writer.EndWriterScope(context); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"TestPopWriter(); ", diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/TagHelperHtmlAttributeRuntimeNodeWriterTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/TagHelperHtmlAttributeRuntimeNodeWriterTest.cs index 0316784842..c848edf293 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/TagHelperHtmlAttributeRuntimeNodeWriterTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/CodeGeneration/TagHelperHtmlAttributeRuntimeNodeWriterTest.cs @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration writer.WriteHtmlAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"AddHtmlAttributeValue("""", 16, ""hello-world"", 16, 11, true); ", @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration writer.WriteCSharpExpressionAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" AddHtmlAttributeValue("" "", 27, false, 28, 6, false); @@ -79,7 +79,7 @@ AddHtmlAttributeValue("" "", 27, false, 28, 6, false); writer.WriteCSharpCodeAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"AddHtmlAttributeValue("" "", 27, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => { PushWriter(__razor_attribute_value_writer); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/DefaultTagHelperTargetExtensionTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/DefaultTagHelperTargetExtensionTest.cs index 8ed76deb3d..a1a1c134fc 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/DefaultTagHelperTargetExtensionTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/DefaultTagHelperTargetExtensionTest.cs @@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteTagHelperBody(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"Render Children ", @@ -118,7 +118,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteTagHelperBody(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__tagHelperExecutionContext = __tagHelperScopeManager.Begin(""p"", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, ""test"", async() => { Render Children @@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteTagHelperCreate(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__TestNamespace_MyTagHelper = CreateTagHelper(); ", @@ -177,7 +177,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteTagHelperCreate(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__TestNamespace_MyTagHelper = CreateTagHelper(); __tagHelperExecutionContext.Add(__TestNamespace_MyTagHelper); @@ -202,7 +202,7 @@ __tagHelperExecutionContext.Add(__TestNamespace_MyTagHelper); extension.WriteTagHelperExecute(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"", csharp, @@ -225,7 +225,7 @@ __tagHelperExecutionContext.Add(__TestNamespace_MyTagHelper); extension.WriteTagHelperExecute(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"await __tagHelperRunner.RunAsync(__tagHelperExecutionContext); if (!__tagHelperExecutionContext.Output.IsContentModified) @@ -270,7 +270,7 @@ __tagHelperExecutionContext = __tagHelperScopeManager.End(); extension.WriteTagHelperHtmlAttribute(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"Render Children Render Children @@ -306,7 +306,7 @@ Render Children extension.WriteTagHelperHtmlAttribute(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"BeginWriteTagHelperAttribute(); Render Children @@ -348,7 +348,7 @@ __tagHelperExecutionContext.AddHtmlAttribute(""name"", Html.Raw(__tagHelperStrin extension.WriteTagHelperHtmlAttribute(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"BeginAddHtmlAttributeValues(__tagHelperExecutionContext, ""name"", 2, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes); Render Children @@ -391,7 +391,7 @@ EndAddHtmlAttributeValues(__tagHelperExecutionContext); extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"Render Children __InputTagHelper.StringProp = ""value""; @@ -432,7 +432,7 @@ __InputTagHelper.StringProp = ""value""; extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"Render Children __InputTagHelper.StringProp = string.Empty; @@ -474,7 +474,7 @@ __InputTagHelper.StringProp = string.Empty; extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 3 ""test.cshtml"" __InputTagHelper.IntProp = 32; @@ -522,7 +522,7 @@ __InputTagHelper.IntProp = 32; extension.WriteTagHelperProperty(context, node2); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__InputTagHelper.IntProp = __OtherTagHelper.IntProp; ", @@ -562,7 +562,7 @@ __InputTagHelper.IntProp = 32; extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__InputTagHelper.IntProp = 32; ", @@ -603,7 +603,7 @@ __InputTagHelper.IntProp = 32; extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 3 ""test.cshtml"" __InputTagHelper.IntIndexer[""bound""] = 32; @@ -647,7 +647,7 @@ __InputTagHelper.IntIndexer[""bound""] = 32; extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__InputTagHelper.IntIndexer[""bound""] = 32; ", @@ -687,7 +687,7 @@ __InputTagHelper.IntIndexer[""bound""] = 32; extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); // The attribute value is not rendered inline because we are not using the preallocated writer. Assert.Equal( @@ -734,7 +734,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(""bound"", __InputTagHelper.St extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 3 ""test.cshtml"" __InputTagHelper.IntProp = 32; @@ -783,7 +783,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(""bound"", __InputTagHelper.In extension.WriteTagHelperProperty(context, node2); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__InputTagHelper.IntProp = __OtherTagHelper.IntProp; ", @@ -823,7 +823,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(""bound"", __InputTagHelper.In extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__InputTagHelper.IntProp = 32; __tagHelperExecutionContext.AddTagHelperAttribute(""bound"", __InputTagHelper.IntProp, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes); @@ -865,7 +865,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(""bound"", __InputTagHelper.In extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"if (__InputTagHelper.IntIndexer == null) { @@ -934,7 +934,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(""foo-bound"", __InputTagHelpe extension.WriteTagHelperProperty(context, node2); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 3 ""test.cshtml"" __InputTagHelper.IntIndexer[""bound""] = 32; @@ -979,7 +979,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(""foo-bound"", __InputTagHelpe extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"if (__InputTagHelper.IntIndexer == null) { @@ -1005,7 +1005,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(""foo-bound"", __InputTagHelpe extension.WriteTagHelperRuntime(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"", csharp, @@ -1025,7 +1025,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(""foo-bound"", __InputTagHelpe extension.WriteTagHelperRuntime(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line hidden #pragma warning disable 0169 diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/DesignTimeDirectiveTargetExtensionTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/DesignTimeDirectiveTargetExtensionTest.cs index ee37b0ce99..e06f7a5dcc 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/DesignTimeDirectiveTargetExtensionTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/DesignTimeDirectiveTargetExtensionTest.cs @@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteDesignTimeDirective(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#pragma warning disable 219 private void __RazorDirectiveTokenHelpers__() { @@ -53,7 +53,7 @@ private void __RazorDirectiveTokenHelpers__() { extension.WriteDesignTimeDirective(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#pragma warning disable 219 private void __RazorDirectiveTokenHelpers__() { @@ -88,7 +88,7 @@ System.String __typeHelper = default(System.String); extension.WriteDesignTimeDirective(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#pragma warning disable 219 private void __RazorDirectiveTokenHelpers__() { @@ -123,7 +123,7 @@ global::System.Object __typeHelper = nameof(System.Collections.Generic); extension.WriteDesignTimeDirective(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#pragma warning disable 219 private void __RazorDirectiveTokenHelpers__() { @@ -165,7 +165,7 @@ global::System.Object Foo = null; extension.WriteDesignTimeDirective(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#pragma warning disable 219 private void __RazorDirectiveTokenHelpers__() { @@ -203,7 +203,7 @@ global::System.Object __typeHelper = ""Value""; extension.WriteDesignTimeDirective(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#pragma warning disable 219 private void __RazorDirectiveTokenHelpers__() { diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/PreallocatedAttributeTargetExtensionTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/PreallocatedAttributeTargetExtensionTest.cs index 72d306791b..58c76cdc53 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/PreallocatedAttributeTargetExtensionTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/PreallocatedAttributeTargetExtensionTest.cs @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteTagHelperHtmlAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"private static readonly global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute MyProp = new global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute(""Foo"", new global::Microsoft.AspNetCore.Html.HtmlString(""Bar""), global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes); ", @@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteTagHelperHtmlAttributeValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"private static readonly global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute _tagHelper1 = new global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute(""Foo""); ", @@ -82,7 +82,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteTagHelperHtmlAttribute(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__tagHelperExecutionContext.AddHtmlAttribute(_tagHelper1); ", @@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteTagHelperPropertyValue(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"private static readonly global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute _tagHelper1 = new global::Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute(""Foo"", ""Bar"", global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes); ", @@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__FooTagHelper.FooProp = (string)_tagHelper1.Value; __tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1); @@ -197,7 +197,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1); extension.WriteTagHelperProperty(context, node); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"if (__FooTagHelper.FooProp == null) { @@ -259,7 +259,7 @@ __tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1); extension.WriteTagHelperProperty(context, node2); // Assert - var csharp = context.CodeWriter.Builder.ToString(); + var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"__FooTagHelper.FooProp[""Foo""] = (string)_tagHelper1.Value; __tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/SectionTargetExtensionTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/SectionTargetExtensionTest.cs index 85790be75a..c2d6b70ebc 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/SectionTargetExtensionTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/SectionTargetExtensionTest.cs @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions ); "; - var output = context.CodeWriter.Builder.ToString(); + var output = context.CodeWriter.GenerateCode(); Assert.Equal(expected, output); } @@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions ); "; - var output = context.CodeWriter.Builder.ToString(); + var output = context.CodeWriter.GenerateCode(); Assert.Equal(expected, output); } } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/TemplateTargetExtensionTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/TemplateTargetExtensionTest.cs index 242373f75d..b24d6f5174 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/TemplateTargetExtensionTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Extensions/TemplateTargetExtensionTest.cs @@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions } )"; - var output = context.CodeWriter.Builder.ToString(); + var output = context.CodeWriter.GenerateCode(); Assert.Equal(expected, output); } }