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
18 changes: 18 additions & 0 deletions src/NetEvolve.CodeBuilder/CSharpCodeBuilder.Clear.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,22 @@ public CSharpCodeBuilder Clear()

return this;
}

/// <summary>
/// Appends a single indentation unit to the current builder without affecting the indentation level.
/// </summary>
/// <returns>The current <see cref="CSharpCodeBuilder"/> instance to allow for method chaining.</returns>
/// <remarks>
/// This method adds one indentation unit directly to the builder based on the <see cref="CodeBuilderBase.UseTabs"/> setting.
/// If <see cref="CodeBuilderBase.UseTabs"/> is <see langword="true"/>, a tab character is appended.
/// If <see cref="CodeBuilderBase.UseTabs"/> is <see langword="false"/>, four space characters are appended.
/// Unlike automatic indentation that occurs at the start of new lines, this method provides manual control
/// over indentation placement and does not modify the current indentation level.
/// </remarks>
public CSharpCodeBuilder Intend()
{
_ = _builder.Append(UseTabs ? '\t' : ' ', UseTabs ? 1 : 4);

return this;
}
}
28 changes: 27 additions & 1 deletion src/NetEvolve.CodeBuilder/CSharpCodeBuilder.Scope.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace NetEvolve.CodeBuilder;
namespace NetEvolve.CodeBuilder;

using System;

Expand All @@ -23,6 +23,32 @@ public partial record CSharpCodeBuilder
/// </example>
public IDisposable Scope() => new ScopeHandler(this);

/// <summary>
/// Appends a line of text and creates a scope that automatically manages indentation levels with braces.
/// </summary>
/// <param name="value">The string value to append before creating the scope. Can be <see langword="null"/>.</param>
/// <returns>A <see cref="ScopeHandler"/> that appends an opening brace, increments indentation on creation, and appends a closing brace with decremented indentation on disposal.</returns>
/// <remarks>
/// This method combines <see cref="AppendLine(string?)"/> with <see cref="Scope()"/> functionality.
/// The returned scope handler implements <see cref="IDisposable"/> and is designed for use with the using statement.
/// When the scope is created, an opening brace is appended and indentation is incremented by one level.
/// When the scope is disposed, indentation is decremented and a closing brace is appended.
/// </remarks>
/// <example>
/// <code>
/// var builder = new CSharpCodeBuilder();
/// using (builder.ScopeLine("public class MyClass"))
/// {
/// builder.AppendLine("public string Name { get; set; }");
/// }
/// </code>
/// </example>
public IDisposable ScopeLine(string? value)
{
_ = AppendLine(value);
return new ScopeHandler(this);
}

/// <summary>
/// A disposable struct that manages indentation scope for a <see cref="CSharpCodeBuilder"/>.
/// </summary>
Expand Down
192 changes: 192 additions & 0 deletions tests/NetEvolve.CodeBuilder.Tests.Unit/CSharpCodeBuilderTests.Clear.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,196 @@ public async Task Clear_Should_Preserve_Capacity()

_ = await Assert.That(builder.Capacity).IsEqualTo(originalCapacity);
}

[Test]
public async Task Intend_Should_Append_Single_Indentation()
{
var builder = new CSharpCodeBuilder();

_ = builder.Intend().Append("Hello");

var result = builder.ToString();
_ = await Assert.That(result).IsEqualTo(" Hello");
}

[Test]
public async Task Intend_Should_Not_Affect_Indentation_Level()
{
var builder = new CSharpCodeBuilder();

_ = builder.Intend().AppendLine("First");
_ = builder.Append("Second");

var result = builder.ToString();
// Second line should not be indented because Intend() doesn't change the level
_ = await Assert.That(result).IsEqualTo(" First" + Environment.NewLine + "Second");
}

[Test]
public async Task Intend_With_Tabs_Should_Append_Tab_Character()
{
var builder = new CSharpCodeBuilder { UseTabs = true };

_ = builder.Intend().Append("Hello");

var result = builder.ToString();
_ = await Assert.That(result).IsEqualTo("\tHello");
}

