Skip to content

SetAction will accept a Func<InvocationContext, CancellationToken, Task<int>> callback and not observe the returned exit code. #2109

Closed
@jander-msft

Description

@jander-msft

The new refactor to change SetHandler to SetAction introduced a new undesirable behavior in that actions that return a Task<int> will not have the result observed and returned from the invoked command.

static async Task<int> Main(string[] args)
{
    RootCommand command = new();
    command.SetAction(CommandAction);

    int result = await command.InvokeAsync(string.Empty);
    // This is 0 (unexpected) but expected to be 42.
    return result;
}

static Task<int> CommandAction(InvocationContext context, CancellationToken token)
{
    return Task.FromResult(42);
}

While I understand that pay-for-play was intended in #2095, the compiler is more than happy to allow Func<InvocationContext, CancellationToken, Task<int>> callbacks to be used for the SetAction method when it's parameter type is Func<InvocationContext, CancellationToken, Task>. The underlying AnnonymousCliAction doesn't check if the returned Task is actually a Task<int> and blindly returns 0.

Because it's valid to pass a Func<InvocationContext, CancellationToken, Task<int>> callback, it is non-obvious that the result will not actually be observed and the developer may have difficulty understanding why their program is not return non-zero exit codes for failure cases.

Suggested Fixes:

Either the AnnonymousCliAction.InvokeAsync should check if the returned Task is actually Task<int> OR a new method should be added to Command that accepts a Func<InvocationContext, CancellationToken, Task<int>> callback.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions