@@ -33,6 +33,19 @@ public MemberAutoNSubstituteDataAttribute(string memberName, params object[] par
3333 /// </summary>
3434 public object [ ] Parameters { get ; }
3535
36+ /// <summary>
37+ /// Produces the final theory data rows by merging member-supplied data with AutoFixture generated specimens.
38+ /// </summary>
39+ /// <param name="testMethod">The target test method whose parameters drive specimen generation.</param>
40+ /// <param name="disposalTracker">xUnit disposal tracker (unused directly here but required by override).</param>
41+ /// <returns>Augmented data rows containing original values plus generated specimens.</returns>
42+ /// <remarks>
43+ /// Processing for each source row:
44+ /// 1. Create an isolated fixture.
45+ /// 2. Apply frozen injection logic (positional + promotion) before resolving additional parameters.
46+ /// 3. Generate remaining parameters using <see cref="GetSpecimen(IFixture, ParameterInfo)"/>.
47+ /// 4. Preserve original row metadata (label, skip, etc.).
48+ /// </remarks>
3649 public override async ValueTask < IReadOnlyCollection < ITheoryDataRow > > GetData (
3750 MethodInfo testMethod ,
3851 DisposalTracker disposalTracker )
@@ -73,6 +86,18 @@ public override async ValueTask<IReadOnlyCollection<ITheoryDataRow>> GetData(
7386 return augmented ;
7487 }
7588
89+ /// <summary>
90+ /// Builds a delegate that performs two-phase frozen value handling for the supplied test method parameters.
91+ /// </summary>
92+ /// <param name="parameters">Ordered parameter list from the test method.</param>
93+ /// <returns>An action taking (suppliedRowValues, fixture) which injects any frozen instances.</returns>
94+ /// <remarks>
95+ /// Phase 1 (Direct): For each parameter marked with <see cref="FrozenAttribute"/>, if the member row already
96+ /// supplies a value at the same index, that instance is injected (frozen) into the fixture.
97+ /// Phase 2 (Promotion): For frozen parameters whose index exceeds the supplied row length, the earliest
98+ /// previously supplied compatible instance (assignable type) is promoted and injected. This enables scenarios
99+ /// where the developer supplies a value earlier and later annotates a parameter of the same type with [Frozen].
100+ /// </remarks>
76101 private static Action < object ? [ ] , IFixture > BuildFrozenInjector ( ParameterInfo [ ] parameters )
77102 {
78103 // Identify parameters decorated with [Frozen]; capture index + type for later injection/promotion.
@@ -122,6 +147,16 @@ public override async ValueTask<IReadOnlyCollection<ITheoryDataRow>> GetData(
122147 } ;
123148 }
124149
150+ /// <summary>
151+ /// Resolves a specimen for a single parameter after applying any parameter-level customizations.
152+ /// </summary>
153+ /// <param name="fixture">The fixture instance configured for the current data row.</param>
154+ /// <param name="parameter">The reflective description of the theory method parameter.</param>
155+ /// <returns>The resolved object instance to be injected into the theory invocation.</returns>
156+ /// <remarks>
157+ /// Customizations are applied in a deterministic order with non-frozen customizations first, ensuring
158+ /// that <see cref="FrozenAttribute"/> observes the final constructed form when freezing an instance.
159+ /// </remarks>
125160 private static object GetSpecimen (
126161 IFixture fixture ,
127162 ParameterInfo parameter )
0 commit comments