feat!: narrow indexer surfaces with more than four keys - #832
Conversation
The accessor narrowing introduced for indexers (#830) stopped at four keys: the narrowed setup/verify types only ship with the library for arities 1-4, so a five-key get-only indexer still offered OnSet and Verify[...].Set(...), which compiled and silently did nothing. Since the setup types for indexers with more than four keys are generated per-compilation anyway, generate the narrowed surface there too: - IndexerSetups.g.cs now emits IIndexerGetterOnlySetup / IIndexerSetterOnlySetup interface hierarchies (builders included) for each affected arity, implements them on the generated IndexerSetup class, and adds the Forever/OnlyOnce extensions for the narrowed when-builders. - Narrowed VerificationIndexerGetterResult / -SetterResult classes are generated in Mockolate.Verify, dispatching through the predicate-based MockRegistry.IndexerGot/IndexerSet overloads that the full VerificationIndexerResult already uses above four keys. Each takes only the member id and predicate of the accessor it exposes. - The facade selection in the mock emission now uses the plain accessor classification for every arity; the narrowed hierarchies are only generated for arities that need them, keyed on the same Getter/Setter nullity that guards body emission. BREAKING CHANGE: on an indexer with more than four keys that the mock reads or writes but not both, Setup[...].OnSet/OnGet, Setup[...].Returns/Throws/InitializeWith and Verify[...].Set(...)/Got() no longer compile for the absent accessor. Each previously compiled and silently had no effect. This closes the gap the four-key narrowing left; the shipped library API is unchanged.
Test Results 24 files ± 0 24 suites ±0 11m 31s ⏱️ + 1m 37s Results for commit 85643c1. ± Comparison against base commit d2f56ed. This pull request removes 2 and adds 24 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
🚀 Benchmark ResultsDetails
Details
Details
Details
Details
Details
|
The generated VerificationIndexerSetterResult for indexers with more than four keys described the expected value with It.Is(value, value?.ToString() ?? "null"). That renders strings unquoted, formats IFormattable values with the current culture instead of the invariant one, and builds the description even when the verification passes. It.IsValue is the matcher the generator already emits for by-value parameters elsewhere, and it exists precisely because generated code cannot see the internal CallerArgumentExpression polyfill the shipped result relies on. It defers formatting to the failure path and renders quoted, invariant values, so a literal now reads the same above four keys as it does on the shipped one-to-four key surface. Also: - Pass the collected IndexerSetupKey array straight into Sources.IndexerSetups instead of rebuilding a Dictionary in the source-output callback. The sorted order from CollectIndexerSetupKeys becomes the only ordering in play, and the repeated tuple type disappears from both files. Generated output is unchanged. - Cover the generated narrowed delegations at five keys: Throws, InitializeWith, SkippingBaseClass, the return-builder When, and OnGet/OnSet with OnlyOnce, When, InParallel, For, the access-counter Do overload and TransitionTo on both facades, plus the rendered expectation string. - Drop the doc sentence about where the narrowed types come from.
|
…e than four keys (#832) by Valentin Breuß
…e than four keys (#832) by Valentin Breuß
|
This is addressed in release v3.4.0. |

The accessor narrowing introduced for indexers (#830) stopped at four keys: the narrowed setup/verify types only ship with the library for arities 1-4, so a five-key get-only indexer still offered OnSet and Verify[...].Set(...), which compiled and silently did nothing.
Since the setup types for indexers with more than four keys are generated per-compilation anyway, generate the narrowed surface there too:
BREAKING CHANGE: on an indexer with more than four keys that the mock reads or writes but not both, Setup[...].OnSet/OnGet, Setup[...].Returns/Throws/InitializeWith and Verify[...].Set(...)/Got() no longer compile for the absent accessor. Each previously compiled and silently had no effect. This closes the gap the four-key narrowing left; the shipped library API is unchanged.