From c8835d3cac34a0b321bf9b6b8e1c6c8ad385819a Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Mon, 6 Jan 2025 12:27:43 +0100 Subject: [PATCH] Analyze default values even if callback is present --- ...endencyPropertyOnManualPropertyAnalyzer.cs | 9 +- .../Test_Analyzers.cs | 102 ++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/Diagnostics/Analyzers/UseGeneratedDependencyPropertyOnManualPropertyAnalyzer.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/Diagnostics/Analyzers/UseGeneratedDependencyPropertyOnManualPropertyAnalyzer.cs index a66f3e7d..893f491d 100644 --- a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/Diagnostics/Analyzers/UseGeneratedDependencyPropertyOnManualPropertyAnalyzer.cs +++ b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/Diagnostics/Analyzers/UseGeneratedDependencyPropertyOnManualPropertyAnalyzer.cs @@ -511,10 +511,15 @@ void HandleSetAccessor(IPropertySymbol propertySymbol, PropertyFlags propertyFla return; } - // If we have a second argument, a 'null' literal is the only supported value for it + // If we have a second argument, a 'null' literal is the only supported value for it. If that's not the case, + // we mark the propertry as not valid, but don't stop here. The reason is that even if we do have a callback, + // meaning we cannot enable the code fixer, we still want to analyze the default value argument. if (objectCreationOperation.Arguments is not ([_] or [_, { Value.ConstantValue: { HasValue: true, Value: null } }])) { - return; + if (fieldFlags is not null) + { + fieldFlags.HasAnyDiagnostics = true; + } } bool isDependencyPropertyUnsetValue = false; diff --git a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.Tests/Test_Analyzers.cs b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.Tests/Test_Analyzers.cs index 5edf3dd4..a9d7878f 100644 --- a/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.Tests/Test_Analyzers.cs +++ b/components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.Tests/Test_Analyzers.cs @@ -2332,6 +2332,108 @@ public Visibility VolumeVisible await CSharpAnalyzerTest.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13); } + // Regression test for a case found in the Microsoft Store + [TestMethod] + [DataRow("default(float)")] + [DataRow("1.0F")] + [DataRow("(float)1.0")] + public async Task UseGeneratedDependencyPropertyOnManualPropertyAnalyzer_InvalidRegisterArguments_WCTDPG0030_WithMismatchedNullableUnderlyingType_DoesNotWarn(string defaultValue) + { + string source = $$""" + using Windows.UI.Xaml; + + namespace MyApp; + + public partial class MyObject : DependencyObject + { + public static readonly DependencyProperty Value1Property = DependencyProperty.Register( + nameof(Value1), + typeof(int?), + typeof(MyObject), + new PropertyMetadata({|WCTDPG0032:{{defaultValue}}|})); + + public static readonly DependencyProperty Value2Property = DependencyProperty.Register( + nameof(Value2), + {|WCTDPG0030:typeof(int?)|}, + typeof(MyObject), + new PropertyMetadata({|WCTDPG0032:{{defaultValue}}|})); + + public static readonly DependencyProperty Value3Property = DependencyProperty.Register( + "Value3", + typeof(int?), + typeof(MyObject), + new PropertyMetadata({|WCTDPG0032:{{defaultValue}}|})); + + public int? {|WCTDPG0017:Value1|} + { + get => (int?)GetValue(Value1Property); + set => SetValue(Value1Property, value); + } + + public float Value2 + { + get => (float)GetValue(Value2Property); + set => SetValue(Value2Property, value); + } + } + """; + + await CSharpAnalyzerTest.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13); + } + + // Same as above, but with property changed callbacks too + [TestMethod] + [DataRow("default(float)")] + [DataRow("1.0F")] + [DataRow("(float)1.0")] + public async Task UseGeneratedDependencyPropertyOnManualPropertyAnalyzer_InvalidRegisterArguments_WCTDPG0030_WithMismatchedNullableUnderlyingType_WithCallbacks_DoesNotWarn(string defaultValue) + { + string source = $$""" + using Windows.UI.Xaml; + + namespace MyApp; + + public partial class MyObject : DependencyObject + { + public static readonly DependencyProperty Value1Property = DependencyProperty.Register( + nameof(Value1), + typeof(int?), + typeof(MyObject), + new PropertyMetadata({|WCTDPG0032:{{defaultValue}}|}, ItemSourcePropertyChanged)); + + public static readonly DependencyProperty Value2Property = DependencyProperty.Register( + nameof(Value2), + {|WCTDPG0030:typeof(int?)|}, + typeof(MyObject), + new PropertyMetadata({|WCTDPG0032:{{defaultValue}}|}, ItemSourcePropertyChanged)); + + public static readonly DependencyProperty Value3Property = DependencyProperty.Register( + "Value3", + typeof(int?), + typeof(MyObject), + new PropertyMetadata({|WCTDPG0032:{{defaultValue}}|}, ItemSourcePropertyChanged)); + + public int? Value1 + { + get => (int?)GetValue(Value1Property); + set => SetValue(Value1Property, value); + } + + public float Value2 + { + get => (float)GetValue(Value2Property); + set => SetValue(Value2Property, value); + } + + private static void ItemSourcePropertyChanged(object sender, DependencyPropertyChangedEventArgs args) + { + } + } + """; + + await CSharpAnalyzerTest.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13); + } + [TestMethod] [DataRow("\"Name\"", "typeof(string)", "typeof(string)", "null")] [DataRow("\"Name\"", "typeof(string)", "typeof(Control)", "null")]