Skip to content
This repository was archived by the owner on Nov 11, 2025. It is now read-only.

Advanced code generation and manipulation library for .NET source generators

Notifications You must be signed in to change notification settings

CyberdyneDevelopment/code-builders

Repository files navigation

FractalDataWorks CodeBuilder

CI NuGet License

A comprehensive framework for programmatic code generation and analysis with language-agnostic interfaces and C# implementations using Roslyn. Designed for building source generators, code analysis tools, and testing generated code.

Architecture Overview

The CodeBuilder framework follows a layered architecture with language-agnostic interfaces and specific implementations:

graph TB
    subgraph "Abstractions Layer"
        A[FractalDataWorks.CodeBuilder.Abstractions<br/>Language-agnostic interfaces]
    end
    
    subgraph "Analysis Layer"
        B[FractalDataWorks.CodeBuilder.Analysis<br/>Testing interfaces]
        C[FractalDataWorks.CodeBuilder.Analysis.CSharp<br/>Roslyn-based testing implementation]
    end
    
    subgraph "Implementation Layer"
        D[FractalDataWorks.CodeBuilder.CSharp<br/>Roslyn-based code generation]
    end
    
    A -.-> B
    B --> C
    A --> D
    C --> D
Loading

Projects

Core Projects

Project Description Purpose
FractalDataWorks.CodeBuilder.Abstractions Language-agnostic interfaces Defines contracts for code builders, generators, and parsers
FractalDataWorks.CodeBuilder.CSharp C# code generation Fluent API for generating C# code using Roslyn
FractalDataWorks.CodeBuilder.Analysis Testing interfaces Language-agnostic interfaces for compilation verification and syntax expectations
FractalDataWorks.CodeBuilder.Analysis.CSharp C# testing implementation Roslyn-based implementation of testing interfaces

Test Projects

Project Description
FractalDataWorks.CodeBuilder.Tests Unit tests for core functionality

Installation

NuGet Package Manager

# For C# code generation
Install-Package FractalDataWorks.CodeBuilder.CSharp

# For testing generated code
Install-Package FractalDataWorks.CodeBuilder.Analysis.CSharp

# For language-agnostic abstractions only
Install-Package FractalDataWorks.CodeBuilder.Abstractions

.NET CLI

# For C# code generation
dotnet add package FractalDataWorks.CodeBuilder.CSharp

# For testing generated code
dotnet add package FractalDataWorks.CodeBuilder.Analysis.CSharp

# For language-agnostic abstractions only
dotnet add package FractalDataWorks.CodeBuilder.Abstractions

Quick Start

Basic Code Generation

using FractalDataWorks.CodeBuilder.CSharp;

// Create a simple class
var code = new ClassBuilder("Person")
    .MakePublic()
    .AddProperty("string", "Name", p => p
        .MakePublic()
        .WithGetter()
        .WithSetter())
    .AddProperty("int", "Age", p => p
        .MakePublic()
        .WithGetter()
        .WithSetter())
    .AddMethod("string", "GetDisplayName", m => m
        .MakePublic()
        .WithBody("return $\"{Name} ({Age})\";"))
    .Build();

Console.WriteLine(code);

Generated Output:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    
    public string GetDisplayName()
    {
        return $"{Name} ({Age})";
    }
}

Testing Generated Code

using FractalDataWorks.CodeBuilder.Testing.CSharp;
using FractalDataWorks.CodeBuilder.Testing;

// Test that generated code compiles and has expected structure
var verifier = new CSharpCompilationVerifier();
var syntaxExpectations = new CSharpSyntaxExpectations();

// Verify compilation
var result = verifier.CompileAndVerify(generatedCode);
Assert.True(result.Success);

// Verify structure
syntaxExpectations
    .ExpectCode(generatedCode)
    .HasClass("Person", c => c
        .HasAccessModifier("public")
        .HasProperty("Name", p => p.HasType("string"))
        .HasProperty("Age", p => p.HasType("int"))
        .HasMethod("GetDisplayName", m => m
            .HasReturnType("string")
            .IsPublic()))
    .Compiles();

Core Features

Code Generation (FractalDataWorks.CodeBuilder.CSharp)

  • Fluent API: Intuitive builder pattern for constructing code elements
  • Type-Safe: Compile-time safety with strongly-typed builders
  • Roslyn Integration: Built on Microsoft's Roslyn compiler platform
  • Rich Support: Classes, interfaces, methods, properties, fields, constructors, enums, records
  • Modern C# Features: Support for nullable reference types, init-only properties, records, and more

Code Analysis and Testing

  • Language-Agnostic Interfaces: Define testing contracts independent of implementation
  • Compilation Verification: Verify that generated code compiles without errors
  • Syntax Expectations: Fluent API for asserting code structure and content
  • Method Invocation: Execute methods from compiled assemblies for integration testing
  • Diagnostic Analysis: Detailed compilation error and warning reporting

Advanced Usage

Building Complex Classes

