Skip to content

Commit 6560a6b

Browse files
committed
Emit diagnostics for option parsing errors
1 parent b08ceaa commit 6560a6b

File tree

5 files changed

+31
-9
lines changed

5 files changed

+31
-9
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,11 @@ public struct Driver {
191191
public init(
192192
args: [String],
193193
env: [String: String] = ProcessEnv.vars,
194-
diagnosticsHandler: @escaping DiagnosticsEngine.DiagnosticsHandler = Driver.stderrDiagnosticsHandler
194+
diagnosticsEngine: DiagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler])
195195
) throws {
196196
self.env = env
197197

198-
self.diagnosticEngine = DiagnosticsEngine(handlers: [diagnosticsHandler])
198+
self.diagnosticEngine = diagnosticsEngine
199199

200200
if case .subcommand = try Self.invocationRunMode(forArgs: args).mode {
201201
throw Error.subcommandPassedToDriver

Sources/SwiftDriver/Options/OptionParsing.swift

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,26 @@
99
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
//
1111
//===----------------------------------------------------------------------===//
12-
public enum OptionParseError : Error, Equatable {
12+
import TSCBasic
13+
14+
public enum OptionParseError : Error, Equatable, DiagnosticData {
1315
case unknownOption(index: Int, argument: String)
1416
case missingArgument(index: Int, argument: String)
15-
case unsupportedOption(index: Int, option: Option)
17+
case unsupportedOption(index: Int, argument: String, option: Option, currentDriverKind: DriverKind)
18+
19+
public var description: String {
20+
switch self {
21+
case let .unknownOption(index: _, argument: arg):
22+
return "unknown argument: '\(arg)'"
23+
case let .missingArgument(index: _, argument: arg):
24+
return "missing argument value for '\(arg)'"
25+
case let .unsupportedOption(index: _, argument: arg, option: option, currentDriverKind: driverKind):
26+
// TODO: This logic to choose the recommended kind is copied from the C++
27+
// driver and could be improved.
28+
let recommendedDriverKind: DriverKind = option.attributes.contains(.noBatch) ? .interactive : .batch
29+
return "option '\(arg)' is not supported by '\(driverKind.usage)'; did you mean to use '\(recommendedDriverKind.usage)'?"
30+
}
31+
}
1632
}
1733

1834
extension OptionTable {
@@ -60,8 +76,11 @@ extension OptionTable {
6076
index: index - 1, argument: argument)
6177
}
6278

79+
// Make sure this option is supported by the current driver kind.
6380
guard option.isAccepted(by: driverKind) else {
64-
throw OptionParseError.unsupportedOption(index: index - 1, option: option)
81+
throw OptionParseError.unsupportedOption(
82+
index: index - 1, argument: argument, option: option,
83+
currentDriverKind: driverKind)
6584
}
6685

6786
// Translate the argument

Sources/swift-driver/main.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import TSCBasic
1616
import TSCUtility
1717

1818
var intHandler: InterruptHandler?
19+
let diagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler])
1920

2021
do {
2122
let processSet = ProcessSet()
@@ -39,7 +40,7 @@ do {
3940
try exec(path: subcommandPath?.pathString ?? "", args: Array(arguments.dropFirst()))
4041
}
4142

42-
var driver = try Driver(args: arguments)
43+
var driver = try Driver(args: arguments, diagnosticsEngine: diagnosticsEngine)
4344
let resolver = try ArgsResolver()
4445
try driver.run(resolver: resolver, processSet: processSet)
4546

@@ -48,6 +49,8 @@ do {
4849
}
4950
} catch Diagnostics.fatalError {
5051
exit(EXIT_FAILURE)
52+
} catch let diagnosticData as DiagnosticData {
53+
diagnosticsEngine.emit(.error(diagnosticData))
5154
} catch {
5255
print("error: \(error)")
5356
exit(EXIT_FAILURE)

Tests/SwiftDriverTests/Helpers/AssertDiagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fileprivate func assertDriverDiagnostics(
2323
let matcher = DiagnosticVerifier()
2424
defer { matcher.verify(file: file, line: line) }
2525

26-
var driver = try Driver(args: args, env: env, diagnosticsHandler: matcher.emit(_:))
26+
var driver = try Driver(args: args, env: env, diagnosticsEngine: DiagnosticsEngine(handlers: [matcher.emit(_:)]))
2727
try body(&driver, matcher)
2828
}
2929

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ final class SwiftDriverTests: XCTestCase {
4646
}
4747

4848
XCTAssertThrowsError(try options.parse(["-o"], for: .interactive)) { error in
49-
XCTAssertEqual(error as? OptionParseError, .unsupportedOption(index: 0, option: .o))
49+
XCTAssertEqual(error as? OptionParseError, .unsupportedOption(index: 0, argument: "-o", option: .o, currentDriverKind: .interactive))
5050
}
5151

5252
XCTAssertThrowsError(try options.parse(["-repl"], for: .batch)) { error in
53-
XCTAssertEqual(error as? OptionParseError, .unsupportedOption(index: 0, option: .repl))
53+
XCTAssertEqual(error as? OptionParseError, .unsupportedOption(index: 0, argument: "-repl", option: .repl, currentDriverKind: .batch))
5454
}
5555

5656
}

0 commit comments

Comments
 (0)