ANcpLua.Roslyn.Utilities.Sources
2.0.2
dotnet add package ANcpLua.Roslyn.Utilities.Sources --version 2.0.2
NuGet\Install-Package ANcpLua.Roslyn.Utilities.Sources -Version 2.0.2
<PackageReference Include="ANcpLua.Roslyn.Utilities.Sources" Version="2.0.2"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="ANcpLua.Roslyn.Utilities.Sources" Version="2.0.2" />
<PackageReference Include="ANcpLua.Roslyn.Utilities.Sources"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add ANcpLua.Roslyn.Utilities.Sources --version 2.0.2
#r "nuget: ANcpLua.Roslyn.Utilities.Sources, 2.0.2"
#:package ANcpLua.Roslyn.Utilities.Sources@2.0.2
#addin nuget:?package=ANcpLua.Roslyn.Utilities.Sources&version=2.0.2
#tool nuget:?package=ANcpLua.Roslyn.Utilities.Sources&version=2.0.2
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
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.2 | 0 | 4/21/2026 |
| 2.0.1 | 0 | 4/21/2026 |
| 2.0.0 | 0 | 4/21/2026 |
| 1.56.1 | 72 | 4/21/2026 |
| 1.56.0 | 30 | 4/21/2026 |
| 1.55.0 | 32 | 4/21/2026 |
| 1.54.1 | 144 | 4/20/2026 |
| 1.54.0 | 56 | 4/20/2026 |
| 1.53.3 | 95 | 4/20/2026 |
| 1.53.2 | 63 | 4/19/2026 |
| 1.53.1 | 64 | 4/19/2026 |
| 1.53.0 | 206 | 4/18/2026 |
| 1.52.1 | 64 | 4/18/2026 |
| 1.52.0 | 81 | 4/15/2026 |
| 1.51.1 | 145 | 4/12/2026 |
| 1.51.0 | 172 | 4/3/2026 |
| 1.50.0 | 99 | 4/3/2026 |
| 1.49.0 | 106 | 4/2/2026 |
| 1.48.0 | 190 | 3/20/2026 |
| 1.47.0 | 167 | 3/12/2026 |