var repositoryClass = new ClassBuilder("UserRepository")
    .MakePublic()
    .AddGenericParameter("T")
    .AddGenericConstraint("T", "class, IEntity")
    .WithInterface("IRepository<T>")
    .WithNamespace("MyApp.Data")
    
    // Fields
    .AddField("DbContext", "_context", f => f
        .MakePrivate()
        .MakeReadOnly())
    
    // Constructor
    .AddConstructor(c => c
        .MakePublic()
        .AddParameter("DbContext", "context")
        .WithBody("_context = context;"))
    
    // Properties
    .AddProperty("IQueryable<T>", "Items", p => p
        .MakePublic()
        .WithGetter("_context.Set<T>().AsQueryable()"))
    
    // Methods
    .AddMethod("Task<T?>", "FindAsync", m => m
        .MakePublic()
        .MakeAsync()
        .AddParameter("int", "id")
        .AddParameter("CancellationToken", "cancellationToken", "default")
        .WithBody(@"
            return await _context.Set<T>()
                .FindAsync(new object[] { id }, cancellationToken);"))
    
    .Build();

Advanced Testing Scenarios

// Test compilation with custom options
var options = new AnalysisOptions
{
    OutputKind = OutputKind.DynamicallyLinkedLibrary,
    OptimizationLevel = OptimizationLevel.Release,
    AllowUnsafe = false,
    References = new[]
    {
        typeof(System.Collections.Generic.IEnumerable<>).Assembly.Location,
        typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute).Assembly.Location
    }
};

var result = verifier.CompileWithOptions(new[] { generatedCode }, options);
Assert.True(result.Success);

// Execute compiled method
var displayName = result.InvokeMethod("Person", "GetDisplayName");
Assert.Equal("John Doe (30)", displayName);

Source Generator Testing

// Test a source generator
public class MySourceGeneratorTests
{
    [Fact]
    public void Generator_ProducesExpectedOutput()
    {
        // Input source code
        var inputSource = @"
            [GenerateBuilder]
            public class Product
            {
                public int Id { get; set; }
                public string Name { get; set; }
            }";

        // Run your source generator
        var generatedSources = RunSourceGenerator<ProductBuilderGenerator>(inputSource);
        
        // Verify generated code structure
        var syntaxExpectations = new CSharpSyntaxExpectations();
        syntaxExpectations
            .ExpectCode(generatedSources.First().SourceText.ToString())
            .HasClass("ProductBuilder", c => c
                .IsPublic()
                .HasMethod("WithId", m => m
                    .HasParameter("id", "int")
                    .HasReturnType("ProductBuilder"))
                .HasMethod("WithName", m => m
                    .HasParameter("name", "string")
                    .HasReturnType("ProductBuilder"))
                .HasMethod("Build", m => m
                    .HasReturnType("Product")))
            .Compiles();
    }
}

Analysis Framework

ICompilationVerifier Interface

Provides language-agnostic compilation verification:

public interface ICompilationVerifier
{
    ICompilationResult CompileAndVerify(params string[] sources);
    ICompilationResult CompileWithOptions(string[] sources, ICompilationOptions options);
}

Key Features:

  • Compilation Results: Success status, diagnostics, and assembly bytes
  • Method Invocation: Execute methods from compiled assemblies
  • Custom Options: Control output type, optimization level, and references
  • Diagnostic Reporting: Detailed error and warning information

ISyntaxExpectations Interface

Provides fluent syntax verification:

public interface ISyntaxExpectations
{
    ISyntaxTreeExpectations ExpectCode(string generatedCode);
    ISyntaxTreeExpectations ExpectSyntaxTree(object syntaxTree);
}

Key Features:

  • Structure Verification: Assert namespaces, classes, interfaces, enums, records
  • Member Verification: Assert methods, properties, fields, constructors
  • Modifier Verification: Assert access modifiers, static, abstract, sealed, etc.
  • Type Verification: Assert parameter types, return types, property types
  • Compilation Verification: Ensure generated code compiles successfully

Language Registry

The framework supports extensibility through a language registry system:

// Register C# language support
var registry = new LanguageRegistry();
registry.RegisterLanguage<CSharpCodeGenerator>("csharp");
registry.RegisterLanguage<CSharpCodeGenerator>("cs");

// Get generator for a language
var generator = registry.GetGenerator("csharp");

Best Practices

Code Generation

  1. Use Fluent API: Chain builder methods for readable code construction
  2. Namespace Organization: Always specify appropriate namespaces
  3. Type Safety: Leverage compile-time checking with strongly-typed builders
  4. Documentation: Add XML documentation to generated code
  5. Formatting: Use consistent indentation and formatting

Testing

  1. Verify Compilation: Always ensure generated code compiles
  2. Test Structure: Use syntax expectations to verify code structure
  3. Test Behavior: Use method invocation to test runtime behavior
  4. Edge Cases: Test error scenarios and edge cases
  5. Integration Tests: Test complete source generator workflows

Migration Notes

From SmartGenerators.TestUtilities

If you're migrating from the previous TestUtilities project:

  1. Namespace Changes: Update from FractalDataWorks.SmartGenerators.TestUtilities to FractalDataWorks.CodeBuilder.Testing.CSharp
  2. Interface Adoption: Use the new language-agnostic interfaces where possible
  3. Compilation Verification: Switch to ICompilationVerifier for testing generated code
  4. Syntax Expectations: Use ISyntaxExpectations for structural assertions

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass
  6. Submit a pull request

License

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

Support

For questions, issues, or contributions:

About

Advanced code generation and manipulation library for .NET source generators

Resources

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages