FractalDataWorks.SmartGenerators.CodeBuilders 0.1.5-alpha-g8cae162c25

This is a prerelease version of FractalDataWorks.SmartGenerators.CodeBuilders.
dotnet add package FractalDataWorks.SmartGenerators.CodeBuilders --version 0.1.5-alpha-g8cae162c25
                    
NuGet\Install-Package FractalDataWorks.SmartGenerators.CodeBuilders -Version 0.1.5-alpha-g8cae162c25
                    
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="FractalDataWorks.SmartGenerators.CodeBuilders" Version="0.1.5-alpha-g8cae162c25">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FractalDataWorks.SmartGenerators.CodeBuilders" Version="0.1.5-alpha-g8cae162c25" />
                    
Directory.Packages.props
<PackageReference Include="FractalDataWorks.SmartGenerators.CodeBuilders">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
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 FractalDataWorks.SmartGenerators.CodeBuilders --version 0.1.5-alpha-g8cae162c25
                    
#r "nuget: FractalDataWorks.SmartGenerators.CodeBuilders, 0.1.5-alpha-g8cae162c25"
                    
#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 FractalDataWorks.SmartGenerators.CodeBuilders@0.1.5-alpha-g8cae162c25
                    
#: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=FractalDataWorks.SmartGenerators.CodeBuilders&version=0.1.5-alpha-g8cae162c25&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=FractalDataWorks.SmartGenerators.CodeBuilders&version=0.1.5-alpha-g8cae162c25&prerelease
                    
Install as a Cake Tool

FractalDataWorks Smart Generators

License

A comprehensive toolkit for building, testing, and deploying Roslyn source generators with a fluent code generation API.

Table of Contents

Overview

FractalDataWorks Smart Generators provides a complete framework for building Roslyn source generators:

  • Fluent Code Building API - Generate C# code with an intuitive builder pattern
  • Incremental Generator Base Classes - Simplified development with best practices built-in
  • Comprehensive Testing Framework - Test generators with expectations and assertions
  • Documentation Support - Extract and format XML documentation

Projects

This solution contains three main projects:

FractalDataWorks.SmartGenerators

Core framework for building incremental source generators with utilities for diagnostics, compilation helpers, and base classes.

FractalDataWorks.SmartGenerators.CodeBuilders

Fluent API for generating C# code including classes, interfaces, methods, properties, and more with proper formatting and documentation.

FractalDataWorks.SmartGenerators.TestUtilities

Testing framework for source generators with compilation builders, assertion helpers, and expectations API.

Installation

Install the packages you need:

# For building generators
dotnet add package FractalDataWorks.SmartGenerators
dotnet add package FractalDataWorks.SmartGenerators.CodeBuilders

# For testing generators
dotnet add package FractalDataWorks.SmartGenerators.TestUtilities

Quick Start

1. Create a Source Generator

using FractalDataWorks.SmartGenerators;
using FractalDataWorks.SmartGenerators.CodeBuilders;
using Microsoft.CodeAnalysis;

[Generator]
public class DtoGenerator : IncrementalGeneratorBase<ClassModel>
{
    protected override bool IsRelevantSyntax(SyntaxNode node)
    {
        return node is ClassDeclarationSyntax cds &&
               cds.AttributeLists.Any(al => 
                   al.Attributes.Any(a => a.Name.ToString().Contains("GenerateDto")));
    }

    protected override ClassModel? TransformSyntax(GeneratorSyntaxContext context)
    {
        var classDecl = (ClassDeclarationSyntax)context.Node;
        var symbol = context.SemanticModel.GetDeclaredSymbol(classDecl);
        
        return new ClassModel
        {
            Name = symbol!.Name,
            Namespace = symbol.ContainingNamespace.ToDisplayString(),
            Properties = symbol.GetMembers()
                .OfType<IPropertySymbol>()
                .Select(p => new PropertyModel 
                { 
                    Name = p.Name, 
                    Type = p.Type.ToDisplayString() 
                })
                .ToList()
        };
    }

    protected override void Execute(SourceProductionContext context, ClassModel model)
    {
        var dto = new ClassBuilder($"{model.Name}Dto")
            .MakePublic()
            .MakePartial()
            .WithNamespace(model.Namespace);

        foreach (var prop in model.Properties)
        {
            dto.AddProperty(prop.Type, prop.Name, p => p
                .MakePublic()
                .WithGetterAndSetter());
        }

        context.AddSource($"{model.Name}Dto.g.cs", dto.Build());
    }
}

2. Test Your Generator

using FractalDataWorks.SmartGenerators.TestUtilities;
using Xunit;
using Shouldly;

public class DtoGeneratorTests
{
    [Fact]
    public void GeneratesDto()
    {
        var source = @"
            [GenerateDto]
            public class Person
            {
                public int Id { get; set; }
                public string Name { get; set; }
            }";

        var result = SourceGeneratorTestHelper.RunGenerator<DtoGenerator>(source);
        
        result.ShouldContain("public partial class PersonDto");
        result.ShouldContain("public int Id { get; set; }");
        result.ShouldContain("public string Name { get; set; }");
    }
}

Generic Type Support

CodeBuilders now support generic types:

ClassBuilder

var builder = new ClassBuilder("MyClass")
    .WithTypeParameter("T")
    .WithTypeConstraint("where T : IDisposable")
    .MakePublic();

