diff --git a/Sources/ArgumentParser/Parsing/CommandParser.swift b/Sources/ArgumentParser/Parsing/CommandParser.swift index 8875772b..f037f5d6 100644 --- a/Sources/ArgumentParser/Parsing/CommandParser.swift +++ b/Sources/ArgumentParser/Parsing/CommandParser.swift @@ -157,6 +157,9 @@ extension CommandParser { // after decoding a command, make sure to validate it do { try parsedCommand.validate() + var lastArgument = decodedArguments.removeLast() + lastArgument.value = parsedCommand + decodedArguments.append(lastArgument) } catch { try checkForBuiltInFlags(split) throw CommandError(commandStack: commandStack, parserError: ParserError.userValidationError(error)) diff --git a/Tests/ArgumentParserEndToEndTests/ValidationEndToEndTests.swift b/Tests/ArgumentParserEndToEndTests/ValidationEndToEndTests.swift index 8228c490..79e2cda2 100644 --- a/Tests/ArgumentParserEndToEndTests/ValidationEndToEndTests.swift +++ b/Tests/ArgumentParserEndToEndTests/ValidationEndToEndTests.swift @@ -146,3 +146,28 @@ extension ValidationEndToEndTests { AssertFullErrorMessage(Foo.self, ["--fail-silently", "Joe"], "") } } + +fileprivate struct FooCommand: ParsableCommand { + @Flag(help: .hidden) + var foo = false + @Flag(help: .hidden) + var bar = false + + mutating func validate() throws { + if foo { + // --foo implies --bar + bar = true + } + } + + func run() throws { + XCTAssertEqual(foo, bar) + } +} + +extension ValidationEndToEndTests { + func testMutationsPreserved() throws { + var foo = try FooCommand.parseAsRoot(["--foo"]) + try foo.run() + } +}