Skip to content

Commit 2c4444f

Browse files
authored
Merge pull request #31211 from dotnet/dev/allichou/TabsSpacesCodeGeneration
Allow Razor generated documents to respect tabs/spaces settings
2 parents d0f23a2 + e70ae71 commit 2c4444f

File tree

10 files changed

+100
-48
lines changed

10 files changed

+100
-48
lines changed

src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/CodeWriter.cs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@ public sealed class CodeWriter
1818
private int _currentLineIndex;
1919
private int _currentLineCharacterIndex;
2020

21-
public CodeWriter()
21+
public CodeWriter() : this(Environment.NewLine, RazorCodeGenerationOptions.CreateDefault())
2222
{
23-
NewLine = Environment.NewLine;
23+
}
24+
25+
public CodeWriter(string newLine, RazorCodeGenerationOptions options)
26+
{
27+
NewLine = newLine;
28+
IndentWithTabs = options.IndentWithTabs;
29+
TabSize = options.IndentSize;
2430
_builder = new StringBuilder();
2531
}
2632

@@ -47,6 +53,10 @@ public string NewLine
4753
}
4854
}
4955

56+
public bool IndentWithTabs { get; }
57+
58+
public int TabSize { get; }
59+
5060
public SourceLocation Location => new SourceLocation(_absoluteIndex, _currentLineIndex, _currentLineCharacterIndex);
5161

5262
public char this[int index]
@@ -62,16 +72,34 @@ public char this[int index]
6272
}
6373
}
6474

65-
// Internal for testing.
66-
internal CodeWriter Indent(int size)
75+
public CodeWriter Indent(int size)
6776
{
68-
if (Length == 0 || this[Length - 1] == '\n')
77+
if (size == 0 || (Length != 0 && this[Length - 1] != '\n'))
6978
{
70-
_builder.Append(' ', size);
79+
return this;
80+
}
7181

72-
_currentLineCharacterIndex += size;
73-
_absoluteIndex += size;
82+
var actualSize = 0;
83+
if (IndentWithTabs)
84+
{
85+
// Avoid writing directly to the StringBuilder here, that will throw off the manual indexing
86+
// done by the base class.
87+
var tabs = size / TabSize;
88+
actualSize += tabs;
89+
_builder.Append('\t', tabs);
90+
91+
var spaces = size % TabSize;
92+
actualSize += spaces;
93+
_builder.Append(' ', spaces);
7494
}
95+
else
96+
{
97+
actualSize = size;
98+
_builder.Append(' ', size);
99+
}
100+
101+
_currentLineCharacterIndex += actualSize;
102+
_absoluteIndex += actualSize;
75103

76104
return this;
77105
}