// Generates: public class MyClass<T> where T : IDisposable

Multiple Type Parameters

var builder = new ClassBuilder("Converter")
    .WithTypeParameters("TInput", "TOutput")
    .WithTypeConstraint("where TInput : class")
    .WithTypeConstraint("where TOutput : struct")
    .MakePublic();

InterfaceBuilder

Same methods available for interfaces:

var builder = new InterfaceBuilder("IRepository")
    .WithTypeParameter("T")
    .WithTypeConstraint("where T : IEntity")
    .MakePublic();

Architecture

Solution Structure

smart-generators/
├── src/
│   ├── FractalDataWorks.SmartGenerators/         # Core framework
│   ├── FractalDataWorks.SmartGenerators.CodeBuilders/  # Code building API
│   └── FractalDataWorks.SmartGenerators.TestUtilities/ # Testing utilities
├── tests/
│   ├── FractalDataWorks.SmartGenerators.Tests/
│   ├── FractalDataWorks.SmartGenerators.CodeBuilder.Tests/
│   └── FractalDataWorks.SmartGenerators.TestUtilities.Tests/
├── docs/                                          # Documentation
└── README.md                                      # This file

Component Architecture

graph TD
    A[Your Generator] -->|inherits| B[IncrementalGeneratorBase]
    A -->|uses| C[Code Builders]
    B -->|part of| D[SmartGenerators Core]
    C -->|part of| E[CodeBuilders Package]
    F[Your Tests] -->|uses| G[Test Utilities]
    G -->|references| D
    G -->|references| E

Generation Flow

sequenceDiagram
    participant Source as Source Code
    participant Gen as Your Generator
    participant Base as IncrementalGeneratorBase
    participant Builder as Code Builder
    participant Output as Generated Code
    
    Source->>Gen: Syntax Node
    Gen->>Base: IsRelevantSyntax()
    Base-->>Gen: true/false
    Gen->>Base: TransformSyntax()
    Base-->>Gen: Model
    Gen->>Builder: Create builders
    Builder->>Builder: Build code
    Builder-->>Gen: String
    Gen->>Output: AddSource()

Developer Guide

Building from Source

# Clone the repository
git clone https://github.com/FractalDataWorks/smart-generators.git
cd smart-generators

# Build the solution
dotnet build

# Run tests
dotnet test

# Pack NuGet packages
dotnet pack -c Release

Project Dependencies

graph BT
    A[SmartGenerators] -->|depends on| R[Roslyn]
    B[CodeBuilders] -->|depends on| A
    C[TestUtilities] -->|depends on| A
    C -->|depends on| B
    D[Your Generator] -->|depends on| A
    D -->|depends on| B
    E[Your Tests] -->|depends on| C

Creating a Custom Builder

public class CustomBuilder : CodeBuilderBase<CustomBuilder>
{
    private readonly string _name;
    
    public CustomBuilder(string name) : base()
    {
        _name = name;
    }
    
    public override string Build()
    {
        var builder = new StringBuilder();
        
        // Add your custom generation logic
        builder.AppendLine($"// Custom generated code for {_name}");
        
        return builder.ToString();
    }
    
    protected override CustomBuilder ThisBuilder => this;
}

Testing Best Practices

  1. Unit Test Builders

    [Fact]
    public void ClassBuilder_GeneratesCorrectSyntax()
    {
        var code = new ClassBuilder("Test")
            .MakePublic()
            .Build();
    
        code.ShouldContain("public class Test");
    }
    
  2. Integration Test Generators

    [Fact]
    public void Generator_HandlesComplexScenarios()
    {
        var source = LoadTestCase("ComplexScenario.cs");
        var output = RunGenerator(source);
    
        CompileAndVerify(source, output);
    }
    
  3. Use Expectations API

    [Fact]
    public void Generator_ProducesExpectedStructure()
    {
        var result = RunGenerator(source);
    
        var expectations = ExpectationsFactory.Create();
        expectations.ExpectClass("MyClass", c => c
            .WithModifier("public")
            .WithMethod("MyMethod"));
    
        expectations.Verify(result);
    }
    

Debugging Generators

  1. Attach Debugger

    #if DEBUG
    if (!Debugger.IsAttached)
    {
        Debugger.Launch();
    }
    #endif
    
  2. Enable Logging

    <PropertyGroup>
      <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
    </PropertyGroup>
    
  3. Use Diagnostics

    context.ReportDiagnostic(Diagnostic.Create(
        DiagnosticDescriptors.Info,
        Location.None,
        $"Processing: {model.Name}"));
    

Contributing

We welcome contributions! Please see our Contributing Guidelines.

Development Process

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add or update tests
  5. Update documentation
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

Code Style

  • Follow existing patterns and conventions
  • Add XML documentation to public APIs
  • Include unit tests for new features
  • Keep commits focused and atomic

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

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 FractalDataWorks.SmartGenerators.CodeBuilders:

Package Downloads
FractalDataWorks.SmartGenerators

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.5-alpha-g8cae162c25 481 7/23/2025
0.1.4-alpha-g4415be49cc 276 7/21/2025
0.1.3-alpha-g2dc2da0077 267 7/20/2025
0.1.2-alpha-gf6ea635473 124 7/14/2025
0.1.1-alpha-gc64e6ae799 118 7/14/2025
0.1.1-alpha-g64f4a16f7b 111 7/14/2025