diff --git a/Sources/ArgumentParser/Parsable Properties/ArgumentVisibility.swift b/Sources/ArgumentParser/Parsable Properties/ArgumentVisibility.swift index 0eb4872d..452cc635 100644 --- a/Sources/ArgumentParser/Parsable Properties/ArgumentVisibility.swift +++ b/Sources/ArgumentParser/Parsable Properties/ArgumentVisibility.swift @@ -57,4 +57,28 @@ extension ArgumentVisibility { internal func isAtLeastAsVisible(as other: Self) -> Bool { self.base._comparableLevel >= other.base._comparableLevel } + + /// Reduce the visibility to a specified level if it is more restricted than the current value. + internal mutating func reduce(to: ArgumentVisibility) { + switch to.base { + case .default: + break // No effect + case .hidden: + if case .default = self.base { + self.base = .hidden + } + case .private: + self.base = .private + } + } +} + +extension ArgumentDefinition { + internal func reducingHelpVisibility(to visibility: ArgumentVisibility) + -> Self + { + var result = self + result.help.visibility.reduce(to: visibility) + return result + } } diff --git a/Sources/ArgumentParser/Parsable Properties/OptionGroup.swift b/Sources/ArgumentParser/Parsable Properties/OptionGroup.swift index 86ca04df..0a0d82cc 100644 --- a/Sources/ArgumentParser/Parsable Properties/OptionGroup.swift +++ b/Sources/ArgumentParser/Parsable Properties/OptionGroup.swift @@ -88,6 +88,9 @@ public struct OptionGroup: Decodable, ParsedWrapper { $0.help.parentTitle = title } } + args.content = args.content.map { arg in + arg.reducingHelpVisibility(to: visibility) + } return args }) self._visibility = visibility diff --git a/Sources/ArgumentParser/Parsable Types/ParsableArguments.swift b/Sources/ArgumentParser/Parsable Types/ParsableArguments.swift index 354d944b..9b5ebd61 100644 --- a/Sources/ArgumentParser/Parsable Types/ParsableArguments.swift +++ b/Sources/ArgumentParser/Parsable Types/ParsableArguments.swift @@ -316,9 +316,6 @@ extension ArgumentSet { guard let codingKey = child.label else { return nil } if let parsed = child.value as? ArgumentSetProvider { - guard parsed._visibility.isAtLeastAsVisible(as: visibility) - else { return nil } - let key = InputKey(name: codingKey, parent: parent) return parsed.argumentSet(for: key) } else { diff --git a/Tests/ArgumentParserUnitTests/HelpGenerationTests+GroupName.swift b/Tests/ArgumentParserUnitTests/HelpGenerationTests+GroupName.swift index 9128369b..8ac5d396 100644 --- a/Tests/ArgumentParserUnitTests/HelpGenerationTests+GroupName.swift +++ b/Tests/ArgumentParserUnitTests/HelpGenerationTests+GroupName.swift @@ -233,6 +233,43 @@ extension HelpGenerationTests { """) } + fileprivate struct NestedGroups: ParsableArguments { + @OptionGroup(visibility: .hidden) + var flagsAndOptions: FlagsAndOptions + + @OptionGroup(visibility: .private) + var argsAndFlags: ArgsAndFlags + } + + fileprivate struct NestedHiddenGroups: ParsableCommand { + @OptionGroup() + var nested: NestedGroups + } + + func testNestedHiddenGroups() { + AssertHelp( + .default, for: NestedHiddenGroups.self, + equals: """ + USAGE: nested-hidden-groups + + OPTIONS: + -h, --help Show help information. + + """) + + AssertHelp( + .hidden, for: NestedHiddenGroups.self, + equals: """ + USAGE: nested-hidden-groups [--experimental] --prefix + + OPTIONS: + --experimental example + --prefix example + -h, --help Show help information. + + """) + } + fileprivate struct ParentWithGroups: ParsableCommand { static var configuration: CommandConfiguration { .init(subcommands: [ChildWithGroups.self])