Skip to content

Commit e025438

Browse files
committed
review comments
1 parent 6d58cd4 commit e025438

File tree

7 files changed

+180
-101
lines changed

7 files changed

+180
-101
lines changed

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ let targets: [Target] = [
118118

119119
// Code generator SwiftPM command
120120
.plugin(
121-
name: "GRPCGeneratorCommand",
121+
name: "GRPCProtobufGeneratorCommand",
122122
capability: .command(
123123
intent: .custom(
124124
verb: "generate-grpc-code-from-protos",
@@ -132,7 +132,7 @@ let targets: [Target] = [
132132
]
133133
),
134134
dependencies: [
135-
"protoc-gen-grpc-swift",
135+
.target(name: "protoc-gen-grpc-swift"),
136136
.product(name: "protoc-gen-swift", package: "swift-protobuf"),
137137
]
138138
),

Plugins/GRPCGeneratorCommand/CommandConfig.swift renamed to Plugins/GRPCProtobufGeneratorCommand/CommandConfig.swift

Lines changed: 117 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import PackagePlugin
2020
struct CommandConfig {
2121
var common: GenerationConfig
2222

23+
var verbose: Bool
2324
var dryRun: Bool
2425

2526
static let defaults = Self(
@@ -33,97 +34,103 @@ struct CommandConfig {
3334
importPaths: [],
3435
outputPath: ""
3536
),
37+
verbose: false,
3638
dryRun: false
3739
)
3840
}
3941

4042
extension CommandConfig {
43+
static func helpRequested(
44+
argumentExtractor: inout ArgumentExtractor,
45+
) -> Bool {
46+
let help = argumentExtractor.extractFlag(named: OptionsAndFlags.help.rawValue)
47+
return help != 0
48+
}
49+
4150
static func parse(
42-
arguments: [String],
51+
argumentExtractor argExtractor: inout ArgumentExtractor,
4352
pluginWorkDirectory: URL
4453
) throws -> (CommandConfig, [String]) {
4554
var config = CommandConfig.defaults
4655

47-
var argExtractor = ArgumentExtractor(arguments)
48-
49-
for flag in Flag.allCases {
56+
for flag in OptionsAndFlags.allCases {
5057
switch flag {
5158
case .accessLevel:
5259
let accessLevel = argExtractor.extractOption(named: flag.rawValue)
53-
if let value = accessLevel.first {
54-
switch value.lowercased() {
55-
case "internal":
56-
config.common.accessLevel = .`internal`
57-
case "public":
58-
config.common.accessLevel = .`public`
59-
case "package":
60-
config.common.accessLevel = .`package`
61-
default:
62-
Diagnostics.error("Unknown accessLevel \(value)")
60+
if let value = extractSingleValue(flag, values: accessLevel) {
61+
if let accessLevel = GenerationConfig.AccessLevel(rawValue: value) {
62+
config.common.accessLevel = accessLevel
6363
}
64-
}
65-
case .servers:
66-
let servers = argExtractor.extractOption(named: flag.rawValue)
67-
if let value = servers.first {
68-
guard let servers = Bool(value) else {
69-
throw CommandPluginError.invalidArgumentValue(value)
64+
else {
65+
Diagnostics.error("Unknown access level '--\(flag.rawValue)' \(value)")
7066
}
71-
config.common.servers = servers
7267
}
73-
case .clients:
74-
let clients = argExtractor.extractOption(named: flag.rawValue)
75-
if let value = clients.first {
76-
guard let clients = Bool(value) else {
77-
throw CommandPluginError.invalidArgumentValue(value)
78-
}
79-
config.common.clients = clients
68+
69+
case .servers, .noServers:
70+
if flag == .noServers { continue } // only process this once
71+
let servers = argExtractor.extractFlag(named: OptionsAndFlags.servers.rawValue)
72+
let noServers = argExtractor.extractFlag(named: OptionsAndFlags.noServers.rawValue)
73+
if noServers > servers {
74+
config.common.servers = false
8075
}
81-
case .messages:
82-
let messages = argExtractor.extractOption(named: flag.rawValue)
83-
if let value = messages.first {
84-
guard let messages = Bool(value) else {
85-
throw CommandPluginError.invalidArgumentValue(value)
86-
}
87-
config.common.messages = messages
76+
77+
case .clients, .noClients:
78+
if flag == .noClients { continue } // only process this once
79+
let clients = argExtractor.extractFlag(named: OptionsAndFlags.clients.rawValue)
80+
let noClients = argExtractor.extractFlag(named: OptionsAndFlags.noClients.rawValue)
81+
if noClients > clients {
82+
config.common.clients = false
83+
}
84+
85+
case .messages, .noMessages:
86+
if flag == .noMessages { continue } // only process this once
87+
let messages = argExtractor.extractFlag(named: OptionsAndFlags.messages.rawValue)
88+
let noMessages = argExtractor.extractFlag(named: OptionsAndFlags.noMessages.rawValue)
89+
if noMessages > messages {
90+
config.common.messages = false
8891
}
92+
8993
case .fileNaming:
9094
let fileNaming = argExtractor.extractOption(named: flag.rawValue)
91-
if let value = fileNaming.first {
92-
switch value.lowercased() {
93-
case "fullPath":
94-
config.common.fileNaming = .fullPath
95-
case "pathToUnderscores":
96-
config.common.fileNaming = .pathToUnderscores
97-
case "dropPath":
98-
config.common.fileNaming = .dropPath
99-
default:
100-
Diagnostics.error("Unknown file naming strategy \(value)")
95+
if let value = extractSingleValue(flag, values: fileNaming) {
96+
if let fileNaming = GenerationConfig.FileNaming(rawValue: value) {
97+
config.common.fileNaming = fileNaming
98+
}
99+
else {
100+
Diagnostics.error("Unknown file naming strategy '--\(flag.rawValue)' \(value)")
101101
}
102102
}
103+
103104
case .accessLevelOnImports:
104105
let accessLevelOnImports = argExtractor.extractOption(named: flag.rawValue)
105-
if let value = accessLevelOnImports.first {
106+
if let value = extractSingleValue(flag, values: accessLevelOnImports) {
106107
guard let accessLevelOnImports = Bool(value) else {
107-
throw CommandPluginError.invalidArgumentValue(value)
108+
throw CommandPluginError.invalidArgumentValue(name: flag.rawValue, value: value)
108109
}
109110
config.common.accessLevelOnImports = accessLevelOnImports
110111
}
112+
111113
case .importPath:
112114
config.common.importPaths = argExtractor.extractOption(named: flag.rawValue)
115+
113116
case .protocPath:
114117
let protocPath = argExtractor.extractOption(named: flag.rawValue)
115-
config.common.protocPath = protocPath.first
118+
config.common.protocPath = extractSingleValue(flag, values: protocPath)
119+
116120
case .output:
117121
let output = argExtractor.extractOption(named: flag.rawValue)
118-
config.common.outputPath = output.first ?? pluginWorkDirectory.absoluteStringNoScheme
122+
config.common.outputPath = extractSingleValue(flag, values: output) ?? pluginWorkDirectory.absoluteStringNoScheme
123+
124+
case .verbose:
125+
let verbose = argExtractor.extractFlag(named: flag.rawValue)
126+
config.verbose = verbose != 0
127+
119128
case .dryRun:
120129
let dryRun = argExtractor.extractFlag(named: flag.rawValue)
121130
config.dryRun = dryRun != 0
131+
122132
case .help:
123-
let help = argExtractor.extractFlag(named: flag.rawValue)
124-
if help != 0 {
125-
throw CommandPluginError.helpRequested
126-
}
133+
() // handled elsewhere
127134
}
128135
}
129136

@@ -141,19 +148,30 @@ extension CommandConfig {
141148
}
142149
}
143150

151+
func extractSingleValue(_ flag: OptionsAndFlags, values: [String]) -> String? {
152+
if values.count > 1 {
153+
Stderr.print("Warning: '--\(flag.rawValue)' was unexpectedly repeated, the first value will be used.")
154+
}
155+
return values.first
156+
}
157+
144158
/// All valid input options/flags
145-
enum Flag: CaseIterable, RawRepresentable {
159+
enum OptionsAndFlags: CaseIterable, RawRepresentable {
146160
typealias RawValue = String
147161

148162
case servers
163+
case noServers
149164
case clients
165+
case noClients
150166
case messages
167+
case noMessages
151168
case fileNaming
152169
case accessLevel
153170
case accessLevelOnImports
154171
case importPath
155172
case protocPath
156173
case output
174+
case verbose
157175
case dryRun
158176

159177
case help
@@ -162,22 +180,30 @@ enum Flag: CaseIterable, RawRepresentable {
162180
switch rawValue {
163181
case "servers":
164182
self = .servers
183+
case "no-servers":
184+
self = .noServers
165185
case "clients":
166186
self = .clients
187+
case "no-clients":
188+
self = .noClients
167189
case "messages":
168190
self = .messages
191+
case "no-messages":
192+
self = .noMessages
169193
case "file-naming":
170194
self = .fileNaming
171195
case "access-level":
172196
self = .accessLevel
173-
case "use-access-level-on-imports":
197+
case "access-level-on-imports":
174198
self = .accessLevelOnImports
175199
case "import-path":
176200
self = .importPath
177201
case "protoc-path":
178202
self = .protocPath
179203
case "output":
180204
self = .output
205+
case "verbose":
206+
self = .verbose
181207
case "dry-run":
182208
self = .dryRun
183209
case "help":
@@ -192,10 +218,16 @@ enum Flag: CaseIterable, RawRepresentable {
192218
switch self {
193219
case .servers:
194220
"servers"
221+
case .noServers:
222+
"no-servers"
195223
case .clients:
196224
"clients"
225+
case .noClients:
226+
"no-clients"
197227
case .messages:
198228
"messages"
229+
case .noMessages:
230+
"no-messages"
199231
case .fileNaming:
200232
"file-naming"
201233
case .accessLevel:
@@ -208,6 +240,8 @@ enum Flag: CaseIterable, RawRepresentable {
208240
"protoc-path"
209241
case .output:
210242
"output"
243+
case .verbose:
244+
"verbose"
211245
case .dryRun:
212246
"dry-run"
213247
case .help:
@@ -216,15 +250,21 @@ enum Flag: CaseIterable, RawRepresentable {
216250
}
217251
}
218252

219-
extension Flag {
253+
extension OptionsAndFlags {
220254
func usageDescription() -> String {
221255
switch self {
222256
case .servers:
223-
return "Whether server code is generated. Defaults to true."
257+
return "Indicate that server code is to be generated. Generated by default."
258+
case .noServers:
259+
return "Indicate that server code is not to be generated. Generated by default."
224260
case .clients:
225-
return "Whether client code is generated. Defaults to true."
261+
return "Indicate that client code is to be generated. Generated by default."
262+
case .noClients:
263+
return "Indicate that client code is not to be generated. Generated by default."
226264
case .messages:
227-
return "Whether message code is generated. Defaults to true."
265+
return "Indicate that message code is to be generated. Generated by default."
266+
case .noMessages:
267+
return "Indicate that message code is not to be generated. Generated by default."
228268
case .fileNaming:
229269
return
230270
"The naming scheme for output files [fullPath/pathToUnderscores/dropPath]. Defaults to fullPath."
@@ -236,27 +276,36 @@ extension Flag {
236276
case .importPath:
237277
return "The directory in which to search for imports."
238278
case .protocPath:
239-
return "The path to the `protoc` binary."
279+
return "The path to the protoc binary."
240280
case .dryRun:
241281
return "Print but do not execute the protoc commands."
242282
case .output:
243283
return "The path into which the generated source files are created."
284+
case .verbose:
285+
return "Emit verbose output."
244286
case .help:
245287
return "Print this help."
246288
}
247289
}
248290

249-
static func printHelp() {
250-
print("Usage: swift package generate-grpc-code-from-protos [flags] [input files]")
251-
print("")
252-
print("Flags:")
253-
print("")
291+
static func printHelp(requested: Bool) {
292+
let printMessage: (String) -> Void
293+
if requested {
294+
printMessage = { message in print(message) }
295+
} else {
296+
printMessage = Stderr.print
297+
}
298+
299+
printMessage("Usage: swift package generate-grpc-code-from-protos [flags] [input files]")
300+
printMessage("")
301+
printMessage("Flags:")
302+
printMessage("")
254303

255304
let spacing = 3
256305
let maxLength =
257-
(Flag.allCases.map(\.rawValue).max(by: { $0.count < $1.count })?.count ?? 0) + spacing
258-
for flag in Flag.allCases {
259-
print(
306+
(OptionsAndFlags.allCases.map(\.rawValue).max(by: { $0.count < $1.count })?.count ?? 0) + spacing
307+
for flag in OptionsAndFlags.allCases {
308+
printMessage(
260309
" --\(flag.rawValue.padding(toLength: maxLength, withPad: " ", startingAt: 0))\(flag.usageDescription())"
261310
)
262311
}

Plugins/GRPCGeneratorCommand/CommandPluginError.swift renamed to Plugins/GRPCProtobufGeneratorCommand/CommandPluginError.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,19 @@
1515
*/
1616

1717
enum CommandPluginError: Error {
18-
case helpRequested
1918
case missingArgumentValue
20-
case invalidArgumentValue(String)
19+
case invalidArgumentValue(name: String, value: String)
2120
case missingInputFile
2221
case unknownOption(String)
2322
}
2423

2524
extension CommandPluginError: CustomStringConvertible {
2625
var description: String {
2726
switch self {
28-
case .helpRequested:
29-
"User requested help."
3027
case .missingArgumentValue:
3128
"Provided option does not have a value."
32-
case .invalidArgumentValue:
33-
"Invalid option value."
29+
case .invalidArgumentValue(let name, let value):
30+
"Invalid value '\(value)', for '\(name)'."
3431
case .missingInputFile:
3532
"No input file(s) specified."
3633
case .unknownOption(let value):

0 commit comments

Comments
 (0)