Skip to content

Commit fa6ef5b

Browse files
committed
Check for cancellation more often in generators
1 parent 327f07b commit fa6ef5b

8 files changed

+84
-4
lines changed

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ public static bool TryGetInfo(
6464
return false;
6565
}
6666

67+
token.ThrowIfCancellationRequested();
68+
6769
// Get the property type and name
6870
string typeNameWithNullabilityAnnotations = fieldSymbol.Type.GetFullyQualifiedNameWithNullabilityAnnotations();
6971
string fieldName = fieldSymbol.Name;
@@ -87,6 +89,8 @@ public static bool TryGetInfo(
8789
return false;
8890
}
8991

92+
token.ThrowIfCancellationRequested();
93+
9094
// Check for special cases that are explicitly not allowed
9195
if (IsGeneratedPropertyInvalid(propertyName, fieldSymbol.Type))
9296
{
@@ -102,6 +106,8 @@ public static bool TryGetInfo(
102106
return false;
103107
}
104108

109+
token.ThrowIfCancellationRequested();
110+
105111
using ImmutableArrayBuilder<string> propertyChangedNames = ImmutableArrayBuilder<string>.Rent();
106112
using ImmutableArrayBuilder<string> propertyChangingNames = ImmutableArrayBuilder<string>.Rent();
107113
using ImmutableArrayBuilder<string> notifiedCommandNames = ImmutableArrayBuilder<string>.Rent();
@@ -114,13 +120,17 @@ public static bool TryGetInfo(
114120
bool hasAnyValidationAttributes = false;
115121
bool isOldPropertyValueDirectlyReferenced = IsOldPropertyValueDirectlyReferenced(fieldSymbol, propertyName);
116122

123+
token.ThrowIfCancellationRequested();
124+
117125
// Get the nullability info for the property
118126
GetNullabilityInfo(
119127
fieldSymbol,
120128
semanticModel,
121129
out bool isReferenceTypeOrUnconstraindTypeParameter,
122130
out bool includeMemberNotNullOnSetAccessor);
123131

132+
token.ThrowIfCancellationRequested();
133+
124134
// Track the property changing event for the property, if the type supports it
125135
if (shouldInvokeOnPropertyChanging)
126136
{
@@ -137,16 +147,22 @@ public static bool TryGetInfo(
137147
hasOrInheritsClassLevelNotifyPropertyChangedRecipients = true;
138148
}
139149

150+
token.ThrowIfCancellationRequested();
151+
140152
// Get the class-level [NotifyDataErrorInfo] setting, if any
141153
if (TryGetNotifyDataErrorInfo(fieldSymbol, out bool isValidationTargetValid))
142154
{
143155
notifyDataErrorInfo = isValidationTargetValid;
144156
hasOrInheritsClassLevelNotifyDataErrorInfo = true;
145157
}
146158

159+
token.ThrowIfCancellationRequested();
160+
147161
// Gather attributes info
148162
foreach (AttributeData attributeData in fieldSymbol.GetAttributes())
149163
{
164+
token.ThrowIfCancellationRequested();
165+
150166
// Gather dependent property and command names
151167
if (TryGatherDependentPropertyChangedNames(fieldSymbol, attributeData, in propertyChangedNames, in builder) ||
152168
TryGatherDependentCommandNames(fieldSymbol, attributeData, in notifiedCommandNames, in builder))
@@ -194,6 +210,8 @@ public static bool TryGetInfo(
194210
}
195211
}
196212

213+
token.ThrowIfCancellationRequested();
214+
197215
// Gather explicit forwarded attributes info
198216
foreach (AttributeListSyntax attributeList in fieldSyntax.AttributeLists)
199217
{
@@ -205,6 +223,8 @@ public static bool TryGetInfo(
205223
continue;
206224
}
207225

226+
token.ThrowIfCancellationRequested();
227+
208228
foreach (AttributeSyntax attribute in attributeList.Attributes)
209229
{
210230
// Roslyn ignores attributes in an attribute list with an invalid target, so we can't get the AttributeData as usual.
@@ -250,6 +270,8 @@ public static bool TryGetInfo(
250270
}
251271
}
252272

273+
token.ThrowIfCancellationRequested();
274+
253275
// Log the diagnostic for missing ObservableValidator, if needed
254276
if (hasAnyValidationAttributes &&
255277
!fieldSymbol.ContainingType.InheritsFromFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableValidator"))
@@ -272,6 +294,8 @@ public static bool TryGetInfo(
272294
fieldSymbol.Name);
273295
}
274296

297+
token.ThrowIfCancellationRequested();
298+
275299
propertyInfo = new PropertyInfo(
276300
typeNameWithNullabilityAnnotations,
277301
fieldName,

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
4242
// Get the hierarchy info for the target symbol, and try to gather the property info
4343
HierarchyInfo hierarchy = HierarchyInfo.From(fieldSymbol.ContainingType);
4444

45+
token.ThrowIfCancellationRequested();
46+
4547
_ = Execute.TryGetInfo(fieldDeclaration, fieldSymbol, context.SemanticModel, token, out PropertyInfo? propertyInfo, out ImmutableArray<DiagnosticInfo> diagnostics);
4648

49+
token.ThrowIfCancellationRequested();
50+
4751
return (Hierarchy: hierarchy, new Result<PropertyInfo?>(propertyInfo, diagnostics));
4852
})
4953
.Where(static item => item.Hierarchy is not null);

src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.Execute.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections.Immutable;
77
using System.Linq;
8+
using System.Threading;
89
using CommunityToolkit.Mvvm.SourceGenerators.ComponentModel.Models;
910
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
1011
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
@@ -37,8 +38,9 @@ public static bool IsObservableValidator(INamedTypeSymbol typeSymbol)
3738
/// Gets the <see cref="ValidationInfo"/> instance from an input symbol.
3839
/// </summary>
3940
/// <param name="typeSymbol">The input <see cref="INamedTypeSymbol"/> instance to inspect.</param>
41+
/// <param name="token">The cancellation token for the current operation.</param>
4042
/// <returns>The resulting <see cref="ValidationInfo"/> instance for <paramref name="typeSymbol"/>.</returns>
41-
public static ValidationInfo GetInfo(INamedTypeSymbol typeSymbol)
43+
public static ValidationInfo GetInfo(INamedTypeSymbol typeSymbol, CancellationToken token)
4244
{
4345
using ImmutableArrayBuilder<string> propertyNames = ImmutableArrayBuilder<string>.Rent();
4446

@@ -49,6 +51,8 @@ public static ValidationInfo GetInfo(INamedTypeSymbol typeSymbol)
4951
continue;
5052
}
5153

54+
token.ThrowIfCancellationRequested();
55+
5256
ImmutableArray<AttributeData> attributes = memberSymbol.GetAttributes();
5357

5458
// Also include fields that are annotated with [ObservableProperty]. This is necessary because
@@ -79,6 +83,8 @@ public static ValidationInfo GetInfo(INamedTypeSymbol typeSymbol)
7983
propertyNames.Add(propertyName);
8084
}
8185

86+
token.ThrowIfCancellationRequested();
87+
8288
return new(
8389
typeSymbol.GetFullyQualifiedMetadataName(),
8490
typeSymbol.GetFullyQualifiedName(),

src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,17 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
4848
return default;
4949
}
5050

51+
token.ThrowIfCancellationRequested();
52+
5153
// Only select types inheriting from ObservableValidator
5254
if (!Execute.IsObservableValidator(typeSymbol))
5355
{
5456
return default;
5557
}
5658

57-
return Execute.GetInfo(typeSymbol);
59+
token.ThrowIfCancellationRequested();
60+
61+
return Execute.GetInfo(typeSymbol, token);
5862
})
5963
.Where(static item => item is not null)!;
6064

