Skip to content

Commit d4e3593

Browse files
authored
fix: resolve build and analyzer issues (#252)
Build - Remove the redundant ReactiveUI.Primitives R3 bridge generator from the test compilation to prevent generated attribute conflicts. - Fix analyzer findings in the ReactiveList library, tests, benchmarks, and ReactiveListTestApp without adding suppressions. - Keep ReactiveUI.Primitives analyzers private to the library package reference where they are only needed during the library build. Tests - Replace the local FluentAssertions shim with analyzer-friendly TUnit assertion extensions. - Add targeted coverage for quaternary collection overload branches and Reactive2DList constructor paths. - Preserve INPC/INCC and reactive collection behavior while expanding multi-target test coverage. Performance - Update benchmark coverage and cleanup for observable isolation, quaternary collections, and parity benchmarks. Verification - build.cmd Compile --configuration Release passed with 0 warnings and 0 errors. - dotnet build src/ReactiveList.sln passed in Debug and Release with 0 warnings and 0 errors. - MTP/TUnit tests passed in Debug and Release across all target frameworks. - Cobertura coverage reports ReactiveList line coverage at 100.00 percent.
1 parent 51529a3 commit d4e3593

79 files changed

Lines changed: 3267 additions & 3177 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/ReactiveList.Benchmarks/BenchmarkObservableExtensions.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,42 @@
66

77
namespace ReactiveList.Benchmarks;
88

9+
/// <summary>Provides BenchmarkObservableExtensions.</summary>
910
internal static class BenchmarkObservableExtensions
1011
{
11-
public static IDisposable SubscribeObserver<T>(this IObservable<T> source, Action<T> onNext)
12+
/// <summary>Provides observable benchmark helpers.</summary>
13+
/// <typeparam name="T">The observable item type.</typeparam>
14+
/// <param name="source">The source observable.</param>
15+
extension<T>(IObservable<T> source)
1216
{
13-
ArgumentNullException.ThrowIfNull(source);
14-
ArgumentNullException.ThrowIfNull(onNext);
17+
/// <summary>Subscribes an action observer.</summary>
18+
/// <param name="onNext">The next-value handler.</param>
19+
/// <returns>The subscription disposable.</returns>
20+
public IDisposable SubscribeObserver(Action<T> onNext)
21+
{
22+
ArgumentNullException.ThrowIfNull(source);
23+
ArgumentNullException.ThrowIfNull(onNext);
1524

16-
return source.Subscribe(new ActionObserver<T>(onNext));
25+
return source.Subscribe(new ActionObserver<T>(onNext));
26+
}
1727
}
1828

29+
/// <summary>Provides ActionObserver.</summary>
30+
/// <typeparam name="T">The T type.</typeparam>
31+
/// <param name="onNext">The onNext value.</param>
1932
private sealed class ActionObserver<T>(Action<T> onNext) : IObserver<T>
2033
{
34+
/// <summary>Provides OnCompleted.</summary>
2135
public void OnCompleted()
2236
{
2337
}
2438

39+
/// <summary>Provides OnError.</summary>
40+
/// <param name="error">The error value.</param>
2541
public void OnError(Exception error) => ExceptionDispatchInfo.Capture(error).Throw();
2642

43+
/// <summary>Provides OnNext.</summary>
44+
/// <param name="value">The value.</param>
2745
public void OnNext(T value) => onNext(value);
2846
}
2947
}

src/ReactiveList.Benchmarks/DynamicDataParityBenchmarks.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,22 @@
1212

1313
namespace ReactiveList.Benchmarks;
1414

15+
/// <summary>Provides DynamicDataParityBenchmarks.</summary>
1516
[MemoryDiagnoser]
1617
public class DynamicDataParityBenchmarks
1718
{
19+
private int[] _data = [];
20+
21+
/// <summary>Gets or sets the item count.</summary>
1822
[Params(1_000, 10_000)]
1923
public int Count { get; set; }
2024

21-
private int[] _data = [];
22-
25+
/// <summary>Provides Setup.</summary>
2326
[GlobalSetup]
2427
public void Setup() => _data = Enumerable.Range(0, Count).ToArray();
2528

29+
/// <summary>Provides ReactiveList_Connect_Preloaded_InitialSnapshot.</summary>
30+
/// <returns>The result.</returns>
2631
[Benchmark]
2732
public int ReactiveList_Connect_Preloaded_InitialSnapshot()
2833
{
@@ -32,6 +37,8 @@ public int ReactiveList_Connect_Preloaded_InitialSnapshot()
3237
return total;
3338
}
3439

40+
/// <summary>Provides SourceList_Connect_Preloaded_InitialSnapshot.</summary>
41+
/// <returns>The result.</returns>
3542
[Benchmark]
3643
public int SourceList_Connect_Preloaded_InitialSnapshot()
3744
{
@@ -42,6 +49,8 @@ public int SourceList_Connect_Preloaded_InitialSnapshot()
4249
return total;
4350
}
4451

52+
/// <summary>Provides ReactiveList_FilterTransformSort.</summary>
53+
/// <returns>The result.</returns>
4554
[Benchmark]
4655
public int ReactiveList_FilterTransformSort()
4756
{
@@ -58,6 +67,8 @@ public int ReactiveList_FilterTransformSort()
5867
return total;
5968
}
6069

70+
/// <summary>Provides SourceList_FilterTransformSortBind.</summary>
71+
/// <returns>The result.</returns>
6172
[Benchmark]
6273
public int SourceList_FilterTransformSortBind()
6374
{
@@ -73,6 +84,8 @@ public int SourceList_FilterTransformSortBind()
7384
return bound.Count;
7485
}
7586

87+
/// <summary>Provides ReactiveList_INCC_AddRange_WithItemsSubscriber.</summary>
88+
/// <returns>The result.</returns>
7689
[Benchmark]
7790
public int ReactiveList_INCC_AddRange_WithItemsSubscriber()
7891
{
@@ -84,6 +97,8 @@ public int ReactiveList_INCC_AddRange_WithItemsSubscriber()
8497
return events;
8598
}
8699

100+
/// <summary>Provides SourceList_INCC_AddRange_WithBoundSubscriber.</summary>
101+
/// <returns>The result.</returns>
87102
[Benchmark]
88103
public int SourceList_INCC_AddRange_WithBoundSubscriber()
89104
{
@@ -98,6 +113,8 @@ public int SourceList_INCC_AddRange_WithBoundSubscriber()
98113
return events;
99114
}
100115

116+
/// <summary>Provides QuaternaryList_Stream_AddRange_DeliveryWait.</summary>
117+
/// <returns>The result.</returns>
101118
[Benchmark]
102119
public int QuaternaryList_Stream_AddRange_DeliveryWait()
103120
{
@@ -116,6 +133,8 @@ public int QuaternaryList_Stream_AddRange_DeliveryWait()
116133
return events;
117134
}
118135

136+
/// <summary>Provides SourceList_Stream_AddRange_Delivery.</summary>
137+
/// <returns>The result.</returns>
119138
[Benchmark]
120139
public int SourceList_Stream_AddRange_Delivery()
121140
{

src/ReactiveList.Benchmarks/ListBenchmarks.cs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,22 @@
99

1010
namespace ReactiveList.Benchmarks;
1111

12+
/// <summary>Provides ListBenchmarks.</summary>
1213
[MemoryDiagnoser]
1314
public class ListBenchmarks
1415
{
16+
private int[] _data = [];
17+
18+
/// <summary>Gets or sets the item count.</summary>
1519
[Params(100, 1_000, 10_000)]
1620
public int Count { get; set; }
1721

18-
private int[] _data = [];
19-
22+
/// <summary>Provides Setup.</summary>
2023
[GlobalSetup]
2124
public void Setup() => _data = Enumerable.Range(0, Count).ToArray();
2225

26+
/// <summary>Provides List_AddRange.</summary>
27+
/// <returns>The result.</returns>
2328
[Benchmark]
2429
public int List_AddRange()
2530
{
@@ -28,6 +33,8 @@ public int List_AddRange()
2833
return list.Count;
2934
}
3035

36+
/// <summary>Provides ReactiveList_AddRange.</summary>
37+
/// <returns>The result.</returns>
3138
[Benchmark]
3239
public int ReactiveList_AddRange()
3340
{
@@ -36,6 +43,8 @@ public int ReactiveList_AddRange()
3643
return list.Count;
3744
}
3845

46+
/// <summary>Provides SourceList_AddRange.</summary>
47+
/// <returns>The result.</returns>
3948
[Benchmark]
4049
public int SourceList_AddRange()
4150
{
@@ -44,6 +53,8 @@ public int SourceList_AddRange()
4453
return list.Count;
4554
}
4655

56+
/// <summary>Provides List_RemoveRange.</summary>
57+
/// <returns>The result.</returns>
4758
[Benchmark]
4859
public int List_RemoveRange()
4960
{
@@ -52,6 +63,8 @@ public int List_RemoveRange()
5263
return list.Count;
5364
}
5465

66+
/// <summary>Provides ReactiveList_RemoveRange.</summary>
67+
/// <returns>The result.</returns>
5568
[Benchmark]
5669
public int ReactiveList_RemoveRange()
5770
{
@@ -60,6 +73,8 @@ public int ReactiveList_RemoveRange()
6073
return list.Count;
6174
}
6275

76+
/// <summary>Provides SourceList_RemoveRange.</summary>
77+
/// <returns>The result.</returns>
6378
[Benchmark]
6479
public int SourceList_RemoveRange()
6580
{
@@ -69,6 +84,8 @@ public int SourceList_RemoveRange()
6984
return list.Count;
7085
}
7186

87+
/// <summary>Provides List_Clear.</summary>
88+
/// <returns>The result.</returns>
7289
[Benchmark]
7390
public int List_Clear()
7491
{
@@ -77,6 +94,8 @@ public int List_Clear()
7794
return list.Count;
7895
}
7996

97+
/// <summary>Provides ReactiveList_Clear.</summary>
98+
/// <returns>The result.</returns>
8099
[Benchmark]
81100
public int ReactiveList_Clear()
82101
{
@@ -85,6 +104,8 @@ public int ReactiveList_Clear()
85104
return list.Count;
86105
}
87106

107+
/// <summary>Provides SourceList_Clear.</summary>
108+
/// <returns>The result.</returns>
88109
[Benchmark]
89110
public int SourceList_Clear()
90111
{
@@ -94,20 +115,26 @@ public int SourceList_Clear()
94115
return list.Count;
95116
}
96117

118+
/// <summary>Provides List_Search.</summary>
119+
/// <returns>The result.</returns>
97120
[Benchmark]
98121
public bool List_Search()
99122
{
100123
var list = new List<int>(_data);
101124
return list.Contains(Count - 1);
102125
}
103126

127+
/// <summary>Provides ReactiveList_Search.</summary>
128+
/// <returns>The result.</returns>
104129
[Benchmark]
105130
public bool ReactiveList_Search()
106131
{
107132
using var list = new ReactiveList<int>(_data);
108133
return list.Contains(Count - 1);
109134
}
110135

136+
/// <summary>Provides SourceList_Search.</summary>
137+
/// <returns>The result.</returns>
111138
[Benchmark]
112139
public bool SourceList_Search()
113140
{
@@ -116,6 +143,8 @@ public bool SourceList_Search()
116143
return list.Items.Contains(Count - 1);
117144
}
118145

146+
/// <summary>Provides ReactiveList_Add_WithObserver.</summary>
147+
/// <returns>The result.</returns>
119148
[Benchmark]
120149
public int ReactiveList_Add_WithObserver()
121150
{
@@ -126,6 +155,8 @@ public int ReactiveList_Add_WithObserver()
126155
return total;
127156
}
128157

158+
/// <summary>Provides SourceList_Add_WithObserver.</summary>
159+
/// <returns>The result.</returns>
129160
[Benchmark]
130161
public int SourceList_Add_WithObserver()
131162
{
@@ -136,20 +167,26 @@ public int SourceList_Add_WithObserver()
136167
return total;
137168
}
138169

170+
/// <summary>Provides List_Filter.</summary>
171+
/// <returns>The result.</returns>
139172
[Benchmark]
140173
public int List_Filter()
141174
{
142175
var list = new List<int>(_data);
143176
return list.Where(x => x % 2 == 0).Count();
144177
}
145178

179+
/// <summary>Provides ReactiveList_Filter.</summary>
180+
/// <returns>The result.</returns>
146181
[Benchmark]
147182
public int ReactiveList_Filter()
148183
{
149184
using var list = new ReactiveList<int>(_data);
150185
return list.Where(x => x % 2 == 0).Count();
151186
}
152187

188+
/// <summary>Provides SourceList_Filter.</summary>
189+
/// <returns>The result.</returns>
153190
[Benchmark]
154191
public int SourceList_Filter()
155192
{
@@ -158,6 +195,8 @@ public int SourceList_Filter()
158195
return list.Items.Where(x => x % 2 == 0).Count();
159196
}
160197

198+
/// <summary>Provides ReactiveList_Connect.</summary>
199+
/// <returns>The result.</returns>
161200
[Benchmark]
162201
public int ReactiveList_Connect()
163202
{
@@ -168,6 +207,8 @@ public int ReactiveList_Connect()
168207
return total;
169208
}
170209

210+
/// <summary>Provides SourceList_Connect.</summary>
211+
/// <returns>The result.</returns>
171212
[Benchmark]
172213
public int SourceList_Connect()
173214
{
@@ -178,6 +219,8 @@ public int SourceList_Connect()
178219
return total;
179220
}
180221

222+
/// <summary>Provides ReactiveList_Connect_Preloaded.</summary>
223+
/// <returns>The result.</returns>
181224
[Benchmark]
182225
public int ReactiveList_Connect_Preloaded()
183226
{
@@ -187,6 +230,8 @@ public int ReactiveList_Connect_Preloaded()
187230
return total;
188231
}
189232

233+
/// <summary>Provides SourceList_Connect_Preloaded.</summary>
234+
/// <returns>The result.</returns>
190235
[Benchmark]
191236
public int SourceList_Connect_Preloaded()
192237
{
@@ -197,6 +242,8 @@ public int SourceList_Connect_Preloaded()
197242
return total;
198243
}
199244

245+
/// <summary>Provides ReactiveList_ReplaceAll.</summary>
246+
/// <returns>The result.</returns>
200247
[Benchmark]
201248
public int ReactiveList_ReplaceAll()
202249
{
@@ -206,6 +253,8 @@ public int ReactiveList_ReplaceAll()
206253
return list.Count;
207254
}
208255

256+
/// <summary>Provides SourceList_ReplaceAll.</summary>
257+
/// <returns>The result.</returns>
209258
[Benchmark]
210259
public int SourceList_ReplaceAll()
211260
{
@@ -220,6 +269,8 @@ public int SourceList_ReplaceAll()
220269
return list.Count;
221270
}
222271

272+
/// <summary>Provides ReactiveList_Move.</summary>
273+
/// <returns>The result.</returns>
223274
[Benchmark]
224275
public int ReactiveList_Move()
225276
{
@@ -228,6 +279,8 @@ public int ReactiveList_Move()
228279
return list.Count;
229280
}
230281

282+
/// <summary>Provides SourceList_Move.</summary>
283+
/// <returns>The result.</returns>
231284
[Benchmark]
232285
public int SourceList_Move()
233286
{
@@ -237,6 +290,8 @@ public int SourceList_Move()
237290
return list.Count;
238291
}
239292

293+
/// <summary>Provides ReactiveList_RemoveMany.</summary>
294+
/// <returns>The result.</returns>
240295
[Benchmark]
241296
public int ReactiveList_RemoveMany()
242297
{
@@ -245,6 +300,8 @@ public int ReactiveList_RemoveMany()
245300
return list.Count;
246301
}
247302

303+
/// <summary>Provides SourceList_RemoveMany.</summary>
304+
/// <returns>The result.</returns>
248305
[Benchmark]
249306
public int SourceList_RemoveMany()
250307
{

0 commit comments

Comments
 (0)