Revert source break in 1.8.0 parse methods#908
Conversation
This removes the `async` overloads to `parse` and `parseAsRoot` that caused a source break in 1.8.0, and introduces new names that disambiguate the methods with `async` behavior. Instead of calling the existing methods with the `await` keyword, users can call `await asyncParse` or `await asyncParseAsRoot`. This change also adds a validation step to the synchronous parsing path to check if an async completions function is called. Users that have already updated their code to work around the source break will revert to the old methods with this change, which will yield a "No 'async' operations occur within 'await' expression" warning. They can remove the `await` keyword or update to call the async versions directly to fix the warning.
rgoldberg
left a comment
There was a problem hiding this comment.
Using #if DEBUG to call the validator in the sync parse(_:) is a great idea.
I just suggest:
- Splitting the error text into 2 separate paragraphs to avoid "wall of text".
- Removing the
validateoverload, since it's unnecessary.
| let error = | ||
| AsyncCompletionsValidator | ||
| .validate(self.rootCommand, parent: nil, forcedSyncParse: true) |
There was a problem hiding this comment.
| let error = | |
| AsyncCompletionsValidator | |
| .validate(self.rootCommand, parent: nil, forcedSyncParse: true) | |
| !self.rootCommand.invalidAsyncCompletions( | |
| parent: nil, | |
| propertyPath: .init(describing: self.rootCommand) | |
| ) | |
| .isEmpty |
The validate overload is unnecessary.
| { | ||
| validate(type, parent: parent, forcedSyncParse: false) | ||
| } | ||
|
|
||
| static func validate( | ||
| _ type: ParsableArguments.Type, | ||
| parent: InputKey?, | ||
| forcedSyncParse: Bool | ||
| ) | ||
| -> ParsableArgumentsValidatorError? |
There was a problem hiding this comment.
| { | |
| validate(type, parent: parent, forcedSyncParse: false) | |
| } | |
| static func validate( | |
| _ type: ParsableArguments.Type, | |
| parent: InputKey?, | |
| forcedSyncParse: Bool | |
| ) | |
| -> ParsableArgumentsValidatorError? |
The validate overload is unnecessary.
| !(type is AsyncParsableCommand.Type) || forcedSyncParse | ||
| else { | ||
| return nil | ||
| } |
There was a problem hiding this comment.
| !(type is AsyncParsableCommand.Type) || forcedSyncParse | |
| else { | |
| return nil | |
| } | |
| !(type is AsyncParsableCommand.Type) | |
| else { return nil } |
The validate overload is unnecessary.
This & the other suggestion together just revert this file back to pre-PR version.
There was a problem hiding this comment.
I don't think it's unnecessary. This validator now gets called two ways:
- The validator process calls it. In that case, we want to verify that a root type that only conforms to
ParsableCommanddoesn't have anyasynccustom completion handlers declared, so we exit early iftypeconforms toAsyncParsableCommand. - The synchronous
parsemethod calls it. Here we are checking for anAsyncParsableCommand(which would have passed validation) that is being parsed synchronously. So we want to perform the "validation" step (aka find out if there are anyasynccustom completion handlers) even though the type (correctly) conforms toAsyncParsableCommand.
So we need a way to say "do this no matter what" in the validator.
There was a problem hiding this comment.
See the suggestion in my earlier comment.
Calling invalidAsyncCompletions(…) directly achieves "do this no matter what", because it avoids the guard in validate(…).
There was a problem hiding this comment.
Ha, right on! That's what I ended up doing in my change, just didn't parse that you'd already shown it upthread. 👍🏻
This removes the
asyncoverloads toparseandparseAsRootthat caused a source break in 1.8.0, and introduces new names that disambiguate the methods withasyncbehavior. Instead of calling the existing methods with theawaitkeyword, users can callawait asyncParseorawait asyncParseAsRoot.This change also adds a validation step to the synchronous parsing path to check if an async completions function is called.
Users that have already updated their code to work around the source break will revert to the old methods with this change, which will yield a "No 'async' operations occur within 'await' expression" warning. They can remove the
awaitkeyword or update to call the async versions directly to fix the warning.Resolves #907