Add net10 Solution.g codegen console + toggle (groundwork to free the SourceGenerators ns2.0 cone)#442
Open
ChrisonSimtian wants to merge 9 commits into
Conversation
First half of freeing the Fallout.SourceGenerators dependency cone (issue Fallout-build#441, Lever 1): introduce a net10 pre-build codegen path for the strongly-typed [Solution] accessor as the future default, with the in-compiler generator retained as the toggle fallback. - src/shared/SolutionEmitter.cs: the Scriban emit logic extracted out of StronglyTypedSolutionGenerator into a single shared source file, linked into BOTH the generator and the new console so they emit byte-identical Solution.g.cs. - StronglyTypedSolutionGenerator: refactored to call SolutionEmitter (behaviour unchanged — still the in-IDE/live fallback). - src/Fallout.Solution.Codegen: net10 console that discovers [Solution(GenerateProjects = true)] members by parsing the build project's .cs syntactically (no compilation available pre-build), reads the solution with the real Fallout.Persistence.Solution parser (no parsing-parity risk), and emits via the shared emitter. Verified end-to-end against this repo's own build/Build.cs + fallout.slnx — output matches the generator. - AssemblyInfo: IVT for the console (it uses Build.Shared's internal Constants). Remaining (next commits on this branch): the packaged pre-build MSBuild target + FalloutSolutionCodegenMode toggle (default = console; suppress the generator in console mode), dogfood-build wiring, and — as the deliberate follow-up — dropping the now-removable cone refs from Fallout.SourceGenerators once the fallback is retired/cone-freed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…1, steps 1-2) - StronglyTypedSolutionGenerator self-suppresses when FalloutSolutionCodegenMode == Build (reads it via CompilerVisibleProperty), so exactly one path emits. - src/Fallout.Solution.Codegen/build/Fallout.Solution.Codegen.targets: reusable pre-build target that runs the console (via FalloutSolutionCodegenProject or a published FalloutSolutionCodegenAssembly), writes <Member>.g.cs into obj/, and includes it. Exposes the toggle to the fallback generator. - build/_build.csproj: dogfoods the console path (FalloutSolutionCodegenMode=Build). Verified: the target runs the console, emits Solution.g.cs from fallout.slnx, the generator suppresses, and _build compiles (0 errors). Full fallout.slnx build green. Default is unchanged for everyone else (generator runs unless a project opts into Build), so this is non-breaking. Remaining follow-ups: ship the console + targets in the consumer package and flip the default to Build, then drop the now-removable cone refs from Fallout.SourceGenerators. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…allout.Solution.Codegen project The generator's output for fallout.slnx now includes the new Fallout.Solution.Codegen project; the only snapshot change is that one accessor line (confirming the shared-emitter refactor preserved output). BOM stripped to match the repo's no-BOM verified convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3 tasks
Contributor
There was a problem hiding this comment.
Pull request overview
Groundwork for issue #441 by introducing a net10 pre-build codegen path for the strongly-typed [Solution] accessor (Solution.g.cs), sharing a single emitter between the console path and the Roslyn generator fallback, and dogfooding the build-path in build/_build.csproj.
Changes:
- Add
Fallout.Solution.Codegen(net10 console) + MSBuild.targetsto generate*.g.csbefore compile whenFalloutSolutionCodegenMode=Build. - Extract shared Scriban emit logic to
src/shared/SolutionEmitter.csand link it into both the console andStronglyTypedSolutionGenerator. - Update solution + Verify snapshot and wire the dogfood build to use the new build-time codegen path.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Fallout.SourceGenerators.Specs/StronglyTypedSolutionGeneratorSpecs.Test#Solution.g.verified.cs | Snapshot update reflecting the new Fallout.Solution.Codegen project presence. |
| src/shared/SolutionEmitter.cs | New shared emitter used by both generator and console to keep output byte-identical. |
| src/Fallout.SourceGenerators/StronglyTypedSolutionGenerator.cs | Refactor onto shared emitter + self-suppress when FalloutSolutionCodegenMode=Build. |
| src/Fallout.SourceGenerators/Fallout.SourceGenerators.csproj | Link in shared emitter source file. |
| src/Fallout.Solution.Codegen/Program.cs | New net10 console that syntactically discovers [Solution(GenerateProjects=true)] and emits *.g.cs. |
| src/Fallout.Solution.Codegen/Fallout.Solution.Codegen.csproj | New net10 console project + linked emitter + references/packages. |
| src/Fallout.Solution.Codegen/build/Fallout.Solution.Codegen.targets | New MSBuild target to run the console pre-build and include generated sources. |
| fallout.slnx | Adds the new Fallout.Solution.Codegen project to the repo solution. |
| build/_build.csproj | Dogfoods the console path (Mode=Build) and imports the new targets. |
| AssemblyInfo.cs | Adds InternalsVisibleTo("Fallout.Solution.Codegen"). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Extract the syntactic [Solution] discovery out of Program into a testable SolutionMemberDiscovery, and tighten it to match the symbol-based generator: - Match the attribute by its rightmost name segment so qualified/aliased usages ([Fallout.Solutions.Solution], [Solutions.Solution], [global::...Attribute]) are recognised, not just the bare [Solution]/[SolutionAttribute]. - Accept the relativePath constructor argument written positionally or as 'relativePath:' (NameColon). - Prune bin/obj/hidden directories in the bare --root fallback scan instead of walking AllDirectories. - Delete any existing *.g.cs in the output directory before emitting, so a removed or renamed [Solution] member can't leave an orphan that still compiles. GenerateProjects/FancyNames stay NameEquals-only on purpose: they are settable properties, so '=' is the only valid syntax. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Unit tests for SolutionMemberDiscovery: rightmost-segment attribute matching, positional vs. relativePath: arguments, FancyNames, property vs. field members, and the negatives (GenerateProjects=false, unrelated attributes). Wires the new project into fallout.slnx and InternalsVisibleTo. The generator Verify snapshot gains one accessor line for the newly-added test project (the generator enumerates the real solution). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the discover -> resolve -> emit loop out of Program's top-level statements into a testable SolutionCodegenRunner; Program is now a thin arg-parsing shell. This puts the previously untested output side-effects under test: - emits the accessor for a discovered member against a real (minimal) .slnx - clears stale *.g.cs before emitting (orphan removal) - removes all outputs when no member remains Also adds a test for EnumerateProjectSources confirming bin/obj/hidden dirs are pruned from the bare --root fallback scan. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The emitter was linked-source into both the Roslyn generator and the net10 console via a src/shared/ directory. Promote it to a proper multi-targeted project, Fallout.Solution.Codegen.Emit (netstandard2.0;net10.0), that both reference: - netstandard2.0 so the in-compiler StronglyTypedSolutionGenerator (also ns2.0) can reference it; its DLL is bundled into the analyzer via the existing GetDependencyTargetPaths mechanism. - net10.0 so the console gets a modern build. When the generator fallback is retired (Fallout-build#441), the ns2.0 target can simply be dropped. SolutionEmitter becomes public (it now crosses an assembly boundary). Scriban moves to the emit project and reaches the console transitively. No /shared. It stays a dedicated codegen library rather than folding into Fallout.Solution: the emitter pulls in Scriban, which shouldn't leak into everything that consumes the Solution model. Output is still byte-identical (the generator Verify snapshot passes; the one delta is the new project's own accessor line). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fills the gaps in the previously thin spots: - Generator self-suppression: asserts the in-compiler generator no-ops when FalloutSolutionCodegenMode=Build (case-insensitive) and still emits otherwise. This is the toggle that guarantees exactly one path emits Solution.g.cs. - Parameters-file fallback: the runner resolves a [Solution] member with no path argument via .fallout/parameters.json. - Multiple members: discovery and the runner both handle more than one [Solution(GenerateProjects = true)] member, emitting one file each. - Emitter escaping: dotted project names become valid identifiers, and names starting with a digit get an underscore prefix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2 tasks
Adds a spec exercising the recursive folder declaration (Unsafe.As / nested SolutionFolder class) — previously only covered transitively by the generator snapshot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ITaluone
approved these changes
Jul 1, 2026
Collaborator
Author
|
@dennisdoomen this one would be good, groundwork PR for other stuff |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Groundwork for #441 (move the Roslyn generator off the netstandard2.0 floor). Adds a net10 pre-build codegen path for the strongly-typed
[Solution]accessor so the in-compiler generator can eventually shed itsSolution/Persistence/Utilities/Globbingdependency cone. Non-breaking and dogfooded.What changed
Fallout.Solution.Codegen(net10 console) — discovers[Solution(GenerateProjects = true)]syntactically (no compilation pre-build), reads the solution with the realFallout.Persistence.Solutionparser, emits<Member>.g.cs.Fallout.Solution.Codegen.Emit(newnetstandard2.0;net10.0project) — the shared emitter, referenced by both the console and the generator. Replaces the oldsrc/shared/linked-source hack; output stays byte-identical. Bundled into the analyzer via the existingGetDependencyTargetPaths.StronglyTypedSolutionGenerator— self-suppresses whenFalloutSolutionCodegenMode == Build; otherwise unchanged, so it remains the in-IDE fallback.Fallout.Solution.Codegen.targets— reusable pre-build target + toggle plumbing (FalloutSolutionCodegenProjectin-repo, orFalloutSolutionCodegenAssemblyfor packaged consumers).build/_build.csproj— dogfoods the console path (Mode=Build).Fallout.Solution.Codegen.Specscovers discovery (qualified/aliased names,relativePath:, properties/fields, multiple members, negatives), the emit pipeline, stale-output removal, the parameters-file fallback, and identifier escaping; plus generator self-suppression specs. Discovery also prunesbin/obj/hidden in the bare---rootfallback scan.Why
The generator parses solutions at compile time, which forces the parser cone to
netstandard2.0. Moving codegen to a net10 console lets the generator later drop those refs. Shipped as non-breaking groundwork: both paths coexist (toggle-gated), so consumers are untouched until the console ships in the NuGet.Verification
fallout.slnxbuild: 0 errors.Fallout.Solution.Codegen.Specs25/25,Fallout.SourceGenerators.Specs10/10 (incl. the generator Verify snapshot)._build: console emitsSolution.g.cs→ generator suppresses → compiles.Part of #441.
Follow-ups (not here)
.EmitDLL) in the consumer NuGet (build/), flip the consumer default toBuild, then drop the generator's cone refs (freesSolution/Utilitiesto net10) and the.Emitns2.0 target..targetshappy path is covered by the dogfood_build(+ Fallout.Canary), not an automated spawn-build test.--sourceon oneExecline; a very largeMode=Buildconsumer could hit the Windows ~32K command-line limit (the--rootfallback mitigates). Batch/response-file if that ever bites.FancyNamesis currently dead code — tracked in [Solution] FancyNames option is dead code #445.