Skip to content

Commit

Permalink
Merge pull request #7240 from AvaloniaUI/fixes/avalonia-styling-nulla…
Browse files Browse the repository at this point in the history
…bility

Added nullable annotations to Avalonia.Styling.
  • Loading branch information
maxkatz6 authored Dec 22, 2021
2 parents 426b7da + 6741358 commit a9900df
Show file tree
Hide file tree
Showing 25 changed files with 132 additions and 128 deletions.
1 change: 1 addition & 0 deletions src/Avalonia.Styling/Avalonia.Styling.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
</ItemGroup>
<Import Project="..\..\build\ApiDiff.props" />
<Import Project="..\..\build\NullableEnable.props" />
</Project>
12 changes: 6 additions & 6 deletions src/Avalonia.Styling/Controls/ChildNameScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@ public ChildNameScope(INameScope parentScope)

public void Register(string name, object element) => _inner.Register(name, element);

public SynchronousCompletionAsyncResult<object> FindAsync(string name)
public SynchronousCompletionAsyncResult<object?> FindAsync(string name)
{
var found = Find(name);
if (found != null)
return new SynchronousCompletionAsyncResult<object>(found);
return new SynchronousCompletionAsyncResult<object?>(found);
// Not found and both current and parent scope are in completed state
if(IsCompleted)
return new SynchronousCompletionAsyncResult<object>(null);
return new SynchronousCompletionAsyncResult<object?>(null);
return DoFindAsync(name);
}

