Skip to content

CodeWriter

Wrapper around StringBuilder that provides formatting and utility methods for code writing.

C# Signature
internal sealed class CodeWriter : System.IDisposable

The following example demonstrates how to write a simple type declaration with a namespace, fields, and a method.

C#
using Hertzole.SourceGen;
public class SourceGenerator
{
public string Generate()
{
// Must dispose when the writer is no longer needed.
using CodeWriter writer = new CodeWriter();
writer.AppendLine("using System;").AppendLine();
writer.AppendNamespace("My.Namespace");
writer.AppendLine("public class MyClass");
// Creates a new indented block surrounded by two brackets.
using (writer.WithBlock())
{
// Now inside the class scope
// Create a new field and a new line below that to add some space.
writer.AppendLine("public int myField;").AppendLine();
writer.AppendLine("public void MyMethod()");
using (writer.WithBlock())
{
writer.AppendLine("Console.WriteLine(\"Hello World!\");");
}
}
// Call ToString to get the final string.
return writer.ToString();
}
}

The returning string from the writer would output this:

C#
using System;
namespace My.Namespace
{
public class MyClass
{
public int myField;
public void MyMethod()
{
Console.WriteLine("Hello World!");
}
}
}

Creates a new instance of a CodeWriter.

C# Signature
public CodeWriter();

The current indent. Each indent is 4 spaces (equivalent to one tab).

C# Signature
public int Indent { get; set; }

Appends string to the current line without creating a new line.

C# Signature
public CodeWriter Append(string? value);

The string to insert.

The current code writer instance after the append operation.

Appends the string representation of the specified ITypeSymbol, along with its required declarations, without creating a newline.

Optionally inserts the partial keyword in the declaration if isPartial is true.

Optionally inserts the namespace if appendNamespace is true.

C# Signature
public CodeWriter Append(ITypeSymbol value, bool isPartial = true, bool appendNamespace = true);

The type to append.

Whether to append the partial keyword in the declaration.

Whether to append the namespace.

The current code writer instance after the append operation.

Appends the string representation of the specified object to the current line without creating a new line.

C# Signature
public CodeWriter Append(object value);

The object to append.

The current code writer instance after the append operation.

Appends bool to the current line without creating a new line.

C# Signature
public CodeWriter Append(bool value);

The bool to insert.

The current code writer instance after the append operation.

Appends decimal with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(decimal value, string format, IFormatProvider? provider = null);

The decimal to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends decimal to the current line without creating a new line.

C# Signature
public CodeWriter Append(decimal value);

The decimal to insert.

The current code writer instance after the append operation.

Appends double with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(double value, string format, IFormatProvider? provider = null);

The double to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends float with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(float value, string format, IFormatProvider? provider = null);

The float to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends float to the current line without creating a new line.

C# Signature
public CodeWriter Append(float value);

The float to insert.

The current code writer instance after the append operation.

Appends ulong with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(ulong value, string format, IFormatProvider? provider = null);

The ulong to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends ulong to the current line without creating a new line.

C# Signature
public CodeWriter Append(ulong value);

The ulong to insert.

The current code writer instance after the append operation.

Appends long with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(long value, string format, IFormatProvider? provider = null);

The long to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends long to the current line without creating a new line.

C# Signature
public CodeWriter Append(long value);

The long to insert.

The current code writer instance after the append operation.

Appends uint with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(uint value, string format, IFormatProvider? provider = null);

The uint to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends uint to the current line without creating a new line.

C# Signature
public CodeWriter Append(uint value);

The uint to insert.

The current code writer instance after the append operation.

Appends int with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(int value, string format, IFormatProvider? provider = null);

The int to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends double to the current line without creating a new line.

C# Signature
public CodeWriter Append(double value);

The double to insert.

The current code writer instance after the append operation.

Appends ushort with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(ushort value, string format, IFormatProvider? provider = null);

