From d914a96654987ccd43845ee1b3bd0df781446390 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 7 Dec 2021 19:37:46 +0100 Subject: [PATCH] Nullable annotations for AvaloniaObject/AvaloniaProperty etc. (#7078) * Add nullable annotations... ...to `AvaloniaObject`/`AvaloniaProperty`-related classes and a few other uncontroversial files. * Check for null before first use. * Don't need this check as base class does it. # Conflicts: # src/Avalonia.Styling/Styling/Activators/PropertyEqualsActivator.cs # src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs --- src/Avalonia.Animation/Animatable.cs | 2 +- src/Avalonia.Base/AttachedProperty.cs | 4 +- .../AvaloniaInternalException.cs | 2 + src/Avalonia.Base/AvaloniaObject.cs | 8 +- src/Avalonia.Base/AvaloniaObjectExtensions.cs | 76 +++++++------- src/Avalonia.Base/AvaloniaProperty.cs | 99 +++++++++---------- src/Avalonia.Base/AvaloniaPropertyMetadata.cs | 2 + src/Avalonia.Base/AvaloniaPropertyRegistry.cs | 48 ++++----- src/Avalonia.Base/AvaloniaProperty`1.cs | 10 +- src/Avalonia.Base/Data/BindingValue.cs | 2 +- src/Avalonia.Base/Data/Core/IPropertyInfo.cs | 6 +- src/Avalonia.Base/DirectProperty.cs | 29 +++--- src/Avalonia.Base/DirectPropertyBase.cs | 6 +- src/Avalonia.Base/DirectPropertyMetadata`1.cs | 6 +- src/Avalonia.Base/EnumExtensions.cs | 2 + src/Avalonia.Base/IDescription.cs | 4 +- src/Avalonia.Base/IDirectPropertyAccessor.cs | 6 +- src/Avalonia.Base/IDirectPropertyMetadata.cs | 6 +- src/Avalonia.Base/IStyledPropertyAccessor.cs | 4 +- src/Avalonia.Base/IStyledPropertyMetadata.cs | 4 +- .../AvaloniaPropertyBindingObservable.cs | 4 +- .../Reactive/TypedBindingAdapter.cs | 10 +- src/Avalonia.Base/StyledProperty.cs | 6 +- src/Avalonia.Base/StyledPropertyBase.cs | 40 +++----- src/Avalonia.Base/StyledPropertyMetadata`1.cs | 10 +- src/Avalonia.Input/Avalonia.Input.csproj | 1 - .../Activators/PropertyEqualsActivator.cs | 8 +- .../Avalonia.Markup/Data/TemplateBinding.cs | 10 +- 28 files changed, 214 insertions(+), 201 deletions(-) diff --git a/src/Avalonia.Animation/Animatable.cs b/src/Avalonia.Animation/Animatable.cs index a415046513..4811028f85 100644 --- a/src/Avalonia.Animation/Animatable.cs +++ b/src/Avalonia.Animation/Animatable.cs @@ -232,7 +232,7 @@ namespace Avalonia.Animation } } - private object GetAnimationBaseValue(AvaloniaProperty property) + private object? GetAnimationBaseValue(AvaloniaProperty property) { var value = this.GetBaseValue(property, BindingPriority.LocalValue); diff --git a/src/Avalonia.Base/AttachedProperty.cs b/src/Avalonia.Base/AttachedProperty.cs index b8ab4d6bf5..352104897a 100644 --- a/src/Avalonia.Base/AttachedProperty.cs +++ b/src/Avalonia.Base/AttachedProperty.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace Avalonia { /// @@ -21,7 +23,7 @@ namespace Avalonia Type ownerType, StyledPropertyMetadata metadata, bool inherits = false, - Func validate = null) + Func? validate = null) : base(name, ownerType, metadata, inherits, validate) { } diff --git a/src/Avalonia.Base/AvaloniaInternalException.cs b/src/Avalonia.Base/AvaloniaInternalException.cs index a536073174..60e3040e01 100644 --- a/src/Avalonia.Base/AvaloniaInternalException.cs +++ b/src/Avalonia.Base/AvaloniaInternalException.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace Avalonia { /// diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs index ce5b37043f..dddfa4bbb5 100644 --- a/src/Avalonia.Base/AvaloniaObject.cs +++ b/src/Avalonia.Base/AvaloniaObject.cs @@ -103,7 +103,7 @@ namespace Avalonia /// Gets or sets the value of a . /// /// The property. - public object this[AvaloniaProperty property] + public object? this[AvaloniaProperty property] { get { return GetValue(property); } set { SetValue(property, value); } @@ -211,7 +211,7 @@ namespace Avalonia /// See https://github.com/AvaloniaUI/Avalonia/pull/2747 for the discussion that prompted /// this. /// - public sealed override bool Equals(object obj) => base.Equals(obj); + public sealed override bool Equals(object? obj) => base.Equals(obj); /// /// Gets the hash code for the object. @@ -233,7 +233,7 @@ namespace Avalonia /// /// The property. /// The value. - public object GetValue(AvaloniaProperty property) + public object? GetValue(AvaloniaProperty property) { property = property ?? throw new ArgumentNullException(nameof(property)); @@ -567,7 +567,7 @@ namespace Avalonia /// The old inheritance parent. internal void InheritanceParentChanged( StyledPropertyBase property, - IAvaloniaObject oldParent) + IAvaloniaObject? oldParent) { var oldValue = oldParent switch { diff --git a/src/Avalonia.Base/AvaloniaObjectExtensions.cs b/src/Avalonia.Base/AvaloniaObjectExtensions.cs index 173c5c1a94..6f1f1cb3b3 100644 --- a/src/Avalonia.Base/AvaloniaObjectExtensions.cs +++ b/src/Avalonia.Base/AvaloniaObjectExtensions.cs @@ -6,6 +6,8 @@ using System.Reactive.Subjects; using Avalonia.Data; using Avalonia.Reactive; +#nullable enable + namespace Avalonia { /// @@ -21,7 +23,7 @@ namespace Avalonia /// An . public static IBinding ToBinding(this IObservable source) { - return new BindingAdaptor(source.Select(x => (object)x)); + return new BindingAdaptor(source.Select(x => (object?)x)); } /// @@ -36,12 +38,11 @@ namespace Avalonia /// /// The subscription to is created using a weak reference. /// - public static IObservable GetObservable(this IAvaloniaObject o, AvaloniaProperty property) + public static IObservable GetObservable(this IAvaloniaObject o, AvaloniaProperty property) { - Contract.Requires(o != null); - Contract.Requires(property != null); - - return new AvaloniaPropertyObservable(o, property); + return new AvaloniaPropertyObservable( + o ?? throw new ArgumentNullException(nameof(o)), + property ?? throw new ArgumentNullException(nameof(property))); } /// @@ -59,10 +60,9 @@ namespace Avalonia /// public static IObservable GetObservable(this IAvaloniaObject o, AvaloniaProperty property) { - Contract.Requires(o != null); - Contract.Requires(property != null); - - return new AvaloniaPropertyObservable(o, property); + return new AvaloniaPropertyObservable( + o ?? throw new ArgumentNullException(nameof(o)), + property ?? throw new ArgumentNullException(nameof(property))); } /// @@ -77,14 +77,13 @@ namespace Avalonia /// /// The subscription to is created using a weak reference. /// - public static IObservable> GetBindingObservable( + public static IObservable> GetBindingObservable( this IAvaloniaObject o, AvaloniaProperty property) { - Contract.Requires(o != null); - Contract.Requires(property != null); - - return new AvaloniaPropertyBindingObservable(o, property); + return new AvaloniaPropertyBindingObservable( + o ?? throw new ArgumentNullException(nameof(o)), + property ?? throw new ArgumentNullException(nameof(property))); } /// @@ -104,10 +103,10 @@ namespace Avalonia this IAvaloniaObject o, AvaloniaProperty property) { - Contract.Requires(o != null); - Contract.Requires(property != null); + return new AvaloniaPropertyBindingObservable( + o ?? throw new ArgumentNullException(nameof(o)), + property ?? throw new ArgumentNullException(nameof(property))); - return new AvaloniaPropertyBindingObservable(o, property); } /// @@ -125,10 +124,9 @@ namespace Avalonia this IAvaloniaObject o, AvaloniaProperty property) { - Contract.Requires(o != null); - Contract.Requires(property != null); - - return new AvaloniaPropertyChangedObservable(o, property); + return new AvaloniaPropertyChangedObservable( + o ?? throw new ArgumentNullException(nameof(o)), + property ?? throw new ArgumentNullException(nameof(property))); } /// @@ -143,13 +141,13 @@ namespace Avalonia /// An which can be used for two-way binding to/from the /// property. /// - public static ISubject GetSubject( + public static ISubject GetSubject( this IAvaloniaObject o, AvaloniaProperty property, BindingPriority priority = BindingPriority.LocalValue) { - return Subject.Create( - Observer.Create(x => o.SetValue(property, x, priority)), + return Subject.Create( + Observer.Create(x => o.SetValue(property, x, priority)), o.GetObservable(property)); } @@ -188,13 +186,13 @@ namespace Avalonia /// An which can be used for two-way binding to/from the /// property. /// - public static ISubject> GetBindingSubject( + public static ISubject> GetBindingSubject( this IAvaloniaObject o, AvaloniaProperty property, BindingPriority priority = BindingPriority.LocalValue) { - return Subject.Create>( - Observer.Create>(x => + return Subject.Create>( + Observer.Create>(x => { if (x.HasValue) { @@ -246,7 +244,7 @@ namespace Avalonia public static IDisposable Bind( this IAvaloniaObject target, AvaloniaProperty property, - IObservable> source, + IObservable> source, BindingPriority priority = BindingPriority.LocalValue) { target = target ?? throw new ArgumentNullException(nameof(target)); @@ -298,7 +296,7 @@ namespace Avalonia public static IDisposable Bind( this IAvaloniaObject target, AvaloniaProperty property, - IObservable source, + IObservable source, BindingPriority priority = BindingPriority.LocalValue) { target = target ?? throw new ArgumentNullException(nameof(target)); @@ -354,7 +352,7 @@ namespace Avalonia this IAvaloniaObject target, AvaloniaProperty property, IBinding binding, - object anchor = null) + object? anchor = null) { target = target ?? throw new ArgumentNullException(nameof(target)); property = property ?? throw new ArgumentNullException(nameof(property)); @@ -420,7 +418,7 @@ namespace Avalonia /// The object. /// The property. /// The value. - public static object GetValue(this IAvaloniaObject target, AvaloniaProperty property) + public static object? GetValue(this IAvaloniaObject target, AvaloniaProperty property) { target = target ?? throw new ArgumentNullException(nameof(target)); property = property ?? throw new ArgumentNullException(nameof(property)); @@ -462,7 +460,7 @@ namespace Avalonia /// /// For direct properties returns . /// - public static object GetBaseValue( + public static object? GetBaseValue( this IAvaloniaObject target, AvaloniaProperty property, BindingPriority maxPriority) @@ -517,10 +515,10 @@ namespace Avalonia /// /// An if setting the property can be undone, otherwise null. /// - public static IDisposable SetValue( + public static IDisposable? SetValue( this IAvaloniaObject target, AvaloniaProperty property, - object value, + object? value, BindingPriority priority = BindingPriority.LocalValue) { target = target ?? throw new ArgumentNullException(nameof(target)); @@ -540,7 +538,7 @@ namespace Avalonia /// /// An if setting the property can be undone, otherwise null. /// - public static IDisposable SetValue( + public static IDisposable? SetValue( this IAvaloniaObject target, AvaloniaProperty property, T value, @@ -633,9 +631,9 @@ namespace Avalonia private class BindingAdaptor : IBinding { - private IObservable _source; + private IObservable _source; - public BindingAdaptor(IObservable source) + public BindingAdaptor(IObservable source) { this._source = source; } @@ -643,7 +641,7 @@ namespace Avalonia public InstancedBinding Initiate( IAvaloniaObject target, AvaloniaProperty targetProperty, - object anchor = null, + object? anchor = null, bool enableDataValidation = false) { return InstancedBinding.OneWay(_source); diff --git a/src/Avalonia.Base/AvaloniaProperty.cs b/src/Avalonia.Base/AvaloniaProperty.cs index 94aefb8869..3e5cfb24a2 100644 --- a/src/Avalonia.Base/AvaloniaProperty.cs +++ b/src/Avalonia.Base/AvaloniaProperty.cs @@ -4,6 +4,8 @@ using Avalonia.Data; using Avalonia.Data.Core; using Avalonia.Utilities; +#nullable enable + namespace Avalonia { /// @@ -36,12 +38,9 @@ namespace Avalonia Type valueType, Type ownerType, AvaloniaPropertyMetadata metadata, - Action notifying = null) + Action? notifying = null) { - Contract.Requires(name != null); - Contract.Requires(valueType != null); - Contract.Requires(ownerType != null); - Contract.Requires(metadata != null); + _ = name ?? throw new ArgumentNullException(nameof(name)); if (name.Contains(".")) { @@ -51,12 +50,12 @@ namespace Avalonia _metadata = new Dictionary(); Name = name; - PropertyType = valueType; - OwnerType = ownerType; + PropertyType = valueType ?? throw new ArgumentNullException(nameof(valueType)); + OwnerType = ownerType ?? throw new ArgumentNullException(nameof(ownerType)); Notifying = notifying; Id = s_nextId++; - _metadata.Add(ownerType, metadata); + _metadata.Add(ownerType, metadata ?? throw new ArgumentNullException(nameof(metadata))); _defaultMetadata = metadata; } @@ -69,16 +68,13 @@ namespace Avalonia protected AvaloniaProperty( AvaloniaProperty source, Type ownerType, - AvaloniaPropertyMetadata metadata) + AvaloniaPropertyMetadata? metadata) { - Contract.Requires(source != null); - Contract.Requires(ownerType != null); - _metadata = new Dictionary(); - Name = source.Name; + Name = source?.Name ?? throw new ArgumentNullException(nameof(source)); PropertyType = source.PropertyType; - OwnerType = ownerType; + OwnerType = ownerType ?? throw new ArgumentNullException(nameof(ownerType)); Notifying = source.Notifying; Id = source.Id; _defaultMetadata = source._defaultMetadata; @@ -149,7 +145,7 @@ namespace Avalonia /// will be true before the property change notifications are sent and false afterwards. This /// callback is intended to support Control.IsDataContextChanging. /// - public Action Notifying { get; } + public Action? Notifying { get; } /// /// Gets the integer ID that represents this property. @@ -192,13 +188,13 @@ namespace Avalonia /// The first property. /// The second property. /// True if the properties are equal, otherwise false. - public static bool operator ==(AvaloniaProperty a, AvaloniaProperty b) + public static bool operator ==(AvaloniaProperty? a, AvaloniaProperty? b) { if (object.ReferenceEquals(a, b)) { return true; } - else if (((object)a == null) || ((object)b == null)) + else if (a is null || b is null) { return false; } @@ -214,7 +210,7 @@ namespace Avalonia /// The first property. /// The second property. /// True if the properties are equal, otherwise false. - public static bool operator !=(AvaloniaProperty a, AvaloniaProperty b) + public static bool operator !=(AvaloniaProperty? a, AvaloniaProperty? b) { return !(a == b); } @@ -238,15 +234,15 @@ namespace Avalonia /// A public static StyledProperty Register( string name, - TValue defaultValue = default(TValue), + TValue defaultValue = default!, bool inherits = false, BindingMode defaultBindingMode = BindingMode.OneWay, - Func validate = null, - Func coerce = null, - Action notifying = null) + Func? validate = null, + Func? coerce = null, + Action? notifying = null) where TOwner : IAvaloniaObject { - Contract.Requires(name != null); + _ = name ?? throw new ArgumentNullException(nameof(name)); var metadata = new StyledPropertyMetadata( defaultValue, @@ -279,14 +275,14 @@ namespace Avalonia /// A public static AttachedProperty RegisterAttached( string name, - TValue defaultValue = default(TValue), + TValue defaultValue = default!, bool inherits = false, BindingMode defaultBindingMode = BindingMode.OneWay, - Func validate = null, - Func coerce = null) + Func? validate = null, + Func? coerce = null) where THost : IAvaloniaObject { - Contract.Requires(name != null); + _ = name ?? throw new ArgumentNullException(nameof(name)); var metadata = new StyledPropertyMetadata( defaultValue, @@ -316,14 +312,14 @@ namespace Avalonia public static AttachedProperty RegisterAttached( string name, Type ownerType, - TValue defaultValue = default(TValue), + TValue defaultValue = default!, bool inherits = false, BindingMode defaultBindingMode = BindingMode.OneWay, - Func validate = null, - Func coerce = null) + Func? validate = null, + Func? coerce = null) where THost : IAvaloniaObject { - Contract.Requires(name != null); + _ = name ?? throw new ArgumentNullException(nameof(name)); var metadata = new StyledPropertyMetadata( defaultValue, @@ -354,14 +350,14 @@ namespace Avalonia public static DirectProperty RegisterDirect( string name, Func getter, - Action setter = null, - TValue unsetValue = default(TValue), + Action? setter = null, + TValue unsetValue = default!, BindingMode defaultBindingMode = BindingMode.OneWay, bool enableDataValidation = false) where TOwner : IAvaloniaObject { - Contract.Requires(name != null); - Contract.Requires(getter != null); + _ = name ?? throw new ArgumentNullException(nameof(name)); + _ = getter ?? throw new ArgumentNullException(nameof(getter)); var metadata = new DirectPropertyMetadata( unsetValue: unsetValue, @@ -394,16 +390,16 @@ namespace Avalonia } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { var p = obj as AvaloniaProperty; - return p != null && Equals(p); + return p is not null && Equals(p); } /// - public bool Equals(AvaloniaProperty other) + public bool Equals(AvaloniaProperty? other) { - return other != null && Id == other.Id; + return Id == other?.Id; } /// @@ -431,7 +427,6 @@ namespace Avalonia /// /// The property metadata. /// - /// public AvaloniaPropertyMetadata GetMetadata(Type type) { if (!_hasMetadataOverrides) @@ -447,9 +442,9 @@ namespace Avalonia /// /// The value. /// True if the value is valid, otherwise false. - public bool IsValidValue(object value) + public bool IsValidValue(object? value) { - return TypeUtilities.TryConvertImplicit(PropertyType, value, out value); + return TypeUtilities.TryConvertImplicit(PropertyType, value, out _); } /// @@ -480,14 +475,14 @@ namespace Avalonia /// Routes an untyped GetValue call to a typed call. /// /// The object instance. - internal abstract object RouteGetValue(IAvaloniaObject o); + internal abstract object? RouteGetValue(IAvaloniaObject o); /// /// Routes an untyped GetBaseValue call to a typed call. /// /// The object instance. /// The maximum priority for the value. - internal abstract object RouteGetBaseValue(IAvaloniaObject o, BindingPriority maxPriority); + internal abstract object? RouteGetBaseValue(IAvaloniaObject o, BindingPriority maxPriority); /// /// Routes an untyped SetValue call to a typed call. @@ -498,9 +493,9 @@ namespace Avalonia /// /// An if setting the property can be undone, otherwise null. /// - internal abstract IDisposable RouteSetValue( + internal abstract IDisposable? RouteSetValue( IAvaloniaObject o, - object value, + object? value, BindingPriority priority); /// @@ -511,10 +506,10 @@ namespace Avalonia /// The priority. internal abstract IDisposable RouteBind( IAvaloniaObject o, - IObservable> source, + IObservable> source, BindingPriority priority); - internal abstract void RouteInheritanceParentChanged(AvaloniaObject o, IAvaloniaObject oldParent); + internal abstract void RouteInheritanceParentChanged(AvaloniaObject o, IAvaloniaObject? oldParent); /// /// Overrides the metadata for the property on the specified type. @@ -523,8 +518,8 @@ namespace Avalonia /// The metadata. protected void OverrideMetadata(Type type, AvaloniaPropertyMetadata metadata) { - Contract.Requires(type != null); - Contract.Requires(metadata != null); + _ = type ?? throw new ArgumentNullException(nameof(type)); + _ = metadata ?? throw new ArgumentNullException(nameof(metadata)); if (_metadata.ContainsKey(type)) { @@ -575,8 +570,8 @@ namespace Avalonia bool IPropertyInfo.CanGet => true; bool IPropertyInfo.CanSet => true; - object IPropertyInfo.Get(object target) => ((AvaloniaObject)target).GetValue(this); - void IPropertyInfo.Set(object target, object value) => ((AvaloniaObject)target).SetValue(this, value); + object? IPropertyInfo.Get(object target) => ((AvaloniaObject)target).GetValue(this); + void IPropertyInfo.Set(object target, object? value) => ((AvaloniaObject)target).SetValue(this, value); } /// diff --git a/src/Avalonia.Base/AvaloniaPropertyMetadata.cs b/src/Avalonia.Base/AvaloniaPropertyMetadata.cs index 2963567b14..4090aab558 100644 --- a/src/Avalonia.Base/AvaloniaPropertyMetadata.cs +++ b/src/Avalonia.Base/AvaloniaPropertyMetadata.cs @@ -1,5 +1,7 @@ using Avalonia.Data; +#nullable enable + namespace Avalonia { /// diff --git a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs index 4cde965400..91db8c16c2 100644 --- a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs +++ b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +#nullable enable + namespace Avalonia { /// @@ -44,7 +46,7 @@ namespace Avalonia /// A collection of definitions. public IReadOnlyList GetRegistered(Type type) { - Contract.Requires(type != null); + _ = type ?? throw new ArgumentNullException(nameof(type)); if (_registeredCache.TryGetValue(type, out var result)) { @@ -78,7 +80,7 @@ namespace Avalonia /// A collection of definitions. public IReadOnlyList GetRegisteredAttached(Type type) { - Contract.Requires(type != null); + _ = type ?? throw new ArgumentNullException(nameof(type)); if (_attachedCache.TryGetValue(type, out var result)) { @@ -109,7 +111,7 @@ namespace Avalonia /// A collection of definitions. public IReadOnlyList GetRegisteredDirect(Type type) { - Contract.Requires(type != null); + _ = type ?? throw new ArgumentNullException(nameof(type)); if (_directCache.TryGetValue(type, out var result)) { @@ -140,7 +142,7 @@ namespace Avalonia /// A collection of definitions. public IReadOnlyList GetRegisteredInherited(Type type) { - Contract.Requires(type != null); + _ = type ?? throw new ArgumentNullException(nameof(type)); if (_inheritedCache.TryGetValue(type, out var result)) { @@ -191,18 +193,18 @@ namespace Avalonia /// A collection of definitions. public IReadOnlyList GetRegistered(IAvaloniaObject o) { - Contract.Requires(o != null); + _ = o ?? throw new ArgumentNullException(nameof(o)); return GetRegistered(o.GetType()); } /// - /// Finds a direct property as registered on an object. + /// Gets a direct property as registered on an object. /// /// The object. /// The direct property. /// - /// The registered property or null if no matching property found. + /// The registered. /// public DirectPropertyBase GetRegisteredDirect( IAvaloniaObject o, @@ -223,10 +225,10 @@ namespace Avalonia /// /// The property name contains a '.'. /// - public AvaloniaProperty FindRegistered(Type type, string name) + public AvaloniaProperty? FindRegistered(Type type, string name) { - Contract.Requires(type != null); - Contract.Requires(name != null); + _ = type ?? throw new ArgumentNullException(nameof(type)); + _ = name ?? throw new ArgumentNullException(nameof(name)); if (name.Contains(".")) { @@ -260,10 +262,10 @@ namespace Avalonia /// /// The property name contains a '.'. /// - public AvaloniaProperty FindRegistered(IAvaloniaObject o, string name) + public AvaloniaProperty? FindRegistered(IAvaloniaObject o, string name) { - Contract.Requires(o != null); - Contract.Requires(name != null); + _ = o ?? throw new ArgumentNullException(nameof(o)); + _ = name ?? throw new ArgumentNullException(nameof(name)); return FindRegistered(o.GetType(), name); } @@ -276,7 +278,7 @@ namespace Avalonia /// /// The registered property or null if no matching property found. /// - public DirectPropertyBase FindRegisteredDirect( + public DirectPropertyBase? FindRegisteredDirect( IAvaloniaObject o, DirectPropertyBase property) { @@ -306,7 +308,7 @@ namespace Avalonia /// /// The property Id. /// The registered property or null if no matching property found. - internal AvaloniaProperty FindRegistered(int id) + internal AvaloniaProperty? FindRegistered(int id) { return id < _properties.Count ? _properties[id] : null; } @@ -319,8 +321,8 @@ namespace Avalonia /// True if the property is registered, otherwise false. public bool IsRegistered(Type type, AvaloniaProperty property) { - Contract.Requires(type != null); - Contract.Requires(property != null); + _ = type ?? throw new ArgumentNullException(nameof(type)); + _ = property ?? throw new ArgumentNullException(nameof(property)); static bool ContainsProperty(IReadOnlyList properties, AvaloniaProperty property) { @@ -349,8 +351,8 @@ namespace Avalonia /// True if the property is registered, otherwise false. public bool IsRegistered(object o, AvaloniaProperty property) { - Contract.Requires(o != null); - Contract.Requires(property != null); + _ = o ?? throw new ArgumentNullException(nameof(o)); + _ = property ?? throw new ArgumentNullException(nameof(property)); return IsRegistered(o.GetType(), property); } @@ -367,8 +369,8 @@ namespace Avalonia /// public void Register(Type type, AvaloniaProperty property) { - Contract.Requires(type != null); - Contract.Requires(property != null); + _ = type ?? throw new ArgumentNullException(nameof(type)); + _ = property ?? throw new ArgumentNullException(nameof(property)); if (!_registered.TryGetValue(type, out var inner)) { @@ -418,8 +420,8 @@ namespace Avalonia /// public void RegisterAttached(Type type, AvaloniaProperty property) { - Contract.Requires(type != null); - Contract.Requires(property != null); + _ = type ?? throw new ArgumentNullException(nameof(type)); + _ = property ?? throw new ArgumentNullException(nameof(property)); if (!property.IsAttached) { diff --git a/src/Avalonia.Base/AvaloniaProperty`1.cs b/src/Avalonia.Base/AvaloniaProperty`1.cs index 247ea0a25a..3485f195c5 100644 --- a/src/Avalonia.Base/AvaloniaProperty`1.cs +++ b/src/Avalonia.Base/AvaloniaProperty`1.cs @@ -3,6 +3,8 @@ using System.Reactive.Subjects; using Avalonia.Data; using Avalonia.Utilities; +#nullable enable + namespace Avalonia { /// @@ -24,7 +26,7 @@ namespace Avalonia string name, Type ownerType, AvaloniaPropertyMetadata metadata, - Action notifying = null) + Action? notifying = null) : base(name, typeof(TValue), ownerType, metadata, notifying) { _changed = new Subject>(); @@ -40,7 +42,7 @@ namespace Avalonia protected AvaloniaProperty( AvaloniaProperty source, Type ownerType, - AvaloniaPropertyMetadata metadata) + AvaloniaPropertyMetadata? metadata) : this(source as AvaloniaProperty ?? throw new InvalidOperationException(), ownerType, metadata) { } @@ -54,7 +56,7 @@ namespace Avalonia protected AvaloniaProperty( AvaloniaProperty source, Type ownerType, - AvaloniaPropertyMetadata metadata) + AvaloniaPropertyMetadata? metadata) : base(source, ownerType, metadata) { _changed = source._changed; @@ -82,7 +84,7 @@ namespace Avalonia protected override IObservable GetChanged() => Changed; - protected BindingValue TryConvert(object value) + protected BindingValue TryConvert(object? value) { if (value == UnsetValue) { diff --git a/src/Avalonia.Base/Data/BindingValue.cs b/src/Avalonia.Base/Data/BindingValue.cs index e8c84ffb21..cc6a2799af 100644 --- a/src/Avalonia.Base/Data/BindingValue.cs +++ b/src/Avalonia.Base/Data/BindingValue.cs @@ -416,7 +416,7 @@ namespace Avalonia.Data /// /// Note that this method uses reflection and as such may be slow. /// - public static BindingValue Convert(this BindingValue value) + public static BindingValue Convert(this BindingValue value) { return value.Type switch { diff --git a/src/Avalonia.Base/Data/Core/IPropertyInfo.cs b/src/Avalonia.Base/Data/Core/IPropertyInfo.cs index 2417d0ffc4..9544565fcb 100644 --- a/src/Avalonia.Base/Data/Core/IPropertyInfo.cs +++ b/src/Avalonia.Base/Data/Core/IPropertyInfo.cs @@ -1,12 +1,14 @@ using System; +#nullable enable + namespace Avalonia.Data.Core { public interface IPropertyInfo { string Name { get; } - object Get(object target); - void Set(object target, object value); + object? Get(object target); + void Set(object target, object? value); bool CanSet { get; } bool CanGet { get; } Type PropertyType { get; } diff --git a/src/Avalonia.Base/DirectProperty.cs b/src/Avalonia.Base/DirectProperty.cs index a8120fbd4f..eb04cfdce0 100644 --- a/src/Avalonia.Base/DirectProperty.cs +++ b/src/Avalonia.Base/DirectProperty.cs @@ -1,6 +1,9 @@ using System; +using System.Diagnostics.CodeAnalysis; using Avalonia.Data; +#nullable enable + namespace Avalonia { /// @@ -26,13 +29,11 @@ namespace Avalonia public DirectProperty( string name, Func getter, - Action setter, + Action? setter, DirectPropertyMetadata metadata) : base(name, typeof(TOwner), metadata) { - Contract.Requires(getter != null); - - Getter = getter; + Getter = getter ?? throw new ArgumentNullException(nameof(getter)); Setter = setter; } @@ -46,13 +47,11 @@ namespace Avalonia private DirectProperty( DirectPropertyBase source, Func getter, - Action setter, + Action? setter, DirectPropertyMetadata metadata) : base(source, typeof(TOwner), metadata) { - Contract.Requires(getter != null); - - Getter = getter; + Getter = getter ?? throw new ArgumentNullException(nameof(getter)); Setter = setter; } @@ -73,7 +72,7 @@ namespace Avalonia /// /// Gets the setter function. /// - public Action Setter { get; } + public Action? Setter { get; } /// /// Registers the direct property on another type. @@ -91,8 +90,8 @@ namespace Avalonia /// The property. public DirectProperty AddOwner( Func getter, - Action setter = null, - TValue unsetValue = default(TValue), + Action? setter = null, + TValue unsetValue = default!, BindingMode defaultBindingMode = BindingMode.Default, bool enableDataValidation = false) where TNewOwner : AvaloniaObject @@ -131,7 +130,7 @@ namespace Avalonia public DirectProperty AddOwnerWithDataValidation( Func getter, Action setter, - TValue unsetValue = default(TValue), + TValue unsetValue = default!, BindingMode defaultBindingMode = BindingMode.Default, bool enableDataValidation = false) where TNewOwner : AvaloniaObject @@ -174,20 +173,20 @@ namespace Avalonia } /// - object IDirectPropertyAccessor.GetValue(IAvaloniaObject instance) + object? IDirectPropertyAccessor.GetValue(IAvaloniaObject instance) { return Getter((TOwner)instance); } /// - void IDirectPropertyAccessor.SetValue(IAvaloniaObject instance, object value) + void IDirectPropertyAccessor.SetValue(IAvaloniaObject instance, object? value) { if (Setter == null) { throw new ArgumentException($"The property {Name} is readonly."); } - Setter((TOwner)instance, (TValue)value); + Setter((TOwner)instance, (TValue)value!); } } } diff --git a/src/Avalonia.Base/DirectPropertyBase.cs b/src/Avalonia.Base/DirectPropertyBase.cs index a057ad2254..4b54ee75ab 100644 --- a/src/Avalonia.Base/DirectPropertyBase.cs +++ b/src/Avalonia.Base/DirectPropertyBase.cs @@ -148,7 +148,7 @@ namespace Avalonia /// internal override IDisposable? RouteSetValue( IAvaloniaObject o, - object value, + object? value, BindingPriority priority) { var v = TryConvert(value); @@ -172,14 +172,14 @@ namespace Avalonia /// internal override IDisposable RouteBind( IAvaloniaObject o, - IObservable> source, + IObservable> source, BindingPriority priority) { var adapter = TypedBindingAdapter.Create(o, this, source); return o.Bind(this, adapter); } - internal override void RouteInheritanceParentChanged(AvaloniaObject o, IAvaloniaObject oldParent) + internal override void RouteInheritanceParentChanged(AvaloniaObject o, IAvaloniaObject? oldParent) { throw new NotSupportedException("Direct properties do not support inheritance."); } diff --git a/src/Avalonia.Base/DirectPropertyMetadata`1.cs b/src/Avalonia.Base/DirectPropertyMetadata`1.cs index eabdef05ed..a265032139 100644 --- a/src/Avalonia.Base/DirectPropertyMetadata`1.cs +++ b/src/Avalonia.Base/DirectPropertyMetadata`1.cs @@ -1,5 +1,7 @@ using Avalonia.Data; +#nullable enable + namespace Avalonia { /// @@ -18,7 +20,7 @@ namespace Avalonia /// Whether the property is interested in data validation. /// public DirectPropertyMetadata( - TValue unsetValue = default(TValue), + TValue unsetValue = default!, BindingMode defaultBindingMode = BindingMode.Default, bool? enableDataValidation = null) : base(defaultBindingMode) @@ -44,7 +46,7 @@ namespace Avalonia public bool? EnableDataValidation { get; private set; } /// - object IDirectPropertyMetadata.UnsetValue => UnsetValue; + object? IDirectPropertyMetadata.UnsetValue => UnsetValue; /// public override void Merge(AvaloniaPropertyMetadata baseMetadata, AvaloniaProperty property) diff --git a/src/Avalonia.Base/EnumExtensions.cs b/src/Avalonia.Base/EnumExtensions.cs index 19eb42a700..1f7c532cce 100644 --- a/src/Avalonia.Base/EnumExtensions.cs +++ b/src/Avalonia.Base/EnumExtensions.cs @@ -1,6 +1,8 @@ using System; using System.Runtime.CompilerServices; +#nullable enable + namespace Avalonia { /// diff --git a/src/Avalonia.Base/IDescription.cs b/src/Avalonia.Base/IDescription.cs index b3d9f16bb7..17a7f98776 100644 --- a/src/Avalonia.Base/IDescription.cs +++ b/src/Avalonia.Base/IDescription.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace Avalonia { /// @@ -11,6 +13,6 @@ namespace Avalonia /// /// The description of the object. /// - string Description { get; } + string? Description { get; } } } diff --git a/src/Avalonia.Base/IDirectPropertyAccessor.cs b/src/Avalonia.Base/IDirectPropertyAccessor.cs index 6ae71bc2c6..e75ca238ad 100644 --- a/src/Avalonia.Base/IDirectPropertyAccessor.cs +++ b/src/Avalonia.Base/IDirectPropertyAccessor.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace Avalonia { /// @@ -23,13 +25,13 @@ namespace Avalonia /// /// The instance. /// The property value. - object GetValue(IAvaloniaObject instance); + object? GetValue(IAvaloniaObject instance); /// /// Sets the value of the property on the instance. /// /// The instance. /// The value. - void SetValue(IAvaloniaObject instance, object value); + void SetValue(IAvaloniaObject instance, object? value); } } diff --git a/src/Avalonia.Base/IDirectPropertyMetadata.cs b/src/Avalonia.Base/IDirectPropertyMetadata.cs index 992fa4ffc9..7b132d192e 100644 --- a/src/Avalonia.Base/IDirectPropertyMetadata.cs +++ b/src/Avalonia.Base/IDirectPropertyMetadata.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace Avalonia { /// @@ -8,11 +10,11 @@ namespace Avalonia /// /// Gets the to use when the property is set to . /// - object UnsetValue { get; } + object? UnsetValue { get; } /// /// Gets a value indicating whether the property is interested in data validation. /// bool? EnableDataValidation { get; } } -} \ No newline at end of file +} diff --git a/src/Avalonia.Base/IStyledPropertyAccessor.cs b/src/Avalonia.Base/IStyledPropertyAccessor.cs index 45d106164f..6ef6391010 100644 --- a/src/Avalonia.Base/IStyledPropertyAccessor.cs +++ b/src/Avalonia.Base/IStyledPropertyAccessor.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace Avalonia { /// @@ -14,6 +16,6 @@ namespace Avalonia /// /// The default value. /// - object GetDefaultValue(Type type); + object? GetDefaultValue(Type type); } } diff --git a/src/Avalonia.Base/IStyledPropertyMetadata.cs b/src/Avalonia.Base/IStyledPropertyMetadata.cs index a68b65e5e0..2a0d09d6a7 100644 --- a/src/Avalonia.Base/IStyledPropertyMetadata.cs +++ b/src/Avalonia.Base/IStyledPropertyMetadata.cs @@ -1,3 +1,5 @@ +#nullable enable + namespace Avalonia { /// @@ -8,6 +10,6 @@ namespace Avalonia /// /// Gets the default value for the property. /// - object DefaultValue { get; } + object? DefaultValue { get; } } } diff --git a/src/Avalonia.Base/Reactive/AvaloniaPropertyBindingObservable.cs b/src/Avalonia.Base/Reactive/AvaloniaPropertyBindingObservable.cs index be044b0559..9a0dc61ba3 100644 --- a/src/Avalonia.Base/Reactive/AvaloniaPropertyBindingObservable.cs +++ b/src/Avalonia.Base/Reactive/AvaloniaPropertyBindingObservable.cs @@ -28,7 +28,7 @@ namespace Avalonia.Reactive { if (_target.TryGetTarget(out var target)) { - _value = (T)target.GetValue(_property); + _value = (T)target.GetValue(_property)!; target.PropertyChanged += PropertyChanged; } } @@ -66,7 +66,7 @@ namespace Avalonia.Reactive if (!Equals(newValue, _value)) { - _value = (T)newValue; + _value = (T)newValue!; PublishNext(_value); } } diff --git a/src/Avalonia.Base/Reactive/TypedBindingAdapter.cs b/src/Avalonia.Base/Reactive/TypedBindingAdapter.cs index b99cef0f51..44803bc7d6 100644 --- a/src/Avalonia.Base/Reactive/TypedBindingAdapter.cs +++ b/src/Avalonia.Base/Reactive/TypedBindingAdapter.cs @@ -7,24 +7,24 @@ using Avalonia.Logging; namespace Avalonia.Reactive { internal class TypedBindingAdapter : SingleSubscriberObservableBase>, - IObserver> + IObserver> { private readonly IAvaloniaObject _target; private readonly AvaloniaProperty _property; - private readonly IObservable> _source; + private readonly IObservable> _source; private IDisposable? _subscription; public TypedBindingAdapter( IAvaloniaObject target, AvaloniaProperty property, - IObservable> source) + IObservable> source) { _target = target; _property = property; _source = source; } - public void OnNext(BindingValue value) + public void OnNext(BindingValue value) { try { @@ -49,7 +49,7 @@ namespace Avalonia.Reactive public static IObservable> Create( IAvaloniaObject target, AvaloniaProperty property, - IObservable> source) + IObservable> source) { return source is IObservable> result ? result : diff --git a/src/Avalonia.Base/StyledProperty.cs b/src/Avalonia.Base/StyledProperty.cs index 75275858cd..4bd24d4a42 100644 --- a/src/Avalonia.Base/StyledProperty.cs +++ b/src/Avalonia.Base/StyledProperty.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace Avalonia { /// @@ -21,8 +23,8 @@ namespace Avalonia Type ownerType, StyledPropertyMetadata metadata, bool inherits = false, - Func validate = null, - Action notifying = null) + Func? validate = null, + Action? notifying = null) : base(name, ownerType, metadata, inherits, validate, notifying) { } diff --git a/src/Avalonia.Base/StyledPropertyBase.cs b/src/Avalonia.Base/StyledPropertyBase.cs index 3e92c3bdf7..526b1175b4 100644 --- a/src/Avalonia.Base/StyledPropertyBase.cs +++ b/src/Avalonia.Base/StyledPropertyBase.cs @@ -4,6 +4,8 @@ using Avalonia.Data; using Avalonia.Reactive; using Avalonia.Utilities; +#nullable enable + namespace Avalonia { /// @@ -27,18 +29,10 @@ namespace Avalonia Type ownerType, StyledPropertyMetadata metadata, bool inherits = false, - Func validate = null, - Action notifying = null) + Func? validate = null, + Action? notifying = null) : base(name, ownerType, metadata, notifying) { - Contract.Requires(name != null); - Contract.Requires(ownerType != null); - - if (name.Contains(".")) - { - throw new ArgumentException("'name' may not contain periods."); - } - _inherits = inherits; ValidateValue = validate; HasCoercion |= metadata.CoerceValue != null; @@ -72,7 +66,7 @@ namespace Avalonia /// /// Gets the value validation callback for the property. /// - public Func ValidateValue { get; } + public Func? ValidateValue { get; } /// /// Gets a value indicating whether this property has any value coercion callbacks defined @@ -99,8 +93,6 @@ namespace Avalonia /// The default value. public TValue GetDefaultValue(Type type) { - Contract.Requires(type != null); - return GetMetadata(type).DefaultValue; } @@ -113,6 +105,7 @@ namespace Avalonia /// public new StyledPropertyMetadata GetMetadata(Type type) { + _ = type ?? throw new ArgumentNullException(nameof(type)); return (StyledPropertyMetadata)base.GetMetadata(type); } @@ -183,7 +176,7 @@ namespace Avalonia } /// - object IStyledPropertyAccessor.GetDefaultValue(Type type) => GetDefaultBoxedValue(type); + object? IStyledPropertyAccessor.GetDefaultValue(Type type) => GetDefaultBoxedValue(type); /// internal override void RouteClearValue(IAvaloniaObject o) @@ -192,22 +185,22 @@ namespace Avalonia } /// - internal override object RouteGetValue(IAvaloniaObject o) + internal override object? RouteGetValue(IAvaloniaObject o) { return o.GetValue(this); } /// - internal override object RouteGetBaseValue(IAvaloniaObject o, BindingPriority maxPriority) + internal override object? RouteGetBaseValue(IAvaloniaObject o, BindingPriority maxPriority) { var value = o.GetBaseValue(this, maxPriority); return value.HasValue ? value.Value : AvaloniaProperty.UnsetValue; } /// - internal override IDisposable RouteSetValue( + internal override IDisposable? RouteSetValue( IAvaloniaObject o, - object value, + object? value, BindingPriority priority) { var v = TryConvert(value); @@ -222,7 +215,7 @@ namespace Avalonia } else if (v.HasError) { - throw v.Error; + throw v.Error!; } return null; @@ -231,7 +224,7 @@ namespace Avalonia /// internal override IDisposable RouteBind( IAvaloniaObject o, - IObservable> source, + IObservable> source, BindingPriority priority) { var adapter = TypedBindingAdapter.Create(o, this, source); @@ -241,15 +234,14 @@ namespace Avalonia /// internal override void RouteInheritanceParentChanged( AvaloniaObject o, - IAvaloniaObject oldParent) + IAvaloniaObject? oldParent) { o.InheritanceParentChanged(this, oldParent); } - private object GetDefaultBoxedValue(Type type) + private object? GetDefaultBoxedValue(Type type) { - Contract.Requires(type != null); - + _ = type ?? throw new ArgumentNullException(nameof(type)); return GetMetadata(type).DefaultValue; } diff --git a/src/Avalonia.Base/StyledPropertyMetadata`1.cs b/src/Avalonia.Base/StyledPropertyMetadata`1.cs index ec7bff4dfb..a9f7eb38de 100644 --- a/src/Avalonia.Base/StyledPropertyMetadata`1.cs +++ b/src/Avalonia.Base/StyledPropertyMetadata`1.cs @@ -1,6 +1,8 @@ using System; using Avalonia.Data; +#nullable enable + namespace Avalonia { /// @@ -19,7 +21,7 @@ namespace Avalonia public StyledPropertyMetadata( Optional defaultValue = default, BindingMode defaultBindingMode = BindingMode.Default, - Func coerce = null) + Func? coerce = null) : base(defaultBindingMode) { _defaultValue = defaultValue; @@ -29,14 +31,14 @@ namespace Avalonia /// /// Gets the default value for the property. /// - public TValue DefaultValue => _defaultValue.GetValueOrDefault(); + public TValue DefaultValue => _defaultValue.GetValueOrDefault()!; /// /// Gets the value coercion callback, if any. /// - public Func CoerceValue { get; private set; } + public Func? CoerceValue { get; private set; } - object IStyledPropertyMetadata.DefaultValue => DefaultValue; + object? IStyledPropertyMetadata.DefaultValue => DefaultValue; /// public override void Merge(AvaloniaPropertyMetadata baseMetadata, AvaloniaProperty property) diff --git a/src/Avalonia.Input/Avalonia.Input.csproj b/src/Avalonia.Input/Avalonia.Input.csproj index 69a80290d1..cc487e285b 100644 --- a/src/Avalonia.Input/Avalonia.Input.csproj +++ b/src/Avalonia.Input/Avalonia.Input.csproj @@ -2,7 +2,6 @@ netstandard2.0 Enable - CS8600;CS8602;CS8603 diff --git a/src/Avalonia.Styling/Styling/Activators/PropertyEqualsActivator.cs b/src/Avalonia.Styling/Styling/Activators/PropertyEqualsActivator.cs index 9e30e4fa14..92e2228500 100644 --- a/src/Avalonia.Styling/Styling/Activators/PropertyEqualsActivator.cs +++ b/src/Avalonia.Styling/Styling/Activators/PropertyEqualsActivator.cs @@ -7,7 +7,7 @@ namespace Avalonia.Styling.Activators /// /// An which listens to a property value on a control. /// - internal class PropertyEqualsActivator : StyleActivatorBase, IObserver + internal class PropertyEqualsActivator : StyleActivatorBase, IObserver { private readonly IStyleable _control; private readonly AvaloniaProperty _property; @@ -31,8 +31,8 @@ namespace Avalonia.Styling.Activators protected override void Deinitialize() => _subscription?.Dispose(); - void IObserver.OnCompleted() { } - void IObserver.OnError(Exception error) { } - void IObserver.OnNext(object value) => PublishNext(Equals(value, _value)); + void IObserver.OnCompleted() { } + void IObserver.OnError(Exception error) { } + void IObserver.OnNext(object value) => PublishNext(Equals(value, _value)); } } diff --git a/src/Markup/Avalonia.Markup/Data/TemplateBinding.cs b/src/Markup/Avalonia.Markup/Data/TemplateBinding.cs index b6c723d68c..2aada7c5b6 100644 --- a/src/Markup/Avalonia.Markup/Data/TemplateBinding.cs +++ b/src/Markup/Avalonia.Markup/Data/TemplateBinding.cs @@ -10,10 +10,10 @@ namespace Avalonia.Data /// /// A XAML binding to a property on a control's templated parent. /// - public class TemplateBinding : SingleSubscriberObservableBase, + public class TemplateBinding : SingleSubscriberObservableBase, IBinding, IDescription, - ISubject, + ISubject, ISetterValue { private bool _isSetterValue; @@ -88,10 +88,10 @@ namespace Avalonia.Data /// public string Description => "TemplateBinding: " + Property; - void IObserver.OnCompleted() => throw new NotImplementedException(); - void IObserver.OnError(Exception error) => throw new NotImplementedException(); + void IObserver.OnCompleted() => throw new NotImplementedException(); + void IObserver.OnError(Exception error) => throw new NotImplementedException(); - void IObserver.OnNext(object value) + void IObserver.OnNext(object? value) { if (_target.TemplatedParent != null && Property != null) {