@@ -308,6 +308,64 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
308308 case ( is CustomDumpStringConvertible , _, is CustomDumpStringConvertible , _) :
309309 diffEverything ( )
310310
311+ case let ( lhs as _CustomDiffObject , _, rhs as _CustomDiffObject , _) where lhs === rhs:
312+ let lhsItem = ObjectIdentifier ( lhs)
313+ let rhsItem = ObjectIdentifier ( rhs)
314+ let subjectType = typeName ( lhsMirror. subjectType)
315+ if visitedItems. contains ( lhsItem) || visitedItems. contains ( rhsItem) {
316+ print (
317+ " \( lhsName. map { " \( $0) : " } ?? " " ) \( subjectType) (↩︎) "
318+ . indenting ( by: indent)
319+ . indenting ( with: format. first + " " ) ,
320+ to: & out
321+ )
322+ print (
323+ " \( rhsName. map { " \( $0) : " } ?? " " ) \( subjectType) (↩︎) "
324+ . indenting ( by: indent)
325+ . indenting ( with: format. second + " " ) ,
326+ terminator: " " ,
327+ to: & out
328+ )
329+ } else if lhsItem == rhsItem {
330+ let ( lhs, rhs) = lhs. _customDiffValues
331+ print (
332+ diffHelp (
333+ lhs,
334+ rhs,
335+ lhsName: lhsName,
336+ rhsName: rhsName,
337+ separator: separator,
338+ indent: indent,
339+ isRoot: isRoot
340+ ) ,
341+ terminator: " " ,
342+ to: & out
343+ )
344+ } else {
345+ let showObjectIdentifiers =
346+ lhsItem != rhsItem
347+ && isMirrorEqual ( Array ( lhsMirror. children) , Array ( rhsMirror. children) )
348+ let lhsMirror =
349+ showObjectIdentifiers
350+ ? Mirror ( lhs, children: [ ( " _ " , lhsItem) ] + lhsMirror. children, displayStyle: . class)
351+ : lhsMirror
352+ let rhsMirror =
353+ showObjectIdentifiers
354+ ? Mirror ( rhs, children: [ ( " _ " , rhsItem) ] + rhsMirror. children, displayStyle: . class)
355+ : rhsMirror
356+ visitedItems. insert ( lhsItem)
357+ diffChildren (
358+ lhsMirror,
359+ rhsMirror,
360+ prefix: " \( subjectType) ( " ,
361+ suffix: " ) " ,
362+ elementIndent: 2 ,
363+ elementSeparator: " , " ,
364+ collapseUnchanged: false ,
365+ filter: macroPropertyFilter ( for: lhs)
366+ )
367+ }
368+
311369 case let ( lhs as CustomDumpRepresentable , _, rhs as CustomDumpRepresentable , _) :
312370 out. write (
313371 diffHelp (
@@ -339,6 +397,22 @@ public func diff<T>(_ lhs: T, _ rhs: T, format: DiffFormat = .default) -> String
339397 terminator: " " ,
340398 to: & out
341399 )
400+ } else if lhsItem == rhsItem,
401+ let ( lhs, rhs) = ( lhs as? _CustomDiffObject ) ? . _customDiffValues
402+ {
403+ print (
404+ diffHelp (
405+ lhs,
406+ rhs,
407+ lhsName: lhsName,
408+ rhsName: rhsName,
409+ separator: separator,
410+ indent: indent,
411+ isRoot: isRoot
412+ ) ,
413+ terminator: " " ,
414+ to: & out
415+ )
342416 } else {
343417 let showObjectIdentifiers =
344418 lhsItem != rhsItem
@@ -636,3 +710,7 @@ private struct Line: CustomDumpStringConvertible, Identifiable {
636710 . init( self . rawValue)
637711 }
638712}
713+
714+ public protocol _CustomDiffObject : AnyObject {
715+ var _customDiffValues : ( Any , Any ) { get }
716+ }
0 commit comments