Skip to content

Commit

Permalink
Fix 'WCTDP0010' with type parameters, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 committed Jan 2, 2025
1 parent 8782e14 commit e3a8de1
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ public override void Initialize(AnalysisContext context)
return;
}

bool isNullableValueType = propertySymbol.Type.IsNullableValueType();
bool isNullableType = !propertySymbol.Type.IsValueType || isNullableValueType;

// If the value is 'null', handle all possible cases:
// - Special placeholder for 'UnsetValue'
// - Explicit 'null' value
Expand All @@ -94,7 +91,7 @@ public override void Initialize(AnalysisContext context)
}

// Warn if the value is not nullable
if (!isNullableType)
if (!propertySymbol.Type.IsDefaultValueNull())
{
context.ReportDiagnostic(Diagnostic.Create(
InvalidPropertyDefaultValueNull,
Expand All @@ -106,7 +103,7 @@ public override void Initialize(AnalysisContext context)
else
{
// Get the target type with a special case for 'Nullable<T>'
ITypeSymbol propertyTypeSymbol = isNullableValueType
ITypeSymbol propertyTypeSymbol = propertySymbol.Type.IsNullableValueType()
? ((INamedTypeSymbol)propertySymbol.Type).TypeArguments[0]
: propertySymbol.Type;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ internal static class DiagnosticDescriptors
helpLinkUri: "https://aka.ms/toolkit/labs/windows");

/// <summary>
/// <c>The property '{0}' is declared with type '{1}', but 'DefaultValue' is set to 'null', which is not compatible (consider fixing the default value, or implementing the 'Get(ref object)' partial method to handle the type mismatch)</c>.
/// <c>The property '{0}' is declared with type '{1}', but 'DefaultValue' is set to 'null', which is not compatible (consider changing the default value, implementing the 'Get(ref object)' partial method to handle the type mismatch, or suppressing the diagnostic if this is the intended behavior)</c>.
/// </summary>
public static readonly DiagnosticDescriptor InvalidPropertyDefaultValueNull = new(
id: "WCTDP0010",
title: "Invalid 'null' default value for [GeneratedDependencyProperty] use",
messageFormat: "The property '{0}' is declared with type '{1}', but 'DefaultValue' is set to 'null', which is not compatible (consider fixing the default value, or implementing the 'Get(ref object)' partial method to handle the type mismatch)",
messageFormat: "The property '{0}' is declared with type '{1}', but 'DefaultValue' is set to 'null', which is not compatible (consider changing the default value, implementing the 'Get(ref object)' partial method to handle the type mismatch, or suppressing the diagnostic if this is the intended behavior)",
category: typeof(DependencyPropertyGenerator).FullName,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1431,6 +1431,35 @@ public partial class MyControl : Control
await CSharpAnalyzerTest<InvalidPropertyDefaultValueTypeAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
}

[TestMethod]
[DataRow("T1")]
[DataRow("T1?")]
[DataRow("T4?")]
public async Task InvalidPropertyDefaultValueTypeAnalyzer_TypeParameter_ExplicitNull_DoesNotWarn(string propertyType)
{
string source = $$"""
using System;
using CommunityToolkit.WinUI;
using Windows.UI.Xaml;
#nullable enable
namespace MyApp;
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
where T1 : class
where T3 : T2, new()
where T4 : unmanaged
where T5 : IDisposable
{
[GeneratedDependencyProperty(DefaultValue = null)]
public partial {{propertyType}} {|CS9248:Name|} { get; set; }
}
""";

await CSharpAnalyzerTest<InvalidPropertyDefaultValueTypeAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
}

[TestMethod]
public async Task InvalidPropertyDefaultValueTypeAnalyzer_NullValue_NonNullable_Warns()
{
Expand All @@ -1452,6 +1481,39 @@ public partial class MyControl : Control
await CSharpAnalyzerTest<InvalidPropertyDefaultValueTypeAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
}

[TestMethod]
[DataRow("T2")]
[DataRow("T2?")]
[DataRow("T3")]
[DataRow("T3?")]
[DataRow("T4")]
[DataRow("T5")]
[DataRow("T5?")]
public async Task InvalidPropertyDefaultValueTypeAnalyzer_TypeParameter_ExplicitNull_Warns(string propertyType)
{
string source = $$"""
using System;
using CommunityToolkit.WinUI;
using Windows.UI.Xaml;
#nullable enable
namespace MyApp;
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
where T1 : class
where T3 : T2, new()
where T4 : unmanaged
where T5 : IDisposable
{
[{|WCTDP0010:GeneratedDependencyProperty(DefaultValue = null)|}]
public partial {{propertyType}} {|CS9248:Name|} { get; set; }
}
""";

await CSharpAnalyzerTest<InvalidPropertyDefaultValueTypeAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
}

[TestMethod]
[DataRow("string", "42")]
[DataRow("string", "3.14")]
Expand Down

0 comments on commit e3a8de1

Please sign in to comment.