Skip to content

Commit 3860d0b

Browse files
authored
Abbreviate enums in diffs (#72)
* Abbreviate enums in diffs We added the ability to abbreviate nested dumps in #71, but this didn't transfer to diffs. * wip * Fix for old Swift runtime
1 parent 87dd388 commit 3860d0b

File tree

8 files changed

+146
-30
lines changed

8 files changed

+146
-30
lines changed

Sources/CustomDump/Conformances/SwiftUI.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
Mirror(reflecting: self).children.first?.value as Any,
2323
name: nil,
2424
indent: 2,
25+
isRoot: false,
2526
maxDepth: .max
2627
)
2728
return """

Sources/CustomDump/Diff.swift

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
3434
lhsName: String?,
3535
rhsName: String?,
3636
separator: String,
37-
indent: Int
37+
indent: Int,
38+
isRoot: Bool
3839
) -> String {
3940
let rhsName = rhsName ?? lhsName
4041
guard !isMirrorEqual(lhs, rhs) else {
41-
return _customDump(lhs, name: rhsName, indent: indent, maxDepth: 0)
42+
return _customDump(lhs, name: rhsName, indent: indent, isRoot: isRoot, maxDepth: 0)
4243
.appending(separator)
4344
.indenting(with: format.both + " ")
4445
}
@@ -48,8 +49,8 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
4849
var out = ""
4950

5051
func diffEverything() {
51-
var lhs = _customDump(lhs, name: lhsName, indent: indent, maxDepth: .max)
52-
var rhs = _customDump(rhs, name: rhsName, indent: indent, maxDepth: .max)
52+
var lhs = _customDump(lhs, name: lhsName, indent: indent, isRoot: isRoot, maxDepth: .max)
53+
var rhs = _customDump(rhs, name: rhsName, indent: indent, isRoot: isRoot, maxDepth: .max)
5354
if lhs == rhs {
5455
if lhsMirror.subjectType != rhsMirror.subjectType {
5556
lhs.append(" as \(typeName(lhsMirror.subjectType))")
@@ -104,6 +105,7 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
104105
lhs,
105106
name: lhsName,
106107
indent: indent,
108+
isRoot: false,
107109
maxDepth: 0
108110
)
109111
.indenting(with: format.first + " "),
@@ -114,6 +116,7 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
114116
rhs,
115117
name: rhsName,
116118
indent: indent,
119+
isRoot: false,
117120
maxDepth: 0
118121
)
119122
.indenting(with: format.second + " "),
@@ -130,6 +133,7 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
130133
lhs,
131134
name: lhsName,
132135
indent: indent,
136+
isRoot: isRoot,
133137
maxDepth: .max
134138
)
135139
.indenting(with: format.first + " "),
@@ -140,6 +144,7 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
140144
rhs,
141145
name: rhsName,
142146
indent: indent,
147+
isRoot: isRoot,
143148
maxDepth: .max
144149
)
145150
.indenting(with: format.second + " "),
@@ -178,6 +183,7 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
178183
child.value,
179184
name: child.label,
180185
indent: indent + elementIndent,
186+
isRoot: false,
181187
maxDepth: 0
182188
)
183189
.indenting(with: format.both + " "),
@@ -234,7 +240,8 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
234240
separator: lhsOffset == lhsChildren.count - 1 && rhsOffset == rhsChildren.count - 1
235241
? ""
236242
: elementSeparator,
237-
indent: indent + elementIndent
243+
indent: indent + elementIndent,
244+
isRoot: false
238245
),
239246
to: &out
240247
)
@@ -250,6 +257,7 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
250257
lhsChild.value,
251258
name: lhsChild.label,
252259
indent: indent + elementIndent,
260+
isRoot: false,
253261
maxDepth: .max
254262
)
255263
.indenting(with: format.first + " "),
@@ -266,6 +274,7 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
266274
rhsChild.value,
267275
name: rhsChild.label,
268276
indent: indent + elementIndent,
277+
isRoot: false,
269278
maxDepth: .max
270279
)
271280
.indenting(with: format.second + " "),
@@ -301,7 +310,8 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
301310
lhsName: lhsName,
302311
rhsName: rhsName,
303312
separator: separator,
304-
indent: indent
313+
indent: indent,
314+
isRoot: isRoot
305315
)
306316
)
307317

@@ -385,16 +395,16 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
385395
let lhs = $0.value as? (key: AnyHashable, value: Any),
386396
let rhs = $1.value as? (key: AnyHashable, value: Any)
387397
else {
388-
return _customDump($0.value, name: nil, indent: 0, maxDepth: 1)
389-
< _customDump($1.value, name: nil, indent: 0, maxDepth: 1)
398+
return _customDump($0.value, name: nil, indent: 0, isRoot: false, maxDepth: 1)
399+
< _customDump($1.value, name: nil, indent: 0, isRoot: false, maxDepth: 1)
390400
}
391-
return _customDump(lhs.key.base, name: nil, indent: 0, maxDepth: 1)
392-
< _customDump(rhs.key.base, name: nil, indent: 0, maxDepth: 1)
401+
return _customDump(lhs.key.base, name: nil, indent: 0, isRoot: false, maxDepth: 1)
402+
< _customDump(rhs.key.base, name: nil, indent: 0, isRoot: false, maxDepth: 1)
393403
}
394404
) { child, _ in
395405
guard let pair = child.value as? (key: AnyHashable, value: Any) else { return }
396406
child = (
397-
_customDump(pair.key.base, name: nil, indent: 0, maxDepth: 1),
407+
_customDump(pair.key.base, name: nil, indent: 0, isRoot: false, maxDepth: 1),
398408
pair.value
399409
)
400410
}
@@ -420,7 +430,7 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
420430
? rhsChildMirror
421431
: Mirror(rhs, unlabeledChildren: [rhsChild.value], displayStyle: .tuple)
422432

423-
let subjectType = typeName(lhsMirror.subjectType)
433+
let subjectType = isRoot ? typeName(lhsMirror.subjectType) : ""
424434
diffChildren(
425435
lhsAssociatedValuesMirror,
426436
rhsAssociatedValuesMirror,
@@ -452,7 +462,8 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
452462
lhsName: lhsName,
453463
rhsName: rhsName,
454464
separator: separator,
455-
indent: indent
465+
indent: indent,
466+
isRoot: isRoot
456467
)
457468
)
458469

@@ -469,8 +480,8 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
469480
isIdentityEqual($0.value, $1.value) || isMirrorEqual($0.value, $1.value)
470481
},
471482
areInIncreasingOrder: {
472-
_customDump($0.value, name: nil, indent: 0, maxDepth: 1)
473-
< _customDump($1.value, name: nil, indent: 0, maxDepth: 1)
483+
_customDump($0.value, name: nil, indent: 0, isRoot: false, maxDepth: 1)
484+
< _customDump($1.value, name: nil, indent: 0, isRoot: false, maxDepth: 1)
474485
}
475486
)
476487

@@ -522,7 +533,10 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
522533
.split(separator: "\n", omittingEmptySubsequences: false)
523534
.map(Line.init(rawValue:))
524535
)
525-
let hashes = String(repeating: "#", count: max(lhs.hashCount, rhs.hashCount))
536+
let hashes = String(
537+
repeating: "#",
538+
count: max(lhs.hashCount(isMultiline: true), rhs.hashCount(isMultiline: true))
539+
)
526540
diffChildren(
527541
lhsMirror,
528542
rhsMirror,
@@ -545,7 +559,7 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
545559

546560
guard !isMirrorEqual(lhs, rhs) else { return nil }
547561

548-
var diff = diffHelp(lhs, rhs, lhsName: nil, rhsName: nil, separator: "", indent: 0)
562+
var diff = diffHelp(lhs, rhs, lhsName: nil, rhsName: nil, separator: "", indent: 0, isRoot: true)
549563
if diff.last == "\n" { diff.removeLast() }
550564
return diff
551565
}

Sources/CustomDump/Dump.swift

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,18 @@ public func customDump<T, TargetStream>(
5656
indent: Int = 0,
5757
maxDepth: Int = .max
5858
) -> T where TargetStream: TextOutputStream {
59+
_customDump(value, to: &target, name: name, indent: indent, isRoot: true, maxDepth: maxDepth)
60+
}
5961

62+
@discardableResult
63+
func _customDump<T, TargetStream>(
64+
_ value: T,
65+
to target: inout TargetStream,
66+
name: String?,
67+
indent: Int,
68+
isRoot: Bool,
69+
maxDepth: Int
70+
) -> T where TargetStream: TextOutputStream {
6071
var idPerItem: [ObjectIdentifier: UInt] = [:]
6172
var occurrencePerType: [String: UInt] = [:]
6273
var visitedItems: Set<ObjectIdentifier> = []
@@ -195,12 +206,14 @@ public func customDump<T, TargetStream>(
195206
let (rhsKey, _) = $1.value as? (key: AnyHashable, value: Any)
196207
else { return false }
197208

198-
return _customDump(lhsKey.base, name: nil, indent: 0, maxDepth: 1)
199-
< _customDump(rhsKey.base, name: nil, indent: 0, maxDepth: 1)
209+
return _customDump(lhsKey.base, name: nil, indent: 0, isRoot: false, maxDepth: 1)
210+
< _customDump(rhsKey.base, name: nil, indent: 0, isRoot: false, maxDepth: 1)
200211
},
201212
{ child, _ in
202213
guard let pair = child.value as? (key: AnyHashable, value: Any) else { return }
203-
let key = _customDump(pair.key.base, name: nil, indent: 0, maxDepth: maxDepth - 1)
214+
let key = _customDump(
215+
pair.key.base, name: nil, indent: 0, isRoot: false, maxDepth: maxDepth - 1
216+
)
204217
child = (key, pair.value)
205218
})
206219
}
@@ -239,8 +252,8 @@ public func customDump<T, TargetStream>(
239252
of: mirror,
240253
prefix: "Set([", suffix: "])",
241254
by: {
242-
_customDump($0.value, name: nil, indent: 0, maxDepth: 1)
243-
< _customDump($1.value, name: nil, indent: 0, maxDepth: 1)
255+
_customDump($0.value, name: nil, indent: 0, isRoot: false, maxDepth: 1)
256+
< _customDump($1.value, name: nil, indent: 0, isRoot: false, maxDepth: 1)
244257
})
245258

246259
case (_, .struct?):
@@ -263,12 +276,15 @@ public func customDump<T, TargetStream>(
263276
if maxDepth == 0 {
264277
out.write("\"\"")
265278
} else {
266-
let hashes = String(repeating: "#", count: value.hashCount)
279+
let hashes = String(repeating: "#", count: value.hashCount(isMultiline: true))
267280
out.write("\(hashes)\"\"\"")
268281
out.write("\n")
269282
print(value.indenting(by: name != nil ? 2 : 0), to: &out)
270283
out.write(name != nil ? " \"\"\"\(hashes)" : "\"\"\"\(hashes)")
271284
}
285+
} else if value.contains("\"") {
286+
let hashes = String(repeating: "#", count: max(value.hashCount(isMultiline: false), 1))
287+
out.write("\(hashes)\"\(value)\"\(hashes)")
272288
} else {
273289
out.write(value.debugDescription)
274290
}
@@ -280,12 +296,14 @@ public func customDump<T, TargetStream>(
280296
target.write((name.map { "\($0): " } ?? "").appending(out).indenting(by: indent))
281297
}
282298

283-
customDumpHelp(value, to: &target, name: name, indent: indent, isRoot: true, maxDepth: maxDepth)
299+
customDumpHelp(
300+
value, to: &target, name: name, indent: indent, isRoot: isRoot, maxDepth: maxDepth
301+
)
284302
return value
285303
}
286304

287-
func _customDump(_ value: Any, name: String?, indent: Int, maxDepth: Int) -> String {
305+
func _customDump(_ value: Any, name: String?, indent: Int, isRoot: Bool, maxDepth: Int) -> String {
288306
var out = ""
289-
customDump(value, to: &out, name: name, indent: indent, maxDepth: maxDepth)
307+
_customDump(value, to: &out, name: name, indent: indent, isRoot: isRoot, maxDepth: maxDepth)
290308
return out
291309
}

Sources/CustomDump/Internal/Box.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ func isMirrorEqual(_ lhs: Any, _ rhs: Any) -> Bool {
2323
lhsMirror.subjectType == rhsMirror.subjectType,
2424
lhsMirror.children.count == rhsMirror.children.count
2525
else { return false }
26+
guard !lhsMirror.children.isEmpty, !rhsMirror.children.isEmpty
27+
else {
28+
return String(describing: lhs) == String(describing: rhs)
29+
}
2630
for (lhsChild, rhsChild) in zip(lhsMirror.children, rhsMirror.children) {
2731
guard
2832
lhsChild.label == rhsChild.label,

Sources/CustomDump/Internal/String.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ extension String {
1010
return "\(prefix)\(self.replacingOccurrences(of: "\n", with: "\n\(prefix)"))"
1111
}
1212

13-
var hashCount: Int {
13+
func hashCount(isMultiline: Bool) -> Int {
14+
let (quote, offset) = isMultiline ? ("\"\"\"", 2) : ("\"", 0)
1415
var substring = self[...]
1516
var hashCount = 0
16-
while let range = substring.range(of: "([#]*\"\"\"|\"\"\"[#]*)", options: .regularExpression) {
17-
let count = substring.distance(from: range.lowerBound, to: range.upperBound) - 2
17+
let pattern = "(\(quote)[#]*)"
18+
while let range = substring.range(of: pattern, options: .regularExpression) {
19+
let count = substring.distance(from: range.lowerBound, to: range.upperBound) - offset
1820
hashCount = max(count, hashCount)
19-
substring.removeSubrange(..<range.upperBound)
21+
substring = substring[range.upperBound...]
2022
}
2123
return hashCount
2224
}

Tests/CustomDumpTests/DiffTests.swift

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,58 @@ final class DiffTests: XCTestCase {
298298
)
299299
"""
300300
)
301+
302+
XCTAssertNoDifference(
303+
diff(
304+
Nested.nest(.fizz(42, buzz: "Blob")),
305+
Nested.nest(.fizz(42, buzz: "Glob"))
306+
),
307+
"""
308+
Nested.nest(
309+
.fizz(
310+
42.0,
311+
- buzz: "Blob"
312+
+ buzz: "Glob"
313+
)
314+
)
315+
"""
316+
)
317+
318+
XCTAssertNoDifference(
319+
diff(
320+
Enum.foo,
321+
Enum.buzz
322+
),
323+
"""
324+
- Enum.foo
325+
+ Enum.buzz
326+
"""
327+
)
328+
329+
XCTAssertNoDifference(
330+
diff(
331+
Nested.nest(.foo),
332+
Nested.nest(.buzz)
333+
),
334+
"""
335+
- Nested.nest(.foo)
336+
+ Nested.nest(.buzz)
337+
"""
338+
)
339+
340+
XCTAssertNoDifference(
341+
diff(
342+
Nested.largerNest(1, .foo),
343+
Nested.largerNest(1, .buzz)
344+
),
345+
"""
346+
Nested.largerNest(
347+
1,
348+
- .foo
349+
+ .buzz
350+
)
351+
"""
352+
)
301353
}
302354