public SynchronousCompletionAsyncResult<object> DoFindAsync(string name)
public SynchronousCompletionAsyncResult<object?> DoFindAsync(string name)
{
var src = new SynchronousCompletionAsyncResultSource<object>();
var src = new SynchronousCompletionAsyncResultSource<object?>();

void ParentSearch()
{
Expand Down Expand Up @@ -56,7 +56,7 @@ void ParentSearch()
return src.AsyncResult;
}

public object Find(string name)
public object? Find(string name)
{
var found = _inner.Find(name);
if (found != null)
Expand Down
4 changes: 2 additions & 2 deletions src/Avalonia.Styling/Controls/INameScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ public interface INameScope
/// </summary>
/// <param name="name">The name.</param>
/// <returns>The element, or null if the name was not found.</returns>
SynchronousCompletionAsyncResult<object> FindAsync(string name);
SynchronousCompletionAsyncResult<object?> FindAsync(string name);

/// <summary>
/// Finds a named element in the name scope, returns immediately, doesn't traverse the name scope stack
/// </summary>
/// <param name="name">The name.</param>
/// <returns>The element, or null if the name was not found.</returns>
object Find(string name);
object? Find(string name);

/// <summary>
/// Marks the name scope as completed, no further registrations will be allowed
Expand Down
30 changes: 14 additions & 16 deletions src/Avalonia.Styling/Controls/NameScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public class NameScope : INameScope

private readonly Dictionary<string, object> _inner = new Dictionary<string, object>();

private readonly Dictionary<string, SynchronousCompletionAsyncResultSource<object>> _pendingSearches =
new Dictionary<string, SynchronousCompletionAsyncResultSource<object>>();
private readonly Dictionary<string, SynchronousCompletionAsyncResultSource<object?>> _pendingSearches =
new Dictionary<string, SynchronousCompletionAsyncResultSource<object?>>();

/// <summary>
/// Gets the value of the attached <see cref="NameScopeProperty"/> on a styled element.
Expand All @@ -32,7 +32,7 @@ public class NameScope : INameScope
/// <returns>The value of the NameScope attached property.</returns>
public static INameScope GetNameScope(StyledElement styled)
{
Contract.Requires<ArgumentNullException>(styled != null);
_ = styled ?? throw new ArgumentNullException(nameof(styled));

return styled.GetValue(NameScopeProperty);
}
Expand All @@ -44,7 +44,7 @@ public static INameScope GetNameScope(StyledElement styled)
/// <param name="value">The value to set.</param>
public static void SetNameScope(StyledElement styled, INameScope value)
{
Contract.Requires<ArgumentNullException>(styled != null);
_ = styled ?? throw new ArgumentNullException(nameof(styled));

styled.SetValue(NameScopeProperty, value);
}
Expand All @@ -54,12 +54,11 @@ public void Register(string name, object element)
{
if (IsCompleted)
throw new InvalidOperationException("NameScope is completed, no further registrations are allowed");
Contract.Requires<ArgumentNullException>(name != null);
Contract.Requires<ArgumentNullException>(element != null);

object existing;
_ = name ?? throw new ArgumentNullException(nameof(name));
_ = element ?? throw new ArgumentNullException(nameof(element));

if (_inner.TryGetValue(name, out existing))
if (_inner.TryGetValue(name, out var existing))
{
if (existing != element)
{
Expand All @@ -77,27 +76,26 @@ public void Register(string name, object element)
}
}

public SynchronousCompletionAsyncResult<object> FindAsync(string name)
public SynchronousCompletionAsyncResult<object?> FindAsync(string name)
{
var found = Find(name);
if (found != null)
return new SynchronousCompletionAsyncResult<object>(found);
return new SynchronousCompletionAsyncResult<object?>(found);
if (IsCompleted)
return new SynchronousCompletionAsyncResult<object>((object)null);
return new SynchronousCompletionAsyncResult<object?>(null);
if (!_pendingSearches.TryGetValue(name, out var tcs))
// We are intentionally running continuations synchronously here
_pendingSearches[name] = tcs = new SynchronousCompletionAsyncResultSource<object>();
_pendingSearches[name] = tcs = new SynchronousCompletionAsyncResultSource<object?>();

return tcs.AsyncResult;
}

/// <inheritdoc />
public object Find(string name)
public object? Find(string name)
{
Contract.Requires<ArgumentNullException>(name != null);
_ = name ?? throw new ArgumentNullException(nameof(name));

object result;
_inner.TryGetValue(name, out result);
_inner.TryGetValue(name, out var result);
return result;
}

Expand Down
28 changes: 14 additions & 14 deletions src/Avalonia.Styling/Controls/NameScopeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ public static class NameScopeExtensions
/// <param name="nameScope">The name scope.</param>
/// <param name="name">The name.</param>
/// <returns>The named element or null if not found.</returns>
public static T Find<T>(this INameScope nameScope, string name)
public static T? Find<T>(this INameScope nameScope, string name)
where T : class
{
Contract.Requires<ArgumentNullException>(nameScope != null);
Contract.Requires<ArgumentNullException>(name != null);
_ = nameScope ?? throw new ArgumentNullException(nameof(nameScope));
_ = name ?? throw new ArgumentNullException(nameof(name));

var result = nameScope.Find(name);

Expand All @@ -31,7 +31,7 @@ public static T Find<T>(this INameScope nameScope, string name)
$"Expected control '{name}' to be '{typeof(T)} but it was '{result.GetType()}'.");
}

return (T)result;
return (T?)result;
}

/// <summary>
Expand All @@ -41,11 +41,11 @@ public static T Find<T>(this INameScope nameScope, string name)
/// <param name="anchor">The control to take the name scope from.</param>
/// <param name="name">The name.</param>
/// <returns>The named element or null if not found.</returns>
public static T Find<T>(this ILogical anchor, string name)
public static T? Find<T>(this ILogical anchor, string name)
where T : class
{
Contract.Requires<ArgumentNullException>(anchor != null);
Contract.Requires<ArgumentNullException>(name != null);
_ = anchor ?? throw new ArgumentNullException(nameof(anchor));
_ = name ?? throw new ArgumentNullException(nameof(name));
var styledAnchor = anchor as StyledElement;
if (styledAnchor == null)
return null;
Expand All @@ -64,8 +64,8 @@ public static T Find<T>(this ILogical anchor, string name)
public static T Get<T>(this INameScope nameScope, string name)
where T : class
{
Contract.Requires<ArgumentNullException>(nameScope != null);
Contract.Requires<ArgumentNullException>(name != null);
_ = nameScope ?? throw new ArgumentNullException(nameof(nameScope));
_ = name ?? throw new ArgumentNullException(nameof(name));

var result = nameScope.Find(name);

Expand Down Expand Up @@ -94,9 +94,9 @@ public static T Get<T>(this INameScope nameScope, string name)
public static T Get<T>(this ILogical anchor, string name)
where T : class
{
Contract.Requires<ArgumentNullException>(anchor != null);
Contract.Requires<ArgumentNullException>(name != null);
_ = anchor ?? throw new ArgumentNullException(nameof(anchor));
_ = name ?? throw new ArgumentNullException(nameof(name));

var nameScope = (anchor as INameScope) ?? NameScope.GetNameScope((StyledElement)anchor);
if (nameScope == null)
throw new InvalidOperationException(
Expand All @@ -105,9 +105,9 @@ public static T Get<T>(this ILogical anchor, string name)
return nameScope.Get<T>(name);
}

public static INameScope FindNameScope(this ILogical control)
public static INameScope? FindNameScope(this ILogical control)
{
Contract.Requires<ArgumentNullException>(control != null);
_ = control ?? throw new ArgumentNullException(nameof(control));

var scope = control.GetSelfAndLogicalAncestors()
.OfType<StyledElement>()
Expand Down
8 changes: 4 additions & 4 deletions src/Avalonia.Styling/Controls/NameScopeLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ public class NameScopeLocator
/// </summary>
/// <param name="scope">The scope relative from which the object should be resolved.</param>
/// <param name="name">The name of the object to find.</param>
public static IObservable<object> Track(INameScope scope, string name)
public static IObservable<object?> Track(INameScope scope, string name)
{
return new NeverEndingSynchronousCompletionAsyncResultObservable<object>(scope.FindAsync(name));
return new NeverEndingSynchronousCompletionAsyncResultObservable<object?>(scope.FindAsync(name));
}

// This class is implemented in such weird way because for some reason
Expand All @@ -22,7 +22,7 @@ public static IObservable<object> Track(INameScope scope, string name)

private class NeverEndingSynchronousCompletionAsyncResultObservable<T> : IObservable<T>
{
private T _value;
private T? _value;
private SynchronousCompletionAsyncResult<T>? _asyncResult;

public NeverEndingSynchronousCompletionAsyncResultObservable(SynchronousCompletionAsyncResult<T> task)
Expand All @@ -47,7 +47,7 @@ public IDisposable Subscribe(IObserver<T> observer)
observer.OnNext(_asyncResult.Value.GetResult());
});
else
observer.OnNext(_value);
observer.OnNext(_value!);

return Disposable.Empty;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Styling/Controls/PseudoClassesExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static class PseudolassesExtensions
/// <param name="value">True to add the pseudoclass or false to remove.</param>
public static void Set(this IPseudoClasses classes, string name, bool value)
{
Contract.Requires<ArgumentNullException>(classes != null);
_ = classes ?? throw new ArgumentNullException(nameof(classes));

if (value)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Styling/Controls/ResourceDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ void IResourceProvider.RemoveOwner(IResourceHost owner)
}
}

private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
}
Expand Down
6 changes: 3 additions & 3 deletions src/Avalonia.Styling/Controls/ResourceNodeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ protected override void Subscribed(IObserver<object?> observer, bool first)
observer.OnNext(Convert(_target.FindResource(_key)));
}

private void ResourcesChanged(object sender, ResourcesChangedEventArgs e)
private void ResourcesChanged(object? sender, ResourcesChangedEventArgs e)
{
PublishNext(Convert(_target.FindResource(_key)));
}
Expand Down Expand Up @@ -159,7 +159,7 @@ private void PublishNext()
}
}

