Skip to content

Commit 575d7c0

Browse files
Use Custom Dump (#736)
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * fix * wip * wip * Model Tic-Tac-Toe board using proper type * wip * wip * wip * wip Co-authored-by: Brandon Williams <[email protected]>
1 parent b73f74f commit 575d7c0

File tree

19 files changed

+192
-1268
lines changed

19 files changed

+192
-1268
lines changed

Examples/CaseStudies/SwiftUICaseStudies/00-Core.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ let rootReducer = Reducer<RootState, RootAction, RootEnvironment>.combine(
280280
environment: { .init(mainQueue: $0.mainQueue, webSocket: $0.webSocket) }
281281
)
282282
)
283+
.debug()
283284
.signpost()
284285

285286
private func liveFetchNumber() -> Effect<Int, Never> {

Examples/CaseStudies/SwiftUICaseStudies/01-GettingStarted-AlertsAndActionSheets.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ let alertAndSheetReducer = Reducer<
8888
return .none
8989
}
9090
}
91-
.debug()
9291

9392
struct AlertAndSheetView: View {
9493
let store: Store<AlertAndSheetState, AlertAndSheetAction>

Examples/TicTacToe/tic-tac-toe/Sources/AppCore/AppCore.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,4 @@ public let appReducer = Reducer<AppState, AppAction, AppEnvironment>.combine(
6464
}
6565
}
6666
)
67+
.debug()

Examples/TicTacToe/tic-tac-toe/Sources/GameCore/GameCore.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ extension Three where Element == Three<Player?> {
8282
)
8383

8484
public var isFilled: Bool {
85-
self.allSatisfy { row in row.allSatisfy { $0 != nil } }
85+
self.allSatisfy { $0.allSatisfy { $0 != nil } }
8686
}
8787

8888
func hasWin(_ player: Player) -> Bool {

Examples/Todos/Todos/Todos.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ let appReducer = Reducer<AppState, AppAction, AppEnvironment>.combine(
8585
}
8686
}
8787
)
88-
89-
.debugActions(actionFormat: .labelsOnly)
88+
.debug()
9089

