EmitWriter¶
A C#-aware text writer for source generator output. Replaces SyntaxFactory + NormalizeWhitespace() with ~100-460x better performance and ~36x less memory allocation.
See also: Emit Overview | IWritable | PartialTypeHierarchy
Constructor¶
| Parameter | Type | Default | Description |
|---|---|---|---|
indentation |
string |
" " |
Indentation string per level (4 spaces) |
endOfLine |
string |
"\n" |
Line ending string |
EmitWriter implements IDisposable. Use using var or using blocks.
Core Writing¶
| Method | Description |
|---|---|
Write(string text) |
Write text (applies indentation at line start) |
WriteLine(string text) |
Write text followed by a newline |
WriteLine() |
Write an empty line (no indentation) |
Write(IWritable writable) |
Delegate to an IWritable component's WriteTo method |
All methods return this for fluent chaining.
Indentation¶
| Method / Property | Description |
|---|---|
Indent() |
Increase indentation by one level |
Outdent() |
Decrease indentation by one level |
IndentLevel |
int — current indentation depth |
Indentation is applied automatically when writing at the start of a line.
Block Helpers¶
| Method | Description |
|---|---|
Block(bool trailingSemicolon = false) |
Write {, indent, return IDisposable that writes } (or };) and outdents |
Block(string declaration, bool trailingSemicolon = false) |
Write declaration, then open block |
// Block with declaration
using (writer.Block("public class Foo"))
{
writer.WriteLine("public int Value { get; set; }");
}
// Produces:
// public class Foo
// {
// public int Value { get; set; }
// }
// Trailing semicolon (enum, record with body)
using (writer.Block("public enum Status", trailingSemicolon: true))
{
writer.WriteLine("Active,");
writer.WriteLine("Inactive,");
}
// Produces:
// public enum Status
// {
// Active,
// Inactive,
// };
C# Helpers¶
| Method | Description |
|---|---|
Comment(string text) |
Write // text |
XmlDoc(string tag, string content) |
Write /// <tag>content</tag> |
XmlDocBlock(string tag, IEnumerable<string> lines) |
Write multi-line /// <tag> block |
Attribute(string attribute) |
Write [attribute] |
NullableEnable() |
Write #nullable enable |
IfDirective(string condition) |
Write #if condition |
EndIfDirective() |
Write #endif |
Region(string name) |
Write #region name |
EndRegion() |
Write #endregion |
Using(string ns) |
Write using ns; |
GlobalUsing(string ns) |
Write global using ns; |
Fluent Chaining¶
All methods return this:
writer
.Comment("<auto-generated/>")
.NullableEnable()
.WriteLine()
.Using("System")
.Using("System.Collections.Generic")
.WriteLine();
Complete Example¶
using var writer = new EmitWriter();
writer.Comment("<auto-generated/>");
writer.NullableEnable();
writer.WriteLine();
writer.Using("System");
writer.WriteLine();
writer.XmlDoc("summary", "A generated service.");
using (writer.Block("public sealed class MyService"))
{
writer.XmlDoc("summary", "Gets the name.");
writer.WriteLine("public string Name { get; }");
writer.WriteLine();
writer.XmlDoc("summary", "Creates a new instance.");
using (writer.Block("public MyService(string name)"))
{
writer.WriteLine("Name = name;");
}
}
context.AddSource("MyService.g.cs", writer.ToString());
Output¶
| Member | Description |
|---|---|
ToString() |
Returns the accumulated output as a string |
Dispose() |
Disposes the underlying StringWriter |
Thread Safety¶
Not thread-safe. Each generator output step should create its own EmitWriter instance.