src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/TransitiveMembersGenerator.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,22 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
7777
// Gather all generation info, and any diagnostics
7878
TInfo? info = ValidateTargetTypeAndGetInfo(typeSymbol, context.Attributes[0], context.SemanticModel.Compilation, out ImmutableArray<DiagnosticInfo> diagnostics);
7979

80+
token.ThrowIfCancellationRequested();
81+
8082
// If there are any diagnostics, there's no need to compute the hierarchy info at all, just return them
8183
if (diagnostics.Length > 0)
8284
{
8385
return new Result<(HierarchyInfo, MetadataInfo?, TInfo?)>(default, diagnostics);
8486
}
8587

8688
HierarchyInfo hierarchy = HierarchyInfo.From(typeSymbol);
89+
90+
token.ThrowIfCancellationRequested();
91+
8792
MetadataInfo metadataInfo = new(typeSymbol.IsSealed, Execute.IsNullabilitySupported(context.SemanticModel.Compilation));
8893

94+
token.ThrowIfCancellationRequested();
95+
8996
return new Result<(HierarchyInfo, MetadataInfo?, TInfo?)>((hierarchy, metadataInfo, info), diagnostics);
9097
})
9198
.Where(static item => item is not null)!;

src/CommunityToolkit.Mvvm.SourceGenerators/Input/RelayCommandGenerator.Execute.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,13 @@ public static bool TryGetInfo(
5656
goto Failure;
5757
}
5858

