Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Xunit;

using IndentCache = Microsoft.AspNetCore.Razor.Language.CodeGeneration.CodeWriter.IndentCache;

namespace Microsoft.AspNetCore.Razor.Language.Test.CodeGeneration;

public class IndentCacheTest
{
[Theory]
[InlineData(0, false, 4, "")]
[InlineData(4, false, 4, " ")]
[InlineData(8, false, 4, " ")]
[InlineData(0, true, 4, "")]
[InlineData(4, true, 4, "\t")]
[InlineData(8, true, 4, "\t\t")]
[InlineData(6, true, 4, "\t ")]
[InlineData(5, true, 4, "\t ")]
[InlineData(3, true, 4, " ")]
public void GetIndentString_ReturnsExpectedString(int size, bool useTabs, int tabSize, string expected)
{
var result = IndentCache.GetIndentString(size, useTabs, tabSize);
Assert.Equal(expected, result.ToString());
}

[Fact]
public void GetIndentString_TabSizeOne_UsesOnlyTabs()
{
var result = IndentCache.GetIndentString(size: 5, useTabs: true, tabSize: 1);
Assert.Equal(new string('\t', 5), result.ToString());
}

[Fact]
public void GetIndentString_TabSizeGreaterThanSize_UsesSpaces()
{
var result = IndentCache.GetIndentString(size: 3, useTabs: true, tabSize: 10);
Assert.Equal(" ", result.ToString());
}

[Fact]
public void GetIndentString_TabsAndSpacesInResultExceedCachedSizes()
{
var spaceCount = IndentCache.MaxSpaceCount + 1;
var tabCount = IndentCache.MaxTabCount + 1;
var tabSize = spaceCount + 1;

var size = tabSize * tabCount + spaceCount;
var result = IndentCache.GetIndentString(size, useTabs: true, tabSize);

var expected = new string('\t', tabCount) + new string(' ', spaceCount);
Assert.Equal(expected, result.ToString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration;

public sealed partial class CodeWriter
{
internal static class IndentCache
{
internal const int MaxTabCount = 64;
internal const int MaxSpaceCount = 128;

private static readonly ReadOnlyMemory<char> s_tabs = new string('\t', MaxTabCount).AsMemory();
private static readonly ReadOnlyMemory<char> s_spaces = new string(' ', MaxSpaceCount).AsMemory();

public static ReadOnlyMemory<char> GetIndentString(int size, bool useTabs, int tabSize)
{
if (!useTabs)
{
return SliceOrCreate(size, s_spaces);
}

var tabCount = size / tabSize;
var spaceCount = size % tabSize;

if (spaceCount == 0)
{
return SliceOrCreate(tabCount, s_tabs);
}

return string.Create(length: tabCount + spaceCount, state: tabCount, static (destination, tabCount) =>
{
destination[..tabCount].Fill('\t');
destination[tabCount..].Fill(' ');
}).AsMemory();
}

private static ReadOnlyMemory<char> SliceOrCreate(int length, ReadOnlyMemory<char> chars)
{
return (length <= chars.Length)
? chars[..length]
: new string(chars.Span[0], length).AsMemory();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration;
Expand Down Expand Up @@ -118,7 +117,7 @@ public int CurrentIndent
if (_indentSize != value)
{
_indentSize = value;
_indentString = ComputeIndent(value, IndentWithTabs, TabSize);
_indentString = IndentCache.GetIndentString(value, IndentWithTabs, TabSize);
}
}
}
Expand Down Expand Up @@ -189,7 +188,7 @@ public CodeWriter Indent(int size)

var indentString = size == _indentSize
? _indentString
: ComputeIndent(size, IndentWithTabs, TabSize);
: IndentCache.GetIndentString(size, IndentWithTabs, TabSize);

AddTextChunk(indentString);

Expand All @@ -200,30 +199,6 @@ public CodeWriter Indent(int size)
return this;
}

private static ReadOnlyMemory<char> ComputeIndent(int size, bool useTabs, int tabSize)
{
if (size == 0)
{
return ReadOnlyMemory<char>.Empty;
}

if (useTabs)
{
var tabCount = size / tabSize;
var spaceCount = size % tabSize;

using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.SetCapacityIfLarger(tabCount + spaceCount);

builder.Append('\t', tabCount);
builder.Append(' ', spaceCount);

return builder.ToString().AsMemory();
}

return new string(' ', size).AsMemory();
}

public CodeWriter Write(string value)
{
ArgHelper.ThrowIfNull(value);
Expand Down