| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- //===----------------------------------------------------------------------===//
- //
- // 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
- //
- //===----------------------------------------------------------------------===//
- /// A validator for positional argument arrays.
- ///
- /// For positional arguments to be valid, there must be at most one
- /// positional array argument, and it must be the last positional argument
- /// in the argument list. Any other configuration leads to ambiguity in
- /// parsing the arguments.
- struct PositionalArgumentsValidator: ParsableArgumentsValidator {
- struct Error: ParsableArgumentsValidatorError, CustomStringConvertible {
- let repeatedPositionalArgument: String
- let positionalArgumentFollowingRepeated: String
- var description: String {
- """
- Can't have a positional argument \
- `\(positionalArgumentFollowingRepeated)` following an array of \
- positional arguments `\(repeatedPositionalArgument)`.
- """
- }
- var kind: ValidatorErrorKind { .failure }
- }
- static func validate(
- _ type: ParsableArguments.Type, parent: InputKey?
- ) -> ParsableArgumentsValidatorError? {
- let sets: [ArgumentSet] = Mirror(reflecting: type.init())
- .children
- .compactMap { child in
- guard
- let codingKey = child.label,
- let parsed = child.value as? ArgumentSetProvider
- else { return nil }
- let key = InputKey(name: codingKey, parent: parent)
- return parsed.argumentSet(for: key)
- }
- guard
- let repeatedPositional = sets.firstIndex(where: {
- $0.firstRepeatedPositionalArgument != nil
- })
- else { return nil }
- guard
- let positionalFollowingRepeated = sets[repeatedPositional...]
- .dropFirst()
- .first(where: { $0.firstPositionalArgument != nil })
- else { return nil }
- // swift-format-ignore: NeverForceUnwrap
- // We know these are non-nil because of the guard statements above.
- let firstRepeatedPositionalArgument: ArgumentDefinition = sets[
- repeatedPositional
- ].firstRepeatedPositionalArgument!
- // swift-format-ignore: NeverForceUnwrap
- let positionalFollowingRepeatedArgument: ArgumentDefinition =
- positionalFollowingRepeated.firstPositionalArgument!
- // swift-format-ignore: NeverForceUnwrap
- return Error(
- repeatedPositionalArgument: firstRepeatedPositionalArgument.help.keys
- .first!.name,
- positionalArgumentFollowingRepeated: positionalFollowingRepeatedArgument
- .help.keys.first!.name)
- }
- }
- extension ArgumentSet {
- fileprivate var firstPositionalArgument: ArgumentDefinition? {
- content.first(where: { $0.isPositional })
- }
- fileprivate var firstRepeatedPositionalArgument: ArgumentDefinition? {
- content.first(where: { $0.isRepeatingPositional })
- }
- }
|