Skip to content

Commit 9560e3f

Browse files
committed
Properly forward nullability annotations for [ICommand]
1 parent 95c30fa commit 9560e3f

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

CommunityToolkit.Mvvm.SourceGenerators/Input/ICommandGenerator.Execute.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,8 @@ private static bool TryMapCommandTypesFromMethod(
419419
commandClassType = "global::CommunityToolkit.Mvvm.Input.RelayCommand";
420420
delegateType = "global::System.Action";
421421
supportsCancellation = false;
422-
commandTypeArguments = ImmutableArray.Create(parameter.Type.GetFullyQualifiedName());
423-
delegateTypeArguments = ImmutableArray.Create(parameter.Type.GetFullyQualifiedName());
422+
commandTypeArguments = ImmutableArray.Create(parameter.Type.GetFullyQualifiedNameWithNullabilityAnnotations());
423+
delegateTypeArguments = ImmutableArray.Create(parameter.Type.GetFullyQualifiedNameWithNullabilityAnnotations());
424424

425425
return true;
426426
}
@@ -453,7 +453,7 @@ private static bool TryMapCommandTypesFromMethod(
453453
delegateType = "global::System.Func";
454454
supportsCancellation = true;
455455
commandTypeArguments = ImmutableArray<string>.Empty;
456-
delegateTypeArguments = ImmutableArray.Create(singleParameter.Type.GetFullyQualifiedName(), "global::System.Threading.Tasks.Task");
456+
delegateTypeArguments = ImmutableArray.Create("global::System.Threading.CancellationToken", "global::System.Threading.Tasks.Task");
457457

458458
return true;
459459
}
@@ -463,8 +463,8 @@ private static bool TryMapCommandTypesFromMethod(
463463
commandClassType = "global::CommunityToolkit.Mvvm.Input.AsyncRelayCommand";
464464
delegateType = "global::System.Func";
465465
supportsCancellation = false;
466-
commandTypeArguments = ImmutableArray.Create(singleParameter.Type.GetFullyQualifiedName());
467-
delegateTypeArguments = ImmutableArray.Create(singleParameter.Type.GetFullyQualifiedName(), "global::System.Threading.Tasks.Task");
466+
commandTypeArguments = ImmutableArray.Create(singleParameter.Type.GetFullyQualifiedNameWithNullabilityAnnotations());
467+
delegateTypeArguments = ImmutableArray.Create(singleParameter.Type.GetFullyQualifiedNameWithNullabilityAnnotations(), "global::System.Threading.Tasks.Task");
468468

469469
return true;
470470
}
@@ -479,8 +479,8 @@ private static bool TryMapCommandTypesFromMethod(
479479
commandClassType = "global::CommunityToolkit.Mvvm.Input.AsyncRelayCommand";
480480
delegateType = "global::System.Func";
481481
supportsCancellation = true;
482-
commandTypeArguments = ImmutableArray.Create(firstParameter.Type.GetFullyQualifiedName());
483-
delegateTypeArguments = ImmutableArray.Create(firstParameter.Type.GetFullyQualifiedName(), secondParameter.Type.GetFullyQualifiedName(), "global::System.Threading.Tasks.Task");
482+
commandTypeArguments = ImmutableArray.Create(firstParameter.Type.GetFullyQualifiedNameWithNullabilityAnnotations());
483+
delegateTypeArguments = ImmutableArray.Create(firstParameter.Type.GetFullyQualifiedNameWithNullabilityAnnotations(), "global::System.Threading.CancellationToken", "global::System.Threading.Tasks.Task");
484484

485485
return true;
486486
}

tests/CommunityToolkit.Mvvm.UnitTests/Test_ICommandAttribute.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,23 @@ public async Task Test_ICommandAttribute_WithOnPrefixes()
500500
Assert.IsTrue(model.HasDownloadCommandRun);
501501
}
502502

503+
// See https://github.com/CommunityToolkit/dotnet/issues/283
504+
[TestMethod]
505+
public void Test_ICommandAttribute_VerifyNoWarningsForNullableValues()
506+
{
507+
ModelWithCommandsWithNullabilityAnnotations model = new();
508+
509+
// Here we just need to verify we don't get any warnings.
510+
// That is, that means the generated code has the right nullability annotations.
511+
model.NullableObjectCommand.Execute(null);
512+
model.ListWithNullableTypeCommand.Execute(null);
513+
model.ListWithNullableTypeCommand.Execute(new List<object?>());
514+
model.TupleWithNullableElementsCommand.Execute((DateTime.Now, null, null, null));
515+
model.TupleWithNullableElementsCommand.Execute((DateTime.Now, null, true, new List<string>()));
516+
model.TupleWithNullableElementsCommand.Execute((null, "Hello", null, null));
517+
model.TupleWithNullableElementsCommand.Execute((null, null, null, null));
518+
}
519+
503520
#region Region
504521
public class Region
505522
{
@@ -871,4 +888,22 @@ private async Task OnDownloadAsync()
871888
HasDownloadCommandRun = true;
872889
}
873890
}
891+
892+
partial class ModelWithCommandsWithNullabilityAnnotations
893+
{
894+
[ICommand]
895+
private void NullableObject(object? parameter)
896+
{
897+
}
898+
899+
[ICommand]
900+
private void ListWithNullableType(List<object?> parameter)
901+
{
902+
}
903+
904+
[ICommand]
905+
private void TupleWithNullableElements((DateTime? date, string? message, bool? shouldPrint, List<string>? stringList) parameter)
906+
{
907+
}
908+
}
874909
}

0 commit comments

Comments
 (0)