9190
struct AppView: View {
9291
let store: Store<AppState, AppAction>

Package.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@ let package = Package(
2020
.package(name: "Benchmark", url: "https://github.com/google/swift-benchmark", from: "0.1.0"),
2121
.package(url: "https://github.com/pointfreeco/combine-schedulers", from: "0.5.0"),
2222
.package(url: "https://github.com/pointfreeco/swift-case-paths", from: "0.4.0"),
23+
.package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "0.1.0"),
2324
.package(url: "https://github.com/pointfreeco/swift-identified-collections", from: "0.1.0"),
24-
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.1.0"),
25+
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.2.0"),
2526
],
2627
targets: [
2728
.target(
2829
name: "ComposableArchitecture",
2930
dependencies: [
3031
.product(name: "CasePaths", package: "swift-case-paths"),
3132
.product(name: "CombineSchedulers", package: "combine-schedulers"),
33+
.product(name: "CustomDump", package: "swift-custom-dump"),
3234
.product(name: "IdentifiedCollections", package: "swift-identified-collections"),
3335
.product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
3436
]

Sources/ComposableArchitecture/Debugging/ReducerDebugging.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,16 @@ extension Reducer {
115115
return .merge(
116116
.fireAndForget {
117117
debugEnvironment.queue.async {
118-
let actionOutput =
119-
actionFormat == .prettyPrint
120-
? debugOutput(localAction).indent(by: 2)
121-
: debugCaseOutput(localAction).indent(by: 2)
118+
var actionOutput = ""
119+
if actionFormat == .prettyPrint {
120+
customDump(localAction, to: &actionOutput, indent: 2)
121+
} else {
122+
actionOutput.write(debugCaseOutput(localAction).indent(by: 2))
123+
}
122124
let stateOutput =
123125
LocalState.self == Void.self
124126
? ""
125-
: debugDiff(previousState, nextState).map { "\($0)\n" } ?? " (No state changes)\n"
127+
: diff(previousState, nextState).map { "\($0)\n" } ?? " (No state changes)\n"
126128
debugEnvironment.printer(
127129
"""
128130
\(prefix.isEmpty ? "" : "\(prefix): ")received action:
Lines changed: 1 addition & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -1,201 +1,9 @@
1+
import CustomDump
12
import Foundation
23

3-
func debugOutput(_ value: Any, indent: Int = 0) -> String {
4-
var visitedItems: Set<ObjectIdentifier> = []
5-
6-
func debugOutputHelp(_ value: Any, indent: Int = 0) -> String {
7-
let mirror = Mirror(reflecting: value)
8-
switch (value, mirror.displayStyle) {
9-
case let (value as CustomDebugOutputConvertible, _):
10-
return value.debugOutput.indent(by: indent)
11-
case (_, .collection?):
12-
return """
13-
[
14-
\(mirror.children.map { "\(debugOutput($0.value, indent: 2)),\n" }.joined())]
15-
"""
16-
.indent(by: indent)
17-
18-
case (_, .dictionary?):
19-
let pairs = mirror.children.map { label, value -> String in
20-
let pair = value as! (key: AnyHashable, value: Any)
21-
return
22-
"\("\(debugOutputHelp(pair.key.base)): \(debugOutputHelp(pair.value)),".indent(by: 2))\n"
23-
}
24-
return """
25-
[
26-
\(pairs.sorted().joined())]
27-
"""
28-
.indent(by: indent)
29-
30-
case (_, .set?):
31-
return """
32-
Set([
33-
\(mirror.children.map { "\(debugOutputHelp($0.value, indent: 2)),\n" }.sorted().joined())])
34-
"""
35-
.indent(by: indent)
36-
37-
case (_, .optional?):
38-
return mirror.children.isEmpty
39-
? "nil".indent(by: indent)
40-
: debugOutputHelp(mirror.children.first!.value, indent: indent)
41-
42-
case (_, .enum?) where !mirror.children.isEmpty:
43-
let child = mirror.children.first!
44-
let childMirror = Mirror(reflecting: child.value)
45-
let elements =
46-
childMirror.displayStyle != .tuple
47-
? debugOutputHelp(child.value, indent: 2)
48-
: childMirror.children.map { child -> String in
49-
let label = child.label!
50-
return "\(label.hasPrefix(".") ? "" : "\(label): ")\(debugOutputHelp(child.value))"
51-
}
52-
.joined(separator: ",\n")
53-
.indent(by: 2)
54-
return """
55-
\(mirror.subjectType).\(child.label!)(
56-
\(elements)
57-
)
58-
"""
59-
.indent(by: indent)
60-
61-
case (_, .enum?):
62-
return """
63-
\(mirror.subjectType).\(value)
64-
"""
65-
.indent(by: indent)
66-
67-
case (_, .struct?) where !mirror.children.isEmpty:
68-
let elements = mirror.children
69-
.map { "\($0.label.map { "\($0): " } ?? "")\(debugOutputHelp($0.value))".indent(by: 2) }
70-
.joined(separator: ",\n")
71-
return """
72-
\(mirror.subjectType)(
73-
\(elements)
74-
)
75-
"""
76-
.indent(by: indent)
77-
78-
case let (value as AnyObject, .class?)
79-
where !mirror.children.isEmpty && !visitedItems.contains(ObjectIdentifier(value)):
80-
visitedItems.insert(ObjectIdentifier(value))
81-
let elements = mirror.children
82-
.map { "\($0.label.map { "\($0): " } ?? "")\(debugOutputHelp($0.value))".indent(by: 2) }
83-
.joined(separator: ",\n")
84-
return """
85-
\(mirror.subjectType)(
86-
\(elements)
87-
)
88-
"""
89-
.indent(by: indent)
90-
91-
case let (value as AnyObject, .class?)
92-
where !mirror.children.isEmpty && visitedItems.contains(ObjectIdentifier(value)):
93-
return "\(mirror.subjectType)(↩︎)"
94-
95-
case let (value as CustomStringConvertible, .class?):
96-
return value.description
97-
.replacingOccurrences(
98-
of: #"^<([^:]+): 0x[^>]+>$"#, with: "$1()", options: .regularExpression
99-
)
100-
.indent(by: indent)
101-
102-
case let (value as CustomDebugStringConvertible, _):
103-
return value.debugDescription
104-
.replacingOccurrences(
105-
of: #"^<([^:]+): 0x[^>]+>$"#, with: "$1()", options: .regularExpression
106-
)
107-
.indent(by: indent)
108-
109-
case let (value as CustomStringConvertible, _):
110-
return value.description
111-
.indent(by: indent)
112-
113-
case (_, .struct?), (_, .class?):
114-
return "\(mirror.subjectType)()"
115-
.indent(by: indent)
116-
117-
case (_, .tuple?) where mirror.children.isEmpty:
118-
return "()"
119-
.indent(by: indent)
120-
121-
case (_, .tuple?):
122-
let elements = mirror.children.map { child -> String in
123-
let label = child.label!
124-
return "\(label.hasPrefix(".") ? "" : "\(label): ")\(debugOutputHelp(child.value))"
125-
.indent(by: 2)
126-
}
127-
return """
128-
(
129-
\(elements.joined(separator: ",\n"))
130-
)
131-
"""
132-
.indent(by: indent)
133-
134-
case (_, nil):
135-
return "\(value)"
136-
.indent(by: indent)
137-
138-
@unknown default:
139-
return "\(value)"
140-
.indent(by: indent)
141-
}
142-
}
143-
144-
return debugOutputHelp(value, indent: indent)
145-
}
146-
147-
func debugDiff<T>(_ before: T, _ after: T, printer: (T) -> String = { debugOutput($0) }) -> String?
148-
{
149-
diff(printer(before), printer(after))
150-
}
151-
1524
extension String {
1535
func indent(by indent: Int) -> String {
1546
let indentation = String(repeating: " ", count: indent)
1557
return indentation + self.replacingOccurrences(of: "\n", with: "\n\(indentation)")
1568
}
1579
}
158-
159-
public protocol CustomDebugOutputConvertible {
160-
var debugOutput: String { get }
161-
}
162-
163-
extension Date: CustomDebugOutputConvertible {
164-
public var debugOutput: String {
165-
dateFormatter.string(from: self)
166-
}
167-
}
168-
169-
private let dateFormatter: ISO8601DateFormatter = {
170-
let formatter = ISO8601DateFormatter()
171-
formatter.timeZone = TimeZone(identifier: "UTC")!
172-
return formatter
173-
}()
174-
175-
extension URL: CustomDebugOutputConvertible {
176-
public var debugOutput: String {
177-
self.absoluteString
178-
}
179-
}
180-
181-
#if DEBUG
182-
#if canImport(Speech)
183-
import Speech
184-
extension SFSpeechRecognizerAuthorizationStatus: CustomDebugOutputConvertible {
185-
public var debugOutput: String {
186-
switch self {
187-
case .notDetermined:
188-
return "notDetermined"
189-
case .denied:
190-
return "denied"
191-
case .restricted:
192-
return "restricted"
193-
case .authorized:
194-
return "authorized"
195-
@unknown default:
196-
return "unknown"
197-
}
198-
}
199-
}
200-
#endif
201-
#endif

Sources/ComposableArchitecture/Internal/Diff.swift

Lines changed: 0 additions & 82 deletions
This file was deleted.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
@_exported import CasePaths
22
@_exported import CombineSchedulers
3+
@_exported import CustomDump
34
@_exported import IdentifiedCollections
5+
@_exported import XCTestDynamicOverlay

0 commit comments

Comments
 (0)