Skip to content

Commit d6743ba

Browse files
committed
Emit diagnostics even if default value is not constant
1 parent 515a42c commit d6743ba

File tree

2 files changed

+67
-10
lines changed

2 files changed

+67
-10
lines changed

components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/Diagnostics/Analyzers/UseGeneratedDependencyPropertyOnManualPropertyAnalyzer.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -736,19 +736,19 @@ void HandleSetAccessor(IPropertySymbol propertySymbol, PropertyFlags propertyFla
736736
// pretending this were the empty string literal instead. This way we can still support the property and convert to an attribute.
737737
fieldFlags.DefaultValue = TypedConstantInfo.Primitive.String.Empty;
738738
}
739-
else
739+
else if (fieldFlags.DefaultValueOperation is IDefaultValueOperation { Type: { } defaultValueExpressionType })
740740
{
741-
// If we don't have a constant, check if it's some constant value we can forward. In this case, we
742-
// did not retrieve it. As a last resort, check if this is explicitly a 'default(T)' expression.
743-
if (fieldFlags.DefaultValueOperation is not IDefaultValueOperation { Type: { } defaultValueExpressionType })
744-
{
745-
continue;
746-
}
747-
748-
// Store the expression type for later, so we can validate it. We cannot validate it from here, as we
749-
// only see the declared property type for metadata. This isn't guaranteed to match the property type.
741+
// We don't have a constant. As a last resort, check if this is explicitly a 'default(T)' expression.
742+
// If so, store the expression type for later, so we can validate it. We cannot validate it here, as
743+
// we still want to execute the rest of the checks below to potentially emit more diagnostics first.
750744
fieldFlags.DefaultValueExpressionType = defaultValueExpressionType;
751745
}
746+
else
747+
{
748+
// At this point we know the property cannot possibly be converted, so mark it as invalid. We do this
749+
// rather than returning immediately, to still allow more diagnostics to be produced in the steps below.
750+
fieldFlags.HasAnyDiagnostics = true;
751+
}
752752
}
753753
}
754754

components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.Tests/Test_Analyzers.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,6 +2234,63 @@ public partial class MyControl : Control
22342234
await CSharpAnalyzerTest<UseGeneratedDependencyPropertyOnManualPropertyAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
22352235
}
22362236

2237+
// Regression test for a case found in the Microsoft Store
2238+
[TestMethod]
2239+
public async Task UseGeneratedDependencyPropertyOnManualPropertyAnalyzer_InvalidRegisterArguments_WCTDP0030_WithObjectInitialization_DoesNotWarn()
2240+
{
2241+
const string source = """
2242+
using Windows.UI.Xaml;
2243+
using Windows.UI.Xaml.Controls;
2244+
2245+
namespace MyApp;
2246+
2247+
public partial class MyControl : Control
2248+
{
2249+
public static readonly DependencyProperty MarginProperty = DependencyProperty.Register(
2250+
nameof(Margin),
2251+
{|WCTDP0030:typeof(double)|},
2252+
typeof(MyControl),
2253+
new PropertyMetadata({|WCTDP0032:new Thickness(0)|}));
2254+
2255+
private Thickness Margin
2256+
{
2257+
get => (Thickness)GetValue(MarginProperty);
2258+
set => SetValue(MarginProperty, value);
2259+
}
2260+
}
2261+
""";
2262+
2263+
await CSharpAnalyzerTest<UseGeneratedDependencyPropertyOnManualPropertyAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
2264+
}
2265+
2266+
[TestMethod]
2267+
public async Task UseGeneratedDependencyPropertyOnManualPropertyAnalyzer_InvalidRegisterArguments_WCTDP0030_WithExplicitDefaultValueNull_DoesNotWarn()
2268+
{
2269+
const string source = """
2270+
using Windows.UI.Xaml;
2271+
using Windows.UI.Xaml.Controls;
2272+
2273+
namespace MyApp;
2274+
2275+
public partial class MyControl : Control
2276+
{
2277+
public static readonly DependencyProperty MarginProperty = DependencyProperty.Register(
2278+
nameof(Margin),
2279+
{|WCTDP0030:typeof(double)|},
2280+
typeof(MyControl),
2281+
new PropertyMetadata({|WCTDP0031:null|}));
2282+
2283+
private Thickness Margin
2284+
{
2285+
get => (Thickness)GetValue(MarginProperty);
2286+
set => SetValue(MarginProperty, value);
2287+
}
2288+
}
2289+
""";
2290+
2291+
await CSharpAnalyzerTest<UseGeneratedDependencyPropertyOnManualPropertyAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
2292+
}
2293+
22372294
// Regression test for a case found in https://github.com/jenius-apps/ambie
22382295
[TestMethod]
22392296
public async Task UseGeneratedDependencyPropertyOnManualPropertyAnalyzer_InvalidRegisterArguments_WCTDP0030_WithInvalidPropertyName_DoesNotWarn()

0 commit comments

Comments
 (0)