src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/CodeWriterExtensions.cs

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -48,29 +48,7 @@ public static CodeWriter WritePadding(this CodeWriter writer, int offset, Source
4848
var basePadding = CalculatePadding();
4949
var resolvedPadding = Math.Max(basePadding - offset, 0);
5050

51-
if (context.Options.IndentWithTabs)
52-
{
53-
// Avoid writing directly to the StringBuilder here, that will throw off the manual indexing
54-
// done by the base class.
55-
var tabs = resolvedPadding / context.Options.IndentSize;
56-
for (var i = 0; i < tabs; i++)
57-
{
58-
writer.Write("\t");
59-
}
60-
61-
var spaces = resolvedPadding % context.Options.IndentSize;
62-
for (var i = 0; i < spaces; i++)
63-
{
64-
writer.Write(" ");
65-
}
66-
}
67-
else
68-
{
69-
for (var i = 0; i < resolvedPadding; i++)
70-
{
71-
writer.Write(" ");
72-
}
73-
}
51+
writer.Indent(resolvedPadding);
7452

7553
return writer;
7654

@@ -86,7 +64,7 @@ int CalculatePadding()
8664
}
8765
else if (@char == '\t')
8866
{
89-
spaceCount += context.Options.IndentSize;
67+
spaceCount += writer.TabSize;
9068
}
9169
else
9270
{
@@ -569,11 +547,11 @@ public struct CSharpCodeWritingScope : IDisposable
569547
private int _tabSize;
570548
private int _startIndent;
571549

572-
public CSharpCodeWritingScope(CodeWriter writer, int tabSize = 4, bool autoSpace = true)
550+
public CSharpCodeWritingScope(CodeWriter writer, bool autoSpace = true)
573551
{
574552
_writer = writer;
575553
_autoSpace = autoSpace;
576-
_tabSize = tabSize;
554+
_tabSize = writer.TabSize;
577555
_startIndent = -1; // Set in WriteStartScope
578556

579557
WriteStartScope();

src/Razor/Microsoft.AspNetCore.Razor.Language/src/CodeGeneration/DefaultDocumentWriter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -32,7 +32,7 @@ public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument
3232
}
3333

3434
var context = new DefaultCodeRenderingContext(
35-
new CodeWriter(),
35+
new CodeWriter(Environment.NewLine, _options),
3636
_codeTarget.CreateNodeWriter(),
3737
codeDocument,
3838
documentNode,

src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorCodeGenerationOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Razor.Language
66
internal class DefaultRazorCodeGenerationOptions : RazorCodeGenerationOptions
77
{
88
public DefaultRazorCodeGenerationOptions(
9-
bool indentWithTabs,
9+
bool indentWithTabs,
1010
int indentSize,
1111
bool designTime,
1212
string rootNamespace,

src/Razor/Microsoft.AspNetCore.Razor.Language/src/PublicAPI.Unshipped.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#nullable enable
2+
Microsoft.AspNetCore.Razor.Language.CodeGeneration.CodeWriter.IndentWithTabs.get -> bool
3+
Microsoft.AspNetCore.Razor.Language.CodeGeneration.CodeWriter.TabSize.get -> int
24
Microsoft.AspNetCore.Razor.Language.Intermediate.CascadingGenericTypeParameter
35
Microsoft.AspNetCore.Razor.Language.Intermediate.CascadingGenericTypeParameter.CascadingGenericTypeParameter() -> void
6+
~Microsoft.AspNetCore.Razor.Language.CodeGeneration.CodeWriter.CodeWriter(string newLine, Microsoft.AspNetCore.Razor.Language.RazorCodeGenerationOptions options) -> void
7+
~Microsoft.AspNetCore.Razor.Language.CodeGeneration.CodeWriter.Indent(int size) -> Microsoft.AspNetCore.Razor.Language.CodeGeneration.CodeWriter
48
~Microsoft.AspNetCore.Razor.Language.Intermediate.CascadingGenericTypeParameter.GenericTypeNames.get -> System.Collections.Generic.IReadOnlyCollection<string>
59
~Microsoft.AspNetCore.Razor.Language.Intermediate.CascadingGenericTypeParameter.GenericTypeNames.set -> void
610
~Microsoft.AspNetCore.Razor.Language.Intermediate.ComponentIntermediateNode.ProvidesCascadingGenericTypes.get -> System.Collections.Generic.Dictionary<string, Microsoft.AspNetCore.Razor.Language.Intermediate.CascadingGenericTypeParameter>

src/Razor/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/CSharpCodeWriterTest.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,5 +359,47 @@ public void WriteAutoPropertyDeclaration_WithModifiers_WritesPropertyDeclaration
359359
var output = writer.GenerateCode();
360360
Assert.Equal("public static global::System.String MyString { get; set; }" + Environment.NewLine, output);
361361
}
362+
363+
[Fact]
364+
public void CSharpCodeWriter_RespectTabSetting()
365+
{
366+
// Arrange
367+
var options = RazorCodeGenerationOptions.Create(o =>
368+
{
369+
o.IndentWithTabs = true;
370+
o.IndentSize = 4;
371+
});
372+
373+
var writer = new CodeWriter(Environment.NewLine, options);
374+
375+
// Act
376+
writer.BuildClassDeclaration(Array.Empty<string>(), "C", "", Array.Empty<string>(), Array.Empty<string>());
377+
writer.WriteField(Array.Empty<string>(), Array.Empty<string>(), "int", "f");
378+
379+
// Assert
380+
var output = writer.GenerateCode();
381+
Assert.Equal("class C" + Environment.NewLine + "{" + Environment.NewLine + "\tint f;" + Environment.NewLine, output);
382+
}
383+
384+
[Fact]
385+
public void CSharpCodeWriter_RespectSpaceSetting()
386+
{
387+
// Arrange
388+
var options = RazorCodeGenerationOptions.Create(o =>
389+
{
390+
o.IndentWithTabs = false;
391+
o.IndentSize = 4;
392+
});
393+
394+
var writer = new CodeWriter(Environment.NewLine, options);
395+
396+
// Act
397+
writer.BuildClassDeclaration(Array.Empty<string>(), "C", "", Array.Empty<string>(), Array.Empty<string>());
398+
writer.WriteField(Array.Empty<string>(), Array.Empty<string>(), "int", "f");
399+
400+
// Assert
401+
var output = writer.GenerateCode();
402+
Assert.Equal("class C" + Environment.NewLine + "{" + Environment.NewLine + " int f;" + Environment.NewLine, output);
403+
}
362404
}
363405
}

src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithCssScope/TestComponent.codegen.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Renderin
7676
#line default
7777
#line hidden
7878
#nullable disable
79-
79+
8080

8181
__o = Microsoft.AspNetCore.Components.BindConverter.FormatValue(
8282
#nullable restore

src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/Component_WithCssScope/TestComponent.mappings.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ Generated Location: (2126:73,38 [18] )
3535
Source Location: (557:12,84 [6] x:\dir\subdir\Test\TestComponent.cshtml)
3636
|
3737
|
38-
Generated Location: (2353:78,96 [6] )
38+
Generated Location: (2341:78,84 [6] )
3939
|
4040
|
4141

4242
Source Location: (589:13,30 [10] x:\dir\subdir\Test\TestComponent.cshtml)
4343
|myVariable|
44-
Generated Location: (2540:83,30 [10] )
44+
Generated Location: (2528:83,30 [10] )
4545
|myVariable|
4646

4747
Source Location: (637:13,78 [3] x:\dir\subdir\Test\TestComponent.cshtml)
4848
|
4949
}|
50-
Generated Location: (2905:92,78 [3] )
50+
Generated Location: (2893:92,78 [3] )
5151
|
5252
}|
5353

