forked from swiftlang/swift-driver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOption.swift
153 lines (133 loc) · 5.64 KB
/
Option.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//===--------------- Option.swift - Swift Command Line Option -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 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
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// Attributes that describe where and how the option is used.
public struct OptionAttributes: OptionSet, Hashable {
public let rawValue: UInt
public init(rawValue: UInt) {
self.rawValue = rawValue
}
public static let helpHidden = OptionAttributes(rawValue: 0x1)
public static let frontend = OptionAttributes(rawValue: 0x2)
public static let noDriver = OptionAttributes(rawValue: 0x4)
public static let noInteractive = OptionAttributes(rawValue: 0x8)
public static let noBatch = OptionAttributes(rawValue: 0x10)
public static let doesNotAffectIncrementalBuild = OptionAttributes(rawValue: 0x20)
public static let autolinkExtract = OptionAttributes(rawValue: 0x40)
public static let moduleWrap = OptionAttributes(rawValue: 0x80)
public static let indent = OptionAttributes(rawValue: 0x100)
public static let argumentIsPath = OptionAttributes(rawValue: 0x200)
public static let moduleInterface = OptionAttributes(rawValue: 0x400)
public static let supplementaryOutput = OptionAttributes(rawValue: 0x800)
public static let argumentIsFileList = OptionAttributes(rawValue: 0x1000)
public static let cacheInvariant = OptionAttributes(rawValue: 0x2000)
}
/// Describes a command-line option.
public struct Option {
/// The kind of option we have, which determines how it will be parsed.
public enum Kind: Hashable {
/// An input file, which doesn't have a spelling but contains a single extension Driver {
/// argument.
case input
/// An option that enables/disables some specific behavior.
case flag
/// An option whose argument directly follows the spelling.
case joined
/// An option whose argument is in the following command-line argument.
case separate
/// An option whose argument either directly follows the spelling (like
/// `.joined`) when non-empty, or otherwise is the following command-line
/// argument (like `.separate`).
case joinedOrSeparate
/// An option with multiple arguments, which are collected from all
/// falling command-line arguments.
case remaining
/// An option with multiple arguments, which are collected by splitting
/// the text directly following the spelling at each comma.
case commaJoined
/// An option with multiple arguments, which the number of arguments is
/// specified by numArgs.
case multiArg
}
/// The spelling of the option, including any leading dashes.
public let spelling: String
/// The kind of option, which determines how it is parsed.
public let kind: Kind
/// The option that this aliases, if any, as a closure that produces the
/// valid.
private let aliasFunction: (() -> Option)?
/// The attributes that describe where and how the attribute is used.
public let attributes: OptionAttributes
/// For options that have an argument, the name of the metavariable to
/// use in documentation.
public let metaVar: String?
/// Help text to display with this option.
public let helpText: String?
/// The group in which this option occurs.
public let group: Group?
/// The number of arguments for MultiArg options.
public let numArgs: UInt
public init(_ spelling: String, _ kind: Kind,
alias: Option? = nil,
attributes: OptionAttributes = [], metaVar: String? = nil,
helpText: String? = nil,
group: Group? = nil,
numArgs: UInt = 0) {
self.spelling = spelling
self.kind = kind
self.aliasFunction = alias.map { aliasOption in { aliasOption }}
self.attributes = attributes
self.metaVar = metaVar
self.helpText = helpText
self.group = group
self.numArgs = numArgs
}
}
extension Option: Equatable {
public static func ==(lhs: Option, rhs: Option) -> Bool {
return lhs.spelling == rhs.spelling
}
}
extension Option: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(spelling)
}
}
extension Option {
/// Whether this option is an alias.
public var isAlias: Bool { aliasFunction != nil }
/// Retrieves the alias option, if there is one.
public var alias: Option? {
aliasFunction.map { function in function() }
}
/// Whether this option's help is hidden under normal circumstances.
public var isHelpHidden: Bool { attributes.contains(.helpHidden) }
/// Whether this option can affect an incremental build.
public var affectsIncrementalBuild: Bool {
!attributes.contains(.doesNotAffectIncrementalBuild)
}
/// Retrieves the canonical option, to be used for comparisons.
public var canonical: Option {
guard let alias = alias else { return self }
return alias.canonical
}
}
extension Option {
/// Whether this option is accepted by a driver of the given kind.
public func isAccepted(by driverKind: DriverKind) -> Bool {
switch driverKind {
case .batch:
return attributes.isDisjoint(with: [.noDriver, .noBatch])
case .interactive:
return attributes.isDisjoint(with: [.noDriver, .noInteractive])
}
}
}