Skip to content

Allow normal Swift default property initialization syntax #170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jun 23, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f918b83
Allow normal Swift default property initialization syntax
MPLew-is May 30, 2020
7517781
Merge branch 'master' into default-property-initialization
MPLew-is Jun 14, 2020
caa77a5
Add simple tests for default property initialization
MPLew-is Jun 14, 2020
07fd64f
Centralize some constructor logic into a private `init`
MPLew-is Jun 14, 2020
60ed36f
Deprecate previous `Option.init` with `default` parameter
MPLew-is Jun 14, 2020
b70dbf1
Document added test cases
MPLew-is Jun 14, 2020
3e32345
Correct punctuation
MPLew-is Jun 14, 2020
79f4fb6
Extend standard default initialization syntax to `Option`s with `tran…
MPLew-is Jun 14, 2020
83cd53f
Actually replace previous `init` with private version
MPLew-is Jun 16, 2020
28d7179
Clean up usage of default parameter values
MPLew-is Jun 16, 2020
a8e2a7d
Clean up documentation
MPLew-is Jun 16, 2020
5c7dba0
Extend standard default initialization to `Argument`s
MPLew-is Jun 16, 2020
f3a6b00
Extend standard default initialization to `Flag`s
MPLew-is Jun 16, 2020
83a70e4
Default flags with inversions to nil/required
MPLew-is Jun 19, 2020
e7397e9
Extend standard default initialization to no-inversion boolean `Flags`
MPLew-is Jun 21, 2020
a371be6
Eliminate deprecation spam from default value initialization
MPLew-is Jun 21, 2020
d41e4f2
Add source compatibility tests for new default syntax and associated …
MPLew-is Jun 21, 2020
e05678f
Update top-level documentation
MPLew-is Jun 21, 2020
8c573a5
Merge branch 'master' into default-property-initialization
MPLew-is Jun 22, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 156 additions & 16 deletions Sources/ArgumentParser/Parsable Properties/Argument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,85 @@ extension Argument: DecodableParsedWrapper where Value: Decodable {}
// MARK: Property Wrapper Initializers

extension Argument where Value: ExpressibleByArgument {
/// Creates a property with an optional default value, intended to be called by other constructors to centralize logic.
///
/// This private `init` allows us to expose multiple other similar constructors to allow for standard default property initialization while reducing code duplication.
private init(
initial: Value?,
help: ArgumentHelp?
) {
self.init(_parsedValue: .init { key in
ArgumentSet(key: key, kind: .positional, parseType: Value.self, name: NameSpecification.long, default: initial, help: help)
})
}

/// Creates a property that reads its value from an argument.
///
/// This method is deprecated, with usage split into two other methods below:
/// - `init(wrappedValue:help:)` for properties with a default value
/// - `init(help:)` for properties with no default value
///
/// Existing usage of the `default` parameter should be replaced such as follows:
/// ```diff
/// -@Argument(default: "bar")
/// -var foo: String
/// +@Argument()
/// +var foo: String = "bar"
/// ```
///
/// - Parameters:
/// - initial: A default value to use for this property. If `initial` is
/// `nil`, the user must supply a value for this argument.
/// - help: Information about how to use this argument.
@available(*, deprecated, message: "Use regular property initialization for default values (`var foo: String = \"bar\"`)")
public init(
default initial: Value? = nil,
default initial: Value?,
help: ArgumentHelp? = nil
) {
self.init(_parsedValue: .init { key in
ArgumentSet(key: key, kind: .positional, parseType: Value.self, name: NameSpecification.long, default: initial, help: help)
})
self.init(
initial: initial,
help: help
)
}

/// Creates a property with a default value provided by standard Swift default value syntax.
///
/// This method is called to initialize an `Argument` with a default value such as:
/// ```swift
/// @Argument()
/// var foo: String = "bar"
/// ```
///
/// - Parameters:
/// - wrappedValue: A default value to use for this property, provided implicitly by the compiler during propery wrapper initialization.
/// - help: Information about how to use this argument.
public init(
wrappedValue: Value,
help: ArgumentHelp? = nil
) {
self.init(
initial: wrappedValue,
help: help
)
}

/// Creates a property with no default value.
///
/// This method is called to initialize an `Argument` without a default value such as:
/// ```swift
/// @Argument()
/// var foo: String
/// ```
///
/// - Parameters:
/// - help: Information about how to use this argument.
public init(
help: ArgumentHelp? = nil
) {
self.init(
initial: nil,
help: help
)
}
}

Expand Down Expand Up @@ -169,18 +235,13 @@ extension Argument {
help: help)
})
}

/// Creates a property that reads its value from an argument, parsing with
/// the given closure.

/// Creates a property with an optional default value, intended to be called by other constructors to centralize logic.
///
/// - Parameters:
/// - initial: A default value to use for this property.
/// - help: Information about how to use this argument.
/// - transform: A closure that converts a string into this property's
/// type or throws an error.
public init(
default initial: Value? = nil,
help: ArgumentHelp? = nil,
/// This private `init` allows us to expose multiple other similar constructors to allow for standard default property initialization while reducing code duplication.
private init(
initial: Value?,
help: ArgumentHelp?,
transform: @escaping (String) throws -> Value
) {
self.init(_parsedValue: .init { key in
Expand All @@ -201,7 +262,86 @@ extension Argument {
return ArgumentSet(alternatives: [arg])
})
}


/// Creates a property that reads its value from an argument, parsing with
/// the given closure.
///
/// This method is deprecated, with usage split into two other methods below:
/// - `init(wrappedValue:help:transform:)` for properties with a default value
/// - `init(help:transform:)` for properties with no default value
///
/// Existing usage of the `default` parameter should be replaced such as follows:
/// ```diff
/// -@Argument(default: "bar", transform: baz)
/// -var foo: String
/// +@Argument(transform: baz)
/// +var foo: String = "bar"
/// ```
///
/// - Parameters:
/// - initial: A default value to use for this property.
/// - help: Information about how to use this argument.
/// - transform: A closure that converts a string into this property's
/// type or throws an error.
@available(*, deprecated, message: "Use regular property initialization for default values (`var foo: String = \"bar\"`)")
public init(
default initial: Value?,
help: ArgumentHelp? = nil,
transform: @escaping (String) throws -> Value
) {
self.init(
initial: initial,
help: help,
transform: transform
)
}

/// Creates a property with a default value provided by standard Swift default value syntax, parsing with the given closure.
///
/// This method is called to initialize an `Argument` with a default value such as:
/// ```swift
/// @Argument(transform: baz)
/// var foo: String = "bar"
/// ```
///
/// - Parameters:
/// - wrappedValue: A default value to use for this property, provided implicitly by the compiler during property wrapper initialization.
/// - help: Information about how to use this argument.
/// - transform: A closure that converts a string into this property's type or throws an error.
public init(
wrappedValue: Value,
help: ArgumentHelp? = nil,
transform: @escaping (String) throws -> Value
) {
self.init(
initial: wrappedValue,
help: help,
transform: transform
)
}

/// Creates a property with no default value, parsing with the given closure.
///
/// This method is called to initialize an `Argument` with no default value such as:
/// ```swift
/// @Argument(transform: baz)
/// var foo: String
/// ```
///
/// - Parameters:
/// - help: Information about how to use this argument.
/// - transform: A closure that converts a string into this property's type or throws an error.
public init(
help: ArgumentHelp? = nil,
transform: @escaping (String) throws -> Value
) {
self.init(
initial: nil,
help: help,
transform: transform
)
}

/// Creates a property that reads an array from zero or more arguments.
///
/// The property has an empty array as its default value.
Expand Down
Loading