Deepstaging.Roslyn.Workspace 1.0.0-dev-20260205052640

This is a prerelease version of Deepstaging.Roslyn.Workspace.
dotnet add package Deepstaging.Roslyn.Workspace --version 1.0.0-dev-20260205052640
                    
NuGet\Install-Package Deepstaging.Roslyn.Workspace -Version 1.0.0-dev-20260205052640
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Deepstaging.Roslyn.Workspace" Version="1.0.0-dev-20260205052640" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Deepstaging.Roslyn.Workspace" Version="1.0.0-dev-20260205052640" />
                    
Directory.Packages.props
<PackageReference Include="Deepstaging.Roslyn.Workspace" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Deepstaging.Roslyn.Workspace --version 1.0.0-dev-20260205052640
                    
#r "nuget: Deepstaging.Roslyn.Workspace, 1.0.0-dev-20260205052640"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Deepstaging.Roslyn.Workspace@1.0.0-dev-20260205052640
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Deepstaging.Roslyn.Workspace&version=1.0.0-dev-20260205052640&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Deepstaging.Roslyn.Workspace&version=1.0.0-dev-20260205052640&prerelease
                    
Install as a Cake Tool

Deepstaging.Roslyn.Workspace

Code fix infrastructure for Roslyn analyzers using the Workspace API.

📚 Full Documentation

See also: Roslyn Toolkit | Testing

What is this?

This library provides base classes and utilities for building Roslyn code fix providers. It simplifies the boilerplate of registering code fixes and working with syntax nodes.

Quick Start

1. Define a code fix with attributes

[ExportCodeFixProvider(LanguageNames.CSharp)]
[CodeFix("MY001")]
[CodeFix("MY002")]  // Can fix multiple diagnostics
public class AddPartialModifierCodeFix : SyntaxCodeFix<TypeDeclarationSyntax>
{
    protected override CodeAction? CreateFix(Document document, ValidSyntax<TypeDeclarationSyntax> syntax)
    {
        return CodeAction.Create(
            title: "Add partial modifier",
            createChangedDocument: ct => AddPartialModifier(document, syntax.Node, ct),
            equivalenceKey: "AddPartial");
    }
    
    private async Task<Document> AddPartialModifier(
        Document document, 
        TypeDeclarationSyntax declaration,
        CancellationToken ct)
    {
        var newDeclaration = declaration
            .AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword));
        
        return await document.ReplaceNode(declaration, newDeclaration, ct);
    }
}

2. That's it!

The base class handles:

  • Reading [CodeFix] attributes to populate FixableDiagnosticIds
  • Finding the syntax node at the diagnostic location
  • Registering the code action with proper error handling

API Reference

SyntaxCodeFix<TSyntax>

Abstract base class for code fix providers:

public abstract class SyntaxCodeFix<TSyntax> : CodeFixProvider
    where TSyntax : SyntaxNode
{
    // Automatically populated from [CodeFix] attributes
    public sealed override ImmutableArray<string> FixableDiagnosticIds { get; }
    
    // Override to create your fix
    protected abstract CodeAction? CreateFix(
        Document document, 
        ValidSyntax<TSyntax> syntax);
}

CodeFixAttribute

Declarative configuration for code fixes:

[CodeFix("MY001")]  // The diagnostic ID this code fix handles
[CodeFix("MY002")]  // Add multiple attributes for multiple diagnostics

Specialized Base Classes

Pre-defined base classes for common syntax types:

// Type declarations
public abstract class ClassCodeFix : SyntaxCodeFix<ClassDeclarationSyntax>;
public abstract class StructCodeFix : SyntaxCodeFix<StructDeclarationSyntax>;
public abstract class InterfaceCodeFix : SyntaxCodeFix<InterfaceDeclarationSyntax>;
public abstract class RecordCodeFix : SyntaxCodeFix<RecordDeclarationSyntax>;
public abstract class EnumCodeFix : SyntaxCodeFix<EnumDeclarationSyntax>;

