WIP: pretty logging

This commit is contained in:
John Rommel Estropia
2016-05-06 09:19:24 +08:00
parent 0073d038e0
commit 4eecd80710
6 changed files with 495 additions and 145 deletions

View File

@@ -7,6 +7,7 @@
//
import UIKit
import CoreData
import CoreStore
@@ -24,10 +25,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
application.statusBarStyle = .LightContent
print(InMemoryStore())
print(SQLiteStore())
print(LocalStorageOptions.None)
print([.AllowSynchronousLightweightMigration, .PreventProgressiveMigration] as LocalStorageOptions)
print(CoreStoreError.MappingModelNotFound(localStoreURL: NSURL(string: "file://sample.db")!, targetModel: NSManagedObjectModel.mergedModelFromBundles(nil)!, targetModelVersion: "Sample-1.0.0"))
CoreStore.defaultStack = DataStack(migrationChain: ["Sample-1.0.0": "Sample-1.0.2", "Sample-1.0.1": "Sample-1.0.2"])
print(CoreStore.defaultStack)
print(CoreStore.beginUnsafe())
return true
}

View File

@@ -157,7 +157,7 @@ class MigrationsDemoViewController: UIViewController {
)
self.setEnabled(false)
let progress = try! dataStack.addStorage(
let progress = dataStack.addStorage(
SQLiteStore(fileName: "MigrationDemo.sqlite"),
completion: { [weak self] (result) -> Void in

View File

@@ -26,6 +26,74 @@
import Foundation
// MARK: - AsynchronousDataTransaction
extension AsynchronousDataTransaction: CustomDebugStringConvertible, IndentableDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return self.cs_dump()
}
// MARK: IndentableDebugStringConvertible
private var cs_dumpInfo: DumpInfo {
return [
("context", self.context),
("supportsUndo", self.supportsUndo),
("bypassesQueueing", self.bypassesQueueing),
("isCommitted", self.isCommitted),
("result", self.result)
]
}
}
// MARK: - CloudStorageOptions
extension CloudStorageOptions: CustomDebugStringConvertible, IndentableDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return self.cs_dump()
}
// MARK: IndentableDebugStringConvertible
private var cs_dumpValue: String {
var flags = [String]()
if self.contains(.RecreateLocalStoreOnModelMismatch) {
flags.append(".RecreateLocalStoreOnModelMismatch")
}
if self.contains(.AllowSynchronousLightweightMigration) {
flags.append(".AllowSynchronousLightweightMigration")
}
switch flags.count {
case 0:
return "[.None]"
case 1:
return "[.\(flags[0])]"
default:
let description = "[\n" + flags.joinWithSeparator(",\n")
return description.indent(1) + "\n]"
}
}
}
// MARK: - CoreStoreError
extension CoreStoreError: CustomDebugStringConvertible, IndentableDebugStringConvertible {
@@ -55,8 +123,8 @@ extension CoreStoreError: CustomDebugStringConvertible, IndentableDebugStringCon
private var cs_dumpInfo: DumpInfo {
var info: DumpInfo = [
("_domain", self._domain.cs_dump()),
("_code", self._code.cs_dump()),
("_domain", self._domain),
("_code", self._code),
]
switch self {
@@ -64,24 +132,78 @@ extension CoreStoreError: CustomDebugStringConvertible, IndentableDebugStringCon
break
case .DifferentStorageExistsAtURL(let existingPersistentStoreURL):
info.append(("existingPersistentStoreURL", existingPersistentStoreURL.cs_dump()))
info.append(("existingPersistentStoreURL", existingPersistentStoreURL))
case .MappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
info.append(("localStoreURL", localStoreURL.cs_dump()))
info.append(("targetModel", targetModel.cs_dump()))
info.append(("targetModelVersion", targetModelVersion.cs_dump()))
info.append(("localStoreURL", localStoreURL))
info.append(("targetModel", targetModel))
info.append(("targetModelVersion", targetModelVersion))
case .ProgressiveMigrationRequired(let localStoreURL):
info.append(("localStoreURL", localStoreURL.cs_dump()))
info.append(("localStoreURL", localStoreURL))
case .InternalError(let NSError):
info.append(("NSError", NSError.cs_dump()))
info.append(("NSError", NSError))
}
return info
}
}
// MARK: - DataStack
extension DataStack: CustomDebugStringConvertible, IndentableDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return self.cs_dump()
}
// MARK: IndentableDebugStringConvertible
private var cs_dumpInfo: DumpInfo {
// TODO: print entities and persistentStores
return [
("coordinator", self.coordinator),
("rootSavingContext", self.rootSavingContext),
("mainContext", self.mainContext),
("model", self.model),
("migrationChain", self.migrationChain)
]
}
}
// MARK: - ICloudStore
extension ICloudStore: CustomDebugStringConvertible, IndentableDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return self.cs_dump()
}
// MARK: IndentableDebugStringConvertible
private var cs_dumpInfo: DumpInfo {
return [
("configuration", self.configuration),
("storeOptions", self.storeOptions),
("cacheFileURL", self.cacheFileURL),
("cloudStorageOptions", self.cloudStorageOptions)
]
}
}
// MARK: - InMemoryStore
extension InMemoryStore: CustomDebugStringConvertible, IndentableDebugStringConvertible {
@@ -106,6 +228,58 @@ extension InMemoryStore: CustomDebugStringConvertible, IndentableDebugStringConv
}
// MARK: - Into
extension Into: CustomDebugStringConvertible, IndentableDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return self.cs_dump()
}
// MARK: IndentableDebugStringConvertible
private var cs_dumpInfo: DumpInfo {
return [
("entityClass", self.entityClass),
("configuration", self.configuration),
("inferStoreIfPossible", self.inferStoreIfPossible)
]
}
}
// MARK: - LegacySQLiteStore
extension LegacySQLiteStore: CustomDebugStringConvertible, IndentableDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return self.cs_dump()
}
// MARK: IndentableDebugStringConvertible
private var cs_dumpInfo: DumpInfo {
return [
("configuration", self.configuration),
("storeOptions", self.storeOptions),
("fileURL", self.fileURL),
("mappingModelBundles", self.mappingModelBundles),
("localStorageOptions", self.localStorageOptions)
]
}
}
// MARK: - LocalStorageOptions
extension LocalStorageOptions: CustomDebugStringConvertible, IndentableDebugStringConvertible {
@@ -151,6 +325,58 @@ extension LocalStorageOptions: CustomDebugStringConvertible, IndentableDebugStri
}
// MARK: - MigrationChain
extension MigrationChain: CustomDebugStringConvertible, IndentableDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return self.cs_dump()
}
// MARK: IndentableDebugStringConvertible
private var cs_dumpValue: String {
guard self.valid else {
return "<invalid migration chain>"
}
var paths = [String]()
for var version in self.rootVersions {
var steps = [version]
while let nextVersion = self.nextVersionFrom(version) {
steps.append(nextVersion)
version = nextVersion
}
paths.append(steps.joinWithSeparator(""))
}
switch paths.count {
case 0:
return "[]"
case 1:
return "[\(paths[0])]"
default:
var dump = "["
paths.forEach {
dump.appendContentsOf("\n\($0);")
}
return dump.indent(1) + "\n]"
}
}
}
// MARK: - SQLiteStore
extension SQLiteStore: CustomDebugStringConvertible, IndentableDebugStringConvertible {
@@ -178,9 +404,9 @@ extension SQLiteStore: CustomDebugStringConvertible, IndentableDebugStringConver
}
// MARK: - LegacySQLiteStore
// MARK: - SynchronousDataTransaction
extension LegacySQLiteStore: CustomDebugStringConvertible, IndentableDebugStringConvertible {
extension SynchronousDataTransaction: CustomDebugStringConvertible, IndentableDebugStringConvertible {
// MARK: CustomDebugStringConvertible
@@ -195,19 +421,43 @@ extension LegacySQLiteStore: CustomDebugStringConvertible, IndentableDebugString
private var cs_dumpInfo: DumpInfo {
return [
("configuration", self.configuration),
("storeOptions", self.storeOptions),
("fileURL", self.fileURL),
("mappingModelBundles", self.mappingModelBundles),
("localStorageOptions", self.localStorageOptions)
("context", self.context),
("supportsUndo", self.supportsUndo),
("bypassesQueueing", self.bypassesQueueing),
("isCommitted", self.isCommitted),
("result", self.result)
]
}
}
// MARK: - Private
// MARK: - UnsafeDataTransaction
private typealias DumpInfo = [(key: String, value: IndentableDebugStringConvertible)]
extension UnsafeDataTransaction: CustomDebugStringConvertible, IndentableDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return self.cs_dump()
}
// MARK: IndentableDebugStringConvertible
private var cs_dumpInfo: DumpInfo {
return [
("context", self.context),
("supportsUndo", self.supportsUndo)
]
}
}
// MARK: - Private: Utilities
private typealias DumpInfo = [(key: String, value: Any)]
private func formattedValue(any: Any) -> String {
@@ -223,6 +473,41 @@ private func formattedValue(any: IndentableDebugStringConvertible) -> String {
return any.cs_dumpValue
}
private extension String {
private static func indention(level: Int = 1) -> String {
return String(count: level * 4, repeatedValue: Character(" "))
}
private func trimSwiftModuleName() -> String {
if self.hasPrefix("Swift.") {
return self.substringFromIndex("Swift.".endIndex)
}
return self
}
private func indent(level: Int) -> String {
return self.stringByReplacingOccurrencesOfString("\n", withString: "\n\(String.indention(level))")
}
private mutating func appendDumpInfo(key: String, _ value: Any) {
self.appendContentsOf("\n.\(key) = \(formattedValue(value));")
}
private mutating func appendDumpInfo(key: String, _ value: IndentableDebugStringConvertible) {
self.appendContentsOf("\n.\(key) = \(formattedValue(value));")
}
}
// MARK: - Private: IndentableDebugStringConvertible
private protocol IndentableDebugStringConvertible {
static func cs_typeString() -> String
@@ -267,70 +552,17 @@ private extension IndentableDebugStringConvertible {
else {
dump.appendContentsOf(" {")
for (key, value) in info {
info.forEach {
dump.appendContentsOf("\n.\(key) = \(formattedValue(value))")
dump.appendDumpInfo($0, $1)
}
return dump.indent(1) + "\n}"
}
}
}
extension String: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\"\(self)\""
}
}
extension NSURL: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\"\(self)\""
}
}
extension Int: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\(self)"
}
}
extension NSManagedObjectModel: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\(self)"
}
}
extension NSMappingModel: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\(self)"
}
}
extension NSError: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\(self)"
}
}
extension NSBundle: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\(self.bundleURL.lastPathComponent ?? "<unknown bundle URL>") (\(self.bundleIdentifier ?? "<unknown bundle identifier>"))"
}
}
// MARK: -
extension Array: IndentableDebugStringConvertible {
@@ -374,6 +606,172 @@ extension Dictionary: IndentableDebugStringConvertible {
}
}
extension NSAttributeDescription: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
var string = "{"
string.appendDumpInfo("attributeType", self.attributeType)
string.appendDumpInfo("attributeValueClassName", self.attributeValueClassName)
string.appendDumpInfo("defaultValue", self.defaultValue)
string.appendDumpInfo("valueTransformerName", self.valueTransformerName)
string.appendDumpInfo("allowsExternalBinaryDataStorage", self.allowsExternalBinaryDataStorage)
string.appendDumpInfo("entity", self.entity.name)
string.appendDumpInfo("name", self.name)
string.appendDumpInfo("optional", self.optional)
string.appendDumpInfo("transient", self.transient)
string.appendDumpInfo("userInfo", self.userInfo)
string.appendDumpInfo("indexed", self.indexed)
string.appendDumpInfo("versionHash", self.versionHash)
string.appendDumpInfo("versionHashModifier", self.versionHashModifier)
string.appendDumpInfo("indexedBySpotlight", self.indexedBySpotlight)
string.appendDumpInfo("storedInExternalRecord", self.storedInExternalRecord)
string.appendDumpInfo("renamingIdentifier", self.renamingIdentifier)
return string.indent(1) + "\n}"
}
}
extension NSAttributeType: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
switch self {
case .UndefinedAttributeType: return ".UndefinedAttributeType"
case .Integer16AttributeType: return ".Integer16AttributeType"
case .Integer32AttributeType: return ".Integer32AttributeType"
case .Integer64AttributeType: return ".Integer64AttributeType"
case .DecimalAttributeType: return ".DecimalAttributeType"
case .DoubleAttributeType: return ".DoubleAttributeType"
case .FloatAttributeType: return ".FloatAttributeType"
case .StringAttributeType: return ".StringAttributeType"
case .BooleanAttributeType: return ".BooleanAttributeType"
case .DateAttributeType: return ".DateAttributeType"
case .BinaryDataAttributeType: return ".BinaryDataAttributeType"
case .TransformableAttributeType: return ".TransformableAttributeType"
case .ObjectIDAttributeType: return ".ObjectIDAttributeType"
}
}
}
extension NSBundle: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\(self.bundleIdentifier.flatMap({ "\"\($0)\"" }) ?? "<unknown bundle identifier>") (\(self.bundleURL.lastPathComponent ?? "<unknown bundle URL>"))"
}
}
extension NSDeleteRule: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
switch self {
case .NoActionDeleteRule: return ".NoActionDeleteRule"
case .NullifyDeleteRule: return ".NullifyDeleteRule"
case .CascadeDeleteRule: return ".CascadeDeleteRule"
case .DenyDeleteRule: return ".DenyDeleteRule"
}
}
}
extension NSEntityDescription: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
var string = "{"
string.appendDumpInfo("managedObjectClassName", self.managedObjectClassName!)
string.appendDumpInfo("name", self.name)
string.appendDumpInfo("abstract", self.abstract)
string.appendDumpInfo("superentity", self.superentity?.name)
string.appendDumpInfo("subentities", self.subentities.map({ $0.name }))
string.appendDumpInfo("properties", self.properties)
string.appendDumpInfo("userInfo", self.userInfo)
string.appendDumpInfo("versionHash", self.versionHash)
string.appendDumpInfo("versionHashModifier", self.versionHashModifier)
string.appendDumpInfo("renamingIdentifier", self.renamingIdentifier)
string.appendDumpInfo("compoundIndexes", self.compoundIndexes)
if #available(iOS 9.0, *) {
string.appendDumpInfo("uniquenessConstraints", self.uniquenessConstraints)
}
return string.indent(1) + "\n}"
}
}
extension NSError: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
var string = "{"
string.appendDumpInfo("domain", self.domain)
string.appendDumpInfo("code", self.code)
string.appendDumpInfo("userInfo", self.userInfo)
return string.indent(1) + "\n}"
}
}
extension NSManagedObjectModel: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
var string = "{"
string.appendDumpInfo("configurations", self.configurations)
string.appendDumpInfo("entities", self.entities)
return string.indent(1) + "\n}"
}
}
extension NSMappingModel: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\(self)"
}
}
extension NSRelationshipDescription: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
var string = "{"
string.appendDumpInfo("destinationEntity", self.destinationEntity?.name)
string.appendDumpInfo("inverseRelationship", self.inverseRelationship?.name)
string.appendDumpInfo("minCount", self.minCount)
string.appendDumpInfo("maxCount", self.maxCount)
string.appendDumpInfo("deleteRule", self.deleteRule)
string.appendDumpInfo("toMany", self.toMany)
string.appendDumpInfo("ordered", self.ordered)
string.appendDumpInfo("entity", self.entity.name)
string.appendDumpInfo("name", self.name)
string.appendDumpInfo("optional", self.optional)
string.appendDumpInfo("transient", self.transient)
string.appendDumpInfo("userInfo", self.userInfo)
string.appendDumpInfo("indexed", self.indexed)
string.appendDumpInfo("versionHash", self.versionHash)
string.appendDumpInfo("versionHashModifier", self.versionHashModifier)
string.appendDumpInfo("indexedBySpotlight", self.indexedBySpotlight)
string.appendDumpInfo("storedInExternalRecord", self.storedInExternalRecord)
string.appendDumpInfo("renamingIdentifier", self.renamingIdentifier)
return string.indent(1) + "\n}"
}
}
extension NSURL: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
return "\"\(self)\""
}
}
extension Optional: IndentableDebugStringConvertible {
private var cs_dumpValue: String {
@@ -386,24 +784,10 @@ extension Optional: IndentableDebugStringConvertible {
}
}
private extension String {
extension String: IndentableDebugStringConvertible {
private static func indention(level: Int = 1) -> String {
private var cs_dumpValue: String {
return String(count: level * 4, repeatedValue: Character(" "))
}
private func trimSwiftModuleName() -> String {
if self.hasPrefix("Swift.") {
return self.substringFromIndex("Swift.".endIndex)
}
return self
}
private func indent(level: Int) -> String {
return self.stringByReplacingOccurrencesOfString("\n", withString: "\n\(String.indention(level))")
return "\"\(self)\""
}
}

View File

@@ -845,27 +845,20 @@ public extension DataStack {
@available(*, deprecated=2.0.0, message="Use addStorage(_:completion:) by passing a InMemoryStore instance.")
public func addInMemoryStore(configuration configuration: String? = nil, completion: (PersistentStoreResult) -> Void) {
do {
try self.addStorage(
InMemoryStore(configuration: configuration),
completion: { result in
self.addStorage(
InMemoryStore(configuration: configuration),
completion: { result in
switch result {
switch result {
case .Success(let storage):
completion(PersistentStoreResult(self.persistentStoreForStorage(storage)!))
case .Failure(let error):
completion(PersistentStoreResult(error as NSError))
}
case .Success(let storage):
completion(PersistentStoreResult(self.persistentStoreForStorage(storage)!))
case .Failure(let error):
completion(PersistentStoreResult(error as NSError))
}
)
}
catch {
completion(PersistentStoreResult(error as NSError))
}
}
)
}
/**
@@ -876,7 +869,7 @@ public extension DataStack {
@available(*, deprecated=2.0.0, message="Use addStorage(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
public func addSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
return try self.addStorage(
return self.addStorage(
LegacySQLiteStore(
fileName: fileName,
configuration: configuration,
@@ -905,7 +898,7 @@ public extension DataStack {
@available(*, deprecated=2.0.0, message="Use addSQLiteStore(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.")
public func addSQLiteStore(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = NSBundle.allBundles(), resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? {
return try self.addStorage(
return self.addStorage(
LegacySQLiteStore(
fileURL: fileURL,
configuration: configuration,

View File

@@ -248,31 +248,3 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D
private let versionTree: [String: String]
}
// MARK: - MigrationChain: CustomDebugStringConvertible
extension MigrationChain: CustomDebugStringConvertible {
public var debugDescription: String {
guard self.valid else {
return "<invalid migration chain>"
}
var paths = [String]()
for var version in self.rootVersions {
var steps = [version]
while let nextVersion = self.nextVersionFrom(version) {
steps.append(nextVersion)
version = nextVersion
}
paths.append(steps.joinWithSeparator(""))
}
return "[" + paths.joinWithSeparator("], [") + "]"
}
}

View File

@@ -83,7 +83,7 @@ public extension CSDataStack {
return bridge(error) {
try self.bridgeToSwift.addStorage(
self.bridgeToSwift.addStorage(
storage.bridgeToSwift,
completion: { completion($0.bridgeToObjectiveC) }
)