Skip to content

Commit

Permalink
[Basic] Add support for handlers in DiagnosticsEngine
Browse files Browse the repository at this point in the history
  • Loading branch information
aciidgh committed Mar 10, 2018
1 parent 19a9813 commit d94a3df
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 2 deletions.
29 changes: 27 additions & 2 deletions Sources/Basic/DiagnosticsEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -253,26 +253,51 @@ public protocol DiagnosticsScope {

public class DiagnosticsEngine: CustomStringConvertible {

public typealias DiagnosticsHandler = (Diagnostic) -> Void

/// Queue to protect concurrent mutations to the diagnositcs engine.
private let queue = DispatchQueue(label: "\(DiagnosticsEngine.self)")

/// Queue for dispatching handlers.
private let handlerQueue = DispatchQueue(label: "\(DiagnosticsEngine.self)-callback")

/// The diagnostics produced by the engine.
public var diagnostics: [Diagnostic] {
return queue.sync { _diagnostics }
}
private var _diagnostics: [Diagnostic] = []

/// The list of handlers to run when a diagnostic is emitted.
///
/// The handler will be called on an unknown queue.
private let handlers: [DiagnosticsHandler]

/// Returns true if there is an error diagnostics in the engine.
public var hasErrors: Bool {
return diagnostics.contains(where: { $0.behavior == .error })
}

public init() {
public init(handlers: [DiagnosticsHandler] = []) {
self.handlers = handlers
}

public func emit(data: DiagnosticData, location: DiagnosticLocation) {
let diagnostic = Diagnostic(location: location, data: data)

queue.sync {
_diagnostics.append(Diagnostic(location: location, data: data))
_diagnostics.append(diagnostic)
}

// Call the handlers on the background queue, if we have any.
if !handlers.isEmpty {
// FIXME: We should probably do this async but then we need
// a way for clients to be able to wait until all handlers
// are called.
handlerQueue.sync {
for handler in self.handlers {
handler(diagnostic)
}
}
}
}

Expand Down
42 changes: 42 additions & 0 deletions Tests/BasicTests/DiagnosticsEngineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,23 @@ import XCTest

import Basic

// FIXME: We should just move this to Basic.
private struct StringDiagnostic: DiagnosticData {
static let id = DiagnosticID(
type: StringDiagnostic.self,
name: "org.swift.diags.string-diagnostic",
description: {
$0 <<< { $0.str }
}
)

let str: String

init(_ str: String) {
self.str = str
}
}

fileprivate struct FooDiag: DiagnosticData {
static let id = DiagnosticID(
type: FooDiag.self,
Expand Down Expand Up @@ -93,8 +110,33 @@ class DiagnosticsEngineTests: XCTestCase {
XCTAssertEqual(engine2.diagnostics.count, 2)
}

func testHandlers() {
var handledDiagnostics: [Diagnostic] = []
let handler: DiagnosticsEngine.DiagnosticsHandler = { diagnostic in
handledDiagnostics.append(diagnostic)
}

let diagnostics = DiagnosticsEngine(handlers: [handler])
let location = FooLocation(name: "location")
diagnostics.emit(
data: FooDiag(arr: ["foo", "bar"], str: "str", int: 2),
location: location
)
diagnostics.emit(data: StringDiagnostic("diag 2"), location: location)
diagnostics.emit(data: StringDiagnostic("end"), location: location)

XCTAssertEqual(handledDiagnostics.count, 3)
for diagnostic in handledDiagnostics {
XCTAssertEqual(diagnostic.location.localizedDescription, location.localizedDescription)
}
XCTAssertEqual(handledDiagnostics[0].localizedDescription, "literal foo, bar 2 str bar str")
XCTAssertEqual(handledDiagnostics[1].localizedDescription, "diag 2")
XCTAssertEqual(handledDiagnostics[2].localizedDescription, "end")
}

static var allTests = [
("testBasics", testBasics),
("testMerging", testMerging),
("testHandlers", testHandlers),
]
}

0 comments on commit d94a3df

Please sign in to comment.