// Member declarations
public abstract class MethodCodeFix : SyntaxCodeFix<MethodDeclarationSyntax>;
public abstract class PropertyCodeFix : SyntaxCodeFix<PropertyDeclarationSyntax>;
public abstract class FieldCodeFix : SyntaxCodeFix<FieldDeclarationSyntax>;
public abstract class ConstructorCodeFix : SyntaxCodeFix<ConstructorDeclarationSyntax>;
public abstract class EventCodeFix : SyntaxCodeFix<EventDeclarationSyntax>;
public abstract class ParameterCodeFix : SyntaxCodeFix<ParameterSyntax>;

Document Extensions

Convenient methods for document manipulation:

// Replace a syntax node (async)
Document newDoc = await document.ReplaceNode(oldNode, newNode, cancellationToken);

// Replace a syntax node (sync, when root is already available)
Document newDoc = document.ReplaceNode(root, oldNode, newNode);

CodeFixContext Extensions

Helper methods for finding syntax nodes:

// Generic find
OptionalSyntax<TSyntax> result = await context.FindDeclaration<TypeDeclarationSyntax>();

// Type-specific helpers
OptionalSyntax<ClassDeclarationSyntax> classDecl = await context.FindClass();
OptionalSyntax<MethodDeclarationSyntax> methodDecl = await context.FindMethod();
OptionalSyntax<PropertyDeclarationSyntax> propDecl = await context.FindProperty();
// Also: FindStruct(), FindInterface(), FindRecord(), FindEnum(),
//       FindField(), FindConstructor(), FindEvent(), FindParameter()

Projections

ValidSyntax<T>

A wrapper guaranteeing a non-null syntax node:

protected override CodeAction? CreateFix(Document document, ValidSyntax<TypeDeclarationSyntax> syntax)
{
    // syntax.Node is guaranteed non-null
    string name = syntax.Node.Identifier.Text;
    
    // Access the underlying node
    TypeDeclarationSyntax node = syntax.Node;
}

Why Use This?

Without this library:

public class MyCodeFix : CodeFixProvider
{
    public override ImmutableArray<string> FixableDiagnosticIds => 
        ImmutableArray.Create("MY001", "MY002");
    
    public override FixAllProvider GetFixAllProvider() => 
        WellKnownFixAllProviders.BatchFixer;
    
    public override async Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
        if (root == null) return;
        
        var diagnostic = context.Diagnostics.First();
        var node = root.FindNode(diagnostic.Location.SourceSpan);
        
        if (node.FirstAncestorOrSelf<TypeDeclarationSyntax>() is not { } typeDecl)
            return;
        
        var codeAction = CodeAction.Create(...);
        context.RegisterCodeFix(codeAction, diagnostic);
    }
}

With this library:

[CodeFix("MY001")]
[CodeFix("MY002")]
public class MyCodeFix : SyntaxCodeFix<TypeDeclarationSyntax>
{
    protected override CodeAction? CreateFix(Document document, ValidSyntax<TypeDeclarationSyntax> syntax)
    {
        return CodeAction.Create(...);
    }
}

License

RPL-1.5 (Reciprocal Public License) — Real reciprocity, no loopholes.

You can use this code, modify it, and share it freely. But when you deploy it — internally or externally, as a service or within your company — you share your improvements back under the same license.

Why? We believe if you benefit from this code, the community should benefit from your improvements. That's the deal we think is fair.

Personal research and experimentation? No obligations. Go learn, explore, and build.

See LICENSE for the full legal text.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Deepstaging.Roslyn.Workspace:

Package Downloads
Deepstaging.Roslyn.Testing

Testing infrastructure for Roslyn analyzers and generators. Includes TUnit base classes and Verify snapshot testing support.

GitHub repositories

This package is not used by any popular GitHub repositories.