[Test]
public async Task Intend_With_Spaces_Should_Append_Four_Spaces()
{
var builder = new CSharpCodeBuilder { UseTabs = false };

_ = builder.Intend().Append("Hello");

var result = builder.ToString();
_ = await Assert.That(result).IsEqualTo(" Hello");
}

[Test]
public async Task Intend_Multiple_Calls_Should_Append_Multiple_Indentations()
{
var builder = new CSharpCodeBuilder();

_ = builder.Intend().Intend().Intend().Append("Hello");

var result = builder.ToString();
_ = await Assert.That(result).IsEqualTo(" Hello"); // 12 spaces (3 * 4)
}

[Test]
public async Task Intend_Multiple_With_Tabs_Should_Append_Multiple_Tabs()
{
var builder = new CSharpCodeBuilder { UseTabs = true };

_ = builder.Intend().Intend().Intend().Append("Hello");

var result = builder.ToString();
_ = await Assert.That(result).IsEqualTo("\t\t\tHello");
}

[Test]
public async Task Intend_Should_Return_Builder_For_Chaining()
{
var builder = new CSharpCodeBuilder();

var result = builder.Intend();

_ = await Assert.That(result).IsEqualTo(builder);
}

[Test]
public async Task Intend_In_Middle_Of_Line_Should_Append_Indentation()
{
var builder = new CSharpCodeBuilder();

_ = builder.Append("Hello").Intend().Append("World");

var result = builder.ToString();
_ = await Assert.That(result).IsEqualTo("Hello World");
}

[Test]
public async Task Intend_After_NewLine_Should_Add_Manual_Indentation()
{
var builder = new CSharpCodeBuilder();

_ = builder.AppendLine("First");
_ = builder.Intend().Append("Second");

var result = builder.ToString();
_ = await Assert.That(result).IsEqualTo("First" + Environment.NewLine + " Second");
}

[Test]
public async Task Intend_With_Automatic_Indentation_Should_Stack()
{
var builder = new CSharpCodeBuilder();
builder.IncrementIndent(); // Set automatic indentation level to 1

_ = builder.AppendLine().Intend().Append("Hello");

var result = builder.ToString();
// Should have both automatic (4 spaces) and manual (4 spaces) indentation
_ = await Assert.That(result).IsEqualTo(Environment.NewLine + " Hello");
}

[Test]
public async Task Intend_Multiple_Mixed_With_Content_Should_Work()
{
var builder = new CSharpCodeBuilder();

_ = builder
.Intend()
.Append("Level 1")
.AppendLine()
.Intend()
.Intend()
.Append("Level 2")
.AppendLine()
.Intend()
.Intend()
.Intend()
.Append("Level 3");

var result = builder.ToString();
_ = await Assert.That(result).Contains(" Level 1");
_ = await Assert.That(result).Contains(" Level 2");
_ = await Assert.That(result).Contains(" Level 3");
}

[Test]
public async Task Intend_Should_Work_With_Empty_Builder()
{
var builder = new CSharpCodeBuilder();

_ = builder.Intend();

var result = builder.ToString();
_ = await Assert.That(result).IsEqualTo(" ");
}

[Test]
public async Task Intend_Should_Work_After_Clear()
{
var builder = new CSharpCodeBuilder();
_ = builder.Append("Hello");
_ = builder.Clear();

_ = builder.Intend().Append("World");

var result = builder.ToString();
_ = await Assert.That(result).IsEqualTo(" World");
}

[Test]
public async Task Intend_Combined_With_Scope_Should_Add_Extra_Indentation()
{
var builder = new CSharpCodeBuilder();

using (builder.Scope())
{
_ = builder.Intend().Append("Extra indented");
}

var result = builder.ToString();
// Should have both scope indentation (4 spaces) and manual indentation (4 spaces)
_ = await Assert.That(result).Contains(" Extra indented"); // 8 spaces
}

[Test]
public async Task Intend_Combined_With_ScopeLine_Should_Add_Extra_Indentation()
{
var builder = new CSharpCodeBuilder();

using (builder.ScopeLine("public class MyClass"))
{
_ = builder.Intend().Append("// Extra indented comment");
}

var result = builder.ToString();
// Should have both scope indentation and manual indentation
_ = await Assert.That(result).Contains(" // Extra indented comment"); // 8 spaces
}
}
Loading