Purview.SourceGeneratorFramework
1.0.0-prerelease.9
See the version list below for details.
dotnet add package Purview.SourceGeneratorFramework --version 1.0.0-prerelease.9
NuGet\Install-Package Purview.SourceGeneratorFramework -Version 1.0.0-prerelease.9
<PackageReference Include="Purview.SourceGeneratorFramework" Version="1.0.0-prerelease.9" />
<PackageVersion Include="Purview.SourceGeneratorFramework" Version="1.0.0-prerelease.9" />
<PackageReference Include="Purview.SourceGeneratorFramework" />
paket add Purview.SourceGeneratorFramework --version 1.0.0-prerelease.9
#r "nuget: Purview.SourceGeneratorFramework, 1.0.0-prerelease.9"
#:package Purview.SourceGeneratorFramework@1.0.0-prerelease.9
#addin nuget:?package=Purview.SourceGeneratorFramework&version=1.0.0-prerelease.9&prerelease
#tool nuget:?package=Purview.SourceGeneratorFramework&version=1.0.0-prerelease.9&prerelease
Purview.SourceGeneratorFramework
Core helpers, models, and MSBuild integration for writing incremental C# source generators with Roslyn.
Installation
dotnet add package Purview.SourceGeneratorFramework
What's included
CodeWriter— allocation-conscious helper for building generated C# source files with indentation, namespaces, type declarations, comments, and XML documentation.IncrementalPipeline— extension methods for composingIncrementalValueProvider<T>andIncrementalValuesProvider<T>pipelines, including attribute-based discovery, generation context creation, and disable-property checks.GenerationContext— a base context record that carries the RoslynCompilation, owns a configuredCodeWriter, and can replace it with a fresh writer using the same build-time settings.GeneratorResult<T>— a value-or-diagnostics result type for incremental source generator transforms.TypeValueObject,TargetSymbolDescriptor,EquatableArray<T>,DiagnosticInfo— reusable models for generator inputs and outputs.SymbolResolver,TypeHelpers,EmbeddedResources— helper classes for common symbol and resource tasks.- MSBuild
.props/.targets— automatically addsglobal usingdirectives for the main namespaces and supports packaging source generators that reference this framework.
Usage
Reference the package from a Roslyn source generator project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsRoslynComponent>true</IsRoslynComponent>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Purview.SourceGeneratorFramework" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" />
</ItemGroup>
</Project>
Implement IIncrementalGenerator and use the framework helpers to build a pipeline:
using Microsoft.CodeAnalysis;
using Purview.SourceGeneratorFramework.Helpers;
using Purview.SourceGeneratorFramework.Models;
[Generator]
public sealed class MyGenerator : IIncrementalGenerator
{
static readonly TypeValueObject AttributeType = new("MyAttribute", "MyNamespace");
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var contextProvider = IncrementalPipeline.DefaultGenerationContextValueProvider(context);
var targets = IncrementalPipeline.ForAttributeWithMetadataName(
context,
AttributeType,
static (ctx, ct) => ctx.TargetSymbol.Name
);
context.RegisterSourceOutput(
targets.CombineWithContext(contextProvider),
static (spc, pair) =>
{
var (name, generationContext) = pair;
var writer = generationContext.CreateCodeWriter();
writer.WriteAutoGeneratedHeader(nameof(MyGenerator));
writer.WriteFileScopedNamespace("MyNamespace");
using (
writer.WriteClass(
new TypeDeclarationOptions(name)
{
Accessibility = TypeDeclarationAccessibility.Public,
IsStatic = true,
}
)
)
{
writer.WriteLine("// generated content");
}
spc.AddSource($"{name}.g.cs", writer.ToString());
}
);
}
}
See SourceGeneratorFramework.ExampleGenerator for a complete reference implementation.
Detecting undisposed CodeWriter scopes
CodeWriter can detect block or indentation scopes that have not been disposed before generated source is materialized. This validation is intended for development and automated tests and is disabled by default.
Enable it in the project consuming the source generator:
<PropertyGroup>
<PurviewSourceGeneratorFrameworkValidateCodeWriterScopes>true</PurviewSourceGeneratorFrameworkValidateCodeWriterScopes>
</PropertyGroup>
The default generation-context provider reads the property automatically:
var contextProvider =
IncrementalPipeline.DefaultGenerationContextValueProvider(context);
Create or reset the writer through the generation context so it inherits the setting:
var writer = generationContext.CreateCodeWriter();
GenerationContext.CodeWriter is initialized through CreateCodeWriter() in the context constructor. Calling CreateCodeWriter() later creates a fresh writer, assigns it to GenerationContext.CodeWriter, and returns that same instance. CodeWriter.ThrowOnUnclosedScopes is read-only; configuration is supplied through its constructor.
When validation is enabled, calling ToString() or implicitly converting a writer to Roslyn SourceText throws a CodeWriterScopeValidationException if OpenScopeCount is not zero. The dedicated exception allows generator error handlers to rethrow this framework invariant failure instead of reducing it to a generic generator diagnostic:
Cannot create generated source while 1 disposable scope(s) remain open. Dispose every scope before calling ToString().
Open scope #1: block — public sealed class Example
at MyGenerator.Generate(...)
The exception's OpenScopes collection exposes the scope kind, block header, and opening stack
trace programmatically. Stack traces are captured only when validation is enabled, avoiding this
diagnostic allocation during normal generator execution.
Both BlockScope and IndentScope are tracked. Prefer using or callback-based blocks so scopes are always closed:
writer.Block(
"if (value is null)",
body => body.WriteLine("return;")
);
Custom generation contexts
Scope validation is applied to every context returned by GenerationContextValueProvider. Custom
contexts do not need to accept or read the build property themselves:
public sealed record MyGenerationContext : GenerationContext
{
public MyGenerationContext(Compilation compilation)
: base(compilation)
{
}
}
Use the ordinary context-provider overload. The framework combines the compiler-visible property, configures the returned context, and replaces its default writer before publishing it downstream:
var contextProvider = IncrementalPipeline.GenerationContextValueProvider(
context,
static (compilation, cancellationToken) =>
{
cancellationToken.ThrowIfCancellationRequested();
return new MyGenerationContext(compilation);
}
);
Generators embedded in another package
If the generator assembly is embedded in a different NuGet package, the outer package must make the property compiler-visible to its consumers. Build assets from Purview.SourceGeneratorFramework are not automatically copied into the outer package.
Include this in a .props file imported by the outer package:
<Project>
<PropertyGroup>
<PurviewSourceGeneratorFrameworkValidateCodeWriterScopes
Condition="'$(PurviewSourceGeneratorFrameworkValidateCodeWriterScopes)' == ''"
>false</PurviewSourceGeneratorFrameworkValidateCodeWriterScopes>
</PropertyGroup>
<ItemGroup>
<CompilerVisibleProperty Include="PurviewSourceGeneratorFrameworkValidateCodeWriterScopes">
<Description>Throws when generated source is materialized while CodeWriter scopes remain undisposed.</Description>
</CompilerVisibleProperty>
</ItemGroup>
</Project>
Pack that file using the outer package's ID so NuGet imports it automatically:
<None
Include="Sdk\Sdk.props"
Pack="true"
PackagePath="buildTransitive\$(PackageId).props"
Visible="false"
/>
Framework-based generator tests enable scope validation by default. Disable it for a test only when partial source materialization is intentional:
new SourceGeneratorTestOptions
{
ValidateCodeWriterScopes = false,
};
Disabling a generator at build time
Use IncrementalPipeline.IsDisabledValueProvider to read an MSBuild analyzer-config property and skip generation when it is set to true:
<PropertyGroup>
<MyGenerator_Disable>true</MyGenerator_Disable>
</PropertyGroup>
var isDisabled = IncrementalPipeline.IsDisabledValueProvider(context, "MyGenerator_Disable");
License
This project is licensed under the MIT license.
| 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
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Purview.SourceGeneratorFramework:
| Package | Downloads |
|---|---|
|
Purview.SourceGeneratorFramework.Testing
Purview SourceGeneratorFramework libraries for building and testing incremental C# source generators. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-prerelease.25 | 54 | 8/27/2026 |
| 1.0.0-prerelease.24 | 65 | 8/19/2026 |
| 1.0.0-prerelease.23 | 66 | 8/19/2026 |
| 1.0.0-prerelease.22 | 68 | 8/19/2026 |
| 1.0.0-prerelease.21 | 66 | 8/18/2026 |
| 1.0.0-prerelease.20 | 71 | 8/18/2026 |
| 1.0.0-prerelease.19 | 72 | 8/17/2026 |
| 1.0.0-prerelease.18 | 73 | 8/16/2026 |
| 1.0.0-prerelease.17 | 64 | 8/14/2026 |
| 1.0.0-prerelease.16 | 64 | 8/13/2026 |
| 1.0.0-prerelease.15 | 65 | 8/13/2026 |
| 1.0.0-prerelease.14 | 60 | 8/13/2026 |
| 1.0.0-prerelease.13 | 66 | 8/13/2026 |
| 1.0.0-prerelease.12 | 68 | 8/12/2026 |
| 1.0.0-prerelease.11 | 65 | 8/12/2026 |
| 1.0.0-prerelease.10 | 60 | 8/12/2026 |
| 1.0.0-prerelease.9 | 75 | 8/11/2026 |
| 1.0.0-prerelease.7 | 68 | 8/9/2026 |
| 1.0.0-prerelease.6 | 65 | 8/8/2026 |
| 1.0.0-prerelease.5 | 62 | 8/7/2026 |