59+
token.ThrowIfCancellationRequested();
60+
5961
// Get the command field and property names
6062
(string fieldName, string propertyName) = GetGeneratedFieldAndPropertyNames(methodSymbol);
6163

64+
token.ThrowIfCancellationRequested();
65+
6266
// Get the command type symbols
6367
if (!TryMapCommandTypesFromMethod(
6468
methodSymbol,
@@ -74,6 +78,8 @@ public static bool TryGetInfo(
7478
goto Failure;
7579
}
7680

81+
token.ThrowIfCancellationRequested();
82+
7783
// Check the switch to allow concurrent executions
7884
if (!TryGetAllowConcurrentExecutionsSwitch(
7985
methodSymbol,
@@ -85,6 +91,8 @@ public static bool TryGetInfo(
8591
goto Failure;
8692
}
8793

94+
token.ThrowIfCancellationRequested();
95+
8896
// Check the switch to control exception flow
8997
if (!TryGetFlowExceptionsToTaskSchedulerSwitch(
9098
methodSymbol,
@@ -96,18 +104,23 @@ public static bool TryGetInfo(
96104
goto Failure;
97105
}
98106

107+
token.ThrowIfCancellationRequested();
108+
99109
// Get the CanExecute expression type, if any
100110
if (!TryGetCanExecuteExpressionType(
101111
methodSymbol,
102112
attributeData,
103113
commandTypeArguments,
114+
token,
104115
in builder,
105116
out string? canExecuteMemberName,
106117
out CanExecuteExpressionType? canExecuteExpressionType))
107118
{
108119
goto Failure;
109120
}
110121

122+
token.ThrowIfCancellationRequested();
123+
111124
// Get the option to include a cancel command, if any
112125
if (!TryGetIncludeCancelCommandSwitch(
113126
methodSymbol,
@@ -120,6 +133,8 @@ public static bool TryGetInfo(
120133
goto Failure;
121134
}
122135

136+
token.ThrowIfCancellationRequested();
137+
123138
// Get all forwarded attributes (don't stop in case of errors, just ignore faulting attributes)
124139
GatherForwardedAttributes(
125140
methodSymbol,
@@ -129,6 +144,8 @@ public static bool TryGetInfo(
129144
out ImmutableArray<AttributeInfo> fieldAttributes,
130145
out ImmutableArray<AttributeInfo> propertyAttributes);
131146

147+
token.ThrowIfCancellationRequested();
148+
132149
commandInfo = new CommandInfo(
133150
methodSymbol.Name,
134151
fieldName,
@@ -749,6 +766,7 @@ private static bool TryGetIncludeCancelCommandSwitch(
749766
/// <param name="methodSymbol">The input <see cref="IMethodSymbol"/> instance to process.</param>
750767
/// <param name="attributeData">The <see cref="AttributeData"/> instance for <paramref name="methodSymbol"/>.</param>
751768
/// <param name="commandTypeArguments">The command type arguments, if any.</param>
769+
/// <param name="token">The cancellation token for the current operation.</param>
752770
/// <param name="diagnostics">The current collection of gathered diagnostics.</param>
753771
/// <param name="canExecuteMemberName">The resulting can execute member name, if available.</param>
754772
/// <param name="canExecuteExpressionType">The resulting expression type, if available.</param>
@@ -757,6 +775,7 @@ private static bool TryGetCanExecuteExpressionType(
757775
IMethodSymbol methodSymbol,
758776
AttributeData attributeData,
759777
ImmutableArray<string> commandTypeArguments,
778+
CancellationToken token,
760779
in ImmutableArrayBuilder<DiagnosticInfo> diagnostics,
761780
out string? canExecuteMemberName,
762781
out CanExecuteExpressionType? canExecuteExpressionType)
@@ -782,7 +801,7 @@ private static bool TryGetCanExecuteExpressionType(
782801
if (canExecuteSymbols.IsEmpty)
783802
{
784803
// Special case for when the target member is a generated property from [ObservableProperty]
785-
if (TryGetCanExecuteMemberFromGeneratedProperty(memberName, methodSymbol.ContainingType, commandTypeArguments, out canExecuteExpressionType))
804+
if (TryGetCanExecuteMemberFromGeneratedProperty(memberName, methodSymbol.ContainingType, commandTypeArguments, token, out canExecuteExpressionType))
786805
{
787806
canExecuteMemberName = memberName;
788807

@@ -892,12 +911,14 @@ private static bool TryGetCanExecuteExpressionFromSymbol(
892911
/// <param name="memberName">The member name passed to <c>[RelayCommand(CanExecute = ...)]</c>.</param>
893912
/// <param name="containingType">The containing type for the method annotated with <c>[RelayCommand]</c>.</param>
894913
/// <param name="commandTypeArguments">The type arguments for the command interface, if any.</param>
914+
/// <param name="token">The cancellation token for the current operation.</param>
895915
/// <param name="canExecuteExpressionType">The resulting can execute expression type, if available.</param>
896916
/// <returns>Whether or not <paramref name="canExecuteExpressionType"/> was set and the input symbol was valid.</returns>
897917
private static bool TryGetCanExecuteMemberFromGeneratedProperty(
898918
string memberName,
899919
INamedTypeSymbol containingType,
900920
ImmutableArray<string> commandTypeArguments,
921+
CancellationToken token,
901922
[NotNullWhen(true)] out CanExecuteExpressionType? canExecuteExpressionType)
902923
{
903924
foreach (ISymbol memberSymbol in containingType.GetAllMembers())
@@ -908,6 +929,8 @@ private static bool TryGetCanExecuteMemberFromGeneratedProperty(
908929
continue;
909930
}
910931

932+
token.ThrowIfCancellationRequested();
933+
911934
ImmutableArray<AttributeData> attributes = memberSymbol.GetAttributes();
912935

913936
// Only filter fields with the [ObservableProperty] attribute
@@ -991,6 +1014,8 @@ static void GatherForwardedAttributes(
9911014
continue;
9921015
}
9931016

1017+
token.ThrowIfCancellationRequested();
1018+
9941019
foreach (AttributeSyntax attribute in attributeList.Attributes)
9951020
{
9961021
// Get the symbol info for the attribute (once again just like in the [ObservableProperty] generator)

src/CommunityToolkit.Mvvm.SourceGenerators/Input/RelayCommandGenerator.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
4040
// Get the hierarchy info for the target symbol, and try to gather the command info
4141
HierarchyInfo? hierarchy = HierarchyInfo.From(methodSymbol.ContainingType);
4242

43+
token.ThrowIfCancellationRequested();
44+
4345
_ = Execute.TryGetInfo(
4446
methodSymbol,
4547
context.Attributes[0],
@@ -48,6 +50,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
4850
out CommandInfo? commandInfo,
4951
out ImmutableArray<DiagnosticInfo> diagnostics);
5052

53+
token.ThrowIfCancellationRequested();
54+
5155
return (Hierarchy: hierarchy, new Result<CommandInfo?>(commandInfo, diagnostics));
5256
})
5357
.Where(static item => item.Hierarchy is not null)!;

src/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,19 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
5252

5353
ImmutableArray<INamedTypeSymbol> interfaceSymbols = Execute.GetInterfaces(typeSymbol);
5454

55+
token.ThrowIfCancellationRequested();
56+
5557
// Check that the type implements at least one IRecipient<TMessage> interface
5658
if (interfaceSymbols.IsEmpty)
5759
{
5860
return default;
5961
}
6062

61-
return Execute.GetInfo(typeSymbol, interfaceSymbols);
63+
RecipientInfo info = Execute.GetInfo(typeSymbol, interfaceSymbols);
64+
65+
token.ThrowIfCancellationRequested();
66+
67+
return info;
6268
})
6369
.Where(static item => item is not null)!;
6470

0 commit comments

Comments
 (0)