Repository navigation
Move CodeGen/ into a shared source-generator toolkit package #192
Description
Activity
matt-edmondson commented
on Aug 27, 2026 ContributorAuthorMore actionsDecision recorded: (a), a new
ktsu-dev/SourceGeneratorToolkitrepoPer the acceptance criteria, the packaging decision is (a). The reasoning in the issue holds:
ktsu.CodeBlockerships eight target frameworks down tonetstandard2.0with one small dependency, and coupling its release cadence to Roslyn's — which moves fast enough that this code pinsMicrosoft.CodeAnalysis5.9 — is the wrong trade.The extraction is done and verified. I can't create the repo.
create_repositoryagainst the org returns:POST https://api.github.com/orgs/ktsu-dev/repos: 403 Resource not accessible by integrationSo the last step needs someone with org permissions. Everything up to it is finished, built and tested locally, and attached to the session as a tarball with the git history intact:
tar xzf SourceGeneratorToolkit.tar.gz cd SourceGeneratorToolkit git remote add origin https://github.com/ktsu-dev/SourceGeneratorToolkit.git git push -u origin main27 tests, 0 failures. Clean under the ktsu.Sdk analyzers and under the Sonar analyzers.
What moved
Exactly the table in the issue:
GeneratorBase.cs,MetadataFile.cs,DiagnosticCatalog.cs,CSharpKeywords.cs, andGeneratorHarness.cs. Namespacektsu.SourceGeneratorToolkit. Nothing physics-specific came with it, and the doc comments that referred to this repository's own history have been restated in terms the package can stand behind.GeneratorHarnessships in the package, not in its test project — a consumer testing their own generator needs it, and it carries theBundleAnalyzerDependencies=falseknowledge the issue flagged as worth not rediscovering.Decisions made along the way
ktsu.Sdk, not plainMicrosoft.NET.Sdk— the issue asked for this to be deliberate.Semantics.SourceGeneratorsisIsPackable=false; this one publishes, so it wants the SDK's packaging metadata and release pipeline.TargetFrameworksis overridden tonetstandard2.0only: a Roslyn component loads into the compiler, and the rest of the SDK's default set would be assemblies the analyzer host can't load.Microsoft.CodeAnalysis.*isPrivateAssets="all";ktsu.CodeBlockerandSystem.Text.Jsonare not — the analyzer host supplies Roslyn and a consuming generator references it at whatever version it builds against, but consumers write templates and models against the other two.- Four analyzer findings came with making these types public rather than internal, and are fixed rather than suppressed: two CA1062 argument guards, a cached
JsonSerializerOptionsfor CA1869, and a range instead ofSubstring.
Two things the repo will need that I couldn't do either
- NuGet publishing secrets. The copied
dotnet.ymlis the shared ktsu pipeline and expects the usual org secrets; I can't set those. MetadataFile.FindLocation's scoped overload is newer than what's onmainhere — it came from SEM001 and SEM003 report without a source location #193 (in Get ubuntu-latest green, and clear the three codegen follow-ups #197, unmerged). The extracted copy has it.
What's still open here
The repoint.
Semantics.SourceGeneratorscan't consume the package untilktsu.SourceGeneratorToolkit1.0.0 is on NuGet — the same sequencing #187 had withktsu.CodeBlocker1.3.0. Once it publishes, the change here is mechanical: add thePackageReference, deleteCodeGen/, deleteSemantics.Test/Quantities/GeneratorHarness.cs, and repoint theusing.Semantics.SourceGeneratorsis thenModels/,Metadata/,Generators/and the Semantics-specific bindings, which is the third acceptance criterion, and #181 can close.So: criterion 1 met, criteria 2–5 blocked behind creating the repo and publishing the package.
Generated by Claude Code
matt-edmondson commented
on Sep 8, 2026 ContributorAuthorMore actionsThe repo exists and the packages are published
ktsu-dev/SourceGeneratorToolkitwas created and filled. Both packages are live at 1.0.0:ktsu.SourceGeneratorToolkit—GeneratorBase/GeneratorBase<T>,MetadataFile/MetadataSet,DiagnosticCatalog/DiagnosticReporting,CSharpKeywordsktsu.SourceGeneratorToolkit.Testing—GeneratorHarness
The repoint here is #207.
One change from the plan recorded above: two packages, not one
The earlier comment said
GeneratorHarnessships in the package rather than in a test project. It does ship — but as a sibling package, not inside the analyzer one.GeneratorHarnessreads metadata off disk (Directory.GetFiles,File.ReadAllText). RS1035 bans exactly those APIs for code that runs in an analyzer host, andEnforceExtendedAnalyzerRulesis what turns that rule on. Putting the harness in the main package would have meant suppressing RS1035 project-wide — and that suppression would then also coverGeneratorBaseandMetadataFile, which genuinely do run inside the compiler. A future contributor adding a file read toGeneratorBasewould get no warning.Splitting keeps the rule on where it matters and off where it doesn't. The intent of the original decision is preserved: a consumer testing their own generator gets the harness from NuGet rather than rediscovering it, and it still carries the
BundleAnalyzerDependencies=falseknowledge — documented in the type's own XML docs and in the README.Acceptance criteria
- Packaging decision made and recorded — (a), a new repo, as decided above.
-
CodeGen/andGeneratorHarnesslive in the chosen package; this repository consumes them (Consume the extracted source-generator toolkit from its package #207). -
Semantics.SourceGeneratorscontains onlyModels/,Metadata/,Generators/and the Semantics-specific bindings (SemanticsGenerator,SemanticsDiagnostics, the physics half ofEmit). - Generated output under
Semantics.Quantities/Generated/unchanged — byte-identical,git statusclean after a full rebuild. - Epic: extract and generalize the code generation stack so other projects can share it #181 can be closed.
Decisions taken along the way
ktsu.Sdk, not plainMicrosoft.NET.Sdk— the issue asked for this to be deliberate.Semantics.SourceGeneratorsisIsPackable=false; these publish, so they want the SDK's packaging metadata and release pipeline.TargetFrameworksis overridden tonetstandard2.0only: a Roslyn component loads into the compiler, and the SDK's default set would be assemblies the analyzer host cannot load.Microsoft.CodeAnalysis.*andSystem.Collections.ImmutablearePrivateAssets="all";ktsu.CodeBlockerandSystem.Text.Jsonare not. Verified against the built.nuspec: the main package's only dependencies arektsu.CodeBlocker,System.Text.Json,System.MemoryandSystem.Threading.Tasks.Extensions. No Roslyn dependency flows.- Analyzer findings from making the types public were fixed, not suppressed —
Ensure.NotNullguards, a cachedJsonSerializerOptions(CA1869), a range instead ofSubstring, andMetadataSetconverted from a primary constructor so its guard could run.
39 tests, 0 failures; clean under both the ktsu.Sdk analyzers and the Sonar analyzers.
Two things that bit, worth recording
icon.pngis LFS-tracked. git-lfs was not installed in the environment that made the first commit, so what landed was the pointer text with no object behind it, and every checkout withlfs: truefailed. Fixed by installing git-lfs and pushing the object.- Dependabot auto-merged a bump mid-run. A
System.Collections.Immutable10.0.1 → 10.0.11 PR merged while the first pipeline was being re-run, so the release job tried to push its metadata commit onto amainthat had moved and was rejected non-fast-forward. Re-running a run pinned to a stale SHA cannot fix that — the pipeline had to be dispatched afresh on the current tip.
Generated by Claude Code
- added a commit that references this issue
on Sep 15, 2026
Summary
The last outstanding piece of #181.
Semantics.SourceGenerators/CodeGen/holds the Roslyn-side infrastructure that has nothing to do with physical quantities. It is already shaped for extraction — a one-way dependency, nothing physics-specific, public where it needs to be — but it still lives in this repository, so a second project cannot use it without depending onktsu.Semantics.Until this lands, #181's definition of done is not met.
What moves
CodeGen/GeneratorBase.csIIncrementalGeneratorbase driven by N JSON metadata files supplied asAdditionalFiles; finds them, hands them toGenerate, reports anything missing or malformedCodeGen/MetadataFile.csMetadataFile/MetadataSet— deserialization, andFindLocationfor pointing a diagnostic at a position in the metadataCodeGen/DiagnosticCatalog.csReport/ReportAthelpersCodeGen/CSharpKeywords.csEmitSemantics.Test/Quantities/GeneratorHarness.csCSharpGeneratorDriverharness — supplies metadata the way MSBuild does, and can run a generator twice to check it reuses its outputWhat stays:
Models/,Metadata/,Generators/,SemanticsDiagnostics,SemanticsGenerator/SemanticsMultiFileGenerator, and the Semantics-specific half ofEmit.The decision this needs first
ktsu-dev/SourceGeneratorToolkitrepo — recommended. Keeps the Roslyn dependency and the analyzer-packaging rules (IsRoslynComponent,EnforceExtendedAnalyzerRules, theGetDependencyTargetPathsbundling target) out ofktsu.CodeBlocker, which ships 8 target frameworks down tonetstandard2.0and has one small dependency.CodeBlockerrepo (ktsu.CodeBlocker.SourceGenerators) — fewer repos, but couples CodeBlocker's release cadence to Roslyn's, and Roslyn moves fast enough that this repository already pinsMicrosoft.CodeAnalysis5.9.Notes for whoever picks it up
SemanticsGenerator<T>binds the diagnostic catalogue and the file header in one place. A second consumer writes its own equivalent — that is the seam, and it should stay.WriteFileHeader/WriteSourceFiletake the copyright as a parameter rather than hard-coding it, so nothing about this repository leaks into the package.AdditionalProperties="BundleAnalyzerDependencies=false", or the bundlednetstandard2.0facades collide with the in-box types (CS0433 onReadOnlySpan<T>,Vector4, and friends).Semantics.SourceGenerators.csprojuses<Project Sdk="Microsoft.NET.Sdk">rather than ktsu.Sdk. Worth deciding deliberately whether the new package follows suit.Acceptance criteria
CodeGen/andGeneratorHarnesslive in the chosen package; this repository consumes them.Semantics.SourceGeneratorscontains onlyModels/,Metadata/,Generators/and the Semantics-specific bindings.Semantics.Quantities/Generated/unchanged (Generated files up to datestays green).Context
Part of #181. #182 shaped this code for extraction; #187 removed the template half of it into
ktsu.CodeBlocker1.3.0. This is the remainder.