mirror of
https://github.com/apple/swift-argument-parser.git
synced 2026-06-06 20:18:23 +00:00
* Allow normal Swift default property initialization syntax This change allows the normal `var foo = "blah"` default initialization syntax for `Option`s, as a parallel initialization method as using the `default` parameter. * Add simple tests for default property initialization * Centralize some constructor logic into a private `init` Preparing for another no-initial value `init` to be added and the existing one with a `default` parameter to be deprecated * Deprecate previous `Option.init` with `default` parameter It's replaced with an `init` containing no default value parameter, which will be used when the user does not provide any value. Also add a (most likely unnecessary) sanity test to make sure initializations without a default value still work. Also copy out documentation to allow clean removal of the older `init` when the time comes. * Document added test cases * Correct punctuation * Extend standard default initialization syntax to `Option`s with `transform` parameters * Actually replace previous `init` with private version This mirrors the non-transform variants, and should have been included in the previous commits * Clean up usage of default parameter values Private `init` doesn't need defaults, and the deprecated public ones shouldn't have it to avoid confusion with the new methods * Clean up documentation Treat new initializers as the originally intended way to allow for clean removal of the deprecated methods Also add some additional documentation to the deprecated methods to help point users in the right direction * Extend standard default initialization to `Argument`s * Extend standard default initialization to `Flag`s * Default flags with inversions to nil/required * Extend standard default initialization to no-inversion boolean `Flags` Prints a warning when that default value is `true` instead of `false`, as the flag value will be pinned regardless of user input * Eliminate deprecation spam from default value initialization All examples and unit tests have been transitioned to the new syntax, with the exception of `SourceCompatEndToEndTests`, which should not have the old style removed until it is no longer valid source. * Add source compatibility tests for new default syntax and associated changes * Update top-level documentation
193 lines
6.3 KiB
Swift
193 lines
6.3 KiB
Swift
//===----------------------------------------------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift Argument Parser open source project
|
|
//
|
|
// Copyright (c) 2020 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import XCTest
|
|
import ArgumentParserTestHelpers
|
|
import ArgumentParser
|
|
|
|
final class NestedCommandEndToEndTests: XCTestCase {
|
|
}
|
|
|
|
// MARK: Single value String
|
|
|
|
fileprivate struct Foo: ParsableCommand {
|
|
static var configuration =
|
|
CommandConfiguration(subcommands: [Build.self, Package.self])
|
|
|
|
@Flag(name: .short)
|
|
var verbose: Bool = false
|
|
|
|
struct Build: ParsableCommand {
|
|
@OptionGroup() var foo: Foo
|
|
|
|
@Argument()
|
|
var input: String
|
|
}
|
|
|
|
struct Package: ParsableCommand {
|
|
static var configuration =
|
|
CommandConfiguration(subcommands: [Clean.self, Config.self])
|
|
|
|
@Flag(name: .short)
|
|
var force: Bool = false
|
|
|
|
struct Clean: ParsableCommand {
|
|
@OptionGroup() var foo: Foo
|
|
@OptionGroup() var package: Package
|
|
}
|
|
|
|
struct Config: ParsableCommand {
|
|
@OptionGroup() var foo: Foo
|
|
@OptionGroup() var package: Package
|
|
}
|
|
}
|
|
}
|
|
|
|
fileprivate func AssertParseFooCommand<A>(_ type: A.Type, _ arguments: [String], file: StaticString = #file, line: UInt = #line, closure: (A) throws -> Void) where A: ParsableCommand {
|
|
AssertParseCommand(Foo.self, type, arguments, file: file, line: line, closure: closure)
|
|
}
|
|
|
|
|
|
extension NestedCommandEndToEndTests {
|
|
func testParsing_package() throws {
|
|
AssertParseFooCommand(Foo.Package.self, ["package"]) { package in
|
|
XCTAssertFalse(package.force)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Clean.self, ["package", "clean"]) { clean in
|
|
XCTAssertEqual(clean.foo.verbose, false)
|
|
XCTAssertEqual(clean.package.force, false)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Clean.self, ["package", "-f", "clean"]) { clean in
|
|
XCTAssertEqual(clean.foo.verbose, false)
|
|
XCTAssertEqual(clean.package.force, true)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-v", "config"]) { config in
|
|
XCTAssertEqual(config.foo.verbose, true)
|
|
XCTAssertEqual(config.package.force, false)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Config.self, ["package", "config", "-v"]) { config in
|
|
XCTAssertEqual(config.foo.verbose, true)
|
|
XCTAssertEqual(config.package.force, false)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Config.self, ["-v", "package", "config"]) { config in
|
|
XCTAssertEqual(config.foo.verbose, true)
|
|
XCTAssertEqual(config.package.force, false)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-f", "config"]) { config in
|
|
XCTAssertEqual(config.foo.verbose, false)
|
|
XCTAssertEqual(config.package.force, true)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Config.self, ["package", "config", "-f"]) { config in
|
|
XCTAssertEqual(config.foo.verbose, false)
|
|
XCTAssertEqual(config.package.force, true)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-v", "config", "-f"]) { config in
|
|
XCTAssertEqual(config.foo.verbose, true)
|
|
XCTAssertEqual(config.package.force, true)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-f", "config", "-v"]) { config in
|
|
XCTAssertEqual(config.foo.verbose, true)
|
|
XCTAssertEqual(config.package.force, true)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-vf", "config"]) { config in
|
|
XCTAssertEqual(config.foo.verbose, true)
|
|
XCTAssertEqual(config.package.force, true)
|
|
}
|
|
|
|
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-fv", "config"]) { config in
|
|
XCTAssertEqual(config.foo.verbose, true)
|
|
XCTAssertEqual(config.package.force, true)
|
|
}
|
|
}
|
|
|
|
func testParsing_build() throws {
|
|
AssertParseFooCommand(Foo.Build.self, ["build", "file"]) { build in
|
|
XCTAssertEqual(build.foo.verbose, false)
|
|
XCTAssertEqual(build.input, "file")
|
|
}
|
|
}
|
|
|
|
func testParsing_fails() throws {
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["clean", "package"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["config", "package"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "c"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "build"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "build", "clean"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "clean", "foo"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "config", "bar"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "clean", "build"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["build"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["build", "-f"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["build", "--build"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["build", "--build", "12"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["-f", "package", "clean"]))
|
|
XCTAssertThrowsError(try Foo.parseAsRoot(["-f", "package", "config"]))
|
|
}
|
|
}
|
|
|
|
private struct Options: ParsableArguments {
|
|
@Option() var firstName: String?
|
|
}
|
|
|
|
private struct UniqueOptions: ParsableArguments {
|
|
@Option() var lastName: String?
|
|
}
|
|
|
|
private struct Super: ParsableCommand {
|
|
static var configuration: CommandConfiguration {
|
|
.init(subcommands: [Sub1.self, Sub2.self])
|
|
}
|
|
|
|
@OptionGroup() var options: Options
|
|
|
|
struct Sub1: ParsableCommand {
|
|
@OptionGroup() var options: Options
|
|
}
|
|
|
|
struct Sub2: ParsableCommand {
|
|
@OptionGroup() var options: UniqueOptions
|
|
}
|
|
}
|
|
|
|
extension NestedCommandEndToEndTests {
|
|
func testParsing_SharedOptions() throws {
|
|
AssertParseCommand(Super.self, Super.self, []) { sup in
|
|
XCTAssertNil(sup.options.firstName)
|
|
}
|
|
|
|
AssertParseCommand(Super.self, Super.self, ["--first-name", "Foo"]) { sup in
|
|
XCTAssertEqual("Foo", sup.options.firstName)
|
|
}
|
|
|
|
AssertParseCommand(Super.self, Super.Sub1.self, ["sub1"]) { sub1 in
|
|
XCTAssertNil(sub1.options.firstName)
|
|
}
|
|
|
|
AssertParseCommand(Super.self, Super.Sub1.self, ["sub1", "--first-name", "Foo"]) { sub1 in
|
|
XCTAssertEqual("Foo", sub1.options.firstName)
|
|
}
|
|
|
|
AssertParseCommand(Super.self, Super.Sub2.self, ["sub2", "--last-name", "Foo"]) { sub2 in
|
|
XCTAssertEqual("Foo", sub2.options.lastName)
|
|
}
|
|
}
|
|
}
|