Lucewave is a multi-phase source generator pipeline orchestrator for .NET. It solves the fundamental limitation in Roslyn where source generators cannot see each other's outputs by enabling chainable, multi-phase code generation.
In Roslyn's current model:
- Source generators run in an unordered manner
- Each generator only sees the original source code
- Generator A cannot consume types generated by Generator B
- This makes complex code generation scenarios (like "generate DTOs from OpenAPI, then generate validators for those DTOs") impossible
Lucewave introduces phased execution:
- Phase 1 generators run and produce output (e.g., contracts, DTOs, interfaces)
- Those outputs are added to a new compilation
- Phase 2 generators run against the enriched compilation
- This continues for any number of phases
- ✅ Multi-phase pipeline execution - Chain generators that depend on each other
- ✅ YAML configuration - Simple, declarative pipeline definition
- ✅ CLI tool - Run pipelines from command line or CI/CD
- ✅ MSBuild integration - Seamless Visual Studio and build integration
- ✅ Caching - Incremental rebuilds based on input hashing
- ✅ Generator discovery - Automatic detection of generators in assemblies
- ✅ Pipeline SDK - Attributes for generator authors to declare dependencies
- ✅ Detailed reporting - Execution times, generated files, and diagnostics
dotnet tool install -g Lucewave.Clilucewave initThis creates a generator-pipeline.yml file:
phases:
- name: contracts
generators:
- MyCompany.OpenApi.Generator
- name: implementations
generators:
- MyCompany.DtoMapper.Generator
- MyCompany.Validator.Generator
options:
outputRoot: obj/gen
cache: truelucewave runAdd the NuGet package to your project:
<PackageReference Include="Lucewave.MsBuild" Version="1.0.0" />The pipeline will automatically run before compilation when a generator-pipeline.yml file exists.
<PropertyGroup>
<LucewaveConfig>custom-pipeline.yml</LucewaveConfig>
<LucewaveOutputRoot>$(IntermediateOutputPath)generated</LucewaveOutputRoot>
<LucewaveEnableCache>true</LucewaveEnableCache>
</PropertyGroup>phases:
- name: contracts
generators:
- OpenApi.Generator
- Protobuf.Generator
phaseOptions:
cache: true
outputDir: contracts
- name: implementations
generators:
- Dapper.Generator
- AutoMapper.Generator
phaseOptions:
cache: true
outputDir: implementations
- name: clients
generators:
- Refit.Generator
- HttpClient.Generator
phaseOptions:
cache: true
outputDir: clients
options:
outputRoot: obj/gen
cache: true
parallel: false
verbosity: normal
continueOnError: false| Option | Type | Default | Description |
|---|---|---|---|
outputRoot |
string | obj/gen |
Root directory for generated files |
cache |
boolean | true |
Enable caching across phases |
parallel |
boolean | false |
Enable parallel execution within phases |
verbosity |
enum | normal |
Logging verbosity (quiet, minimal, normal, detailed, diagnostic) |
continueOnError |
boolean | false |
Continue pipeline on generator errors |
Lucewave provides an SDK for generator authors to declare their phase preferences and dependencies:
using Lucewave.Sdk;
[GeneratorPhase(1, PhaseName = "contracts")]
[Consumes("OpenApiSpec")]
[Produces("IApiClient")]
[DependsOnGenerator("OpenApi.Generator")]
public class MyGenerator : IIncrementalGenerator
{
// ...
}Generators can include a LucewaveManifest.json file:
{
"packageId": "MyCompany.MyGenerator",
"manifestVersion": "1.0",
"preferredPhase": 1,
"outputCategory": "Contracts",
"inputs": ["OpenApiSpec", "IEntity"],
"outputs": ["IApiClient", "EntityDto"],
"dependsOn": ["OpenApi.Generator"]
}┌─────────────────────────────────────────────────────────────┐
│ Lucewave │
├─────────────────────────────────────────────────────────────┤
│ CLI / MSBuild Task │
│ ├── Configuration Parser (YAML) │
│ ├── Pipeline Executor │
│ │ ├── Phase 1: Run generators → Save output │
│ │ ├── Phase 2: Load previous + Run → Save output │
│ │ └── Phase N: Continue... │
│ ├── Generator Discovery │
│ ├── Caching (SHA256-based) │
│ └── Diagnostics & Reporting │
└─────────────────────────────────────────────────────────────┘
# Run the pipeline
lucewave run [options]
-c, --config <file> Configuration file (default: generator-pipeline.yml)
-p, --project <dir> Project directory (default: current)
-o, --output <dir> Output directory
-v, --verbose Verbose output
--no-cache Disable caching
# Initialize configuration
lucewave init [options]
-t, --template <name> Template to use (basic, advanced)
# Cache management
lucewave cache clear# Clone the repository
git clone https://github.com/Taiizor/Lucewave.git
cd Lucewave
# Build
dotnet build
# Run tests
dotnet test├── src/
│ ├── Lucewave.Core/ # Core pipeline logic
│ ├── Lucewave.Cli/ # Command-line tool
│ ├── Lucewave.MsBuild/ # MSBuild integration
│ └── Lucewave.Sdk/ # SDK for generator authors
├── tests/
│ └── Lucewave.Tests/ # Unit tests
└── samples/ # Sample projects
- NuGet package resolver for generator references
- Visual Studio extension for pipeline visualization
- F# and VB.NET project support
- Parallel phase execution
- Remote generator caching
- Language Server Protocol integration
Contributions are welcome! Please read our contributing guidelines before submitting a pull request.
This project is licensed under the MIT License - see the LICENSE file for details.
This project was inspired by the ongoing discussions in the Roslyn community about chainable source generators and the "Two-Phase Incremental Generators" proposal.