The ushort to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends ReadOnlyMemory<char> to the current line without creating a new line.

C# Signature
public CodeWriter Append(ReadOnlyMemory<char> value);

The ReadOnlyMemory<char> to insert.

The current code writer instance after the append operation.

Appends ArrayBuilder<char> to the current line without creating a new line.

C# Signature
public CodeWriter Append(ArrayBuilder<char> value);

The ArrayBuilder<char> to insert.

The current code writer instance after the append operation.

Appends char to the current line without creating a new line.

C# Signature
public CodeWriter Append(char value);

The char to insert.

The current code writer instance after the append operation.

Appends the specified number of copies of the specified char value to the current line without creating a new line.

C# Signature
public CodeWriter Append(char value, int repeatCount);

The char to append.

How many times the char should be inserted.

The current code writer instance after the append operation.

Appends the specified char array to the current line without creating a new line.

C# Signature
public CodeWriter Append(char[] value);

The char array to append.

The current code writer instance after the append operation.

Appends int to the current line without creating a new line.

C# Signature
public CodeWriter Append(int value);

The int to insert.

The current code writer instance after the append operation.

Appends ReadOnlySpan<char> to the current line without creating a new line.

C# Signature
public CodeWriter Append(ReadOnlySpan<char> value);

The ReadOnlySpan<char> to insert.

The current code writer instance after the append operation.

Appends a subarray of characters to the current line without creating a new line.

C# Signature
public CodeWriter Append(char[] value, int startIndex, int charCount);

The character array to append.

The starting position in the character array.

The number of characters to append.

The current code writer instance after the append operation.

Appends byte with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(byte value, string format, IFormatProvider? provider = null);

The byte to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends sbyte to the current line without creating a new line.

C# Signature
public CodeWriter Append(sbyte value);

The sbyte to insert.

The current code writer instance after the append operation.

Appends sbyte with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(sbyte value, string format, IFormatProvider? provider = null);

The sbyte to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends short to the current line without creating a new line.

C# Signature
public CodeWriter Append(short value);

The short to insert.

The current code writer instance after the append operation.

Appends short with the specified format to the current line without creating a new line.

C# Signature
public CodeWriter Append(short value, string format, IFormatProvider? provider = null);

The short to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends ushort to the current line without creating a new line.

C# Signature
public CodeWriter Append(ushort value);

The ushort to insert.

The current code writer instance after the append operation.

Appends byte to the current line without creating a new line.

C# Signature
public CodeWriter Append(byte value);

The byte to insert.

The current code writer instance after the append operation.

