refactor(generator): split CliParserGenerator.cs into partial files and decompose oversized methods - #69
Merged
Conversation
…nContext expansion path The SourceProductionContext-based registration path (ExpandTypeRegistration, ExpandMapStringDelegate, ExpandMapRootCommand, AddMethodsFromType) was superseded when analysis moved into the incremental Select step (DiagnosticAccumulator path) but was never deleted. Removes it along with its byte-for-byte validator twins (ReportDuplicateCliNames, ReportBoolNegationSwitchConflicts, ValidateExpandedParameterLayout, ValidateVariadicPositionalIsLast) and the three FlattenAsParametersType(context) overloads. Also removes the SourceProductionContext overloads of CommandModel.FromMethod/FromRootMethod and BuildParameterModels. Follow-on simplification: drops SourceProductionContext? reportCtx from all ParameterModel.From* factory signatures and simplifies ReportFilesystemPathAttributeIssues to a single DiagnosticAccumulator? acc path, removing the nested ReportFilesystemDiag/ ReportFilesystemDiagTwo helpers. Generated output is bit-identical; all 202 tests pass. Also enables EmitCompilerGeneratedFiles in Tests.CliHost temporarily for baseline diffing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CliParserGenerator.cs drops from 11 105 lines to 279 — the incremental pipeline wiring only. Content moves wholesale into focused partial files under src/Nullean.Argh.Generator/: .Diagnostics.cs — AGH0001-33 descriptors, DiagnosticAccumulator .Models.cs — RegistryNode, AppEmitModel, AI* records, enums .Analysis.cs — AnalyzeInvocation, TryBuildAppEmitModel, expansion helpers .SymbolReaders.cs — attribute/type interrogation, options-model builders .Validation.cs — ReportBool*, ReportDuplicate*, ReadValidationConstraints .Emit.Dispatch.cs — EmitEmpty, EmitApp, EmitHierarchical, dispatch/route emitters .Emit.Dto.cs — DtoBindingTarget, EmitDtoBindingMethods, EmitDtoTypeExtensions .Emit.Parsing.cs — EmitOptionsTryParse, EmitValidationChecks, EmitCommandRunner .Emit.Runner.cs — EmitCommandRunner through EmitLambdaInvocation, flag helpers .Emit.Help.cs — EmitCommandHelpPrinter, EmitHelpOptionRows*, UsageSynopsis .Documentation.cs — TryExtract* doc helpers, TransformRemarksInnerXml .CommandModel.cs — CommandModel record and ParseOptionsFlagDocumentation .ParameterModel.cs — ParameterModel record and factories .Naming.cs — Escape*, OptionsStaticFieldName*, Naming static class Pure mechanical split — generated output is bit-identical (verified by diffing ArghGenerated.g.cs against the Phase 1 baseline). All 294 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t-check helpers The 330-line flat switch over ValidationConstraint subtypes becomes a 14-line dispatch table. Each arm is extracted into an Emit<X>ConstraintCheck private static method following the EmitCollectionFilesystemValidation signature pattern (sb, [constraint,] p, cliName, varName, failureExit, flagHelpStdErr, runHint). The outer loop removes the isNullable/isNullableValueType locals; each helper derives them from p instead. Generated output is bit-identical. All 302 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nd helpers The 326-line method becomes a flat if-chain dispatch of 8 guards. Each scalar-kind branch is extracted to a private static helper matching the existing EmitNullableNumericParseFromString / EmitNullableTemporalParseFromString signature convention (sb, p, rawExpr, targetVar, ind, outVarKeyword, failureExit, helpMethodName, flagHelpStdErrMethodName, parseFailureRunHint): EmitEnumParseFromString — enum switch-case block (~27 lines) EmitFileInfoParseFromString — optional/required FileInfo (~42 lines) EmitDirectoryInfoParseFromString — optional/required DirectoryInfo (~42 lines) EmitUriParseFromString — optional/required Uri (~38 lines) EmitCustomParserFromString — IArgumentParser<T> adapter (~15 lines) EmitPrimitiveScalarParseFromString — non-nullable scalar switch (~136 lines) Generated output is bit-identical. All 302 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Temporary property added for baseline diff capture during Phase 2 split is no longer needed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Summary
CliParserGenerator.cswas 11,717 lines — the largest file in the repo by a factor of 20. This PR eliminates the outlier without any behaviour change.SourceProductionContext-based registration path (ExpandTypeRegistrationand everything it reached transitively) was superseded by theDiagnosticAccumulatorincremental path but never removed. Its non-Accvalidator twins were an active sync hazard; they're gone.partial classfiles under the existingCliParserGenerator.<Area>.csconvention (.Schema.csand.Completion.cswere already there).CliParserGenerator.csitself is now ~280 lines of pipeline wiring.EmitValidationChecks(330 → 59 lines, 14 extractedEmit*ConstraintCheckhelpers) andEmitParseFromString(326 → ~30 lines, 6 extracted per-scalar-kind helpers). Both follow the shape of helpers that already existed in the file (EmitCollectionFilesystemValidation,EmitNullableNumericParseFromString, etc.).Verification
All phases were verified bit-identical against a baseline
ArghGenerated.g.cscaptured before any changes (zero diff except the version hash line). Full test suite (302 tests) passes at each commit.File layout after this PR
CliParserGenerator.cs.Diagnostics.csDiagnosticAccumulator.Models.cs.Analysis.csAnalyzeInvocation,TryBuildAppEmitModel.SymbolReaders.cs.Validation.csValidationConstrainthierarchy + validators.Emit.Dispatch.cs.Emit.Dto.cs.Emit.Help.cs.Emit.Parsing.cs.Emit.Runner.cs.Documentation.cs.Naming.csNamingstatic class + escape helpers.CommandModel.csCommandModelrecord.ParameterModel.csParameterModelrecord + factoriesTest plan
dotnet build -c Release— 0 errors at each commitdotnet test -c Release --logger:pretty— 302 tests pass at each commitArghGenerated.g.csdiff vs baseline — empty at each commit./build.sh release— build + test + pack all pass (validatepackages fails on a pre-existingSystem.Reactiveenv issue unrelated to this PR)🤖 Generated with Claude Code