private void OwnerChanged(object sender, EventArgs e)
private void OwnerChanged(object? sender, EventArgs e)
{
if (_owner is object)
{
Expand All @@ -176,7 +176,7 @@ private void OwnerChanged(object sender, EventArgs e)
PublishNext();
}

private void ResourcesChanged(object sender, ResourcesChangedEventArgs e)
private void ResourcesChanged(object? sender, ResourcesChangedEventArgs e)
{
PublishNext();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Styling/INamed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ public interface INamed
/// <summary>
/// Gets the element name.
/// </summary>
string Name { get; }
string? Name { get; }
}
}
16 changes: 8 additions & 8 deletions src/Avalonia.Styling/LogicalTree/ControlLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ namespace Avalonia.LogicalTree
/// </summary>
public static class ControlLocator
{
public static IObservable<ILogical> Track(ILogical relativeTo, int ancestorLevel, Type ancestorType = null)
public static IObservable<ILogical?> Track(ILogical relativeTo, int ancestorLevel, Type? ancestorType = null)
{
return new ControlTracker(relativeTo, ancestorLevel, ancestorType);
}

private class ControlTracker : LightweightObservableBase<ILogical>
private class ControlTracker : LightweightObservableBase<ILogical?>
{
private readonly ILogical _relativeTo;
private readonly int _ancestorLevel;
private readonly Type _ancestorType;
private ILogical _value;
private readonly Type? _ancestorType;
private ILogical? _value;

public ControlTracker(ILogical relativeTo, int ancestorLevel, Type ancestorType)
public ControlTracker(ILogical relativeTo, int ancestorLevel, Type? ancestorType)
{
_relativeTo = relativeTo;
_ancestorLevel = ancestorLevel;
Expand All @@ -43,18 +43,18 @@ protected override void Deinitialize()
_value = null;
}

protected override void Subscribed(IObserver<ILogical> observer, bool first)
protected override void Subscribed(IObserver<ILogical?> observer, bool first)
{
observer.OnNext(_value);
}

private void Attached(object sender, LogicalTreeAttachmentEventArgs e)
private void Attached(object? sender, LogicalTreeAttachmentEventArgs e)
{
Update();
PublishNext(_value);
}

private void Detached(object sender, LogicalTreeAttachmentEventArgs e)
private void Detached(object? sender, LogicalTreeAttachmentEventArgs e)
{
_value = null;
PublishNext(null);
Expand Down
6 changes: 3 additions & 3 deletions src/Avalonia.Styling/LogicalTree/ILogical.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ public interface ILogical
/// <summary>
/// Raised when the control is attached to a rooted logical tree.
/// </summary>
event EventHandler<LogicalTreeAttachmentEventArgs> AttachedToLogicalTree;
event EventHandler<LogicalTreeAttachmentEventArgs>? AttachedToLogicalTree;

/// <summary>
/// Raised when the control is detached from a rooted logical tree.
/// </summary>
event EventHandler<LogicalTreeAttachmentEventArgs> DetachedFromLogicalTree;
event EventHandler<LogicalTreeAttachmentEventArgs>? DetachedFromLogicalTree;

/// <summary>
/// Gets a value indicating whether the element is attached to a rooted logical tree.
Expand All @@ -27,7 +27,7 @@ public interface ILogical
/// <summary>
/// Gets the logical parent.
/// </summary>
ILogical LogicalParent { get; }
ILogical? LogicalParent { get; }

/// <summary>
/// Gets the logical children.
Expand Down
Loading

0 comments on commit a9900df

Please sign in to comment.