Skip to content

Commit 86d689c

Browse files
committed
Update ICommandGenerator to generate cancel commands
1 parent 63a6676 commit 86d689c

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

CommunityToolkit.Mvvm.SourceGenerators/Input/ICommandGenerator.Execute.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,71 @@ public static ImmutableArray<MemberDeclarationSyntax> GetSyntax(CommandInfo comm
236236
.AddArgumentListArguments(commandCreationArguments.ToArray()))))
237237
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
238238

239+
// Conditionally declare the additional members for the cancel commands
240+
if (commandInfo.IncludeCancelCommand)
241+
{
242+
// Prepare all necessary member and type names
243+
string cancelCommandFieldName = $"{commandInfo.FieldName.Substring(0, commandInfo.FieldName.Length - "Command".Length)}CancelCommand";
244+
string cancelCommandPropertyName = $"{commandInfo.PropertyName.Substring(0, commandInfo.PropertyName.Length - "Command".Length)}CancelCommand";
245+
246+
// Construct the generated field for the cancel command as follows:
247+
//
248+
// /// <summary>The backing field for <see cref="<COMMAND_PROPERTY_NAME>"/></summary>
249+
// [global::System.CodeDom.Compiler.GeneratedCode("...", "...")]
250+
// private global::System.Windows.Input.ICommand? <CANCEL_COMMAND_FIELD_NAME>;
251+
FieldDeclarationSyntax cancelCommandFieldDeclaration =
252+
FieldDeclaration(
253+
VariableDeclaration(NullableType(IdentifierName("global::System.Windows.Input.ICommand")))
254+
.AddVariables(VariableDeclarator(Identifier(cancelCommandFieldName))))
255+
.AddModifiers(Token(SyntaxKind.PrivateKeyword))
256+
.AddAttributeLists(
257+
AttributeList(SingletonSeparatedList(
258+
Attribute(IdentifierName("global::System.CodeDom.Compiler.GeneratedCode"))
259+
.AddArgumentListArguments(
260+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ICommandGenerator).FullName))),
261+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ICommandGenerator).Assembly.GetName().Version.ToString()))))))
262+
.WithOpenBracketToken(Token(TriviaList(Comment($"/// <summary>The backing field for <see cref=\"{cancelCommandPropertyName}\"/>.</summary>")), SyntaxKind.OpenBracketToken, TriviaList())));
263+
264+
// Construct the generated property as follows (the explicit delegate cast is needed to avoid overload resolution conflicts):
265+
//
266+
// /// <summary>Gets an <see cref="global::System.Windows.Input.ICommand" instance that can be used to cancel <see cref="<COMMAND_PROPERTY_NAME>"/>.</summary>
267+
// [global::System.CodeDom.Compiler.GeneratedCode("...", "...")]
268+
// [global::System.Diagnostics.DebuggerNonUserCode]
269+
// [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
270+
// public global::System.Windows.Input.ICommand <CANCEL_COMMAND_PROPERTY_NAME> => <CANCEL_COMMAND_FIELD_NAME> ??= global::CommunityToolkit.Mvvm.Input.IAsyncRelayCommandExtensions.CreateCancelCommand(<COMMAND_PROPERTY_NAME>);
271+
PropertyDeclarationSyntax cancelCommandPropertyDeclaration =
272+
PropertyDeclaration(
273+
IdentifierName("global::System.Windows.Input.ICommand"),
274+
Identifier(cancelCommandPropertyName))
275+
.AddModifiers(Token(SyntaxKind.PublicKeyword))
276+
.AddAttributeLists(
277+
AttributeList(SingletonSeparatedList(
278+
Attribute(IdentifierName("global::System.CodeDom.Compiler.GeneratedCode"))
279+
.AddArgumentListArguments(
280+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ICommandGenerator).FullName))),
281+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ICommandGenerator).Assembly.GetName().Version.ToString()))))))
282+
.WithOpenBracketToken(Token(TriviaList(Comment(
283+
$"/// <summary>Gets an <see cref=\"global::System.Windows.Input.ICommand\"/> instance that can be used to cancel <see cref=\"{commandInfo.PropertyName}\"/>.</summary>")),
284+
SyntaxKind.OpenBracketToken,
285+
TriviaList())),
286+
AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))),
287+
AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))))
288+
.WithExpressionBody(
289+
ArrowExpressionClause(
290+
AssignmentExpression(
291+
SyntaxKind.CoalesceAssignmentExpression,
292+
IdentifierName(cancelCommandFieldName),
293+
InvocationExpression(
294+
MemberAccessExpression(
295+
SyntaxKind.SimpleMemberAccessExpression,
296+
IdentifierName("global::CommunityToolkit.Mvvm.Input.IAsyncRelayCommandExtensions"),
297+
IdentifierName("CreateCancelCommand")))
298+
.AddArgumentListArguments(Argument(IdentifierName(commandInfo.PropertyName))))))
299+
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
300+
301+
return ImmutableArray.Create<MemberDeclarationSyntax>(fieldDeclaration, propertyDeclaration, cancelCommandFieldDeclaration, cancelCommandPropertyDeclaration);
302+
}
303+
239304
return ImmutableArray.Create<MemberDeclarationSyntax>(fieldDeclaration, propertyDeclaration);
240305
}
241306

0 commit comments

Comments
 (0)