Skip to content

Commit 139068f

Browse files
committed
Enable class-level [NotifyDataErrorInfo] usage
1 parent 0f0d7bb commit 139068f

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ internal static class Execute
9090
ImmutableArray<string>.Builder notifiedCommandNames = ImmutableArray.CreateBuilder<string>();
9191
ImmutableArray<AttributeInfo>.Builder forwardedAttributes = ImmutableArray.CreateBuilder<AttributeInfo>();
9292
bool notifyRecipients = false;
93-
bool alsoValidateProperty = false;
93+
bool notifyDataErrorInfo = false;
9494
bool hasAnyValidationAttributes = false;
9595

9696
// Track the property changing event for the property, if the type supports it
@@ -108,6 +108,12 @@ internal static class Execute
108108
notifyRecipients = isBroadcastTargetValid;
109109
}
110110

111+
// Get the class-level [NotifyDataErrorInfo] setting, if any
112+
if (TryGetNotifyDataErrorInfo(fieldSymbol, out bool isValidationTargetValid))
113+
{
114+
notifyDataErrorInfo = isValidationTargetValid;
115+
}
116+
111117
// Gather attributes info
112118
foreach (AttributeData attributeData in fieldSymbol.GetAttributes())
113119
{
@@ -127,9 +133,9 @@ internal static class Execute
127133
}
128134

129135
// Check whether the property should also be validated
130-
if (TryGetIsValidatingProperty(fieldSymbol, attributeData, builder, out bool isValidationTargetValid))
136+
if (TryGetNotifyDataErrorInfo(fieldSymbol, attributeData, builder, out isValidationTargetValid))
131137
{
132-
alsoValidateProperty = isValidationTargetValid;
138+
notifyDataErrorInfo = isValidationTargetValid;
133139

134140
continue;
135141
}
@@ -171,7 +177,7 @@ internal static class Execute
171177
}
172178

173179
// Log the diagnostic for missing validation attributes, if any
174-
if (alsoValidateProperty && !hasAnyValidationAttributes)
180+
if (notifyDataErrorInfo && !hasAnyValidationAttributes)
175181
{
176182
builder.Add(
177183
MissingValidationAttributesForNotifyDataErrorInfoError,
@@ -190,7 +196,7 @@ internal static class Execute
190196
propertyChangedNames.ToImmutable(),
191197
notifiedCommandNames.ToImmutable(),
192198
notifyRecipients,
193-
alsoValidateProperty,
199+
notifyDataErrorInfo,
194200
forwardedAttributes.ToImmutable());
195201
}
196202

@@ -482,6 +488,35 @@ private static bool TryGetIsNotifyingRecipients(
482488
return false;
483489
}
484490

491+
/// <summary>
492+
/// Checks whether a given generated property should also validate its value.
493+
/// </summary>
494+
/// <param name="fieldSymbol">The input <see cref="IFieldSymbol"/> instance to process.</param>
495+
/// <param name="isValidationTargetValid">Whether or not the the property is in a valid target that can validate values.</param>
496+
/// <returns>Whether or not the generated property for <paramref name="fieldSymbol"/> used <c>[NotifyDataErrorInfo]</c>.</returns>
497+
private static bool TryGetNotifyDataErrorInfo(IFieldSymbol fieldSymbol, out bool isValidationTargetValid)
498+
{
499+
if (fieldSymbol.ContainingType?.HasOrInheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.NotifyDataErrorInfoAttribute") == true)
500+
{
501+
// If the containing type is valid, track it
502+
if (fieldSymbol.ContainingType.InheritsFromFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableValidator"))
503+
{
504+
isValidationTargetValid = true;
505+
506+
return true;
507+
}
508+
509+
// Otherwise, ignore the attribute but don't emit a diagnostic (same as above)
510+
isValidationTargetValid = false;
511+
512+
return true;
513+
}
514+
515+
isValidationTargetValid = false;
516+
517+
return false;
518+
}
519+
485520
/// <summary>
486521
/// Checks whether a given generated property should also validate its value.
487522
/// </summary>
@@ -490,7 +525,7 @@ private static bool TryGetIsNotifyingRecipients(
490525
/// <param name="diagnostics">The current collection of gathered diagnostics.</param>
491526
/// <param name="isValidationTargetValid">Whether or not the the property is in a valid target that can validate values.</param>
492527
/// <returns>Whether or not the generated property for <paramref name="fieldSymbol"/> used <c>[NotifyDataErrorInfo]</c>.</returns>
493-
private static bool TryGetIsValidatingProperty(
528+
private static bool TryGetNotifyDataErrorInfo(
494529
IFieldSymbol fieldSymbol,
495530
AttributeData attributeData,
496531
ImmutableArray<Diagnostic>.Builder diagnostics,

CommunityToolkit.Mvvm/ComponentModel/Attributes/NotifyDataErrorInfoAttribute.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ namespace CommunityToolkit.Mvvm.ComponentModel;
3838
/// }
3939
/// </code>
4040
/// </summary>
41-
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
41+
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
4242
public sealed class NotifyDataErrorInfoAttribute : Attribute
4343
{
4444
}

0 commit comments

Comments
 (0)