Skip to content

Commit

Permalink
Prevent diagnostics on .NET SDK 8.0.100 (#2049)
Browse files Browse the repository at this point in the history
Address collection expression diagnostics

In most cases, we now just use the new (C# 12.0) collection expression syntax. However, we've disabled IDE0305 because it makes suggestions that aren't an obvious improvement. It wants to rewrite use of ToArray() to be a collection expression. E.g. something.ToArray() would become [.. something]. Perhaps that will seem natural once we've all got used to spreads in collection expressions, but to me (idg10) today that looks odd.

Add comment explaining why we've disable IDE0290

Make UWP test runner use the same warning settings as everything else, except for CS0618, which a large number of tests appear to depend on.
  • Loading branch information
idg10 authored Nov 22, 2023
1 parent bd4fb9e commit 57e4c42
Show file tree
Hide file tree
Showing 55 changed files with 143 additions and 148 deletions.
18 changes: 15 additions & 3 deletions Rx.NET/Source/Directory.build.props
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<EnableNETAnalyzers>true</EnableNETAnalyzers>

<!--
Disable diagnostics:
Disabled diagnostics:
CA1001 - types holding disposable fields should implement IDisposable. See next item.
CA2213 - IDisposable types should Dispose any IDisposable fields. This rule finds over 600
examples! These are all in subtle multithreaded or async code. Some of them appear
Expand All @@ -74,9 +74,21 @@
IDE0056 - Use of index/range syntax - relevant types not available on all targets, so we can't
IDE0057 do this.
IDE0290 - Primary ctors. This diagnostic suggests them in a lot of places where we don't want
them. E.g., in most types with multiple constructors I find I prefer not to have
a primary ctor. Since this is all or nothing, we turn it off.
IDE0305 - Suggests Collection expressions in place of .ToArray. E.g, wants to change this:
_readyList.ToArray()
to this:
[.. readyList]
This won't improve performance as far as we know (sometimes a reason for using that
syntax), and it's not obviously an improvement in readability.
CA1510 - use ArgumentNullException.ThrowIf (not available on all targets)
CA1513 - use ObjectDisposedException.ThrowIf (not available on all targets)
-->
<!-- Get diagnostics back to the level that the .NET 5.0 SDK had for now. Fix these properly before release. -->
<NoWarn>$(NoWarn);CA1001;CA2213;IDE0056;IDE0057</NoWarn>
<NoWarn>$(NoWarn);CA1001;CA2213;CA1510;CA1513;IDE0056;IDE0057;IDE0290;IDE0305</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal class ColdObservable<T> : ITestableObservable<T>
{
private readonly TestScheduler _scheduler;
private readonly Recorded<Notification<T>>[] _messages;
private readonly List<Subscription> _subscriptions = new();
private readonly List<Subscription> _subscriptions = [];

public ColdObservable(TestScheduler scheduler, params Recorded<Notification<T>>[] messages)
{
Expand Down
4 changes: 2 additions & 2 deletions Rx.NET/Source/src/Microsoft.Reactive.Testing/HotObservable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ namespace Microsoft.Reactive.Testing
internal class HotObservable<T> : ITestableObservable<T>
{
private readonly TestScheduler _scheduler;
private readonly List<IObserver<T>> _observers = new();
private readonly List<Subscription> _subscriptions = new();
private readonly List<IObserver<T>> _observers = [];
private readonly List<Subscription> _subscriptions = [];
private readonly Recorded<Notification<T>>[] _messages;

public HotObservable(TestScheduler scheduler, params Recorded<Notification<T>>[] messages)
Expand Down
3 changes: 1 addition & 2 deletions Rx.NET/Source/src/Microsoft.Reactive.Testing/MockObserver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@ namespace Microsoft.Reactive.Testing
internal class MockObserver<T> : ITestableObserver<T>
{
private readonly TestScheduler _scheduler;
private readonly List<Recorded<Notification<T>>> _messages;
private readonly List<Recorded<Notification<T>>> _messages = [];

public MockObserver(TestScheduler scheduler)
{
_scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
_messages = new List<Recorded<Notification<T>>>();
}

public void OnNext(T value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public partial class LocalScheduler
/// Set of disposable handles to all of the current short term work Schedule calls,
/// allowing those to be cancelled upon a system clock change.
/// </summary>
private readonly HashSet<IDisposable> _shortTermWork = new();
private readonly HashSet<IDisposable> _shortTermWork = [];

/// <summary>
/// Threshold where an item is considered to be short term work or gets moved from
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,11 @@ private abstract class InvokeRecBaseState : IDisposable
{
protected readonly IScheduler Scheduler;

protected readonly CompositeDisposable Group;
protected readonly CompositeDisposable Group = [];

protected InvokeRecBaseState(IScheduler scheduler)
{
Scheduler = scheduler;
Group = new CompositeDisposable();
}

public void Dispose()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ namespace System.Reactive.Concurrency
//
public static partial class Scheduler
{
internal static Type[] Optimizations = {
internal static Type[] Optimizations =
[
typeof(ISchedulerLongRunning),
typeof(IStopwatchProvider),
typeof(ISchedulerPeriodic)
/* update this list if new interface-based optimizations are added */
};
];

/// <summary>
/// Returns the <see cref="ISchedulerLongRunning"/> implementation of the specified scheduler, or <c>null</c> if no such implementation is available.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ namespace System.Reactive.Concurrency
internal abstract class SchedulerWrapper : IScheduler, IServiceProvider
{
protected readonly IScheduler _scheduler;
private readonly ConditionalWeakTable<IScheduler, IScheduler> _cache;
private readonly ConditionalWeakTable<IScheduler, IScheduler> _cache =
#if NET472_OR_GREATER || NETSTANDARD2_0_OR_GREATER
new();
#else
[];
#endif

protected SchedulerWrapper(IScheduler scheduler)
{
_scheduler = scheduler;
_cache = new ConditionalWeakTable<IScheduler, IScheduler>();
}

protected SchedulerWrapper(IScheduler scheduler, ConditionalWeakTable<IScheduler, IScheduler> cache)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ internal sealed class MemberNotNullAttribute : Attribute
/// The field or property member that is promised to be not-null.
/// </param>
#pragma warning disable CA1019 // Define accessors for attribute arguments - this needs to be identical to the real type
public MemberNotNullAttribute(string member) => Members = new[] { member };
public MemberNotNullAttribute(string member) => Members = [member];
#pragma warning restore CA1019

/// <summary>Initializes the attribute with the list of field and property members.</summary>
Expand Down Expand Up @@ -125,7 +125,7 @@ public MemberNotNullWhenAttribute(bool returnValue, string member)
#pragma warning restore CA1019
{
ReturnValue = returnValue;
Members = new[] { member };
Members = [member];
}

/// <summary>Initializes the attribute with the specified return value condition and list of field and property members.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public sealed class CompositeDisposable : ICollection<IDisposable>, ICancelable
/// </summary>
public CompositeDisposable()
{
_disposables = new List<IDisposable?>();
_disposables = [];
}

/// <summary>
Expand Down Expand Up @@ -387,7 +387,7 @@ public IEnumerator<IDisposable> GetEnumerator()
/// method to avoid allocation on disposed or empty composites.
/// </summary>
private static readonly CompositeEnumerator EmptyEnumerator =
new(Array.Empty<IDisposable?>());
new([]);

/// <summary>
/// An enumerator for an array of disposables.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ public void Dispose()
}

/// <inheritdoc/>
public override bool Equals(object? obj) => false;
public override readonly bool Equals(object? obj) => false;

/// <inheritdoc/>
public override int GetHashCode() => 0;
public override readonly int GetHashCode() => 0;

#pragma warning disable IDE0060 // (Remove unused parameter.) Required part of public API
public static bool operator ==(SingleAssignmentDisposableValue left, SingleAssignmentDisposableValue right) => false;
Expand Down
2 changes: 0 additions & 2 deletions Rx.NET/Source/src/System.Reactive/EventPattern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ public class EventPattern<TEventArgs> : EventPattern<object, TEventArgs>
/// </summary>
/// <param name="sender">The sender object that raised the event.</param>
/// <param name="e">The event data that was generated by the event.</param>
#pragma warning disable CA2109 // (Consider making non-public.) This has long been part of the public API so we couldn't change this even if we wanted to.
public EventPattern(object? sender, TEventArgs e)
#pragma warning restore CA2109
: base(sender, e)
{
}
Expand Down
3 changes: 1 addition & 2 deletions Rx.NET/Source/src/System.Reactive/EventPatternSourceBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void SetResource(IDisposable resource)
}

private readonly IObservable<EventPattern<TSender, TEventArgs>> _source;
private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions;
private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions = [];
private readonly Action<Action<TSender?, TEventArgs>, /*object,*/ EventPattern<TSender, TEventArgs>> _invokeHandler;

/// <summary>
Expand All @@ -89,7 +89,6 @@ protected EventPatternSourceBase(IObservable<EventPattern<TSender, TEventArgs>>
{
_source = source ?? throw new ArgumentNullException(nameof(source));
_invokeHandler = invokeHandler ?? throw new ArgumentNullException(nameof(invokeHandler));
_subscriptions = new Dictionary<Delegate, Stack<IDisposable>>();
}

/// <summary>
Expand Down
3 changes: 1 addition & 2 deletions Rx.NET/Source/src/System.Reactive/EventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ namespace System.Reactive
internal sealed class EventSource<T> : IEventSource<T>
{
private readonly IObservable<T> _source;
private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions;
private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions = [];
private readonly Action<Action<T>, /*object,*/ T> _invokeHandler;

public EventSource(IObservable<T> source, Action<Action<T>, /*object,*/ T> invokeHandler)
{
_source = source;
_invokeHandler = invokeHandler;
_subscriptions = new Dictionary<Delegate, Stack<IDisposable>>();
}

public event Action<T> OnNext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal sealed class ImmutableList<T>

private readonly T[] _data;

private ImmutableList() => _data = Array.Empty<T>();
private ImmutableList() => _data = [];

public ImmutableList(T[] data) => _data = data;

Expand Down
2 changes: 1 addition & 1 deletion Rx.NET/Source/src/System.Reactive/Internal/Lookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void Add(K key, E element)
{
if (!_dictionary.TryGetValue(key, out var list))
{
_dictionary[key] = list = new List<E>();
_dictionary[key] = list = [];
}

list.Add(element);
Expand Down
4 changes: 2 additions & 2 deletions Rx.NET/Source/src/System.Reactive/Internal/SystemClock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static class SystemClock
{
private static readonly Lazy<ISystemClock> ServiceSystemClock = new(InitializeSystemClock);
private static readonly Lazy<INotifySystemClockChanged> ServiceSystemClockChanged = new(InitializeSystemClockChanged);
internal static readonly HashSet<WeakReference<LocalScheduler>> SystemClockChanged = new();
internal static readonly HashSet<WeakReference<LocalScheduler>> SystemClockChanged = [];
private static IDisposable? _systemClockChangedHandlerCollector;

private static int _refCount;
Expand Down Expand Up @@ -123,7 +123,7 @@ private static void CollectHandlers()
{
if (!handler.TryGetTarget(out _))
{
remove ??= new HashSet<WeakReference<LocalScheduler>>();
remove ??= [];

remove.Add(handler);
}
Expand Down
2 changes: 1 addition & 1 deletion Rx.NET/Source/src/System.Reactive/Joins/ActivePlan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace System.Reactive.Joins
{
internal abstract class ActivePlan
{
private readonly Dictionary<IJoinObserver, IJoinObserver> _joinObservers = new();
private readonly Dictionary<IJoinObserver, IJoinObserver> _joinObservers = [];

protected readonly Action _onCompleted;

Expand Down
3 changes: 1 addition & 2 deletions Rx.NET/Source/src/System.Reactive/Joins/JoinObserver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal sealed class JoinObserver<T> : ObserverBase<Notification<T>>, IJoinObse
private object? _gate;
private readonly IObservable<T> _source;
private readonly Action<Exception> _onError;
private readonly List<ActivePlan> _activePlans;
private readonly List<ActivePlan> _activePlans = [];
private SingleAssignmentDisposableValue _subscription;
private bool _isDisposed;

Expand All @@ -28,7 +28,6 @@ public JoinObserver(IObservable<T> source, Action<Exception> onError)
_source = source;
_onError = onError;
Queue = new Queue<Notification<T>>();
_activePlans = new List<ActivePlan>();
}

public Queue<Notification<T>> Queue { get; }
Expand Down
18 changes: 9 additions & 9 deletions Rx.NET/Source/src/System.Reactive/Linq/Observable/Buffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ public TimeHopping(IObservable<TSource> source, TimeSpan timeSpan, IScheduler sc
internal sealed class _ : Sink<TSource, IList<TSource>>
{
private readonly object _gate = new();
private List<TSource> _list = new();
private List<TSource> _list = [];

public _(IObserver<IList<TSource>> observer)
: base(observer)
Expand Down Expand Up @@ -465,7 +465,7 @@ private void Tick()
lock (_gate)
{
ForwardOnNext(_list);
_list = new List<TSource>();
_list = [];
}
}

Expand Down Expand Up @@ -521,7 +521,7 @@ internal sealed class _ : Sink<TSource, IList<TSource>>
{
private readonly Ferry _parent;
private readonly object _gate = new();
private List<TSource> _s = new();
private List<TSource> _s = [];

public _(Ferry parent, IObserver<IList<TSource>> observer)
: base(observer)
Expand Down Expand Up @@ -574,7 +574,7 @@ private void Tick(int id)
var newId = ++_windowId;

var res = _s;
_s = new List<TSource>();
_s = [];
ForwardOnNext(res);

CreateTimer(newId);
Expand All @@ -598,7 +598,7 @@ public override void OnNext(TSource value)
newId = ++_windowId;

var res = _s;
_s = new List<TSource>();
_s = [];
ForwardOnNext(res);
}

Expand Down Expand Up @@ -653,7 +653,7 @@ internal sealed class _ : Sink<TSource, IList<TSource>>
private readonly AsyncLock _bufferGate = new();
private readonly Func<IObservable<TBufferClosing>> _bufferClosingSelector;

private List<TSource> _buffer = new();
private List<TSource> _buffer = [];
private SerialDisposableValue _bufferClosingSerialDisposable;

public _(Selector parent, IObserver<IList<TSource>> observer)
Expand Down Expand Up @@ -706,7 +706,7 @@ private void CloseBuffer(IDisposable closingSubscription)
lock (_gate)
{
var res = _buffer;
_buffer = new List<TSource>();
_buffer = [];
ForwardOnNext(res);
}

Expand Down Expand Up @@ -785,7 +785,7 @@ internal sealed class _ : Sink<TSource, IList<TSource>>
{
private readonly object _gate = new();

private List<TSource> _buffer = new();
private List<TSource> _buffer = [];
private SingleAssignmentDisposableValue _boundariesDisposable;

public _(IObserver<IList<TSource>> observer)
Expand Down Expand Up @@ -823,7 +823,7 @@ public void OnNext(TBufferClosing value)
lock (_parent._gate)
{
var res = _parent._buffer;
_parent._buffer = new List<TSource>();
_parent._buffer = [];
_parent.ForwardOnNext(res);
}
}
Expand Down
2 changes: 1 addition & 1 deletion Rx.NET/Source/src/System.Reactive/Linq/Observable/Delay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ protected Base(IObservable<TSource> source)

internal abstract class _ : IdentitySink<TSource>
{
private readonly CompositeDisposable _delays = new();
private readonly CompositeDisposable _delays = [];
private readonly object _gate = new();

private readonly Func<TSource, IObservable<TDelay>> _delaySelector;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private Action AddHandlerCore(Delegate handler)
private Action AddHandlerCoreWinRT(Delegate handler)
{
var token = _addMethod.Invoke(_target, new object[] { handler });
return () => _removeMethod.Invoke(_target, new[] { token });
return () => _removeMethod.Invoke(_target, [token]);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal sealed class _ : Sink<TSource, IGroupedObservable<TKey, TElement>>
{
private readonly object _gate = new();
private readonly object _nullGate = new();
private readonly CompositeDisposable _groupDisposable = new();
private readonly CompositeDisposable _groupDisposable = [];
private readonly RefCountDisposable _refCountDisposable;
private readonly Map<TKey, ISubject<TElement>> _map;

Expand Down
Loading

0 comments on commit 57e4c42

Please sign in to comment.