@@ -62,7 +62,7 @@ Source Location: (651:16,7 [245] x:\dir\subdir\Test\TestComponent.cshtml)
6262
for (var i = 0; i < 10; i++)
6363
{
6464
|
65-
Generated Location: (3087:102,7 [245] )
65+
Generated Location: (3075:102,7 [245] )
6666
|
6767
ElementReference myElementReference;
6868
TemplatedComponent myComponentReference;
@@ -76,12 +76,12 @@ Generated Location: (3087:102,7 [245] )
7676

7777
Source Location: (912:25,28 [1] x:\dir\subdir\Test\TestComponent.cshtml)
7878
|i|
79-
Generated Location: (3499:119,28 [1] )
79+
Generated Location: (3487:119,28 [1] )
8080
|i|
8181

8282
Source Location: (925:25,41 [1] x:\dir\subdir\Test\TestComponent.cshtml)
8383
|i|
84-
Generated Location: (3675:127,41 [1] )
84+
Generated Location: (3663:127,41 [1] )
8585
|i|
8686

8787
Source Location: (931:25,47 [166] x:\dir\subdir\Test\TestComponent.cshtml)
@@ -93,7 +93,7 @@ Source Location: (931:25,47 [166] x:\dir\subdir\Test\TestComponent.cshtml)
9393
System.GC.KeepAlive(myVariable);
9494
}
9595
|
96-
Generated Location: (3847:134,47 [166] )
96+
Generated Location: (3835:134,47 [166] )
9797
|
9898
}
9999

src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/SingleLineControlFlowStatements_InCodeBlock/TestComponent.codegen.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Renderin
4545
#line default
4646
#line hidden
4747
#nullable disable
48-
48+
4949

5050
}
5151
#pragma warning restore 1998

src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/SingleLineControlFlowStatements_InCodeBlock/TestComponent.mappings.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Generated Location: (1301:42,16 [6] )
2424
Source Location: (216:6,26 [2] x:\dir\subdir\Test\TestComponent.cshtml)
2525
|
2626
|
27-
Generated Location: (1398:47,38 [2] )
27+
Generated Location: (1386:47,26 [2] )
2828
|
2929
|
3030

0 commit comments

Comments
 (0)