Enable nullability in various test projects (#20374)

* Enable nullability in RenderTests

* Enable nullability in LeakTests

* Enable nullability in Skia.UnitTests

* Enable nullability in Generators.Tests

* Enable nullability in DesignerSupport.Tests

* Enable nullability in Build.Tasks.UnitTests
This commit is contained in:
Julien Lebosquain
2025-12-30 10:10:50 +01:00
committed by GitHub
parent 960cb39414
commit ee748802b3
24 changed files with 66 additions and 50 deletions
@@ -14,6 +14,7 @@
<Import Project="..\..\build\HarfBuzzSharp.props" />
<Import Project="..\..\build\XUnit.props" />
<Import Project="..\..\build\SharedVersion.props" />
<Import Project="..\..\build\NullableEnable.props" />
<ItemGroup>
<Content Include="..\TestFiles\BuildTasks\PInvoke\bin\$(Configuration)\$(AvsCurrentTargetFramework)\PInvoke.dll" Link="Assets\PInvoke.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@@ -40,11 +40,11 @@ internal class UnitTestBuildEngine : IBuildEngine, IDisposable
public bool ContinueOnError { get; }
public int LineNumberOfTaskNode { get; }
public int LineNumberOfTaskNode => 0;
public int ColumnNumberOfTaskNode { get; }
public int ColumnNumberOfTaskNode => 0;
public string ProjectFileOfTaskNode { get; }
public string ProjectFileOfTaskNode => string.Empty;
public IReadOnlyList<UnitTestBuildEngineMessage> Errors => _errors;
@@ -25,4 +25,5 @@
<ProjectReference Include="..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" />
</ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\NullableEnable.props" />
</Project>
@@ -9,6 +9,7 @@
<Import Project="..\..\build\XUnit.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\Microsoft.Reactive.Testing.props" />
<Import Project="..\..\build\NullableEnable.props" />
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj" />
<ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj" />
@@ -82,7 +82,7 @@ namespace Avalonia.DesignerSupport.Tests
var sessionId = Guid.NewGuid();
long handle = 0;
bool success = false;
string error = null;
string? error = null;
var resultMessageReceivedToken = new CancellationTokenSource();
@@ -1,15 +1,14 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Avalonia.DesignerSupport.Tests
{
static class Helpers
{
public static void StructDiff(object parsed, object expected) => StructDiff(parsed, expected, "{root}");
public static void StructDiff(object? parsed, object? expected) => StructDiff(parsed, expected, "{root}");
static void StructDiff(object parsed, object expected, string path)
static void StructDiff(object? parsed, object? expected, string path)
{
if (parsed == null && expected == null)
return;
@@ -17,7 +16,7 @@ namespace Avalonia.DesignerSupport.Tests
throw new Exception(
$"{path}: Null mismatch: {(parsed == null ? "null" : "not-null")} {(expected == null ? "null" : "not-null")}");
if (parsed.GetType() != expected.GetType())
if (parsed!.GetType() != expected!.GetType())
throw new Exception($"{path}: Type mismatch: {parsed.GetType()} {expected.GetType()}");
if (parsed is string || parsed.GetType().IsPrimitive)
@@ -21,27 +21,29 @@ namespace Avalonia.DesignerSupport.Tests
private const int TimeoutInMs = 1000;
private readonly List<IDisposable> _disposables = new List<IDisposable>();
private IAvaloniaRemoteTransportConnection _server;
private IAvaloniaRemoteTransportConnection _client;
private IAvaloniaRemoteTransportConnection? _server;
private IAvaloniaRemoteTransportConnection? _client;
private BlockingCollection<object> _serverMessages = new BlockingCollection<object>();
private BlockingCollection<object> _clientMessages = new BlockingCollection<object>();
private SynchronizationContext _originalContext;
private SynchronizationContext? _originalContext;
class DisabledSyncContext : SynchronizationContext
{
public override void Post(SendOrPostCallback d, object state)
public override void Post(SendOrPostCallback d, object? state)
{
throw new InvalidCastException("Not allowed");
}
public override void Send(SendOrPostCallback d, object state)
public override void Send(SendOrPostCallback d, object? state)
{
throw new InvalidCastException("Not allowed");
}
}
void Init(IMessageTypeResolver clientResolver = null, IMessageTypeResolver serverResolver = null)
[MemberNotNull(nameof(_server))]
[MemberNotNull(nameof(_client))]
void Init(IMessageTypeResolver? clientResolver = null, IMessageTypeResolver? serverResolver = null)
{
_originalContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(new DisabledSyncContext());
@@ -63,6 +65,7 @@ namespace Avalonia.DesignerSupport.Tests
_disposables.Add(_client);
_client.OnMessage += (_, m) => _clientMessages.Add(m);
tcs.Task.Wait();
Assert.NotNull(_server);
_disposables.Add(_server);
_server.OnMessage += (_, m) => _serverMessages.Add(m);
@@ -95,8 +98,10 @@ namespace Avalonia.DesignerSupport.Tests
{
if (t.IsArray)
{
var arr = Array.CreateInstance(t.GetElementType(), 1);
((IList)arr)[0] = GetRandomValue(t.GetElementType(), pathInfo);
var elementType = t.GetElementType();
Assert.NotNull(elementType);
var arr = Array.CreateInstance(elementType, 1);
((IList)arr)[0] = GetRandomValue(elementType, pathInfo);
return arr;
}
@@ -217,12 +222,12 @@ namespace Avalonia.DesignerSupport.Tests
public double Width { get; set; }
public int SomeNewProperty { get; set; }
public int[] SomeArrayProperty { get; set; }
public int[]? SomeArrayProperty { get; set; }
public class SubObject
{
public int Foo { get; set; }
}
public SubObject SubObjectProperty { get; set; }
public SubObject? SubObjectProperty { get; set; }
public double Height { get; set; }
}
}
@@ -21,4 +21,5 @@
<Import Project="..\..\build\UnitTests.NetCore.targets" />
<Import Project="..\..\build\XUnit.props" />
<Import Project="..\..\build\SharedVersion.props" />
<Import Project="..\..\build\NullableEnable.props" />
</Project>
@@ -36,7 +36,7 @@ public static class View
return await reader.ReadToEndAsync();
}
public static CSharpCompilation CreateAvaloniaCompilation(string excludedPattern = null)
public static CSharpCompilation CreateAvaloniaCompilation(string? excludedPattern = null)
{
var compilation = CSharpCompilation
.Create("AvaloniaLib", options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
@@ -73,4 +73,4 @@ public static class View
CSharpSyntaxTree.ParseText(
"using Avalonia.Controls;" +
"namespace Sample.App { public class BaseView<TViewModel> : UserControl { } }"));
}
}
@@ -6,6 +6,7 @@
<Import Project="..\..\build\XUnit.props" />
<Import Project="..\..\build\NetFX.props" />
<Import Project="..\..\build\SharedVersion.props" />
<Import Project="..\..\build\NullableEnable.props" />
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Controls.ColorPicker\Avalonia.Controls.ColorPicker.csproj" />
<ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
@@ -1,6 +1,4 @@
#nullable enable
using System;
using System;
using System.ComponentModel;
using System.Reactive.Subjects;
using System.Runtime.CompilerServices;
-2
View File
@@ -1,5 +1,3 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -1,14 +1,12 @@
using Avalonia.Rendering;
using System.Threading.Tasks;
using System;
namespace Avalonia.Skia.RenderTests
{
public class ManualRenderTimer : IRenderTimer
{
public event Action<TimeSpan> Tick;
public event Action<TimeSpan>? Tick;
public bool RunsInBackground => false;
public void TriggerTick() => Tick?.Invoke(TimeSpan.Zero);
public Task TriggerBackgroundTick() => Task.Run(TriggerTick);
}
}
+1 -1
View File
@@ -92,7 +92,7 @@ namespace Avalonia.Skia.RenderTests
}
}
protected void CompareImagesNoRenderer([CallerMemberName] string testName = "", string expectedName = null)
protected void CompareImagesNoRenderer([CallerMemberName] string testName = "", string? expectedName = null)
{
var expectedPath = Path.Combine(OutputPath, (expectedName ?? testName) + ".expected.png");
var actualPath = Path.Combine(OutputPath, testName + ".out.png");
@@ -44,6 +44,8 @@ static class TestRenderHelper
public static Task RenderToFile(Control target, string path, bool immediate, double dpi = 96)
{
var dir = Path.GetDirectoryName(path);
Assert.NotNull(dir);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
@@ -119,24 +121,23 @@ static class TestRenderHelper
{
var path = Directory.GetCurrentDirectory();
while (path.Length > 0 && Path.GetFileName(path) != "tests")
while (!string.IsNullOrEmpty(path) && Path.GetFileName(path) != "tests")
{
path = Path.GetDirectoryName(path);
}
Assert.NotNull(path);
return path;
}
private class TestDispatcherImpl : IDispatcherImpl
{
public bool CurrentThreadIsLoopThread => MainThread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId;
public bool CurrentThreadIsLoopThread => MainThread?.ManagedThreadId == Thread.CurrentThread.ManagedThreadId;
public Thread MainThread { get; set; }
public Thread? MainThread { get; set; }
#pragma warning disable 67
public event Action Signaled;
public event Action Timer;
#pragma warning restore 67
public event Action? Signaled { add { } remove { } }
public event Action? Timer { add { } remove { } }
public void Signal()
{
+3 -3
View File
@@ -12,7 +12,7 @@ namespace Avalonia.Skia.RenderTests
{
private readonly IRenderTarget _renderTarget;
public Size ClientSize { get; private set; }
internal IRenderer Renderer { get; private set; }
internal IRenderer Renderer { get; private set; } = null!;
IRenderer IRenderRoot.Renderer => Renderer;
IHitTester IRenderRoot.HitTester => new NullHitTester();
public double RenderScaling { get; }
@@ -25,9 +25,9 @@ namespace Avalonia.Skia.RenderTests
class NullHitTester : IHitTester
{
public IEnumerable<Visual> HitTest(Point p, Visual root, Func<Visual, bool> filter) => Array.Empty<Visual>();
public IEnumerable<Visual> HitTest(Point p, Visual root, Func<Visual, bool>? filter) => Array.Empty<Visual>();
public Visual HitTestFirst(Point p, Visual root, Func<Visual, bool> filter) => null;
public Visual? HitTestFirst(Point p, Visual root, Func<Visual, bool>? filter) => null;
}
internal void Initialize(IRenderer renderer, Control child)
@@ -36,4 +36,5 @@
<Import Project="..\..\build\ImageSharp.props" />
<Import Project="..\..\build\SkiaSharp.props" />
<Import Project="..\..\build\SharedVersion.props" />
<Import Project="..\..\build\NullableEnable.props" />
</Project>
@@ -8,6 +8,7 @@
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\Microsoft.Reactive.Testing.props" />
<Import Project="..\..\build\SharedVersion.props" />
<Import Project="..\..\build\NullableEnable.props" />
<ItemGroup>
<EmbeddedResource Include="..\Avalonia.RenderTests\Assets\**\*.ttf" LinkBase="Assets" />
<None Remove="Fonts\**\*.ttf" />
@@ -143,7 +143,7 @@ namespace Avalonia.Skia.UnitTests.Media
var result = FontManager.Current.TryGetGlyphTypeface(Typeface.Default, out var glyphTypeface);
Assert.True(result);
Assert.NotNull(glyphTypeface);
Assert.Equal("Noto Mono", glyphTypeface.FamilyName);
}
}
@@ -226,7 +226,7 @@ namespace Avalonia.Skia.UnitTests.Media
[Theory]
[InlineData("NotFound, Unknown", null)] // system fonts
[InlineData("/#NotFound, /#Unknown", "avares://some/path")] // embedded fonts
public void Should_Match_Character_With_Fallbacks(string familyName, string baseUri)
public void Should_Match_Character_With_Fallbacks(string familyName, string? baseUri)
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface.With(fontManagerImpl: new FontManagerImpl())))
{
@@ -379,7 +379,7 @@ namespace Avalonia.Skia.UnitTests.Media
var result = FontManager.Current.TryGetGlyphTypeface(new Typeface("Abc, Segoe UI"), out var glyphTypeface);
Assert.True(result);
Assert.NotNull(glyphTypeface);
Assert.Equal("Inter", glyphTypeface.FamilyName);
}
}
@@ -16,7 +16,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
public static TextRange TextRange => new TextRange(0, 50);
public TextRun GetTextRun(int textSourceIndex)
public TextRun? GetTextRun(int textSourceIndex)
{
if (textSourceIndex >= 50)
{
@@ -16,7 +16,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
_addEndOfParagraph = addEndOfParagraph;
}
public TextRun GetTextRun(int textSourceIndex)
public TextRun? GetTextRun(int textSourceIndex)
{
if (textSourceIndex >= _text.Length)
{
@@ -67,6 +67,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal("1 ", actual);
Assert.NotNull(textRun.Properties);
Assert.Equal(foreground, textRun.Properties.ForegroundBrush);
}
}
@@ -236,6 +237,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal("01", actual);
Assert.NotNull(textRun.Properties);
Assert.Equal(foreground, textRun.Properties.ForegroundBrush);
}
}
@@ -272,6 +274,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal("89", actual);
Assert.NotNull(textRun.Properties);
Assert.Equal(foreground, textRun.Properties.ForegroundBrush);
}
}
@@ -304,6 +307,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal(1, textRun.Length);
Assert.NotNull(textRun.Properties);
Assert.Equal(foreground, textRun.Properties.ForegroundBrush);
}
}
@@ -342,6 +346,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal("😄", actual);
Assert.NotNull(textRun.Properties);
Assert.Equal(foreground, textRun.Properties.ForegroundBrush);
}
}
@@ -435,9 +440,9 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
maxHeight: 125,
textStyleOverrides: spans);
Assert.Equal(foreground, layout.TextLines[0].TextRuns[1].Properties.ForegroundBrush);
Assert.Equal(foreground, layout.TextLines[1].TextRuns[0].Properties.ForegroundBrush);
Assert.Equal(foreground, layout.TextLines[2].TextRuns[0].Properties.ForegroundBrush);
Assert.Equal(foreground, layout.TextLines[0].TextRuns[1].Properties?.ForegroundBrush);
Assert.Equal(foreground, layout.TextLines[1].TextRuns[0].Properties?.ForegroundBrush);
Assert.Equal(foreground, layout.TextLines[2].TextRuns[0].Properties?.ForegroundBrush);
}
}
@@ -865,7 +870,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Brushes.Black,
flowDirection: FlowDirection.RightToLeft);
var firstRun = layout.TextLines[0].TextRuns[0] as ShapedTextRun;
var firstRun = Assert.IsType<ShapedTextRun>(layout.TextLines[0].TextRuns[0]);
var hit = layout.HitTestPoint(new Point());
@@ -891,7 +896,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
currentX += advance;
}
var secondRun = layout.TextLines[0].TextRuns[1] as ShapedTextRun;
var secondRun = Assert.IsType<ShapedTextRun>(layout.TextLines[0].TextRuns[1]);
hit = layout.HitTestPoint(new Point(firstRun.Size.Width, 0));
@@ -52,6 +52,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var splitResult = buffer.Split(1);
Assert.NotNull(splitResult.First);
Assert.Equal(1, splitResult.First.Length);
buffer = splitResult.Second;
@@ -61,6 +62,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
//\"๊
splitResult = buffer.Split(1);
Assert.NotNull(splitResult.First);
Assert.Equal(2, splitResult.First.Length);
buffer = splitResult.Second;
@@ -86,6 +88,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var first = splitResult.First;
Assert.NotNull(first);
Assert.Equal(6, first.Length);
}
}
@@ -101,6 +104,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var splitResult = buffer.Split(0);
Assert.NotNull(splitResult.First);
Assert.Equal(0, splitResult.First.Length);
Assert.NotNull(splitResult.Second);
@@ -23,4 +23,5 @@
<Import Project="..\..\..\..\build\ReferenceCoreLibraries.props" />
<Import Project="..\..\..\..\build\BuildTargets.targets" />
<Import Project="..\..\..\..\build\SourceGenerators.props" />
<Import Project="..\..\..\..\build\NullableEnable.props" />
</Project>