303355
func testOptional() {

Tests/CustomDumpTests/DumpTests.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,29 @@ final class DumpTests: XCTestCase {
412412
)
413413
}
414414

415+
func testString() {
416+
var dump = ""
417+
customDump("Hello!", to: &dump)
418+
XCTAssertNoDifference(
419+
dump,
420+
#""Hello!""#
421+
)
422+
423+
dump = ""
424+
customDump(#"Hello, "world!""#, to: &dump)
425+
XCTAssertNoDifference(
426+
dump,
427+
##"#"Hello, "world!""#"##
428+
)
429+
430+
dump = ""
431+
customDump(####"This has a "### in it"####, to: &dump)
432+
XCTAssertNoDifference(
433+
dump,
434+
#####"####"This has a "### in it"####"#####
435+
)
436+
}
437+
415438
func testMultilineString() {
416439
var dump = ""
417440
customDump("Hello,\nWorld!", to: &dump)

Tests/CustomDumpTests/Mocks.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,12 @@ enum Enum {
3939
case baz(fizz: Double, buzz: String)
4040
case fizz(Double, buzz: String)
4141
case fu(bar: Int)
42+
case buzz
4243
}
4344

4445
enum Nested {
4546
case nest(Enum)
47+
case largerNest(Int, Enum)
4648
}
4749

4850
enum Namespaced {

0 commit comments

Comments
 (0)