From 50659d9c2a21aa4e79260d0e2f920f02769225cb Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 15 Dec 2021 23:12:19 +0100 Subject: [PATCH 1/2] Enable nullable reference checking via .props file. The Nullable annotations on netstandard2.0 are incomplete and incorrect in places. Ignore nullable warnings on netstandard2.0 and make them errors on later target frameworks. --- build/NullableEnable.props | 11 +++++++++++ src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj | 2 +- src/Avalonia.Input/Avalonia.Input.csproj | 2 +- src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj | 3 +-- src/Markup/Avalonia.Markup/Avalonia.Markup.csproj | 3 +-- .../Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj | 4 ++-- 6 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 build/NullableEnable.props diff --git a/build/NullableEnable.props b/build/NullableEnable.props new file mode 100644 index 0000000000..cf5f9069d4 --- /dev/null +++ b/build/NullableEnable.props @@ -0,0 +1,11 @@ + + + + enable + $(WarningsAsErrors);nullable + $(NoWarn);nullable + + diff --git a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj index 7d64e3d82f..871821dd70 100644 --- a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj +++ b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj @@ -3,7 +3,6 @@ netstandard2.0;net6.0 Avalonia Avalonia.Diagnostics - enable @@ -34,4 +33,5 @@ + diff --git a/src/Avalonia.Input/Avalonia.Input.csproj b/src/Avalonia.Input/Avalonia.Input.csproj index 8b33fdcc02..a1640a62f8 100644 --- a/src/Avalonia.Input/Avalonia.Input.csproj +++ b/src/Avalonia.Input/Avalonia.Input.csproj @@ -1,7 +1,6 @@  netstandard2.0;net6.0 - Enable @@ -15,4 +14,5 @@ + diff --git a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj index a5f4b8073a..189b156569 100644 --- a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj +++ b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj @@ -3,8 +3,6 @@ netstandard2.0;net6.0 Avalonia.ReactiveUI false - enable - nullable @@ -12,4 +10,5 @@ + diff --git a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj index e560732b41..c8f60924c6 100644 --- a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj +++ b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj @@ -2,8 +2,6 @@ netstandard2.0;net6.0 Avalonia - Enable - CS8600;CS8602;CS8603 @@ -19,4 +17,5 @@ + diff --git a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj b/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj index 8b7babe5b1..94350b40cf 100644 --- a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj +++ b/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj @@ -2,7 +2,6 @@ net6.0 - enable enable Avalonia.Web.Blazor preview @@ -32,7 +31,8 @@ - + + true From c9c9d0509815eec47b9712112c5199a92288a619 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 15 Dec 2021 23:13:47 +0100 Subject: [PATCH 2/2] Fix nullable reference errors. The projects that have nullable reference types enabled are now generating errors instead of warnings, so fix those errors. --- .../ViewModels/AvaloniaPropertyViewModel.cs | 2 +- .../ViewModels/ClrPropertyViewModel.cs | 2 +- .../ViewModels/ControlDetailsViewModel.cs | 2 +- .../ViewModels/PropertyViewModel.cs | 11 +++-- .../Diagnostics/Views/MainWindow.xaml.cs | 6 +-- src/Avalonia.Input/AccessKeyHandler.cs | 10 ++-- src/Avalonia.Input/FocusManager.cs | 5 +- .../KeyboardNavigationHandler.cs | 2 +- src/Avalonia.Input/MouseDevice.cs | 13 +++--- src/Avalonia.Input/Pointer.cs | 2 +- .../TextInput/InputMethodManager.cs | 5 +- .../TextInput/TransformTrackingHelper.cs | 6 +-- .../Avalonia.Interactivity.csproj | 3 +- src/Avalonia.Interactivity/RoutedEvent.cs | 4 +- .../Avalonia.Markup/Data/BindingBase.cs | 2 +- .../Avalonia.Markup/Data/TemplateBinding.cs | 4 +- .../Markup/Data/DelayedBinding.cs | 4 +- .../Markup/Parsers/Nodes/StringIndexerNode.cs | 2 +- src/Shared/PlatformSupport/AssetLoader.cs | 46 +++++++++---------- .../Avalonia.Web.Blazor/WindowingPlatform.cs | 9 ++-- 20 files changed, 74 insertions(+), 66 deletions(-) diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/AvaloniaPropertyViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/AvaloniaPropertyViewModel.cs index 04fc038e2b..c23fdc166a 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/AvaloniaPropertyViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/AvaloniaPropertyViewModel.cs @@ -34,7 +34,7 @@ namespace Avalonia.Diagnostics.ViewModels public override System.Type Type => _type; - public override string Value + public override string? Value { get => ConvertToString(_value); set diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ClrPropertyViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ClrPropertyViewModel.cs index d5748c1d8d..8cf1be154d 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ClrPropertyViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ClrPropertyViewModel.cs @@ -35,7 +35,7 @@ namespace Avalonia.Diagnostics.ViewModels public override System.Type Type => _type; - public override string Value + public override string? Value { get => ConvertToString(_value); set diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs index 3f9c69a2a3..16293e35d2 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs @@ -437,7 +437,7 @@ namespace Avalonia.Diagnostics.ViewModels } } - protected void NavigateToProperty(object o, string entityName) + protected void NavigateToProperty(object o, string? entityName) { var oldSelectedEntity = SelectedEntity; if (oldSelectedEntity is IAvaloniaObject ao1) diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs index 557ad64d86..d5909d0553 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs @@ -16,12 +16,12 @@ namespace Avalonia.Diagnostics.ViewModels public abstract string Group { get; } public abstract Type Type { get; } public abstract Type? DeclaringType { get; } - public abstract string Value { get; set; } + public abstract string? Value { get; set; } public abstract string Priority { get; } public abstract bool? IsAttached { get; } public abstract void Update(); - protected static string ConvertToString(object? value) + protected static string? ConvertToString(object? value) { if (value is null) { @@ -59,8 +59,13 @@ namespace Avalonia.Diagnostics.ViewModels throw new InvalidCastException("Unable to convert value."); } - protected static object? ConvertFromString(string s, Type targetType) + protected static object? ConvertFromString(string? s, Type targetType) { + if (s is null) + { + return null; + } + var converter = TypeDescriptor.GetConverter(targetType); if (converter.CanConvertFrom(typeof(string))) diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs index 73d867bf10..8d4bead3d3 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs @@ -17,7 +17,7 @@ namespace Avalonia.Diagnostics.Views { internal class MainWindow : Window, IStyleHost { - private readonly IDisposable _keySubscription; + private readonly IDisposable? _keySubscription; private readonly Dictionary _frozenPopupStates; private TopLevel? _root; @@ -25,7 +25,7 @@ namespace Avalonia.Diagnostics.Views { InitializeComponent(); - _keySubscription = InputManager.Instance.Process + _keySubscription = InputManager.Instance?.Process .OfType() .Where(x => x.Type == RawKeyEventType.KeyDown) .Subscribe(RawKeyDown); @@ -82,7 +82,7 @@ namespace Avalonia.Diagnostics.Views protected override void OnClosed(EventArgs e) { base.OnClosed(e); - _keySubscription.Dispose(); + _keySubscription?.Dispose(); foreach (var state in _frozenPopupStates) { diff --git a/src/Avalonia.Input/AccessKeyHandler.cs b/src/Avalonia.Input/AccessKeyHandler.cs index 5082265ea6..24feb357b9 100644 --- a/src/Avalonia.Input/AccessKeyHandler.cs +++ b/src/Avalonia.Input/AccessKeyHandler.cs @@ -133,7 +133,7 @@ namespace Avalonia.Input /// /// The event sender. /// The event args. - protected virtual void OnPreviewKeyDown(object sender, KeyEventArgs e) + protected virtual void OnPreviewKeyDown(object? sender, KeyEventArgs e) { if (e.Key == Key.LeftAlt || e.Key == Key.RightAlt) { @@ -172,7 +172,7 @@ namespace Avalonia.Input /// /// The event sender. /// The event args. - protected virtual void OnKeyDown(object sender, KeyEventArgs e) + protected virtual void OnKeyDown(object? sender, KeyEventArgs e) { bool menuIsOpen = MainMenu?.IsOpen == true; @@ -207,7 +207,7 @@ namespace Avalonia.Input /// /// The event sender. /// The event args. - protected virtual void OnPreviewKeyUp(object sender, KeyEventArgs e) + protected virtual void OnPreviewKeyUp(object? sender, KeyEventArgs e) { switch (e.Key) { @@ -234,7 +234,7 @@ namespace Avalonia.Input /// /// The event sender. /// The event args. - protected virtual void OnPreviewPointerPressed(object sender, PointerEventArgs e) + protected virtual void OnPreviewPointerPressed(object? sender, PointerEventArgs e) { if (_showingAccessKeys) { @@ -251,7 +251,7 @@ namespace Avalonia.Input _owner!.ShowAccessKeys = _showingAccessKeys = false; } - private void MainMenuClosed(object sender, EventArgs e) + private void MainMenuClosed(object? sender, EventArgs e) { _owner!.ShowAccessKeys = false; } diff --git a/src/Avalonia.Input/FocusManager.cs b/src/Avalonia.Input/FocusManager.cs index 2efd33df1d..177e6035b0 100644 --- a/src/Avalonia.Input/FocusManager.cs +++ b/src/Avalonia.Input/FocusManager.cs @@ -215,8 +215,11 @@ namespace Avalonia.Input /// /// The event sender. /// The event args. - private static void OnPreviewPointerPressed(object sender, RoutedEventArgs e) + private static void OnPreviewPointerPressed(object? sender, RoutedEventArgs e) { + if (sender is null) + return; + var ev = (PointerPressedEventArgs)e; var visual = (IVisual)sender; diff --git a/src/Avalonia.Input/KeyboardNavigationHandler.cs b/src/Avalonia.Input/KeyboardNavigationHandler.cs index 6493777105..b2ebee9ef5 100644 --- a/src/Avalonia.Input/KeyboardNavigationHandler.cs +++ b/src/Avalonia.Input/KeyboardNavigationHandler.cs @@ -98,7 +98,7 @@ namespace Avalonia.Input /// /// The event sender. /// The event args. - protected virtual void OnKeyDown(object sender, KeyEventArgs e) + protected virtual void OnKeyDown(object? sender, KeyEventArgs e) { var current = FocusManager.Instance.Current; diff --git a/src/Avalonia.Input/MouseDevice.cs b/src/Avalonia.Input/MouseDevice.cs index 401c6cb2ac..6eccb3f101 100644 --- a/src/Avalonia.Input/MouseDevice.cs +++ b/src/Avalonia.Input/MouseDevice.cs @@ -298,10 +298,10 @@ namespace Avalonia.Input root = root ?? throw new ArgumentNullException(nameof(root)); var hit = HitTest(root, p); + var source = GetSource(hit); - if (hit != null) + if (source is not null) { - var source = GetSource(hit); var e = new PointerReleasedEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, _lastMouseDownButton); @@ -321,10 +321,10 @@ namespace Avalonia.Input root = root ?? throw new ArgumentNullException(nameof(root)); var hit = HitTest(root, p); + var source = GetSource(hit); - if (hit != null) + if (source is not null) { - var source = GetSource(hit); var e = new PointerWheelEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, delta); source?.RaiseEvent(e); @@ -334,9 +334,10 @@ namespace Avalonia.Input return false; } - private IInteractive GetSource(IVisual hit) + private IInteractive? GetSource(IVisual? hit) { - hit = hit ?? throw new ArgumentNullException(nameof(hit)); + if (hit is null) + return null; return _pointer.Captured ?? (hit as IInteractive) ?? diff --git a/src/Avalonia.Input/Pointer.cs b/src/Avalonia.Input/Pointer.cs index a477711584..433b275ce4 100644 --- a/src/Avalonia.Input/Pointer.cs +++ b/src/Avalonia.Input/Pointer.cs @@ -59,7 +59,7 @@ namespace Avalonia.Input return parent as IInputElement ?? parent.FindAncestorOfType(); } - private void OnCaptureDetached(object sender, VisualTreeAttachmentEventArgs e) + private void OnCaptureDetached(object? sender, VisualTreeAttachmentEventArgs e) { Capture(GetNextCapture(e.Parent)); } diff --git a/src/Avalonia.Input/TextInput/InputMethodManager.cs b/src/Avalonia.Input/TextInput/InputMethodManager.cs index dafd397348..64422a7fdf 100644 --- a/src/Avalonia.Input/TextInput/InputMethodManager.cs +++ b/src/Avalonia.Input/TextInput/InputMethodManager.cs @@ -8,7 +8,6 @@ namespace Avalonia.Input.TextInput private ITextInputMethodImpl? _im; private IInputElement? _focusedElement; private ITextInputMethodClient? _client; - private IDisposable? _subscribeDisposable; private readonly TransformTrackingHelper _transformTracker = new TransformTrackingHelper(); public TextInputMethodManager() @@ -64,7 +63,7 @@ namespace Avalonia.Input.TextInput } } - private void OnTextViewVisualChanged(object sender, EventArgs e) + private void OnTextViewVisualChanged(object? sender, EventArgs e) => _transformTracker.SetVisual(_client?.TextViewVisual); private void UpdateCursorRect() @@ -79,7 +78,7 @@ namespace Avalonia.Input.TextInput _im.SetCursorRect(_client.CursorRectangle.TransformToAABB(transform.Value)); } - private void OnCursorRectangleChanged(object sender, EventArgs e) + private void OnCursorRectangleChanged(object? sender, EventArgs e) { if (sender == _client) UpdateCursorRect(); diff --git a/src/Avalonia.Input/TextInput/TransformTrackingHelper.cs b/src/Avalonia.Input/TextInput/TransformTrackingHelper.cs index 4211360a8f..325c72bcb5 100644 --- a/src/Avalonia.Input/TextInput/TransformTrackingHelper.cs +++ b/src/Avalonia.Input/TextInput/TransformTrackingHelper.cs @@ -80,7 +80,7 @@ namespace Avalonia.Input.TextInput } } - private void OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs visualTreeAttachmentEventArgs) + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs visualTreeAttachmentEventArgs) { SubscribeToParents(); UpdateMatrix(); @@ -94,13 +94,13 @@ namespace Avalonia.Input.TextInput Dispatcher.UIThread.Post(UpdateMatrix, DispatcherPriority.Render); } - private void PropertyChangedHandler(object sender, AvaloniaPropertyChangedEventArgs e) + private void PropertyChangedHandler(object? sender, AvaloniaPropertyChangedEventArgs e) { if (e.IsEffectiveValueChange && e.Property == Visual.BoundsProperty) EnqueueForUpdate(); } - private void OnDetachedFromVisualTree(object sender, VisualTreeAttachmentEventArgs visualTreeAttachmentEventArgs) + private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs visualTreeAttachmentEventArgs) { UnsubscribeFromParents(); UpdateMatrix(); diff --git a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj index 341b7bff78..effb0e4c99 100644 --- a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj +++ b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj @@ -1,8 +1,6 @@  netstandard2.0;net6.0 - Enable - CS8600;CS8602;CS8603 @@ -12,4 +10,5 @@ + \ No newline at end of file diff --git a/src/Avalonia.Interactivity/RoutedEvent.cs b/src/Avalonia.Interactivity/RoutedEvent.cs index 3f38a61048..a9b7dc8c89 100644 --- a/src/Avalonia.Interactivity/RoutedEvent.cs +++ b/src/Avalonia.Interactivity/RoutedEvent.cs @@ -120,7 +120,7 @@ namespace Avalonia.Interactivity bool handledEventsToo = false) where TTarget : class, IInteractive { - void Adapter(object sender, RoutedEventArgs e) + void Adapter(object? sender, RoutedEventArgs e) { if (sender is TTarget target && e is TEventArgs args) { @@ -136,7 +136,7 @@ namespace Avalonia.Interactivity RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble, bool handledEventsToo = false) where TTarget : class, IInteractive { - void Adapter(object sender, RoutedEventArgs e) + void Adapter(object? sender, RoutedEventArgs e) { if (sender is TTarget target && e is TEventArgs args) { diff --git a/src/Markup/Avalonia.Markup/Data/BindingBase.cs b/src/Markup/Avalonia.Markup/Data/BindingBase.cs index e69d9570e2..0cffde6043 100644 --- a/src/Markup/Avalonia.Markup/Data/BindingBase.cs +++ b/src/Markup/Avalonia.Markup/Data/BindingBase.cs @@ -272,7 +272,7 @@ namespace Avalonia.Data _target.PropertyChanged -= PropertyChanged; } - private void PropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e) + private void PropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) { if (e.Property == _property) { diff --git a/src/Markup/Avalonia.Markup/Data/TemplateBinding.cs b/src/Markup/Avalonia.Markup/Data/TemplateBinding.cs index 8c33a7b721..265af3c5da 100644 --- a/src/Markup/Avalonia.Markup/Data/TemplateBinding.cs +++ b/src/Markup/Avalonia.Markup/Data/TemplateBinding.cs @@ -160,7 +160,7 @@ namespace Avalonia.Data PublishValue(); } - private void TargetPropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e) + private void TargetPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) { if (e.Property == StyledElement.TemplatedParentProperty) { @@ -173,7 +173,7 @@ namespace Avalonia.Data } } - private void TemplatedParentPropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e) + private void TemplatedParentPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) { if (e.Property == Property) { diff --git a/src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs b/src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs index b15081155f..3d6703daa3 100644 --- a/src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs +++ b/src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs @@ -95,9 +95,9 @@ namespace Avalonia.Markup.Data } } - private static void ApplyBindings(object sender, EventArgs e) + private static void ApplyBindings(object? sender, EventArgs e) { - var target = (IStyledElement)sender; + var target = (IStyledElement)sender!; ApplyBindings(target); target.Initialized -= ApplyBindings; } diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/Nodes/StringIndexerNode.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/Nodes/StringIndexerNode.cs index 57d99ef913..3857c9aff0 100644 --- a/src/Markup/Avalonia.Markup/Markup/Parsers/Nodes/StringIndexerNode.cs +++ b/src/Markup/Avalonia.Markup/Markup/Parsers/Nodes/StringIndexerNode.cs @@ -297,7 +297,7 @@ namespace Avalonia.Markup.Parsers.Nodes protected override bool ShouldUpdate(object? sender, PropertyChangedEventArgs e) { - if (sender is null) + if (sender is null || e.PropertyName is null) return false; var typeInfo = sender.GetType().GetTypeInfo(); return typeInfo.GetDeclaredProperty(e.PropertyName)?.GetIndexParameters().Any() ?? false; diff --git a/src/Shared/PlatformSupport/AssetLoader.cs b/src/Shared/PlatformSupport/AssetLoader.cs index 90b341297c..affb861de0 100644 --- a/src/Shared/PlatformSupport/AssetLoader.cs +++ b/src/Shared/PlatformSupport/AssetLoader.cs @@ -17,7 +17,7 @@ namespace Avalonia.Shared.PlatformSupport private static readonly Dictionary AssemblyNameCache = new Dictionary(); - private AssemblyDescriptor _defaultResmAssembly; + private AssemblyDescriptor? _defaultResmAssembly; /// /// Initializes a new instance of the class. @@ -25,7 +25,7 @@ namespace Avalonia.Shared.PlatformSupport /// /// The default assembly from which to load resm: assets for which no assembly is specified. /// - public AssetLoader(Assembly assembly = null) + public AssetLoader(Assembly? assembly = null) { if (assembly == null) assembly = Assembly.GetEntryAssembly(); @@ -50,7 +50,7 @@ namespace Avalonia.Shared.PlatformSupport /// A base URI to use if is relative. /// /// True if the asset could be found; otherwise false. - public bool Exists(Uri uri, Uri baseUri = null) + public bool Exists(Uri uri, Uri? baseUri = null) { return GetAsset(uri, baseUri) != null; } @@ -66,7 +66,7 @@ namespace Avalonia.Shared.PlatformSupport /// /// The asset could not be found. /// - public Stream Open(Uri uri, Uri baseUri = null) => OpenAndGetAssembly(uri, baseUri).Item1; + public Stream Open(Uri uri, Uri? baseUri = null) => OpenAndGetAssembly(uri, baseUri).Item1; /// /// Opens the asset with the requested URI and returns the asset stream and the @@ -82,7 +82,7 @@ namespace Avalonia.Shared.PlatformSupport /// /// The asset could not be found. /// - public (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null) + public (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri? baseUri = null) { var asset = GetAsset(uri, baseUri); @@ -94,11 +94,11 @@ namespace Avalonia.Shared.PlatformSupport return (asset.GetStream(), asset.Assembly); } - public Assembly GetAssembly(Uri uri, Uri baseUri) + public Assembly? GetAssembly(Uri uri, Uri baseUri) { if (!uri.IsAbsoluteUri && baseUri != null) uri = new Uri(baseUri, uri); - return GetAssembly(uri).Assembly; + return GetAssembly(uri)?.Assembly; } /// @@ -113,7 +113,7 @@ namespace Avalonia.Shared.PlatformSupport { var assembly = GetAssembly(uri); - return assembly?.Resources.Where(x => x.Key.Contains(uri.AbsolutePath)) + return assembly?.Resources?.Where(x => x.Key.Contains(uri.AbsolutePath)) .Select(x =>new Uri($"resm:{x.Key}?assembly={assembly.Name}")) ?? Enumerable.Empty(); } @@ -139,7 +139,7 @@ namespace Avalonia.Shared.PlatformSupport return Enumerable.Empty(); } - private Uri EnsureAbsolute(Uri uri, Uri baseUri) + private Uri EnsureAbsolute(Uri uri, Uri? baseUri) { if (uri.IsAbsoluteUri) return uri; @@ -153,7 +153,7 @@ namespace Avalonia.Shared.PlatformSupport return new Uri(baseUri, uri); } - private IAssetDescriptor GetAsset(Uri uri, Uri baseUri) + private IAssetDescriptor? GetAsset(Uri uri, Uri? baseUri) { if (uri.IsAbsoluteUri && uri.Scheme == "resm") { @@ -166,10 +166,9 @@ namespace Avalonia.Shared.PlatformSupport "don't know where to look up for the resource, try specifying assembly explicitly."); } - IAssetDescriptor rv; - var resourceKey = uri.AbsolutePath; - asm.Resources.TryGetValue(resourceKey, out rv); + IAssetDescriptor? rv = null; + asm.Resources?.TryGetValue(resourceKey, out rv); return rv; } @@ -193,7 +192,7 @@ namespace Avalonia.Shared.PlatformSupport return (asm, uri.AbsolutePath); } - private AssemblyDescriptor GetAssembly(Uri uri) + private AssemblyDescriptor? GetAssembly(Uri? uri) { if (uri != null) { @@ -205,9 +204,8 @@ namespace Avalonia.Shared.PlatformSupport if (uri.Scheme == "resm") { var qs = ParseQueryString(uri); - string assemblyName; - if (qs.TryGetValue("assembly", out assemblyName)) + if (qs.TryGetValue("assembly", out var assemblyName)) { return GetAssembly(assemblyName); } @@ -222,8 +220,7 @@ namespace Avalonia.Shared.PlatformSupport if (name == null) throw new ArgumentNullException(nameof(name)); - AssemblyDescriptor rv; - if (!AssemblyNameCache.TryGetValue(name, out rv)) + if (!AssemblyNameCache.TryGetValue(name, out var rv)) { var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); var match = loadedAssemblies.FirstOrDefault(a => a.GetName().Name == name); @@ -275,7 +272,8 @@ namespace Avalonia.Shared.PlatformSupport public Stream GetStream() { - return _asm.GetManifestResourceStream(_name); + var s = _asm.GetManifestResourceStream(_name); + return s ?? throw new InvalidOperationException($"Could not find manifest resource stream '{_name}',"); } public Assembly Assembly => _asm; @@ -296,7 +294,9 @@ namespace Avalonia.Shared.PlatformSupport public Stream GetStream() { - return new SlicedStream(Assembly.GetManifestResourceStream(AvaloniaResourceName), _offset, _length); + var s = Assembly.GetManifestResourceStream(AvaloniaResourceName) ?? + throw new InvalidOperationException($"Could not find manifest resource stream '{AvaloniaResourceName}',"); + return new SlicedStream(s, _offset, _length); } } @@ -383,9 +383,9 @@ namespace Avalonia.Shared.PlatformSupport } public Assembly Assembly { get; } - public Dictionary Resources { get; } - public Dictionary AvaloniaResources { get; } - public string Name { get; } + public Dictionary? Resources { get; } + public Dictionary? AvaloniaResources { get; } + public string? Name { get; } } public static void RegisterResUriParsers() diff --git a/src/Web/Avalonia.Web.Blazor/WindowingPlatform.cs b/src/Web/Avalonia.Web.Blazor/WindowingPlatform.cs index a3f2de5b61..4439ec161c 100644 --- a/src/Web/Avalonia.Web.Blazor/WindowingPlatform.cs +++ b/src/Web/Avalonia.Web.Blazor/WindowingPlatform.cs @@ -12,7 +12,7 @@ namespace Avalonia.Web.Blazor public class BlazorWindowingPlatform : IWindowingPlatform, IPlatformSettings, IPlatformThreadingInterface { private bool _signaled; - private static int s_uiThreadId = -1; + private static KeyboardDevice? s_keyboard; public IWindowImpl CreateWindow() => throw new NotSupportedException(); @@ -26,16 +26,17 @@ namespace Avalonia.Web.Blazor return null; } - public static KeyboardDevice Keyboard { get; private set; } + public static KeyboardDevice Keyboard => s_keyboard ?? + throw new InvalidOperationException("BlazorWindowingPlatform not registered."); public static void Register() { var instance = new BlazorWindowingPlatform(); - Keyboard = new KeyboardDevice(); + s_keyboard = new KeyboardDevice(); AvaloniaLocator.CurrentMutable .Bind().ToSingleton() .Bind().ToSingleton() - .Bind().ToConstant(Keyboard) + .Bind().ToConstant(s_keyboard) .Bind().ToConstant(instance) .Bind().ToConstant(instance) .Bind().ToConstant(new RenderLoop())