diff --git a/Sources/ArgumentParser/CMakeLists.txt b/Sources/ArgumentParser/CMakeLists.txt index 2a65d2262..bace0ad5e 100644 --- a/Sources/ArgumentParser/CMakeLists.txt +++ b/Sources/ArgumentParser/CMakeLists.txt @@ -23,7 +23,6 @@ add_library(ArgumentParser Parsing/ArgumentDecoder.swift Parsing/ArgumentDefinition.swift Parsing/ArgumentSet.swift - Parsing/ArgumentSetSequence.swift Parsing/CommandParser.swift Parsing/InputOrigin.swift Parsing/Name.swift diff --git a/Sources/ArgumentParser/Parsable Properties/Argument.swift b/Sources/ArgumentParser/Parsable Properties/Argument.swift index dea1b7d76..69a55ab41 100644 --- a/Sources/ArgumentParser/Parsable Properties/Argument.swift +++ b/Sources/ArgumentParser/Parsable Properties/Argument.swift @@ -280,8 +280,8 @@ extension Argument { values.set(v, forKey: key, inputOrigin: origin) } }) - return ArgumentSet(alternatives: [arg]) - }) + return ArgumentSet(arg) + }) } /// Creates a property that reads its value from an argument, parsing with @@ -403,7 +403,7 @@ extension Argument { update: .appendToArray(forType: Element.self, key: key), initial: setInitialValue) arg.help.defaultValue = helpDefaultValue - return ArgumentSet(alternatives: [arg]) + return ArgumentSet(arg) }) } @@ -501,7 +501,7 @@ extension Argument { }), initial: setInitialValue) arg.help.defaultValue = helpDefaultValue - return ArgumentSet(alternatives: [arg]) + return ArgumentSet(arg) }) } diff --git a/Sources/ArgumentParser/Parsable Properties/Flag.swift b/Sources/ArgumentParser/Parsable Properties/Flag.swift index 1cba8becf..d7d313fd3 100644 --- a/Sources/ArgumentParser/Parsable Properties/Flag.swift +++ b/Sources/ArgumentParser/Parsable Properties/Flag.swift @@ -400,9 +400,7 @@ extension Flag where Value: EnumerableFlag { hasUpdated = try ArgumentSet.updateFlag(key: key, value: value, origin: origin, values: &values, hasUpdated: hasUpdated, exclusivity: exclusivity) })) } - return exclusivity == .exclusive - ? ArgumentSet(exclusive: args) - : ArgumentSet(additive: args) + return ArgumentSet(args) }) } @@ -525,9 +523,7 @@ extension Flag { })) } - return exclusivity == .exclusive - ? ArgumentSet(exclusive: args) - : ArgumentSet(additive: args) + return ArgumentSet(args) }) } @@ -553,7 +549,7 @@ extension Flag { }) })) } - return ArgumentSet(additive: args) + return ArgumentSet(args) }) } @@ -628,9 +624,7 @@ extension Flag where Value: CaseIterable, Value: RawRepresentable, Value: Equata hasUpdated = try ArgumentSet.updateFlag(key: key, value: value, origin: origin, values: &values, hasUpdated: hasUpdated, exclusivity: exclusivity) })) } - return exclusivity == .exclusive - ? ArgumentSet(exclusive: args) - : ArgumentSet(additive: args) + return ArgumentSet(args) }) } } @@ -656,9 +650,7 @@ extension Flag { hasUpdated = try ArgumentSet.updateFlag(key: key, value: value, origin: origin, values: &values, hasUpdated: hasUpdated, exclusivity: exclusivity) })) } - return exclusivity == .exclusive - ? ArgumentSet(exclusive: args) - : ArgumentSet(additive: args) + return ArgumentSet(args) }) } @@ -686,7 +678,7 @@ extension Flag { }) })) } - return ArgumentSet(additive: args) + return ArgumentSet(args) }) } } diff --git a/Sources/ArgumentParser/Parsable Properties/Option.swift b/Sources/ArgumentParser/Parsable Properties/Option.swift index adc1f52f8..c4851cffa 100644 --- a/Sources/ArgumentParser/Parsable Properties/Option.swift +++ b/Sources/ArgumentParser/Parsable Properties/Option.swift @@ -391,7 +391,7 @@ extension Option { }) arg.help.options.formUnion(ArgumentDefinition.Help.Options(type: Value.self)) arg.help.defaultValue = initial.map { "\($0)" } - return ArgumentSet(alternatives: [arg]) + return ArgumentSet(arg) }) } @@ -534,7 +534,7 @@ extension Option { initial: setInitialValue ) arg.help.defaultValue = helpDefaultValue - return ArgumentSet(alternatives: [arg]) + return ArgumentSet(arg) }) } @@ -636,7 +636,7 @@ extension Option { initial: setInitialValue ) arg.help.defaultValue = helpDefaultValue - return ArgumentSet(alternatives: [arg]) + return ArgumentSet(arg) }) } diff --git a/Sources/ArgumentParser/Parsable Types/ParsableArguments.swift b/Sources/ArgumentParser/Parsable Types/ParsableArguments.swift index e7fe0686d..25fedcfcb 100644 --- a/Sources/ArgumentParser/Parsable Types/ParsableArguments.swift +++ b/Sources/ArgumentParser/Parsable Types/ParsableArguments.swift @@ -237,7 +237,7 @@ extension ArgumentSet { let key = InputKey(rawValue: codingKey) return parsed.argumentSet(for: key) } - self.init(additive: a) + self.init(sets: a) } } diff --git a/Sources/ArgumentParser/Parsable Types/ParsableArgumentsValidation.swift b/Sources/ArgumentParser/Parsable Types/ParsableArgumentsValidation.swift index 2a26ab39c..bbbb9dbae 100644 --- a/Sources/ArgumentParser/Parsable Types/ParsableArgumentsValidation.swift +++ b/Sources/ArgumentParser/Parsable Types/ParsableArgumentsValidation.swift @@ -55,21 +55,11 @@ extension ParsableArguments { fileprivate extension ArgumentSet { var firstPositionalArgument: ArgumentDefinition? { - switch content { - case .arguments(let arguments): - return arguments.first(where: { $0.isPositional }) - case .sets(let sets): - return sets.first(where: { $0.firstPositionalArgument != nil })?.firstPositionalArgument - } + content.first(where: { $0.isPositional }) } var firstRepeatedPositionalArgument: ArgumentDefinition? { - switch content { - case .arguments(let arguments): - return arguments.first(where: { $0.isRepeatingPositional }) - case .sets(let sets): - return sets.first(where: { $0.firstRepeatedPositionalArgument != nil })?.firstRepeatedPositionalArgument - } + content.first(where: { $0.isRepeatingPositional }) } } @@ -234,13 +224,8 @@ struct ParsableArgumentsUniqueNamesValidator: ParsableArgumentsValidator { } let countedNames: [String: Int] = argSets.reduce(into: [:]) { countedNames, args in - switch args.content { - case .arguments(let defs): - for name in defs.flatMap({ $0.names }) { - countedNames[name.synopsisString, default: 0] += 1 - } - default: - break + for name in args.content.flatMap({ $0.names }) { + countedNames[name.synopsisString, default: 0] += 1 } } diff --git a/Sources/ArgumentParser/Parsing/ArgumentSet.swift b/Sources/ArgumentParser/Parsing/ArgumentSet.swift index 40e84d689..606c4b7ed 100644 --- a/Sources/ArgumentParser/Parsing/ArgumentSet.swift +++ b/Sources/ArgumentParser/Parsing/ArgumentSet.swift @@ -19,74 +19,38 @@ /// The `-v | -f` part is one *set* that’s optional, ` ` is /// another. Both of these can then be combined into a third set. struct ArgumentSet { - enum Content { - /// A leaf list of arguments. - case arguments([ArgumentDefinition]) - /// A node with additional `[ArgumentSet]` - case sets([ArgumentSet]) - } - var content: Content - var kind: Kind + var content: [ArgumentDefinition] = [] + var namePositions: [Name: Int] = [:] - /// Used to generate _help_ text. - enum Kind { - /// Independent - case additive - /// Mutually exclusive - case exclusive - /// Several ways of achieving the same behavior. Should only display one. - case alternatives + init(_ arguments: S) where S.Element == ArgumentDefinition { + self.content = Array(arguments) + self.namePositions = Dictionary( + content.enumerated().flatMap { i, arg in arg.names.map { ($0, i) } }, + uniquingKeysWith: { first, _ in first }) } - init(arguments: [ArgumentDefinition], kind: Kind) { - self.content = .arguments(arguments) - self.kind = kind - } + init() {} - init(sets: [ArgumentSet], kind: Kind) { - self.content = .sets(sets) - self.kind = kind + init(_ arg: ArgumentDefinition) { + self.init([arg]) + } + + init(sets: [ArgumentSet]) { + self.init(sets.joined()) } } extension ArgumentSet: CustomDebugStringConvertible { var debugDescription: String { - switch content { - case .arguments(let args): - return args - .map { $0.debugDescription } - .joined(separator: " / ") - case .sets(let sets): - return sets - .map { "{\($0.debugDescription)}" } - .joined(separator: " / ") - } + content + .map { $0.debugDescription } + .joined(separator: " / ") } } -extension ArgumentSet { - init() { - self.init(arguments: [], kind: .additive) - } - - init(_ arg: ArgumentDefinition) { - self.init(arguments: [arg], kind: .additive) - } - - init(additive args: [ArgumentDefinition]) { - self.init(arguments: args, kind: .additive) - } - - init(exclusive args: [ArgumentDefinition]) { - self.init(arguments: args, kind: args.count == 1 ? .additive : .exclusive) - } - - init(alternatives args: [ArgumentDefinition]) { - self.init(arguments: args, kind: args.count == 1 ? .additive : .alternatives) - } - - init(additive sets: [ArgumentSet]) { - self.init(sets: sets, kind: .additive) +extension ArgumentSet: Sequence { + func makeIterator() -> Array.Iterator { + return content.makeIterator() } } @@ -150,7 +114,7 @@ extension ArgumentSet { let disableArg = ArgumentDefinition(kind: .named(disableNames), help: ArgumentDefinition.Help(options: [.isOptional], key: key), completion: .default, update: .nullary({ (origin, name, values) in hasUpdated = try ArgumentSet.updateFlag(key: key, value: false, origin: origin, values: &values, hasUpdated: hasUpdated, exclusivity: exclusivity) }), initial: { _, _ in }) - return ArgumentSet(exclusive: [enableArg, disableArg]) + return ArgumentSet([enableArg, disableArg]) } /// Creates an argument set for an incrementing integer flag. @@ -390,7 +354,7 @@ extension ArgumentSet { func first( matching parsed: ParsedArgument ) -> ArgumentDefinition? { - return first(where: { $0.names.contains(parsed.name) }) + namePositions[parsed.name].map { content[$0] } } func firstPositional( diff --git a/Sources/ArgumentParser/Parsing/ArgumentSetSequence.swift b/Sources/ArgumentParser/Parsing/ArgumentSetSequence.swift deleted file mode 100644 index 6287b38d1..000000000 --- a/Sources/ArgumentParser/Parsing/ArgumentSetSequence.swift +++ /dev/null @@ -1,63 +0,0 @@ -//===----------------------------------------------------------*- 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 -// -//===----------------------------------------------------------------------===// - -/// Allows iteration over arguments in an `ArgumentSet`. -extension ArgumentSet: Sequence { - func makeIterator() -> Iterator { - return Iterator(set: self) - } - - var underestimatedCount: Int { return 0 } - - struct Iterator: IteratorProtocol { - enum Content { - case arguments(ArraySlice) - case sets([Iterator]) - case empty - } - - var content: Content - - init(set: ArgumentSet) { - switch set.content { - case .arguments(let a): - self.content = .arguments(a[a.startIndex.. ArgumentDefinition? { - switch content { - case .arguments(var a): - guard !a.isEmpty else { return nil } - let n = a.remove(at: 0) - content = .arguments(a) - return n - case .sets(var sets): - defer { - content = .sets(sets) - } - while true { - guard !sets.isEmpty else { return nil } - if let n = sets[0].next() { - return n - } - sets.remove(at: 0) - } - case .empty: - return nil - } - } - } -} diff --git a/Sources/ArgumentParser/Parsing/Name.swift b/Sources/ArgumentParser/Parsing/Name.swift index 267d9e48d..cd940d9ca 100644 --- a/Sources/ArgumentParser/Parsing/Name.swift +++ b/Sources/ArgumentParser/Parsing/Name.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -enum Name: Equatable { +enum Name: Hashable { /// A name (usually multi-character) prefixed with `--` (2 dashes) or equivalent. case long(String) /// A single character name prefixed with `-` (1 dash) or equivalent. diff --git a/Sources/ArgumentParser/Usage/UsageGenerator.swift b/Sources/ArgumentParser/Usage/UsageGenerator.swift index 05f844ecd..d8d18d89b 100644 --- a/Sources/ArgumentParser/Usage/UsageGenerator.swift +++ b/Sources/ArgumentParser/Usage/UsageGenerator.swift @@ -27,7 +27,7 @@ extension UsageGenerator { } init(toolName: String, definition: [ArgumentSet]) { - self.init(toolName: toolName, definition: ArgumentSet(additive: definition)) + self.init(toolName: toolName, definition: ArgumentSet(sets: definition)) } }