Skip to content

Commit f7f3e86

Browse files
committed
Analyze more cases even with invalid field declarations
1 parent c8835d3 commit f7f3e86

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,16 +191,16 @@ public override void Initialize(AnalysisContext context)
191191
}
192192
else if (memberSymbol is IFieldSymbol
193193
{
194-
DeclaredAccessibility: Accessibility.Public,
195194
IsStatic: true,
196-
IsReadOnly: true,
197195
IsFixedSizeBuffer: false,
198196
IsRequired: false,
199197
Type.IsReferenceType: true,
200198
IsVolatile: false
201199
} fieldSymbol)
202200
{
203-
// We only care about fields that are 'DependencyProperty'
201+
// We only care about fields that are 'DependencyProperty'. Note that we should also be checking the declared
202+
// accessibility here and the fact the field is readonly, but we delay that in the initialization callback.
203+
// This is done so that we can still emit more diagnostics when analyzing the symbol completes below.
204204
if (!SymbolEqualityComparer.Default.Equals(dependencyPropertySymbol, fieldSymbol.Type))
205205
{
206206
continue;
@@ -395,6 +395,16 @@ void HandleSetAccessor(IPropertySymbol propertySymbol, PropertyFlags propertyFla
395395
fieldFlags.FieldSymbol = fieldSymbol;
396396
}
397397

398+
// Do the accessibility and readonly check here, to still enable diagnostics at the end in more scenarios.
399+
// If the field is invalid, just mark it as such, but continue executing the rest of the analysis here.
400+
if (fieldSymbol is { DeclaredAccessibility: not Accessibility.Public } or { IsReadOnly: false })
401+
{
402+
if (fieldFlags is not null)
403+
{
404+
fieldFlags.HasAnyDiagnostics = true;
405+
}
406+
}
407+
398408
// Additional diagnostic #1: the dependency property field name should have the "Property" suffix
399409
if (!fieldSymbol.Name.EndsWith("Property"))
400410
{

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3226,6 +3226,64 @@ public void Dispose()
32263226
await CSharpAnalyzerTest<UseGeneratedDependencyPropertyOnManualPropertyAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
32273227
}
32283228

3229+
[TestMethod]
3230+
[DataRow("private static readonly")]
3231+
[DataRow("public static")]
3232+
public async Task UseGeneratedDependencyPropertyOnManualPropertyAnalyzer_InvalidFieldDeclaration_DoesNotWarn(string fieldDeclaration)
3233+
{
3234+
string source = $$"""
3235+
using Windows.UI.Xaml;
3236+
3237+
namespace MyApp;
3238+
3239+
public partial class MyObject : DependencyObject
3240+
{
3241+
{{fieldDeclaration}} DependencyProperty NameProperty = DependencyProperty.Register(
3242+
name: "Name",
3243+
propertyType: typeof(string),
3244+
ownerType: typeof(MyObject),
3245+
typeMetadata: null);
3246+
3247+
public string? Name
3248+
{
3249+
get => (string?)GetValue(NameProperty);
3250+
set => SetValue(NameProperty, value);
3251+
}
3252+
}
3253+
""";
3254+
3255+
await CSharpAnalyzerTest<UseGeneratedDependencyPropertyOnManualPropertyAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
3256+
}
3257+
3258+
[TestMethod]
3259+
[DataRow("private static readonly")]
3260+
[DataRow("public static")]
3261+
public async Task UseGeneratedDependencyPropertyOnManualPropertyAnalyzer_InvalidFieldDeclaration_EmitsAdditionalDiagnosticsToo_DoesNotWarn(string fieldDeclaration)
3262+
{
3263+
string source = $$"""
3264+
using Windows.UI.Xaml;
3265+
3266+
namespace MyApp;
3267+
3268+
public partial class MyObject : DependencyObject
3269+
{
3270+
{{fieldDeclaration}} DependencyProperty NameProperty = DependencyProperty.Register(
3271+
{|WCTDPG0027:{|WCTDPG0028:name: "Name2"|}|},
3272+
{|WCTDPG0030:propertyType: typeof(int?)|},
3273+
ownerType: typeof(MyObject),
3274+
typeMetadata: null);
3275+
3276+
public string? Name
3277+
{
3278+
get => (string?)GetValue(NameProperty);
3279+
set => SetValue(NameProperty, value);
3280+
}
3281+
}
3282+
""";
3283+
3284+
await CSharpAnalyzerTest<UseGeneratedDependencyPropertyOnManualPropertyAnalyzer>.VerifyAnalyzerAsync(source, LanguageVersion.CSharp13);
3285+
}
3286+
32293287
[TestMethod]
32303288
public async Task InvalidPropertyForwardedAttributeDeclarationAnalyzer_NoDependencyPropertyAttribute_DoesNotWarn()
32313289
{

0 commit comments

Comments
 (0)