//===--- JSONDiagnosticConsumer.swift - JSON Serializer for Diagnostics ---===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 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 // //===----------------------------------------------------------------------===// // This file provides a JSON serializer for compiler diagnostics emitted using // the DiagnosticEngine. //===----------------------------------------------------------------------===// import Foundation public final class JSONDiagnosticConsumer: DiagnosticConsumer { /// Enumerates the possible places this consumer might output diagnostics. private enum OutputFormat { case url(URL) case stdout } /// The current set of diagnostics that have been emitted. private var diagnostics = [Diagnostic]() /// The output format this consumer will output the generated JSON to. private let outputFormat: OutputFormat /// Creates a JSONDiagnosticConsumer that will output the generated JSON /// to a file at the given URL. /// - parameter outputURL: The URL that the consumer will write JSON /// diagnostics to. /// - note: If a file exists at the URL already, it will be overwritten. public init(outputURL: URL) { self.outputFormat = .url(outputURL) } /// Creates a JSONDiagnosticConsumer that will output the generated JSON /// to standard output. public init() { self.outputFormat = .stdout } /// Adds the diagnostic to the list of registered diagnostics. public func handle(_ diagnostic: Diagnostic) { self.diagnostics.append(diagnostic) } /// Writes the contents of the diagnostics as JSON out to the specified /// output location. public func finalize() { do { let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted let data = try encoder.encode(diagnostics) switch outputFormat { case .url(let url): if FileManager.default.fileExists(atPath: url.path) { try FileManager.default.removeItem(at: url) } FileManager.default.createFile(atPath: url.path, contents: data) case .stdout: FileHandle.standardOutput.write(data) } } catch { let dummyEngine = DiagnosticEngine() let printingConsumer = PrintingDiagnosticConsumer() dummyEngine.addConsumer(printingConsumer) dummyEngine.diagnose(.couldNotOutputJSON) } } } extension Diagnostic.Message { static let couldNotOutputJSON = Diagnostic.Message(.error, "failed emitting JSON diagnostics") }