TedToolkit.RoslynHelper
2026.9.9
dotnet add package TedToolkit.RoslynHelper --version 2026.9.9
NuGet\Install-Package TedToolkit.RoslynHelper -Version 2026.9.9
<PackageReference Include="TedToolkit.RoslynHelper" Version="2026.9.9" />
<PackageVersion Include="TedToolkit.RoslynHelper" Version="2026.9.9" />
<PackageReference Include="TedToolkit.RoslynHelper" />
paket add TedToolkit.RoslynHelper --version 2026.9.9
#r "nuget: TedToolkit.RoslynHelper, 2026.9.9"
#:package TedToolkit.RoslynHelper@2026.9.9
#addin nuget:?package=TedToolkit.RoslynHelper&version=2026.9.9
#tool nuget:?package=TedToolkit.RoslynHelper&version=2026.9.9
TedToolkit.RoslynHelper
A fluent API for generating C# source code, designed for Roslyn source generators, analyzers, and other code generation workflows.
Good Fit
This library is useful when you want to compose:
- files, namespaces, and type declarations
- methods, properties, fields, events, indexers, and constructors
- expressions and statements
- XML documentation comments
- conditional compilation blocks
- code-generation syntax derived from Roslyn symbols
It targets netstandard2.0 and can be distributed as part of analyzer-oriented packages.
Installation
<ItemGroup>
<PackageReference Include="TedToolkit.RoslynHelper" Version="1.0.0" />
</ItemGroup>
Quick Start
using TedToolkit.RoslynHelper;
using TedToolkit.RoslynHelper.Syntaxes;
using static TedToolkit.RoslynHelper.SourceComposer;
var code = File()
.AddUsing(Using("System"))
.AddNameSpace(NameSpace("Demo.Space")
.AddMember(Class("Sample").Public
.AddMember(
new Method("Run")
.Public
.Static
.AddStatement(1.ToLiteral().Return))))
.ToCode();
By default, the generated output includes the auto-generated file header and #pragma warning disable, plus the using directives, namespaces, and members you add. File options can preserve warnings and enable nullable checking.
Common Capabilities
1. Generate types and members
using TedToolkit.RoslynHelper.Syntaxes;
var typeDeclaration = new TypeDeclaration("Sample", TypeDeclarationType.CLASS)
.Public
.Partial
.AddBaseType<IDisposable>()
.AddMember(new Field(DataType.Int, "count"))
.AddMember(
new Property(DataType.String, "Name")
.AddAccessor(new Accessor(AccessorType.GET)))
.AddMember(
new Method("Run")
.AddStatement("count".ToSimpleName().Return));
Primary declaration types include:
TypeDeclarationMethodPropertyFieldEventIndexerConstructorOperatorConversionEnumDelegate
2. Generate expressions and statements
using TedToolkit.RoslynHelper.Syntaxes;
var statement = new IfStatement("ready".ToSimpleName())
.AddStatement("work".ToSimpleName())
.Else()
.AddStatement("fallback".ToSimpleName());
var expression = "items".ToSimpleName()
.Sub("Count")
.Add(1.ToLiteral());
Common statement types covered by the current library include:
StatementReturnStatementIfStatementForEachStatementUsingStatementTryStatementSwitchStatement
3. Generate conditional compilation
using TedToolkit.RoslynHelper.Syntaxes;
using TedToolkit.RoslynHelper.Syntaxes.Preprocessors;
var field = new Field(DataType.Int, "count")
.AddCondition(PreprocessorExpression.Debug);
var block = new ConditionalCompilationStatement(PreprocessorExpression.Debug)
.AddStatement("work".ToSimpleName())
.Else()
.AddStatement("fallback".ToSimpleName());
This is useful when the generated output needs #if DEBUG-style structure.
4. Convert Roslyn symbols into generation syntax
using Microsoft.CodeAnalysis;
using TedToolkit.RoslynHelper;
Parameter parameter = SourceComposer.Parameter(parameterSymbol, compilation);
var dataType = DataType.FromSymbol(typeSymbol, compilation);
var attribute = SourceComposer.Attribute(attributeData, compilation);
var typeParameter = SourceComposer.TypeParameter(typeParameterSymbol, compilation);
This is the main bridge between Roslyn analysis data and generated code composition.
5. Stamp generated members with generator metadata
using static TedToolkit.RoslynHelper.SourceComposer<MyGenerator>;
var method = Method("Run")
.Public
.AddStatement("value".ToSimpleName().Return);
When you create members through SourceComposer<TGenerator>, the library automatically adds GeneratedCodeAttribute.
6. Compose async code
var call = "ReadAsync".ToSimpleName().Invoke("cancellationToken".ToSimpleName());
var method = new Method("ExecuteAsync", new ReturnType(DataType.TaskOf(DataType.Int)))
.Public.Async
.AddParameter(new Parameter(DataType.FromType<CancellationToken>(), "cancellationToken"))
.AddStatement(call.ConfigureAwait(false).Await().Return);
.Async sets Method.IsAsync and preserves the declared return type. The same Method can be added as a local function through AddStatement. DataType.Task, TaskOf(resultType), ValueTask, and ValueTaskOf(resultType) create fresh mutable type representations; the result type can come from DataType.FromSymbol.
.Await() emits only await. Add .ConfigureAwait(false) explicitly when appropriate; the expression overload accepts a variable or other configuration expression. Use parentheses explicitly when composing compound operands or accessing the awaited result:
task.Coalesce(fallback).Parenthesized.ConfigureAwait(false).Await();
call.Await().Parenthesized.Sub("Length"); // (await ReadAsync(...)).Length
Async iteration and disposal use the existing statement builders:
var iteration = "items".ToSimpleName().ForEach(DataType.Var, "item").Await
.AddStatement("Process".ToSimpleName().Invoke("item".ToSimpleName()));
var lifetime = "resource".ToSimpleName().Using.Await.AddStatement(iteration);
These generate await foreach (...) and await using (...) { ... }; set IsAwait = false to return to synchronous syntax. The target compilation must supply the relevant awaitable types and language support.
7. Pass arguments and configure generated files
Invoke(params IExpression[]), AddArgument(IExpression), and AddArguments(params IExpression[]) accept positional expressions. Existing Argument objects remain available for named and ref/in/out arguments:
var call = "Update".ToSimpleName().Invoke(1.ToLiteral())
.AddArgument(new Argument("value".ToSimpleName()).Ref);
var creation = new DataType("global::System.Version").New.AddArguments(1.ToLiteral(), 2.ToLiteral());
var file = new SourceFile
{
DisableWarnings = false,
NullableContext = Microsoft.CodeAnalysis.NullableContextOptions.Enable,
}.AddMember(new TypeDeclaration("GlobalWorker", TypeDeclarationType.CLASS)
.AddMember(new Method("Run").Public));
SourceFile.Members and AddMember emit declarations in the global namespace. File-level using directives precede assembly attributes; global members precede named namespaces. Empty namespaces use blocks when sharing a file with global members or other namespaces.
DisableWarnings defaults to true. NullableContext defaults to null (no directive), and supports Disable, Enable, Annotations, and Warnings. To report nullable warnings, enable their nullable context and set DisableWarnings = false.
Empty TryStatement, CatchClause, and FinallyClause bodies always emit {}. A TryStatement still needs a catch or finally clause to form valid C#.
Notes
- This is a code generation helper library, not a full semantic rewriter
- String and character literals escape C# special characters. Floating-point literals support NaN and infinity; doubles include a
Dsuffix to preserve their type and negative zero. - The main public namespaces used by examples are
TedToolkit.RoslynHelperandTedToolkit.RoslynHelper.Syntaxes - It is best suited to composing code first, then emitting it through
ToCode()orSourceFile.Generate(...)
License
LGPL-3.0-or-later.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.CodeAnalysis.CSharp (>= 5.0.0)
- System.Memory (>= 4.6.3)
- ZString (>= 2.6.0)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on TedToolkit.RoslynHelper:
| Package | Downloads |
|---|---|
|
TedToolkit.CppBindings.Generator
Provider-neutral C++ binding generation stages, source publication, and Windows loading support. |
|
|
TedToolkit.CppBindings.Cgal.Generator
Generate deterministic finite-profile managed and native CGAL bindings. |
|
|
TedToolkit.CppBindings.Occt.Generator
Generate exact-layout managed and native OCCT bindings through the reusable C++ bindings platform. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.9.9 | 393 | 9/9/2026 |
| 2026.9.4 | 113 | 9/4/2026 |
| 2026.7.15 | 135 | 7/15/2026 |
| 2026.7.8 | 124 | 7/8/2026 |
| 2026.7.6 | 131 | 7/6/2026 |
| 2026.6.19 | 254 | 6/19/2026 |
| 2026.6.18 | 142 | 6/18/2026 |
| 2026.6.9 | 137 | 6/9/2026 |
| 2026.6.5.3 | 115 | 6/5/2026 |
| 2026.6.5.2 | 114 | 6/5/2026 |
| 2026.6.5.1 | 114 | 6/5/2026 |
| 2026.6.5 | 116 | 6/5/2026 |
| 2026.4.17.1 | 157 | 4/17/2026 |
| 2026.4.17 | 115 | 4/17/2026 |
| 2026.4.14.1 | 127 | 4/14/2026 |
| 2026.4.14 | 117 | 4/14/2026 |
| 2026.4.8 | 123 | 4/8/2026 |
| 2026.3.31 | 144 | 3/31/2026 |
| 2026.3.30.2 | 120 | 3/30/2026 |
| 2026.3.30.1 | 138 | 3/30/2026 |