Skip to content

Conversation

cmcgee1024
Copy link
Contributor

@cmcgee1024 cmcgee1024 commented Aug 16, 2025

Create a property wrapper called ParentCommand that allows a subcommand to
gain access to the state of one of its parent commands based on the type.

Checklist

  • I've added at least one test that validates that my change is working, if appropriate
  • I've followed the code style of the rest of the project
  • I've read the Contribution Guidelines
  • I've updated the documentation if necessary

@cmcgee1024
Copy link
Contributor Author

@swift-ci please test

@natecook1000
Copy link
Member

I like this design, but with the generic property wrapper I'm not sure how @ParentCommand differs from @OptionGroup. The original PR cited re-using a subcommand type in different parts of the command hierarchy as a motivation; needing to specify the parent type would prevent that usage. Would it work to require that the wrappedValue of the property wrapper be any ParsableCommand?

@cmcgee1024
Copy link
Contributor Author

Would it work to require that the wrappedValue of the property wrapper be any ParsableCommand?

The ParentCommand property wrapper constrains the Value generic parameter to ParsableCommand so that the wrapper cannot be used on things that aren't commands.

Also, unlike the OptionGroup, the intent is to make it so that the options of the parent command aren't available as part of the child command's options. I believe that's the way that this patch should work. Maybe I'm missing something?

@cmcgee1024
Copy link
Contributor Author

@swift-ci please test

@cmcgee1024
Copy link
Contributor Author

@swift-ci please test

@cmcgee1024 cmcgee1024 marked this pull request as ready for review September 3, 2025 15:25
@cmcgee1024
Copy link
Contributor Author

@swift-ci please test

@cmcgee1024
Copy link
Contributor Author

@swift-ci please test

Copy link
Member

@natecook1000 natecook1000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @cmcgee1024! In addition to the notes here, could you include something in the tests that verifies that the parent command's contents aren't included in the child command's help screen?

Comment on lines 157 to 162
XCTAssertNotNil(toolInfo.command.arguments!.first { $0.valueName == "foo" })
let childInfo = toolInfo.command.subcommands!.first { cmd in
cmd.commandName == "child"
}
// It's not there in the child subcommand
XCTAssertNil(childInfo!.arguments!.first { $0.valueName == "foo" })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you leave out the force unwraps here? The output is a better when there's a test failure rather than a trap during the test.

@propertyWrapper
public struct ParentCommand<Value: ParsableCommand>: Decodable, ParsedWrapper {
internal var _parsedValue: Parsed<Value>
internal var _visibility: ArgumentVisibility
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this property?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property isn't needed. The visibility is always effectively hidden for parent command references. It's removed now.


/// A wrapper that adds a reference to a parent command.
///
/// Use the parent command wrapper to gain access to a parent command's state.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be useful to compare/contrast with @OptionGroup here. Something like:

Suggested change
/// Use the parent command wrapper to gain access to a parent command's state.
/// Use the `@ParentCommand` wrapper to gain access to a parent command's state.
/// The arguments, options, and flags in a `@ParentCommand` type are omitted from
/// the help screen for the including child command, and only appear in the parent's
/// help screen. To include the help in both screens, use the ``OptionGroup``
/// wrapper instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've incorporated this additional text in the latest commit.

Avoid using force unwrap in the test case

Add more detail to the ParentCommand property wrapper documentation to distinguish from OptionGroup
@cmcgee1024
Copy link
Contributor Author

Thanks, @cmcgee1024! In addition to the notes here, could you include something in the tests that verifies that the parent command's contents aren't included in the child command's help screen?

I believe that the first section of the test case verifies the child command's help screen to assert that there aren't parent options showing up in there: https://github.com/apple/swift-argument-parser/pull/802/files#diff-4e092f6da2faedbd5525e77af586a9fce9327b926db3225813b72ea6119e06b2R143

Copy link
Member

@natecook1000 natecook1000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cmcgee1024 Missed that part of the test, sorry! LGTM!

@natecook1000 natecook1000 merged commit 05cfc38 into apple:main Sep 12, 2025
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants