ANcpLua.Roslyn.Utilities
2.2.11
dotnet add package ANcpLua.Roslyn.Utilities --version 2.2.11
NuGet\Install-Package ANcpLua.Roslyn.Utilities -Version 2.2.11
<PackageReference Include="ANcpLua.Roslyn.Utilities" Version="2.2.11" />
<PackageVersion Include="ANcpLua.Roslyn.Utilities" Version="2.2.11" />
<PackageReference Include="ANcpLua.Roslyn.Utilities" />
paket add ANcpLua.Roslyn.Utilities --version 2.2.11
#r "nuget: ANcpLua.Roslyn.Utilities, 2.2.11"
#:package ANcpLua.Roslyn.Utilities@2.2.11
#addin nuget:?package=ANcpLua.Roslyn.Utilities&version=2.2.11
#tool nuget:?package=ANcpLua.Roslyn.Utilities&version=2.2.11
ANcpLua.Roslyn.Utilities
A focused utility library for writing Roslyn source generators, analyzers, and code-fix providers. The shape is opinionated: the types here are the ones that make an incremental generator actually cache, a symbol comparison actually readable, and a code emission actually deterministic.
Agent test doubles, MAF conformance suites, and workflow fixtures live in the sibling ANcpLua.Agents package. This repo focuses on Roslyn/MSBuild/OTel-for-analyzer-authors.
The library is the author's own. Use it, improve it (the upstream is this repo), or propose switching directions — don't reinvent locally.
Packages
| Package | Target | What it's for |
|---|---|---|
ANcpLua.Roslyn.Utilities |
netstandard2.0 | Runtime + Roslyn utilities as a normal NuGet reference |
ANcpLua.Roslyn.Utilities.Sources |
source-only | Embeds the utilities as internal source into source generators (generators can't load NuGet DLLs at runtime) |
ANcpLua.Roslyn.Utilities.Polyfills |
source-only | init, required, Index/Range, nullable & trim attributes for netstandard2.0 |
ANcpLua.Roslyn.Utilities.Testing |
net10.0 | Generator/analyzer/codefix test infrastructure, MSBuild/NuGet integration tests, cross-framework web testing (xUnit/NUnit/TUnit/Bunit), OTel instrumentation helpers, BitNetFixture live-LLM integration |
ANcpLua.Roslyn.Utilities.Testing.Aot |
netstandard2.0 | AOT/trim test attributes ([AotTest], [TrimTest], [AotSafe], [TrimSafe]), TrimAssert, FeatureSwitches, MSBuild orchestration for standalone AOT verification |
Quickstart — writing a source generator
dotnet add package ANcpLua.Roslyn.Utilities.Sources
A canonical incremental generator is ~25 lines when the utilities do their job — see src/ANcpLua.AotReflection/AotReflectionGenerator.cs in this repo for the reference shape:
[Generator]
public sealed class MyGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var flows = context.SyntaxProvider.ForAttributeWithMetadataName(
"MyNamespace.TracedAttribute",
static (node, _) => node is ClassDeclarationSyntax,
static (ctx, ct) => TypeExtractor.Extract(ctx, ct));
var types = flows.ReportAndStop(context);
var files = types
.Select(static (m, _) => OutputGenerator.Generate(m))
.CollectAsEquatableArray();
files.AddSources(context);
}
}
What the library provides at each step:
ForAttributeWithMetadataName— filter syntax before expensive semantic work (Roslyn built-in; the library wraps for ergonomics)DiagnosticFlow<T>— railway-oriented pipeline carrying value + accumulated diagnostics, value-equatable for incremental cachingReportAndStop— drain the flow intoReportDiagnosticand yield valuesCollectAsEquatableArray/ToEquatableArray/ToEquatableArrayOrDefault— value-equatable collections so the generator cache actually hitsAddSources— emitFileWithNamerecords without boilerplateMatch.Type()/Match.Method()— fluent symbol matching, no string comparisonsIndentedStringBuilder—BeginBlock()/EndBlock()scopes, no hardcoded indentation stringsGeneratedCodeHelpers—<auto-generated/>headers,#nullable enable, pragma helpers
Testing an agent or a MAF workflow
Agent test doubles (FakeChatClient, FakeReplayAgent, ActivityCollector), the provider-agnostic MAF conformance suite (RunTests, RunStreamingTests, ChatClientAgentRunTests, StructuredOutputRunTests), reference fixtures for OpenAI / Azure / Anthropic / Ollama / Gemini / OpenRouter, and the WorkflowFixture<TInput> harness ship in the sibling ANcpLua.Agents package.
What's in the box
Incremental pipeline (generator authors)
DiagnosticFlow<T>+DiagnosticFlowReportingExtensions— railway-oriented flow with value + accumulatedDiagnosticInfoIncrementalValuesProviderExtensions—ReportAndStop,CollectAsEquatableArray,AddSources, and other pipeline verbsSyntaxValueProviderExtensions— ergonomicForAttributeWithMetadataNamewrappersSourceProductionContextExtensions— context helpersEquatableArray<T>+EquatableArrayExtensions(.ToEquatableArray,.ToEquatableArrayOrDefault,.AsEquatableArray) — value equality so the cache actually hitsFileWithName— record for emitted-file payloadDiagnosticInfo+LocationInfo+EquatableMessageArgs— value-equatable diagnostic carriersResultWithDiagnostics<T>— result payload paired with diagnostics, for pipelines where the value survives errors
Symbol analysis & matching
Matchfluent DSL —Match.Type()/Match.Method()/Match.Property()/Match.Field()/Match.Parameter()with the per-kind matchers underMatching/(MethodMatcher,TypeMatcher, etc.)Invoke/InvocationMatcher— invocation-shape matchingSymbolExtensions,TypeSymbolExtensions,MethodSymbolExtensions,NamespaceExtensions—IsEqualTo,ImplementsInterface,GetAllBaseTypesAndSelf, and the usual suspectsAttributeExtensions—GetAttribute,HasAttribute,TryGetAttributewith constructor-arg accessorsInvocationExtensions/OperationExtensions/OperationHelper—IInvocationOperationanalysis helpersSemanticGuard<T>+SemanticGuard— chain semantic predicates with early-exitSemanticModelExtensions/CompilationExtensions/SyntaxExtensions
Code emission
IndentedStringBuilder+IndentScope—BeginBlock()/EndBlock()scopes, no hardcoded indentationGeneratedCodeHelpers—<auto-generated/>header, nullable/pragma directivesValueStringBuilder— stack-allocatedStringBuilderfor hot pathsSyntaxBuilders(Analyzers/) — fluent builders for common code-fix patterns (ExtensionCall,StaticCall,NameOf)
Analyzer authoring
DiagnosticAnalyzerBase— convention base classDiagnosticCategories/DiagnosticSeverities— category/severity constantsDeprecatedOtelAttributes— 50+ attribute-name mappings synced to OTel GenAI semconv 1.40 (catchesgen_ai.systemand friends during analysis)IncrementalPipelineHelpers— pipeline wiring utilitiesMappingRegistry/TypeCache<TEnum>— cached lookups for analyzer hot paths
Async & time
AsyncSequenceExtensions— LINQ-ish operators overIAsyncEnumerable<T>ParallelAsyncExtensions— channel-based parallel enumeration with ordering controlExpiringCache<TKey,TValue>— TTL cache for analyzer resultsTimeConversions— OTel nanosecond helpers
Dictionary & collection ergonomics
DictionaryExtensions—GetOrInsert(key, context, factory)(closure-free, hot-path),GetOrAdd(key)/GetOrAdd(key, factory)(ergonomic),MapIfAbsent(src, dst, transform)(cross-key copy for vendor-adapter telemetry mappers)EnumerableExtensions— dedup, partition, chunking,MinBy/MaxByListExtensions— in-place mutation helpers
Guards & null handling
Guard— null / range / path / type guardsNullableExtensions—Map-style combinators forT?TryExtensions—TryParseX, dictionaryGetOrNull/GetOrDefault/GetOrElse
Models & OTel enums
SpanKind,SpanStatusCode— OTel enumsPagedResult<T>— standard paginated response shape
Polyfills
Language and API backports for netstandard2.0 consumers (via the separate .Polyfills package):
| Polyfill | Enables | Opt-out |
|---|---|---|
Index / Range |
array[^1], array[1..3] |
InjectIndexRangeOnLegacy=false |
IsExternalInit |
record types, init setters |
InjectIsExternalInitOnLegacy=false |
| Nullable attributes | [NotNull], [MaybeNull], [MemberNotNull], [NotNullWhen] |
InjectNullabilityAttributesOnLegacy=false |
| Trim/AOT attributes | [RequiresUnreferencedCode], [DynamicallyAccessedMembers] |
InjectTrimAttributesOnLegacy=false |
TimeProvider |
Testable time abstraction | InjectTimeProviderPolyfill=false |
Lock |
System.Threading.Lock |
InjectLockPolyfill=false |
required, params collections, CallerArgumentExpression, UnreachableException, StackTraceHidden, ExperimentalAttribute |
C# 11–13 language features on ns2.0 | per-feature MSBuild props |
Disable all at once: <InjectAllPolyfillsOnLegacy>false</InjectAllPolyfillsOnLegacy>
Testing — what ships in .Testing
Generator, analyzer, codefix, refactoring, MSBuild integration, and cross-framework web testing.
- Generator tests:
Test<TGenerator>(fluent entry),GeneratorTestHelper.RunGenerator<TGenerator>()(assertion-oriented one-liners),GeneratorCachingReport(compares two runs, detects cache hits),Compile/CompileResult(dynamic compilation with Shouldly-style assertions) - Analyzer / CodeFix / Refactoring tests:
AnalyzerTest<TAnalyzer>,CodeFixTest<TAnalyzer,TCodeFix>,CodeFixTestWithEditorConfig<TAnalyzer,TCodeFix>,RefactoringTest<TRefactoring>,SolutionRefactoringTest<TRefactoring>,LogAssert - MSBuild integration tests:
ProjectBuilder,PackageProjectBuilder,PackageTestBase<TFixture>/NuGetPackageTestBase,NuGetPackageFixture,BuildResult+BuildResultAssertions,SarifFileparsers,DotNetSdkHelpers/NetSdkVersion,MSBuildConstants - Web testing — one base per framework:
- xUnit (root):
IntegrationTestBase<TProgram>,KestrelTestBase<TProgram> WebTesting/NUnit/,WebTesting/TUnit/,WebTesting/Bunit/— per-framework equivalents- Plus
FakeLoggerExtensionsfor structured log capture
- xUnit (root):
- OTel instrumentation:
ActivityInstrumentation,MetricsInstrumentation,LoggingConventions,LogEnricherInfrastructure,DataClassificationHelpers(PII/Secret redaction) - Live-LLM integration:
BitNetFixture,BitNetAttribute,BitNetTestGroup— xUnit v3 collection fixture for llama.cpp BitNet server
AOT testing — what ships in .Testing.Aot
Separate package (netstandard2.0, zero runtime deps). Attributes + MSBuild props for verifying AOT/trim behavior.
[AotTest],[AotSafe],[AotUnsafe]— mark methods as AOT-verified or AOT-excluded[TrimTest],[TrimSafe],[TrimUnsafe]— same for IL trimming;TrimModeenum selectsPartial/FullTrimAssert.TypePreserved(...)/TypeRemoved(...)— runtime assertions against the trimmed binaryFeatureSwitches— constants for common AOT feature switches (e.g.JsonReflection)AotRuntime— runtime AOT/trim detection- MSBuild orchestration (
build/*.props+*.targets+ProjectTemplate.csproj.txt) ships inside the package itself; no external SDK dependency
Separate: AOT reflection generator
This repo also ships ANcpLua.Analyzers.AotReflection — an incremental source generator that replaces runtime typeof(T).GetProperties() with compile-time metadata, making types NativeAOT- and trim-safe. Mark a type [AotReflection] and a generated FooMetadata class appears with strongly-typed getter/setter/invoker delegates. Pair with ANcpLua.Roslyn.Utilities.Testing.Aot to verify the output survives PublishAot=true and PublishTrimmed=true.
Design principles
- Compile-time over runtime reflection.
EquatableArray<T>for generator caching,DiagnosticFlow<T>for pipeline error accumulation,IndentedStringBuilderfor emission — the shape of an incremental generator the compiler cache actually likes. - Allocation-conscious in analyzer hot paths.
ValueStringBuilderfor stack-allocated string building,Boxesfor cached boxed primitives, closure-freeGetOrInsert<TContext>for dictionary inserts. - OTel semconv 1.40 native.
DeprecatedOtelAttributescatchesgen_ai.systemand 50+ other deprecated attribute names during analysis. - Test discipline.
GeneratorCachingReportover hand-rolled cache assertions.Test<TGenerator>fluent runner over hand-rolledCSharpGeneratorDriverplumbing. The shipped-internallyForbiddenTypeAnalyzercatchesISymbol/Compilationsnuck into pipeline models. Agent-specific test doubles live in the siblingANcpLua.Agentspackage. - Source-only delivery for generators. The
.Sourcespackage rewrites the utilities tointernalvia a pack-time PowerShell transform (Transform-Sources.ps1), because source generators can't load NuGet DLLs at runtime.
Documentation
ancplua.mintlify.app/utilities — full API reference with examples.
Related
- ANcpLua.NET.Sdk — opinionated .NET SDK wrapper built on the same conventions
- ANcpLua.Analyzers — the author's analyzer catalogue, built on these utilities
- ANcpLua.Agents — agent test doubles, MAF conformance, workflow fixtures
License
MIT © Alexander Nachtmann
| Product | Versions 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. |
-
.NETStandard 2.0
- Microsoft.Bcl.AsyncInterfaces (>= 10.0.7)
- Microsoft.Bcl.HashCode (>= 6.0.0)
- Microsoft.CodeAnalysis.Analyzers (>= 5.3.0)
- Microsoft.CodeAnalysis.CSharp (>= 5.3.0)
- System.Threading.Channels (>= 10.0.7)
NuGet packages (12)
Showing the top 5 NuGet packages that depend on ANcpLua.Roslyn.Utilities:
| Package | Downloads |
|---|---|
|
ANcpLua.Roslyn.Utilities.Testing
Fluent testing framework for Roslyn analyzers, code fixes, and incremental generators with caching validation, forbidden type detection, and comprehensive assertion support. |
|
|
ErrorOrX
Discriminated unions for .NET with fluent error handling. ErrorOr<T> provides railway-oriented programming, nullable-to-ErrorOr extensions (OrNotFound, OrValidation, OrError), Match/Then/Else/Switch/FailIf fluent API, and rich typed errors mapped to HTTP status codes. |
|
|
ANcpLua.Agents
Consumer toolkit spine for Microsoft Agent Framework. Bundling facades plus governance primitives: call lineage, spawn tracker, budget enforcer, concurrency limiter, governed AIFunction, tracing decorators, and tool-decorating chat client. |
|
|
ANcpLua.Agents.Testing
Test infrastructure for Microsoft Agent Framework. Fake agents, scripted chat clients, SSE parsing, mock HTTP handlers, and IChatClientAgentFixture reference implementations for OpenAI, Azure OpenAI, Anthropic, Ollama, Google Gemini, and OpenRouter. |
|
|
ANcpLua.Agents.Testing.Workflows
Test infrastructure for Microsoft Agent Framework Workflows. Fluent fixture base with assertion builders, an execution-environment parametric axis, and ANcpLua-authored facades over MAF Workflows internals (facade / decorator / railway / fluent / extension methods) — designed for expressiveness and loose coupling, not a 1:1 mirror of upstream. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.2.11 | 110 | 5/9/2026 |
| 2.2.10 | 84 | 5/8/2026 |
| 2.2.9 | 91 | 5/7/2026 |
| 2.2.8 | 59 | 5/7/2026 |
| 2.2.7 | 74 | 5/7/2026 |
| 2.2.6 | 57 | 5/7/2026 |
| 2.2.5 | 1,404 | 5/6/2026 |
| 2.2.4 | 86 | 5/6/2026 |
| 2.2.3 | 242 | 5/5/2026 |
| 2.2.2 | 130 | 5/4/2026 |
| 2.2.1 | 153 | 5/4/2026 |
| 2.2.0 | 1,141 | 4/30/2026 |
| 2.1.1 | 173 | 4/27/2026 |
| 2.1.0 | 122 | 4/27/2026 |
| 2.0.7 | 1,147 | 4/27/2026 |
| 2.0.6 | 128 | 4/26/2026 |
| 2.0.5 | 187 | 4/25/2026 |
| 2.0.4 | 320 | 4/24/2026 |
| 2.0.3 | 158 | 4/24/2026 |
| 2.0.2 | 411 | 4/21/2026 |