Last active
June 13, 2019 16:32
-
-
Save victor-pavlychko/d037745acfe2abd074132477c383a79d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
public struct ErrorSourceReference { | |
public let file: StaticString | |
public let line: Int | |
public var location: String { | |
return "\(file):\(line)" | |
} | |
public let function: StaticString | |
@_transparent | |
public init(file: StaticString = #file, line: Int = #line, function: StaticString = #function) { | |
self.file = file | |
self.line = line | |
self.function = function | |
} | |
} | |
extension ErrorSourceReference { | |
public var description: String { | |
return "`\(function)` at `\(location)`" | |
} | |
} | |
public struct ErrorCallStackSymbols { | |
#if DEBUG || targetEnvironment(simulator) | |
public static var isCallStackReportingEnabled = true | |
#else | |
public static var isCallStackReportingEnabled = false | |
#endif | |
public let callStackSymbols: [String] | |
@_transparent | |
public init() { | |
if type(of: self).isCallStackReportingEnabled { | |
self.callStackSymbols = Thread.callStackSymbols | |
} else { | |
self.callStackSymbols = [] | |
} | |
} | |
} | |
extension ErrorCallStackSymbols: CustomStringConvertible { | |
public var description: String { | |
return callStackSymbols.joined(separator: "\n") | |
} | |
} | |
public struct GenericError: Error { | |
public let message: String? | |
public let wrapped: Error? | |
public let sourceReference: ErrorSourceReference | |
public let callStackSymbols: ErrorCallStackSymbols | |
public init(_ message: String? = nil, wrapping wrapped: Error? = nil, file: StaticString = #file, line: Int = #line, function: StaticString = #function) { | |
self.message = message | |
self.wrapped = wrapped | |
self.sourceReference = .init(file: file, line: line, function: function) | |
self.callStackSymbols = .init() | |
} | |
} | |
extension GenericError: CustomStringConvertible { | |
public var description: String { | |
let message = self.message ?? "Error" | |
return "\(message) in \(sourceReference)" | |
} | |
} | |
extension Error { | |
@_transparent | |
public func withSourceReference(file: StaticString = #file, line: Int = #line, function: StaticString = #function) -> Error { | |
return GenericError(wrapping: self, file: file, line: line, function: function) | |
} | |
} | |
extension GenericError: CustomDebugStringConvertible { | |
public var debugDescription: String { | |
var lines: [String] = [ | |
description, | |
] | |
if !callStackSymbols.callStackSymbols.isEmpty { | |
lines.append(contentsOf: [ | |
"", | |
"Call Stack Symbols:", | |
callStackSymbols.description, | |
]) | |
} | |
if let wrapped = wrapped { | |
lines.append(contentsOf: [ | |
"", | |
"Underlying Error:", | |
wrapped.localizedDescription | |
.components(separatedBy: .newlines) | |
.map { "> \($0)" } | |
.joined(separator: "\n") | |
]) | |
} | |
return lines | |
.compactMap { $0 } | |
.joined(separator: "\n") | |
} | |
} | |
extension GenericError: LocalizedError { | |
public var errorDescription: String? { | |
return debugDescription | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment