TimeWarp.Nuru includes a built-in Roslyn analyzer that provides compile-time validation of your route patterns, catching errors before you run your application.
The analyzer prevents common mistakes that would otherwise fail at runtime:
// ❌ This compiles without analyzer, fails at runtime
builder.Map("deploy <env>", handler); // Wrong syntax
// ❌ This compiles without analyzer, creates ambiguous routing
builder.Map("run {file?} {*args}", handler); // Invalid combination
// ✅ With analyzer: Both caught at compile-time with clear error messagesNo separate installation needed! The analyzer is automatically included with TimeWarp.Nuru (version 2.1.0-beta.9+).
<PackageReference Include="TimeWarp.Nuru" Version="2.1.0-beta.9" />The analyzer:
- Runs during compilation only
- Has zero runtime performance impact
- Doesn't affect application size
- Works in all IDEs (Visual Studio, VS Code, Rider, JetBrains IDEs)
Syntax issues in route patterns - malformed brackets, invalid characters, unsupported types.
Logical issues that create ambiguity or conflicts - duplicate parameters, invalid parameter ordering, incompatible combinations.
Missing package dependencies required for specific features.
Problem: Using wrong bracket syntax for parameters
// ❌ Error: Invalid syntax
builder.Map("deploy <env>", handler); // Should use curly braces
// ✅ Correct
builder.Map("deploy {env}", handler);Problem: Missing opening or closing brace
// ❌ Error: Missing closing brace
builder.Map("deploy {env", handler);
// ❌ Error: Missing opening brace
builder.Map("deploy env}", handler);
// ✅ Correct
builder.Map("deploy {env}", handler);Problem: Incorrect option naming (multi-character with single dash)
// ❌ Error: Multi-character option needs double-dash
builder.Map("build -verbose", handler);
// ✅ Correct: Double-dash for long options
builder.Map("build --verbose", handler);
// ✅ Correct: Single dash for single character
builder.Map("build -v", handler);
// ✅ Best: Provide both
builder.Map("build --verbose,-v", handler);Problem: Using unsupported or misspelled type names
// ❌ Error: 'integer' is not supported
builder.Map("process {id:integer}", handler);
// ✅ Correct: Use 'int'
builder.Map("process {id:int}", handler);Supported types: string, int, double, bool, DateTime, Guid, long, decimal, TimeSpan, uri
See Supported Types for complete list.
Problem: Same parameter name used multiple times
// ❌ Error: Parameter 'arg' appears twice
builder.Map("run {arg} {arg}", handler);
// ✅ Correct: Use unique names
builder.Map("run {source} {dest}", handler);Problem: Multiple consecutive optional parameters create ambiguity
// ❌ Error: Which parameter gets the value?
builder.Map("deploy {env?} {version?}", handler);
// If user types "deploy v2.0", is it env or version?
// ✅ Correct: Only last parameter optional
builder.Map("deploy {env} {version?}", handler);
// ✅ Alternative: Use options for multiple optional values
builder.Map("deploy {env} --version? {ver?}", handler);Problem: Catch-all parameter must be last
// ❌ Error: Catch-all in middle
builder.Map("exec {*args} {script}", handler);
// ✅ Correct: Catch-all at end
builder.Map("exec {script} {*args}", handler);Problem: Cannot combine optional and catch-all parameters
// ❌ Error: Invalid combination
builder.Map("run {script?} {*args}", handler);
// ✅ Use one pattern:
builder.Map("run {script} {*args}", handler); // Required + catch-all
// OR
builder.Map("run {script?}", handler); // Just optionalProblem: Optional parameters must come after required ones
// ❌ Error: Optional before required
builder.Map("copy {source?} {dest}", handler);
// ✅ Correct: Required first
builder.Map("copy {source} {dest?}", handler);Problem: Using Map<TCommand> without required Mediator packages
// ❌ Error: Mediator packages not installed
builder.Map<PingCommand>("ping");
// ✅ Fix: Install packages
// dotnet add package Mediator.Abstractions
// dotnet add package Mediator.SourceGeneratorThe Map<TCommand> pattern uses Mediator for request handling. Both packages must be directly referenced (not transitive).
The analyzer works automatically in all modern .NET IDEs:
| IDE | Support |
|---|---|
| Visual Studio 2022+ | ✅ Full support |
| Visual Studio Code (C# extension) | ✅ Full support |
| JetBrains Rider | ✅ Full support |
Command-line (dotnet build) |
✅ Full support |
Errors appear in multiple places:
- Code editor: Red squiggles under problematic code
- Error List: Detailed error messages with error codes
- Build output: Compilation errors with file/line references
- IntelliSense: Real-time feedback as you type
// This code would compile, then fail at runtime
builder.Map("deploy <env?> <ver?>", handler);
// ↑ ↑
// Multiple problems invisible until runtime// Build fails immediately with clear errors:
// NURU_P001: Invalid parameter syntax - use {env} not <env>
// NURU_S002: Conflicting optional parameters
builder.Map("deploy <env?> <ver?>", handler);// Errors fixed, builds successfully
builder.Map("deploy {env} --version? {ver?}", handler);| Without Analyzer | With Analyzer |
|---|---|
| Errors found at runtime | Errors found at compile-time |
| Cryptic runtime messages | Clear, actionable error messages |
| Trial-and-error debugging | Instant feedback in IDE |
| Production failures possible | Guaranteed valid routes |
If you have a valid reason to suppress an error (rare), you can:
#pragma warning disable NURU_S002
builder.Map("risky {a?} {b?}", handler); // NOT RECOMMENDED
#pragma warning restore NURU_S002[*.cs]
dotnet_diagnostic.NURU_S002.severity = warning # Downgrade to warning
# or
dotnet_diagnostic.NURU_S002.severity = none # Completely suppress<PropertyGroup>
<NoWarn>$(NoWarn);NURU_S002</NoWarn>
</PropertyGroup>TimeWarp.Nuru includes debug diagnostics (NURU_DEBUG*) that are hidden by default. These provide detailed information about the source generator's processing.
Add to your .editorconfig:
[*.cs]
# Enable specific debug diagnostics
dotnet_diagnostic.NURU_DEBUG001.severity = suggestion
dotnet_diagnostic.NURU_DEBUG002.severity = suggestion
# Or enable all debug diagnostics
dotnet_diagnostic.NURU_DEBUG.severity = suggestion| Value | Description |
|---|---|
none |
Diagnostic completely suppressed |
silent |
Same as none |
suggestion |
Shows as informational message |
warning |
Shows as compiler warning |
error |
Shows as compiler error |
Note: info is NOT a valid severity value (common mistake).
Why Hidden by Default?
Debug diagnostics are verbose and primarily useful for:
- Troubleshooting source generator issues
- Understanding what routes are being generated
- Debugging custom type converter registration
For normal development, keep them hidden.
| Code | Description |
|---|---|
| NURU_P001 | Invalid parameter syntax (wrong brackets) |
| NURU_P002 | Unbalanced braces |
| NURU_P003 | Invalid option format |
| NURU_P004 | Invalid type constraint |
| NURU_P005 | Invalid character in pattern |
| NURU_P006 | Unexpected token |
| NURU_P007 | Null route pattern |
| Code | Description |
|---|---|
| NURU_S001 | Duplicate parameter names |
| NURU_S002 | Conflicting optional parameters |
| NURU_S003 | Catch-all not at end |
| NURU_S004 | Mixed catch-all with optional |
| NURU_S005 | Option with duplicate alias |
| NURU_S006 | Optional before required |
| NURU_S007 | Invalid end-of-options separator |
| NURU_S008 | Options after end-of-options separator |
| Code | Description |
|---|---|
| NURU_D001 | Missing Mediator packages for Map<TCommand> |
- Routing Patterns - Complete route syntax guide
- Supported Types - Available type constraints
- Developer Guide: Using Analyzers - Implementation details