Appends a conditional preprocessor directive (e.g. #if DEBUG). Does nothing if the condition is null or whitespace.

C# Signature
public CodeWriter AppendConditionalSymbol(string? condition);

The condition for the preprocessor directive.

The current code writer instance after the append operation.

Appends an [Embedded] attribute to the current line. You should only use this if you’ve added Microsoft.CodeAnalysis.EmbeddedAttribute.

C# Signature
public CodeWriter AppendEmbeddedAttribute();

The current code writer instance after the append operation.

Appends an ExcludeFromCodeCoverage attribute to the current line, followed by a newline.

C# Signature
public CodeWriter AppendExcludeFromCodeCoverageAttribute();

The current code writer instance after the append operation.

AppendGeneratedCodeAttribute(string, string)

Section titled “AppendGeneratedCodeAttribute(string, string)”

Appends a GeneratedCode attribute to the current line, followed by a newline.

C# Signature
public CodeWriter AppendGeneratedCodeAttribute(string generator, string version);

The name of the code generator.

The version of the code generator.

The current code writer instance after the append operation.

Appends an entire multi-line string to the writer and handles the indentation.

C# Signature
public CodeWriter AppendIndentedSource(ReadOnlySpan<char> value);

The value to append.

The following example demonstrates how to use AppendIndentedSource to insert a multi-line string.

C#
using Hertzole.SourceGen;
internal static class CodeHelper
{
public static void AppendDisposedBlock(CodeWriter writer)
{
writer.AppendIndentedSource(
"""
if (isDisposed)
{
throw new System.ObjectDisposedException("This object is disposed.");
}
"""
);
}
}

This method automatically indents each line of the string according to the current indentation level. It normalizes line endings and replaces tabs with spaces.

The current code writer instance after the append operation.

Appends an entire multi-line string to the writer and handles the indentation.

C# Signature
public CodeWriter AppendIndentedSource(string value);

The value to append.

The following example demonstrates how to use AppendIndentedSource to insert a multi-line string.

C#
using Hertzole.SourceGen;
internal static class CodeHelper
{
public static void AppendDisposedBlock(CodeWriter writer)
{
writer.AppendIndentedSource(
"""
if (isDisposed)
{
throw new System.ObjectDisposedException("This object is disposed.");
}
"""
);
}
}

This method automatically indents each line of the string according to the current indentation level. It normalizes line endings and replaces tabs with spaces.

The current code writer instance after the append operation.

AppendLine(long, string, IFormatProvider?)

Section titled “AppendLine(long, string, IFormatProvider?)”

Appends long with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(long value, string format, IFormatProvider? provider = null);

The long to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends ulong followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(ulong value);

The ulong to insert.

The current code writer instance after the append operation.

AppendLine(ulong, string, IFormatProvider?)

Section titled “AppendLine(ulong, string, IFormatProvider?)”

Appends ulong with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(ulong value, string format, IFormatProvider? provider = null);

The ulong to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends float followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(float value);

The float to insert.

The current code writer instance after the append operation.

AppendLine(float, string, IFormatProvider?)

Section titled “AppendLine(float, string, IFormatProvider?)”

Appends float with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(float value, string format, IFormatProvider? provider = null);

The float to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends double followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(double value);

The double to insert.

The current code writer instance after the append operation.

Appends decimal followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(decimal value);

The decimal to insert.

The current code writer instance after the append operation.

Appends long followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(long value);

The long to insert.

The current code writer instance after the append operation.

AppendLine(decimal, string, IFormatProvider?)

Section titled “AppendLine(decimal, string, IFormatProvider?)”

Appends decimal with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(decimal value, string format, IFormatProvider? provider = null);

The decimal to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends bool followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(bool value);

The bool to insert.

The current code writer instance after the append operation.

Appends the string representation of the specified object followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(object value);

The object to append.

The current code writer instance after the append operation.

Appends the string representation of the specified ITypeSymbol, along with its required declarations, followed by a newline.

Optionally inserts the partial keyword in the declaration if isPartial is true.

Optionally inserts the namespace if appendNamespace is true.

C# Signature
public CodeWriter AppendLine(ITypeSymbol value, bool isPartial = true, bool appendNamespace = true);

The type to append.

Whether to append the partial keyword in the declaration.

Whether to append the namespace.

The current code writer instance after the append operation.

AppendLine(double, string, IFormatProvider?)

Section titled “AppendLine(double, string, IFormatProvider?)”

Appends double with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(double value, string format, IFormatProvider? provider = null);

The double to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

AppendLine(uint, string, IFormatProvider?)

Section titled “AppendLine(uint, string, IFormatProvider?)”

Appends uint with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(uint value, string format, IFormatProvider? provider = null);

The uint to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends a subarray of characters followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(char[] value, int startIndex, int charCount);

The character array to append.

The starting position in the character array.

The number of characters to append.

The current code writer instance after the append operation.

Appends int with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(int value, string format, IFormatProvider? provider = null);

The int to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends a newline to the current line.

C# Signature
public CodeWriter AppendLine();

The current code writer instance after the append operation.

Appends string followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(string? value);

The string to insert.

The current code writer instance after the append operation.

Appends ReadOnlySpan<char> followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(ReadOnlySpan<char> value);

The ReadOnlySpan<char> to insert.

The current code writer instance after the append operation.

Appends ReadOnlyMemory<char> followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(ReadOnlyMemory<char> value);

The ReadOnlyMemory<char> to insert.

The current code writer instance after the append operation.

Appends uint followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(uint value);

The uint to insert.

The current code writer instance after the append operation.

Appends char followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(char value);

The char to insert.

The current code writer instance after the append operation.

Appends the specified number of copies of the specified char followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(char value, int repeatCount);

The char to append.

How many times the char should be inserted.

The current code writer instance after the append operation.

Appends the specified char array followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(char[] value);

The char array to append.

The current code writer instance after the append operation.

Appends ArrayBuilder<char> followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(ArrayBuilder<char> value);

The ArrayBuilder<char> to insert.

The current code writer instance after the append operation.

Appends ushort followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(ushort value);

The ushort to insert.

The current code writer instance after the append operation.

Appends int followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(int value);

The int to insert.

The current code writer instance after the append operation.

AppendLine(ushort, string, IFormatProvider?)

Section titled “AppendLine(ushort, string, IFormatProvider?)”

Appends ushort with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(ushort value, string format, IFormatProvider? provider = null);

The ushort to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends byte followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(byte value);

The byte to insert.

The current code writer instance after the append operation.

AppendLine(short, string, IFormatProvider?)

Section titled “AppendLine(short, string, IFormatProvider?)”

Appends short with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(short value, string format, IFormatProvider? provider = null);

The short to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

AppendLine(sbyte, string, IFormatProvider?)

Section titled “AppendLine(sbyte, string, IFormatProvider?)”

Appends sbyte with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(sbyte value, string format, IFormatProvider? provider = null);

The sbyte to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends sbyte followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(sbyte value);

The sbyte to insert.

The current code writer instance after the append operation.

AppendLine(byte, string, IFormatProvider?)

Section titled “AppendLine(byte, string, IFormatProvider?)”

Appends byte with the specified format followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(byte value, string format, IFormatProvider? provider = null);

The byte to insert.

A standard or custom numeric format string.

A optional object that supplies culture-specific formatting information.

The current code writer instance after the append operation.

Appends short followed by a newline to the current line.

C# Signature
public CodeWriter AppendLine(short value);

The short to insert.

The current code writer instance after the append operation.

Appends a namespace declaration for the specified symbol. Does nothing if the symbol is null or a global namespace.

C# Signature
public CodeWriter AppendNamespace(INamespaceSymbol? symbol);

The namespace symbol to append.

The current code writer instance after the append operation.

Appends a namespace declaration. Does nothing if the value is null or empty.

C# Signature
public CodeWriter AppendNamespace(string value);

The namespace name to append.

The current code writer instance after the append operation.

Appends #nullable enable. If appended, #nullable restore will be appended at the end of the file.

C# Signature
public CodeWriter AppendNullable();

The current code writer instance after the append operation.

Appends a preprocessor symbol. Prepends # if the value does not already start with it. Does nothing if the value is null or whitespace.

C# Signature
public CodeWriter AppendPreprocessorSymbol(string? value);

The preprocessor symbol to append (e.g. #endif or endif).

The current code writer instance after the append operation.

Clears all written content and resets the writer state.

C# Signature
public CodeWriter Clear();

The current code writer instance after the append operation.

Disposes the code writer and returns the underlying StringBuilder to the pool.

C# Signature
public void Dispose();

Returns the written content as a string. Closes any open namespace block and appends #nullable restore if needed.

C# Signature
public override string ToString();

The written content as a string.

Opens a new code block. Returns a disposable scope that closes the block and restores indentation when disposed.

C# Signature
public BlockScope WithBlock(bool newLineOnDispose = false);

If true, a newline will be inserted when the block scope is disposed.

The following example demonstrates how to use WithBlock.

C#
using Hertzole.SourceGen;
internal static class CodeHelper
{
public static string Write()
{
using CodeWriter writer = new CodeWriter();
AppendMethod(writer, "Method1", true);
AppendMethod(writer, "Method2", false);
return writer.ToString();
}
public static void AppendMethod(CodeWriter writer, string methodName, bool isPublic)
{
writer.Append(isPublic ? "public " : "private ")
.Append("void ").Append(methodName).AppendLine("()");
// Must dispose the scope to close the block and restore indentation.
using (writer.WithBlock())
{
writer.AppendLine("Console.WriteLine(\"Hello World!\");");
}
}
}

The output from the writer would be:

C#
public void Method1()
{
Console.WriteLine("Hello World!");
}
public void Method2()
{
Console.WriteLine("Hello World!");
}

The following examples demonstrates the output when newLineOnDispose is set to true.

C#
using Hertzole.SourceGen;
internal static class CodeHelper
{
public static string Write()
{
using CodeWriter writer = new CodeWriter();
AppendMethod(writer, "Method1", true);
AppendMethod(writer, "Method2", false);
return writer.ToString();
}
public static void AppendMethod(CodeWriter writer, string methodName, bool isPublic)
{
writer.Append(isPublic ? "public " : "private ")
.Append("void ").Append(methodName).AppendLine("()");
// Must dispose the scope to close the block and restore indentation.
// This will add a new line when closing the block.
using (writer.WithBlock(true))
{
writer.AppendLine("Console.WriteLine(\"Hello World!\");");
}
}
}

The output from the writer would be:

C#
public void Method1()
{
Console.WriteLine("Hello World!");
}
public void Method2()
{
Console.WriteLine("Hello World!");
}

A disposable scope that closes the block when disposed.

Creates a scope in a preprocessor conditional block (#if CONDITION). Returns a disposable scope that closes the conditional block (#endif) when disposed.

C# Signature
public ConditionalScope WithCondition(string? condition);

The condition.

The following example demonstrates how to use WithCondition to wrap the content in a preprocessor conditional block.

C#
using Hertzole.SourceGen;
internal static class CodeHelper
{
public static void Write()
{
using CodeWriter writer = new CodeWriter();
writer.AppendLine("public void Method()");
using (writer.WithBlock())
{
AppendDebugLog(writer, "Calling method!");
writer.AppendLine("// TODO: Method stuff");
}
}
public static void AppendDebugLog(CodeWriter writer, string message)
{
using (writer.WithCondition("DEBUG"))
{
writer.AppendLine($"System.Diagnostics.Debug.WriteLine(\"{message}\");");
}
}
}

The output from the writer would be:

C#
public void Method()
{
#if DEBUG
System.Diagnostics.Debug.WriteLine("Calling method!");
#endif
// TODO: Method stuff
}

You can write #if CONDITION, if CONDITION or just CONDITION and the condition will be wrapped in #if and #endif, as long as the provided string isn’t null or empty/whitespace.

A disposable scope that closes the conditional block when disposed.

Temporarily changes the indentation level. Returns a disposable scope that restores the original indentation when disposed.

C# Signature
public IndentScope WithIndent(int newIndent);

The indentation level to use within the scope.

The following example demonstrates how to use WithIndent to change indentation.

C#
using Hertzole.SourceGen;
internal static class CodeHelper
{
public static void Write()
{
using CodeWriter writer = new CodeWriter();
writer.Indent = 1;
writer.AppendLine("// Stairs");
AppendStairs(writer, 5);
}
public static void AppendStairs(CodeWriter writer, int length)
{
using (writer.WithIndent(0))
{
for (int i = 0; i < length; i++)
{
writer.Append(' ', i).AppendLine('_');
}
}
}
}

The output from the writer would be:

C#
// Stairs
_
_
_
_
_

A disposable scope that restores the original indentation when disposed.