Skip to content

Commit 6eb4fd1

Browse files
authored
Merge pull request #129 from abertelrud/eng/diagnostic-improvements
Add a way for emittable diagnostics (e.g. Swift.Errors) to provide custom DiagnosticLocations
2 parents 4c65c74 + eeb8a75 commit 6eb4fd1

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

Sources/TSCUtility/Diagnostics.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
4+
Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See http://swift.org/LICENSE.txt for license information
@@ -18,6 +18,13 @@ public protocol DiagnosticDataConvertible {
1818
var diagnosticData: DiagnosticData { get }
1919
}
2020

21+
22+
/// Protocol for types that can provide a diagnostic location. A common use is
23+
/// for specializations of Swift.Error that can have diagnostic locations.
24+
public protocol DiagnosticLocationProviding {
25+
var diagnosticLocation: DiagnosticLocation? { get }
26+
}
27+
2128
/// DiagnosticData wrapper for Swift errors.
2229
public struct AnyDiagnostic: DiagnosticData {
2330
public let anyError: Swift.Error
@@ -69,6 +76,7 @@ extension DiagnosticsEngine {
6976
_ error: Swift.Error,
7077
location: DiagnosticLocation? = nil
7178
) {
79+
let location = location ?? (error as? DiagnosticLocationProviding)?.diagnosticLocation
7280
if let diagnosticData = error as? DiagnosticData {
7381
emit(.error(diagnosticData), location: location)
7482
} else if case let convertible as DiagnosticDataConvertible = error {
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2020 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import XCTest
12+
13+
import TSCBasic
14+
import TSCUtility
15+
16+
class DiagnosticsTests: XCTestCase {
17+
18+
func testDiagnosticsLocationProviding() throws {
19+
let diagnostics = DiagnosticsEngine()
20+
21+
struct BazLocation: DiagnosticLocation {
22+
let name: String
23+
24+
var description: String {
25+
return name
26+
}
27+
}
28+
29+
struct CustomError: Error, CustomStringConvertible, DiagnosticLocationProviding {
30+
var location: String?
31+
var diagnosticLocation: DiagnosticLocation? {
32+
return location.flatMap{ BazLocation(name: $0) }
33+
}
34+
var description: String {
35+
return "provided location is '\(location ?? "nil")'"
36+
}
37+
}
38+
39+
diagnostics.with(location: BazLocation(name: "elsewhere")) { diagnostics in
40+
diagnostics.wrap {
41+
throw CustomError(location: "somewhere")
42+
}
43+
diagnostics.wrap {
44+
throw CustomError(location: nil)
45+
}
46+
}
47+
48+
XCTAssertEqual(diagnostics.diagnostics.count, 2)
49+
50+
let firstDiagnostic = try XCTUnwrap(diagnostics.diagnostics.first)
51+
XCTAssertEqual(firstDiagnostic.location.description, "somewhere")
52+
XCTAssertEqual(firstDiagnostic.description, "provided location is 'somewhere'")
53+
XCTAssertEqual(firstDiagnostic.message.behavior, .error)
54+
55+
let secondDiagnostic = try XCTUnwrap(diagnostics.diagnostics.last)
56+
XCTAssertEqual(secondDiagnostic.location.description, "elsewhere")
57+
XCTAssertEqual(secondDiagnostic.description, "provided location is 'nil'")
58+
XCTAssertEqual(secondDiagnostic.message.behavior, .error)
59+
}
60+
}

0 commit comments

Comments
 (0)