Files
swift-argument-parser/Sources/ArgumentParser/Validators/NonsenseFlagsValidator.swift

69 lines
2.1 KiB
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
//
//===----------------------------------------------------------------------===//
/// A validator that prevents declaring flags that can't be turned off.
struct NonsenseFlagsValidator: ParsableArgumentsValidator {
struct Error: ParsableArgumentsValidatorError, CustomStringConvertible {
var names: [String]
var description: String {
"""
One or more Boolean flags is declared with an initial value of `true`. \
This results in the flag always being `true`, no matter whether the user \
specifies the flag or not.
To resolve this error, change the default to `false`, provide a value \
for the `inversion:` parameter, or remove the `@Flag` property wrapper \
altogether.
Affected flag(s):
\(names.joined(separator: "\n"))
"""
}
var kind: ValidatorErrorKind { .warning }
}
static func validate(_ type: ParsableArguments.Type, parent: InputKey?)
-> ParsableArgumentsValidatorError?
{
let argSets: [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)
}
let nonsenseFlags: [String] = argSets.flatMap { args -> [String] in
args.compactMap { def in
if case .nullary = def.update,
!def.help.isComposite,
def.help.options.contains(.isOptional),
def.help.defaultValue == "true"
{
return def.unadornedSynopsis
} else {
return nil
}
}
}
return nonsenseFlags.isEmpty
? nil
: Error(names: nonsenseFlags)
}
}