From 34ef8abe152b1ffc561f387626bb57ad40d277ba Mon Sep 17 00:00:00 2001 From: Kuniwak Date: Mon, 24 Jul 2017 18:41:17 +0900 Subject: [PATCH] Support recursive diff (#12) Resolve #10 * Fix a children format bug * Support recursive diff * Add a test for #10 * Better naming for ChildKind * Better naming for DiffrentiiaUnit.child * Fix recursive diff feature --- MirrorDiffKit.xcodeproj/project.pbxproj | 94 ++++++---- Sources/ComparableDifferentiaUnits.swift | 36 ++++ Sources/Diffable.diff.swift | 78 +++++--- Sources/DiffableDictionary.swift | 19 +- Sources/DiffableSequence.swift | 8 +- Sources/DiffableSet.swift | 6 +- Sources/Differentia+PrettyPrintable.swift | 10 - Sources/Differentia.swift | 15 -- Sources/DifferentiaUnit+PrettyPrintable.swift | 107 +++++++++-- ...t => DifferentiaUnit.DictionaryType.swift} | 6 +- Sources/DifferentiaUnit.SequenceType.swift | 25 +++ Sources/DifferentiaUnit.swift | 9 +- Sources/MirrorDiffKit.swift | 8 +- Sources/PrettyPrintable.swift | 8 +- Sources/PrettyPrinter.swift | 7 + .../Diffable+PrettyPrintableTests.swift | 158 ---------------- .../DiffableSequenceTests.swift | 44 ++--- .../MirrorDiffKitTests/DiffableSetTests.swift | 30 +-- ...DifferentiaUnit+PrettyPrintableTests.swift | 174 ++++++++++++++++++ Tests/MirrorDiffKitTests/Issue10Tests.swift | 70 +++++++ .../MirrorDiffKitIntegrationTests.swift | 28 ++- 21 files changed, 604 insertions(+), 336 deletions(-) create mode 100644 Sources/ComparableDifferentiaUnits.swift delete mode 100644 Sources/Differentia+PrettyPrintable.swift delete mode 100644 Sources/Differentia.swift rename Sources/{DifferentiaUnit.ChildKind.swift => DifferentiaUnit.DictionaryType.swift} (85%) create mode 100644 Sources/DifferentiaUnit.SequenceType.swift create mode 100644 Sources/PrettyPrinter.swift delete mode 100644 Tests/MirrorDiffKitTests/Diffable+PrettyPrintableTests.swift create mode 100644 Tests/MirrorDiffKitTests/DifferentiaUnit+PrettyPrintableTests.swift create mode 100644 Tests/MirrorDiffKitTests/Issue10Tests.swift diff --git a/MirrorDiffKit.xcodeproj/project.pbxproj b/MirrorDiffKit.xcodeproj/project.pbxproj index d783208..9aef5c8 100644 --- a/MirrorDiffKit.xcodeproj/project.pbxproj +++ b/MirrorDiffKit.xcodeproj/project.pbxproj @@ -13,22 +13,23 @@ 2475E068E23A0E8B62E92ABD /* DiffableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF7A4F7D367ED7E87048 /* DiffableTests.swift */; }; 2475E074447578D9EA23D0ED /* RoughEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E0D0C6F529D98D395544 /* RoughEquatable.swift */; }; 2475E07738299099E0BBF127 /* DiffableSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EDF4A917EDE713051BCF /* DiffableSequence.swift */; }; + 2475E082185996AC064348F1 /* Issue10Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF0B7F6E2A9FACA5B13D /* Issue10Tests.swift */; }; 2475E0AA42246215941652D5 /* DifferentiaUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E14CDEF8BEC52D5E00CE /* DifferentiaUnit.swift */; }; 2475E0B5C20CDBAB617F16DC /* DiffableSequenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E181CA7D757D18DEC5E2 /* DiffableSequenceTests.swift */; }; 2475E0CC7C02E2A884E1DF65 /* DiffableSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EDF4A917EDE713051BCF /* DiffableSequence.swift */; }; 2475E0D2B8ADAD8150A51FF0 /* DiffableConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E050A29FC16D1340F755 /* DiffableConvertible.swift */; }; 2475E0F6CAAD02CD70690FAE /* Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E42D3D741A2F398087E0 /* Stubs.swift */; }; - 2475E1004FE07F269F01B103 /* Differentia.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E3B19066BFA063A057A8 /* Differentia.swift */; }; 2475E11BC79C1A8758170CCA /* DiffableSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EDF4A917EDE713051BCF /* DiffableSequence.swift */; }; 2475E1312041D4B87DA8AA54 /* DifferentiaUnit+PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E15B817A9292B0B84F81 /* DifferentiaUnit+PrettyPrintable.swift */; }; - 2475E14D673A19A2CA38BDD9 /* Differentia+PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E144B76F651EFBC1F3BD /* Differentia+PrettyPrintable.swift */; }; + 2475E13F335DF769C891FC28 /* PrettyPrinter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E0DC8CBF4477606DA8F2 /* PrettyPrinter.swift */; }; 2475E161DC8C84DD8BE403A4 /* DiffableDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB2B1D820FCDC5957FC3 /* DiffableDictionary.swift */; }; 2475E169B154F08110A53A10 /* DiffableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E78DE55347318233BC0C /* DiffableSet.swift */; }; + 2475E1808B3B7433243CCE6C /* PrettyPrinter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E0DC8CBF4477606DA8F2 /* PrettyPrinter.swift */; }; 2475E1926F92CC5DD8E0C256 /* DiffableSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EDF4A917EDE713051BCF /* DiffableSequence.swift */; }; 2475E1AB7F0EADD63B194BDF /* Dwifft.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E262206573A251280E94 /* Dwifft.swift */; }; 2475E21346AF4049EDA93368 /* Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E8ED7A24111E5500F1F4 /* Diffable.swift */; }; 2475E22258EE196EDD943C69 /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EC645A805B526D4FF547 /* Transformer.swift */; }; - 2475E24082A75666B4FC4D4E /* Diffable+PrettyPrintableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475ED3A27C5E753EA30F2A4 /* Diffable+PrettyPrintableTests.swift */; }; + 2475E24082A75666B4FC4D4E /* DifferentiaUnit+PrettyPrintableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475ED3A27C5E753EA30F2A4 /* DifferentiaUnit+PrettyPrintableTests.swift */; }; 2475E2847D8FC02BF79B02B9 /* DiffableDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB2B1D820FCDC5957FC3 /* DiffableDictionary.swift */; }; 2475E2887DA3EBD63495590C /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EC645A805B526D4FF547 /* Transformer.swift */; }; 2475E28AF26479F0EF76BB1E /* MirrorDiffKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E27C1F43721CD0A6BFD0 /* MirrorDiffKit.swift */; }; @@ -38,7 +39,6 @@ 2475E2D4F86772F7D5ED3EBD /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E55AD7C7C9AEFEF1643C /* Util.swift */; }; 2475E2E683F9EEE5109AF6B6 /* LinuxMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EE61530F256A1D549339 /* LinuxMain.swift */; }; 2475E2FB375A5C54598AE82E /* Diffable.from.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E963BDADFC88CFAE1D99 /* Diffable.from.swift */; }; - 2475E346CE7ADC54C22E426F /* Differentia+PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E144B76F651EFBC1F3BD /* Differentia+PrettyPrintable.swift */; }; 2475E357813342BCC4A43F1F /* Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E42D3D741A2F398087E0 /* Stubs.swift */; }; 2475E3832FE428ECD51446EC /* ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF87F9F7B45846D04C65 /* ExampleTests.swift */; }; 2475E39944EBDAAB4DA03482 /* PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E7D5313E857DB19ECDCA /* PrettyPrintable.swift */; }; @@ -50,7 +50,7 @@ 2475E4A752C8888E0F58F52E /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E55AD7C7C9AEFEF1643C /* Util.swift */; }; 2475E4CEC7626F499F7C563F /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E55AD7C7C9AEFEF1643C /* Util.swift */; }; 2475E52262734230D4DFA81E /* ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF87F9F7B45846D04C65 /* ExampleTests.swift */; }; - 2475E541D415B3DCC2A03CF2 /* DifferentiaUnit.ChildKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB054307543C8491D77E /* DifferentiaUnit.ChildKind.swift */; }; + 2475E541D415B3DCC2A03CF2 /* DifferentiaUnit.DictionaryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB054307543C8491D77E /* DifferentiaUnit.DictionaryType.swift */; }; 2475E573438370F32B4D3106 /* EnumRepresentationDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF30C4592782E2D0E371 /* EnumRepresentationDetector.swift */; }; 2475E57913C5E083CC762BBD /* DiffableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E78DE55347318233BC0C /* DiffableSet.swift */; }; 2475E5B0222EC649EB7B3420 /* DiffableConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E050A29FC16D1340F755 /* DiffableConvertible.swift */; }; @@ -61,38 +61,45 @@ 2475E6538A6F9FA25C581877 /* DiffableConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E050A29FC16D1340F755 /* DiffableConvertible.swift */; }; 2475E66135171B41D48D07D0 /* Diffable.diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E23B2FE90297580DAB62 /* Diffable.diff.swift */; }; 2475E6ABAD8DF9348F5A3028 /* Diffable.diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E23B2FE90297580DAB62 /* Diffable.diff.swift */; }; - 2475E6EE3AB794CD1EC0BA9D /* DifferentiaUnit.ChildKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB054307543C8491D77E /* DifferentiaUnit.ChildKind.swift */; }; + 2475E6EE3AB794CD1EC0BA9D /* DifferentiaUnit.DictionaryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB054307543C8491D77E /* DifferentiaUnit.DictionaryType.swift */; }; 2475E71653DD16AA64B578AF /* MirrorDiffKitIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E2CB822ABAA3DC298818 /* MirrorDiffKitIntegrationTests.swift */; }; 2475E716E6256CE75B58D920 /* Dwifft.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E262206573A251280E94 /* Dwifft.swift */; }; 2475E71B66942EF2806F018D /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EC645A805B526D4FF547 /* Transformer.swift */; }; 2475E766A21D84D5A92EB4DC /* Diffable.from.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E963BDADFC88CFAE1D99 /* Diffable.from.swift */; }; 2475E795E5263D357C00EA24 /* Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E42D3D741A2F398087E0 /* Stubs.swift */; }; + 2475E7A1B46109486CD62508 /* DifferentiaUnit.SequenceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E5087E79D9A4E8170014 /* DifferentiaUnit.SequenceType.swift */; }; + 2475E7A7DC4BAD891ACF5FE3 /* ComparableDifferentiaUnits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E89FF094AA0E2FA8A881 /* ComparableDifferentiaUnits.swift */; }; 2475E82E5774572294871E48 /* DiffableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E78DE55347318233BC0C /* DiffableSet.swift */; }; 2475E85513F9A091CB525C07 /* DiffableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E78DE55347318233BC0C /* DiffableSet.swift */; }; 2475E85F28DD3C5E6AC9903A /* DifferentiaUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E14CDEF8BEC52D5E00CE /* DifferentiaUnit.swift */; }; 2475E89F382BEDD9A7E6C7F5 /* DiffableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF7A4F7D367ED7E87048 /* DiffableTests.swift */; }; 2475E8A374D9584A1E5A34AA /* TransformerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E08093ED284E24090A38 /* TransformerTests.swift */; }; 2475E8E58C92BDB6A7BC2A74 /* Diffable.diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E23B2FE90297580DAB62 /* Diffable.diff.swift */; }; + 2475E909B3A3740A4CD0C9B1 /* PrettyPrinter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E0DC8CBF4477606DA8F2 /* PrettyPrinter.swift */; }; + 2475E9346E5C544E2DC16735 /* Issue10Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF0B7F6E2A9FACA5B13D /* Issue10Tests.swift */; }; + 2475E971863459464D5E5B69 /* ComparableDifferentiaUnits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E89FF094AA0E2FA8A881 /* ComparableDifferentiaUnits.swift */; }; 2475E9CA33ED9943CC857ABA /* Diffable+CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EDD7BFE0FD8514BA620E /* Diffable+CustomStringConvertible.swift */; }; + 2475E9EB7C5AD5906B7497C2 /* DifferentiaUnit.SequenceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E5087E79D9A4E8170014 /* DifferentiaUnit.SequenceType.swift */; }; 2475E9FBCB01E15F28FBCCF3 /* PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E7D5313E857DB19ECDCA /* PrettyPrintable.swift */; }; 2475EA07EE6A5903F188FC2A /* DiffableDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB2B1D820FCDC5957FC3 /* DiffableDictionary.swift */; }; + 2475EA09F19732DF8CC356AB /* PrettyPrinter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E0DC8CBF4477606DA8F2 /* PrettyPrinter.swift */; }; 2475EA0F6F65A2B4D4257C9A /* PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E7D5313E857DB19ECDCA /* PrettyPrintable.swift */; }; - 2475EA283A269816E1BF841A /* Differentia+PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E144B76F651EFBC1F3BD /* Differentia+PrettyPrintable.swift */; }; 2475EA4FF764ACAC01995D33 /* DiffableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF7A4F7D367ED7E87048 /* DiffableTests.swift */; }; + 2475EA5DC96A9C243FBB4F21 /* DifferentiaUnit.SequenceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E5087E79D9A4E8170014 /* DifferentiaUnit.SequenceType.swift */; }; 2475EAD03D7E372DF752F123 /* Diffable.from.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E963BDADFC88CFAE1D99 /* Diffable.from.swift */; }; 2475EAD30889B46DD4EC7EB7 /* ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF87F9F7B45846D04C65 /* ExampleTests.swift */; }; 2475EAD8C209925A1859DA6F /* MirrorDiffKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E27C1F43721CD0A6BFD0 /* MirrorDiffKit.swift */; }; - 2475EADF49EB4F91209156E0 /* Diffable+PrettyPrintableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475ED3A27C5E753EA30F2A4 /* Diffable+PrettyPrintableTests.swift */; }; + 2475EADF49EB4F91209156E0 /* DifferentiaUnit+PrettyPrintableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475ED3A27C5E753EA30F2A4 /* DifferentiaUnit+PrettyPrintableTests.swift */; }; 2475EB002E0C38547118001E /* DifferentiaUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E14CDEF8BEC52D5E00CE /* DifferentiaUnit.swift */; }; - 2475EB2C3363762D07CAED98 /* DifferentiaUnit.ChildKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB054307543C8491D77E /* DifferentiaUnit.ChildKind.swift */; }; + 2475EB2C3363762D07CAED98 /* DifferentiaUnit.DictionaryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB054307543C8491D77E /* DifferentiaUnit.DictionaryType.swift */; }; + 2475EB2EA5FE3BA11A413CDD /* ComparableDifferentiaUnits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E89FF094AA0E2FA8A881 /* ComparableDifferentiaUnits.swift */; }; 2475EB34A7C10789D6BC3E8C /* RoughEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E0D0C6F529D98D395544 /* RoughEquatable.swift */; }; - 2475EB53F8621D75FABAE1E7 /* Differentia.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E3B19066BFA063A057A8 /* Differentia.swift */; }; 2475EB709F18B8F9C5853B44 /* DifferentiaUnit+PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E15B817A9292B0B84F81 /* DifferentiaUnit+PrettyPrintable.swift */; }; 2475EB90BCC55C01357C286D /* EnumRepresentationDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF30C4592782E2D0E371 /* EnumRepresentationDetector.swift */; }; - 2475EC175632640216EF7335 /* DifferentiaUnit.ChildKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB054307543C8491D77E /* DifferentiaUnit.ChildKind.swift */; }; + 2475EC175632640216EF7335 /* DifferentiaUnit.DictionaryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EB054307543C8491D77E /* DifferentiaUnit.DictionaryType.swift */; }; + 2475EC3E916B40DF4AB7414C /* Issue10Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF0B7F6E2A9FACA5B13D /* Issue10Tests.swift */; }; 2475EC44070AAA124CE3EC11 /* Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E8ED7A24111E5500F1F4 /* Diffable.swift */; }; 2475EC4661DF374C9C9FE156 /* TransformerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E08093ED284E24090A38 /* TransformerTests.swift */; }; - 2475EC609231BB1F16889E37 /* Differentia.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E3B19066BFA063A057A8 /* Differentia.swift */; }; 2475EC76A0FF3FFD53B1300E /* EnumRepresentationDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EF30C4592782E2D0E371 /* EnumRepresentationDetector.swift */; }; 2475EC82D19663BF468E4014 /* MirrorDiffKitIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E2CB822ABAA3DC298818 /* MirrorDiffKitIntegrationTests.swift */; }; 2475ECA328D49E5119BCD709 /* Diffable+CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EDD7BFE0FD8514BA620E /* Diffable+CustomStringConvertible.swift */; }; @@ -103,13 +110,13 @@ 2475EDF02B748C4D96059FDF /* DiffableSequenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E181CA7D757D18DEC5E2 /* DiffableSequenceTests.swift */; }; 2475EE2884507B9D0ED36A4C /* PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E7D5313E857DB19ECDCA /* PrettyPrintable.swift */; }; 2475EE531FFEDD682F7680B5 /* Dwifft.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E262206573A251280E94 /* Dwifft.swift */; }; - 2475EE66780EF10C9F2FF6FF /* Differentia.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E3B19066BFA063A057A8 /* Differentia.swift */; }; 2475EE8D2529E83CFD1BA569 /* DiffableSetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E2E82C8E152A456073DA /* DiffableSetTests.swift */; }; 2475EE97D17042EA78C7DB41 /* Dwifft.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E262206573A251280E94 /* Dwifft.swift */; }; + 2475EEC2137F41EE61606E20 /* DifferentiaUnit.SequenceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E5087E79D9A4E8170014 /* DifferentiaUnit.SequenceType.swift */; }; 2475EEC4E83BB3F35A24CEB2 /* RoughEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E0D0C6F529D98D395544 /* RoughEquatable.swift */; }; - 2475EF569997D6980469B073 /* Diffable+PrettyPrintableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475ED3A27C5E753EA30F2A4 /* Diffable+PrettyPrintableTests.swift */; }; + 2475EED85108098C53E39A6F /* ComparableDifferentiaUnits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E89FF094AA0E2FA8A881 /* ComparableDifferentiaUnits.swift */; }; + 2475EF569997D6980469B073 /* DifferentiaUnit+PrettyPrintableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475ED3A27C5E753EA30F2A4 /* DifferentiaUnit+PrettyPrintableTests.swift */; }; 2475EF59D9ACD2A391CAE753 /* Diffable+CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EDD7BFE0FD8514BA620E /* Diffable+CustomStringConvertible.swift */; }; - 2475EF62D8E0B8C6EB9C8B4D /* Differentia+PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E144B76F651EFBC1F3BD /* Differentia+PrettyPrintable.swift */; }; 2475EFACDD64E2A59B4D6F53 /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475EC645A805B526D4FF547 /* Transformer.swift */; }; 2475EFCA6F65DD1C7EF28C5A /* DifferentiaUnit+PrettyPrintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E15B817A9292B0B84F81 /* DifferentiaUnit+PrettyPrintable.swift */; }; 2475EFE88FA546641AAD76F2 /* TransformerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2475E08093ED284E24090A38 /* TransformerTests.swift */; }; @@ -147,7 +154,7 @@ 2475E050A29FC16D1340F755 /* DiffableConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffableConvertible.swift; sourceTree = ""; }; 2475E08093ED284E24090A38 /* TransformerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformerTests.swift; sourceTree = ""; }; 2475E0D0C6F529D98D395544 /* RoughEquatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoughEquatable.swift; sourceTree = ""; }; - 2475E144B76F651EFBC1F3BD /* Differentia+PrettyPrintable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Differentia+PrettyPrintable.swift"; sourceTree = ""; }; + 2475E0DC8CBF4477606DA8F2 /* PrettyPrinter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrettyPrinter.swift; sourceTree = ""; }; 2475E14CDEF8BEC52D5E00CE /* DifferentiaUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DifferentiaUnit.swift; sourceTree = ""; }; 2475E15B817A9292B0B84F81 /* DifferentiaUnit+PrettyPrintable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DifferentiaUnit+PrettyPrintable.swift"; sourceTree = ""; }; 2475E181CA7D757D18DEC5E2 /* DiffableSequenceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffableSequenceTests.swift; sourceTree = ""; }; @@ -156,21 +163,23 @@ 2475E27C1F43721CD0A6BFD0 /* MirrorDiffKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MirrorDiffKit.swift; sourceTree = ""; }; 2475E2CB822ABAA3DC298818 /* MirrorDiffKitIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MirrorDiffKitIntegrationTests.swift; sourceTree = ""; }; 2475E2E82C8E152A456073DA /* DiffableSetTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffableSetTests.swift; sourceTree = ""; }; - 2475E3B19066BFA063A057A8 /* Differentia.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Differentia.swift; sourceTree = ""; }; 2475E42D3D741A2F398087E0 /* Stubs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stubs.swift; sourceTree = ""; }; + 2475E5087E79D9A4E8170014 /* DifferentiaUnit.SequenceType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DifferentiaUnit.SequenceType.swift; sourceTree = ""; }; 2475E55AD7C7C9AEFEF1643C /* Util.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Util.swift; sourceTree = ""; }; 2475E5B1B9EB8376144D192A /* run */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = run; sourceTree = ""; }; 2475E78DE55347318233BC0C /* DiffableSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffableSet.swift; sourceTree = ""; }; 2475E7D5313E857DB19ECDCA /* PrettyPrintable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrettyPrintable.swift; sourceTree = ""; }; + 2475E89FF094AA0E2FA8A881 /* ComparableDifferentiaUnits.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComparableDifferentiaUnits.swift; sourceTree = ""; }; 2475E8ED7A24111E5500F1F4 /* Diffable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Diffable.swift; sourceTree = ""; }; 2475E963BDADFC88CFAE1D99 /* Diffable.from.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Diffable.from.swift; sourceTree = ""; }; - 2475EB054307543C8491D77E /* DifferentiaUnit.ChildKind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DifferentiaUnit.ChildKind.swift; sourceTree = ""; }; + 2475EB054307543C8491D77E /* DifferentiaUnit.DictionaryType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DifferentiaUnit.DictionaryType.swift; sourceTree = ""; }; 2475EB2B1D820FCDC5957FC3 /* DiffableDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffableDictionary.swift; sourceTree = ""; }; 2475EC645A805B526D4FF547 /* Transformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Transformer.swift; sourceTree = ""; }; - 2475ED3A27C5E753EA30F2A4 /* Diffable+PrettyPrintableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Diffable+PrettyPrintableTests.swift"; sourceTree = ""; }; + 2475ED3A27C5E753EA30F2A4 /* DifferentiaUnit+PrettyPrintableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DifferentiaUnit+PrettyPrintableTests.swift"; sourceTree = ""; }; 2475EDD7BFE0FD8514BA620E /* Diffable+CustomStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Diffable+CustomStringConvertible.swift"; sourceTree = ""; }; 2475EDF4A917EDE713051BCF /* DiffableSequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffableSequence.swift; sourceTree = ""; }; 2475EE61530F256A1D549339 /* LinuxMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinuxMain.swift; sourceTree = ""; }; + 2475EF0B7F6E2A9FACA5B13D /* Issue10Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Issue10Tests.swift; sourceTree = ""; }; 2475EF30C4592782E2D0E371 /* EnumRepresentationDetector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnumRepresentationDetector.swift; sourceTree = ""; }; 2475EF7A4F7D367ED7E87048 /* DiffableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffableTests.swift; sourceTree = ""; }; 2475EF87F9F7B45846D04C65 /* ExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleTests.swift; sourceTree = ""; }; @@ -259,11 +268,12 @@ 2475EDD7BFE0FD8514BA620E /* Diffable+CustomStringConvertible.swift */, 2475E262206573A251280E94 /* Dwifft.swift */, 2475EF30C4592782E2D0E371 /* EnumRepresentationDetector.swift */, - 2475E3B19066BFA063A057A8 /* Differentia.swift */, 2475E14CDEF8BEC52D5E00CE /* DifferentiaUnit.swift */, - 2475EB054307543C8491D77E /* DifferentiaUnit.ChildKind.swift */, - 2475E144B76F651EFBC1F3BD /* Differentia+PrettyPrintable.swift */, + 2475EB054307543C8491D77E /* DifferentiaUnit.DictionaryType.swift */, 2475E15B817A9292B0B84F81 /* DifferentiaUnit+PrettyPrintable.swift */, + 2475E5087E79D9A4E8170014 /* DifferentiaUnit.SequenceType.swift */, + 2475E89FF094AA0E2FA8A881 /* ComparableDifferentiaUnits.swift */, + 2475E0DC8CBF4477606DA8F2 /* PrettyPrinter.swift */, ); path = Sources; sourceTree = ""; @@ -287,8 +297,9 @@ 2475E2E82C8E152A456073DA /* DiffableSetTests.swift */, 2475E08093ED284E24090A38 /* TransformerTests.swift */, 2475E181CA7D757D18DEC5E2 /* DiffableSequenceTests.swift */, - 2475ED3A27C5E753EA30F2A4 /* Diffable+PrettyPrintableTests.swift */, + 2475ED3A27C5E753EA30F2A4 /* DifferentiaUnit+PrettyPrintableTests.swift */, 2475E2CB822ABAA3DC298818 /* MirrorDiffKitIntegrationTests.swift */, + 2475EF0B7F6E2A9FACA5B13D /* Issue10Tests.swift */, ); path = MirrorDiffKitTests; sourceTree = ""; @@ -637,11 +648,12 @@ 2475EDD21E5135F23CCF2003 /* Diffable+CustomStringConvertible.swift in Sources */, 2475EE531FFEDD682F7680B5 /* Dwifft.swift in Sources */, 2475E573438370F32B4D3106 /* EnumRepresentationDetector.swift in Sources */, - 2475EC609231BB1F16889E37 /* Differentia.swift in Sources */, 2475EB002E0C38547118001E /* DifferentiaUnit.swift in Sources */, - 2475EC175632640216EF7335 /* DifferentiaUnit.ChildKind.swift in Sources */, - 2475E346CE7ADC54C22E426F /* Differentia+PrettyPrintable.swift in Sources */, + 2475EC175632640216EF7335 /* DifferentiaUnit.DictionaryType.swift in Sources */, 2475E1312041D4B87DA8AA54 /* DifferentiaUnit+PrettyPrintable.swift in Sources */, + 2475E7A1B46109486CD62508 /* DifferentiaUnit.SequenceType.swift in Sources */, + 2475E7A7DC4BAD891ACF5FE3 /* ComparableDifferentiaUnits.swift in Sources */, + 2475E1808B3B7433243CCE6C /* PrettyPrinter.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -656,8 +668,9 @@ 2475EE8D2529E83CFD1BA569 /* DiffableSetTests.swift in Sources */, 2475EFE88FA546641AAD76F2 /* TransformerTests.swift in Sources */, 2475E0B5C20CDBAB617F16DC /* DiffableSequenceTests.swift in Sources */, - 2475EF569997D6980469B073 /* Diffable+PrettyPrintableTests.swift in Sources */, + 2475EF569997D6980469B073 /* DifferentiaUnit+PrettyPrintableTests.swift in Sources */, 2475E0590370D6374C4146C5 /* MirrorDiffKitIntegrationTests.swift in Sources */, + 2475EC3E916B40DF4AB7414C /* Issue10Tests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -680,11 +693,12 @@ 2475EF59D9ACD2A391CAE753 /* Diffable+CustomStringConvertible.swift in Sources */, 2475EE97D17042EA78C7DB41 /* Dwifft.swift in Sources */, 2475EC76A0FF3FFD53B1300E /* EnumRepresentationDetector.swift in Sources */, - 2475EB53F8621D75FABAE1E7 /* Differentia.swift in Sources */, 2475E85F28DD3C5E6AC9903A /* DifferentiaUnit.swift in Sources */, - 2475EB2C3363762D07CAED98 /* DifferentiaUnit.ChildKind.swift in Sources */, - 2475EA283A269816E1BF841A /* Differentia+PrettyPrintable.swift in Sources */, + 2475EB2C3363762D07CAED98 /* DifferentiaUnit.DictionaryType.swift in Sources */, 2475E5DD1E1B764F9A317F1F /* DifferentiaUnit+PrettyPrintable.swift in Sources */, + 2475EA5DC96A9C243FBB4F21 /* DifferentiaUnit.SequenceType.swift in Sources */, + 2475EB2EA5FE3BA11A413CDD /* ComparableDifferentiaUnits.swift in Sources */, + 2475E909B3A3740A4CD0C9B1 /* PrettyPrinter.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -707,11 +721,12 @@ 2475E9CA33ED9943CC857ABA /* Diffable+CustomStringConvertible.swift in Sources */, 2475E716E6256CE75B58D920 /* Dwifft.swift in Sources */, 2475E5DCE6B2629DDF3FA44E /* EnumRepresentationDetector.swift in Sources */, - 2475EE66780EF10C9F2FF6FF /* Differentia.swift in Sources */, 2475E0AA42246215941652D5 /* DifferentiaUnit.swift in Sources */, - 2475E6EE3AB794CD1EC0BA9D /* DifferentiaUnit.ChildKind.swift in Sources */, - 2475E14D673A19A2CA38BDD9 /* Differentia+PrettyPrintable.swift in Sources */, + 2475E6EE3AB794CD1EC0BA9D /* DifferentiaUnit.DictionaryType.swift in Sources */, 2475EB709F18B8F9C5853B44 /* DifferentiaUnit+PrettyPrintable.swift in Sources */, + 2475EEC2137F41EE61606E20 /* DifferentiaUnit.SequenceType.swift in Sources */, + 2475E971863459464D5E5B69 /* ComparableDifferentiaUnits.swift in Sources */, + 2475EA09F19732DF8CC356AB /* PrettyPrinter.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -734,11 +749,12 @@ 2475ECA328D49E5119BCD709 /* Diffable+CustomStringConvertible.swift in Sources */, 2475E1AB7F0EADD63B194BDF /* Dwifft.swift in Sources */, 2475EB90BCC55C01357C286D /* EnumRepresentationDetector.swift in Sources */, - 2475E1004FE07F269F01B103 /* Differentia.swift in Sources */, 2475E47A145236943D538105 /* DifferentiaUnit.swift in Sources */, - 2475E541D415B3DCC2A03CF2 /* DifferentiaUnit.ChildKind.swift in Sources */, - 2475EF62D8E0B8C6EB9C8B4D /* Differentia+PrettyPrintable.swift in Sources */, + 2475E541D415B3DCC2A03CF2 /* DifferentiaUnit.DictionaryType.swift in Sources */, 2475EFCA6F65DD1C7EF28C5A /* DifferentiaUnit+PrettyPrintable.swift in Sources */, + 2475E9EB7C5AD5906B7497C2 /* DifferentiaUnit.SequenceType.swift in Sources */, + 2475EED85108098C53E39A6F /* ComparableDifferentiaUnits.swift in Sources */, + 2475E13F335DF769C891FC28 /* PrettyPrinter.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -753,8 +769,9 @@ 2475EDC9D53B420705443293 /* DiffableSetTests.swift in Sources */, 2475E8A374D9584A1E5A34AA /* TransformerTests.swift in Sources */, 2475EDF02B748C4D96059FDF /* DiffableSequenceTests.swift in Sources */, - 2475EADF49EB4F91209156E0 /* Diffable+PrettyPrintableTests.swift in Sources */, + 2475EADF49EB4F91209156E0 /* DifferentiaUnit+PrettyPrintableTests.swift in Sources */, 2475EC82D19663BF468E4014 /* MirrorDiffKitIntegrationTests.swift in Sources */, + 2475E9346E5C544E2DC16735 /* Issue10Tests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -769,8 +786,9 @@ 2475EFF96CBD44AF5AF43EF5 /* DiffableSetTests.swift in Sources */, 2475EC4661DF374C9C9FE156 /* TransformerTests.swift in Sources */, 2475E0021A7DDCC37F737BB4 /* DiffableSequenceTests.swift in Sources */, - 2475E24082A75666B4FC4D4E /* Diffable+PrettyPrintableTests.swift in Sources */, + 2475E24082A75666B4FC4D4E /* DifferentiaUnit+PrettyPrintableTests.swift in Sources */, 2475E71653DD16AA64B578AF /* MirrorDiffKitIntegrationTests.swift in Sources */, + 2475E082185996AC064348F1 /* Issue10Tests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/ComparableDifferentiaUnits.swift b/Sources/ComparableDifferentiaUnits.swift new file mode 100644 index 0000000..67ac28a --- /dev/null +++ b/Sources/ComparableDifferentiaUnits.swift @@ -0,0 +1,36 @@ +import Foundation + + + +// NOTE: This class is for only the purpose that is making [String: [DifferentiaUnit]] equatable. +// TODO: Fix me when conditional conformance (SE-0143) is arrived. +struct DifferentiaUnitComparableDictionary: Equatable { + let dictionary: [String: ComparableDifferentiaUnits] + + + + static func ==(lhs: DifferentiaUnitComparableDictionary, rhs: DifferentiaUnitComparableDictionary) -> Bool { + return lhs.dictionary == rhs.dictionary + } + + + static func from(dictionary: [String: [DifferentiaUnit]]) -> DifferentiaUnitComparableDictionary { + var result: [String: ComparableDifferentiaUnits] = [:] + + dictionary.forEach { (key, units) in + result[key] = ComparableDifferentiaUnits(units: units) + } + + return DifferentiaUnitComparableDictionary(dictionary: result) + } + + + struct ComparableDifferentiaUnits: Equatable { + let units: [DifferentiaUnit] + + + static func ==(lhs: ComparableDifferentiaUnits, rhs: ComparableDifferentiaUnits) -> Bool { + return lhs.units == rhs.units + } + } +} diff --git a/Sources/Diffable.diff.swift b/Sources/Diffable.diff.swift index e92126e..a73b01c 100644 --- a/Sources/Diffable.diff.swift +++ b/Sources/Diffable.diff.swift @@ -3,55 +3,77 @@ import Foundation extension Diffable { - static func diff (between a: Diffable, and b: Diffable) -> Differentia { + static func diff (between a: Diffable, and b: Diffable) -> [DifferentiaUnit] { guard a != b else { - return Differentia(units: [.notChanged(a)]) + return [.notChanged(a)] } switch (a, b) { case let (.array(l), .array(r)): - return DiffableSequence.diff( - between: DiffableSequence(l), - and: DiffableSequence(r) - ) + return [ + .sequenceChanged( + kind: .array, + DiffableSequence.diff( + between: DiffableSequence(l), + and: DiffableSequence(r) + ) + ) + ] case let (.set(l), .set(r)): - return DiffableSet.diff( - between: DiffableSet(l), - and: DiffableSet(r) - ) + return [ + .sequenceChanged( + kind: .set, + DiffableSet.diff( + between: DiffableSet(l), + and: DiffableSet(r) + ) + ) + ] case let (.dictionary(l), .dictionary(r)): - return DiffableDictionary.diff( - between: DiffableDictionary.from(diffableTuples: l), - and: DiffableDictionary.from(diffableTuples: r), - forKind: .dictionary - ) + return [ + .dictionaryChanged( + kind: .dictionary, + DiffableDictionary.diff( + between: DiffableDictionary.from(diffableTuples: l), + and: DiffableDictionary.from(diffableTuples: r) + ) + ) + ] case let (.anyStruct(type: lt, entries: ld), .anyStruct(type: rt, entries: rd)): guard lt == rt else { - return Differentia(units: [.deleted(a), .inserted(b)]) + return [.deleted(a), .inserted(b)] } - return DiffableDictionary.diff( - between: DiffableDictionary(ld), - and: DiffableDictionary(rd), - forKind: .anyStruct(type: lt) - ) + return [ + .dictionaryChanged( + kind: .anyStruct(type: lt), + DiffableDictionary.diff( + between: DiffableDictionary(ld), + and: DiffableDictionary(rd) + ) + ) + ] case let (.anyClass(type: lt, entries: ld), .anyClass(type: rt, entries: rd)): guard lt == rt else { - return Differentia(units: [.deleted(a), .inserted(b)]) + return [.deleted(a), .inserted(b)] } - return DiffableDictionary.diff( - between: DiffableDictionary(ld), - and: DiffableDictionary(rd), - forKind: .anyClass(type: lt) - ) + return [ + .dictionaryChanged( + kind: .anyClass(type: lt), + DiffableDictionary.diff( + between: DiffableDictionary(ld), + and: DiffableDictionary(rd) + ) + ) + ] default: - return Differentia(units: [.deleted(a), .inserted(b)]) + return [.deleted(a), .inserted(b)] } } } diff --git a/Sources/DiffableDictionary.swift b/Sources/DiffableDictionary.swift index 574bd61..d76626e 100644 --- a/Sources/DiffableDictionary.swift +++ b/Sources/DiffableDictionary.swift @@ -40,11 +40,11 @@ struct DiffableDictionary { } - static func diff(between lhs: DiffableDictionary, and rhs: DiffableDictionary, forKind kind: DifferentiaUnit.ChildKind) -> Differentia { + static func diff(between lhs: DiffableDictionary, and rhs: DiffableDictionary) -> [String: [DifferentiaUnit]] { // note: elements of [diffable] may not conform to hashable. // so we cannot use o(1) algorithm such as hash map. - var result: [String: Differentia] = [:] + var result: [String: [DifferentiaUnit]] = [:] let keys = Set(lhs.dictionary.keys) .union(Set(rhs.dictionary.keys)) @@ -55,27 +55,22 @@ struct DiffableDictionary { fatalError("This case cannot be executed.") case let (.some(lv), .none): - result[key] = Differentia(units: [.inserted(lv)]) + result[key] = [.inserted(lv)] case let (.none, .some(rv)): - result[key] = Differentia(units: [.deleted(rv)]) + result[key] = [.deleted(rv)] case let (.some(lv), .some(rv)): guard lv != rv else { - result[key] = Differentia(units: [.notChanged(lv)]) + result[key] = [.notChanged(lv)] return } - result[key] = Differentia(units: [ - .deleted(lv), - .inserted(rv), - ]) + result[key] = Diffable.diff(between: lv, and: rv) } } - return Differentia(units: [ - .child(kind: kind, result) - ]) + return result } } diff --git a/Sources/DiffableSequence.swift b/Sources/DiffableSequence.swift index 55afc95..b62bacf 100644 --- a/Sources/DiffableSequence.swift +++ b/Sources/DiffableSequence.swift @@ -11,9 +11,9 @@ class DiffableSequence { } - static func diff(between: DiffableSequence, and: DiffableSequence) -> Differentia { - var lcs = between.elements.LCS(and.elements) - let diff = between.elements.diff(and.elements) + static func diff(between a: DiffableSequence, and b: DiffableSequence) -> [DifferentiaUnit] { + var lcs = a.elements.LCS(b.elements) + let diff = a.elements.diff(b.elements) // NOTE; This algorithm is based on the following table: // @@ -113,7 +113,7 @@ class DiffableSequence { } } - return Differentia(units: result) + return result } diff --git a/Sources/DiffableSet.swift b/Sources/DiffableSet.swift index 4360206..9270746 100644 --- a/Sources/DiffableSet.swift +++ b/Sources/DiffableSet.swift @@ -11,7 +11,7 @@ struct DiffableSet { } - static func diff(between a: DiffableSet, and b: DiffableSet) -> Differentia { + static func diff(between a: DiffableSet, and b: DiffableSet) -> [DifferentiaUnit] { // NOTE: Elements of [Diffable] may not conform to Hashable. // So we cannot use O(1) algorithm such as hash map. @@ -27,8 +27,7 @@ struct DiffableSet { } } - return Differentia(units: - (deleted + return (deleted .sorted { String(describing: $0) < String(describing: $1) } .map { .deleted($0) }) + (inserted @@ -37,7 +36,6 @@ struct DiffableSet { + (notChanged .sorted { String(describing: $0) < String(describing: $1) } .map { .notChanged($0) }) - ) } } diff --git a/Sources/Differentia+PrettyPrintable.swift b/Sources/Differentia+PrettyPrintable.swift deleted file mode 100644 index 04e7e1f..0000000 --- a/Sources/Differentia+PrettyPrintable.swift +++ /dev/null @@ -1,10 +0,0 @@ -import Foundation - - - -extension Differentia: PrettyPrintable { - var prettyLines: [PrettyLine] { - return self.units - .flatMap { unit -> [PrettyLine] in unit.prettyLines } - } -} diff --git a/Sources/Differentia.swift b/Sources/Differentia.swift deleted file mode 100644 index dc2382d..0000000 --- a/Sources/Differentia.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Foundation - - - -struct Differentia { - let units: [DifferentiaUnit] -} - - - -extension Differentia: Equatable { - static func == (_ lhs: Differentia, _ rhs: Differentia) -> Bool { - return lhs.units == rhs.units - } -} diff --git a/Sources/DifferentiaUnit+PrettyPrintable.swift b/Sources/DifferentiaUnit+PrettyPrintable.swift index 3a78c91..b8820de 100644 --- a/Sources/DifferentiaUnit+PrettyPrintable.swift +++ b/Sources/DifferentiaUnit+PrettyPrintable.swift @@ -11,17 +11,92 @@ extension DifferentiaUnit: PrettyPrintable { return [.line("- \(deleted.description)")] case let .inserted(inserted): return [.line("+ \(inserted.description)")] - case let .child(kind: kind, dictionary): - return self.childPrettyLines(kind: kind, dictionary) + case let .dictionaryChanged(kind: kind, dictionary): + return self.createPrettyLinesForDictionary(kind: kind, dictionary) + case let .sequenceChanged(kind: kind, array): + return self.createPrettyLinesForSequence(kind: kind, array) } } - private func childPrettyLines(kind: DifferentiaUnit.ChildKind, _ dictionary: [String: Differentia]) -> [PrettyLine] { + private func createPrettyLinesForSequence( + kind: DifferentiaUnit.SequenceType, + _ array: [DifferentiaUnit] + ) -> [PrettyLine] { + let lines = self.createSequenceContentLines(by: array) + + guard !lines.isEmpty else { + return [.line(" []")] + } + + return [.line(" [")] + lines + [.line(" ]")] + } + + + private func createPrettyLinesForSequenceWithKey( + key: String, + kind: DifferentiaUnit.SequenceType, + _ array: [DifferentiaUnit] + ) -> [PrettyLine] { + let lines = self.createSequenceContentLines(by: array) + + guard !lines.isEmpty else { + return [.line(" \(key): []")] + } + + return [.line(" \(key): [")] + + lines + + [.line(" ]")] + } + + + private func createSequenceContentLines(by array: [DifferentiaUnit]) -> [PrettyLine] { + let lines: [PrettyLine] = array + .flatMap { (unit) -> [PrettyLine] in unit.prettyLines } + .map { .indent($0) } + + return lines + } + + + private func createPrettyLinesForDictionary( + kind: DifferentiaUnit.DictionaryType, + _ dictionary: [String: [DifferentiaUnit]] + ) -> [PrettyLine] { + let lines = self.createDictionaryContentLines(by: dictionary) + + guard !lines.isEmpty else { + return [.line(" \(kind.token.open)\(kind.token.close)")] + } + + return [.line(" \(kind.token.open)")] + + lines + + [.line(" \(kind.token.close)")] + } + + + private func createPrettyLinesForDictionaryWithKey( + key: String, + kind: DifferentiaUnit.DictionaryType, + _ dictionary: [String: [DifferentiaUnit]] + ) -> [PrettyLine] { + let lines = self.createDictionaryContentLines(by: dictionary) + + guard !lines.isEmpty else { + return [.line(" \(key): \(kind.token.open)\(kind.token.close)")] + } + + return [.line(" \(key): \(kind.token.open)")] + + lines + + [.line(" \(kind.token.close)")] + } + + + private func createDictionaryContentLines(by dictionary: [String: [DifferentiaUnit]]) -> [PrettyLine] { let lines: [PrettyLine] = entries(fromDictionary: dictionary) .sorted { $0.0 < $1.0 } - .flatMap { (childKey, childDiff) -> [PrettyLine] in - let childLines: [PrettyLine] = childDiff.units.flatMap { childDiffUnit -> [PrettyLine] in + .flatMap { (childKey, diffUnits) -> [PrettyLine] in + let childLines: [PrettyLine] = diffUnits.flatMap { childDiffUnit -> [PrettyLine] in switch childDiffUnit { case let .notChanged(value): return [.line(" \(childKey): \(value.description)")] @@ -29,8 +104,18 @@ extension DifferentiaUnit: PrettyPrintable { return [.line("- \(childKey): \(value.description)")] case let .inserted(value): return [.line("+ \(childKey): \(value.description)")] - case let .child(kind: childKind, childDictionary): - return self.childPrettyLines(kind: childKind, childDictionary) + case let .dictionaryChanged(kind: childKind, childDictionary): + return self.createPrettyLinesForDictionaryWithKey( + key: childKey, + kind: childKind, + childDictionary + ) + case let .sequenceChanged(kind: childKind, childArray): + return self.createPrettyLinesForSequenceWithKey( + key: childKey, + kind: childKind, + childArray + ) } } @@ -38,12 +123,6 @@ extension DifferentiaUnit: PrettyPrintable { } .map { .indent($0) } - guard !lines.isEmpty else { - return [.line(" \(kind.token.open)\(kind.token.close)")] - } - - return [.line(" \(kind.token.open)")] - + lines - + [.line(" \(kind.token.close)")] + return lines } } diff --git a/Sources/DifferentiaUnit.ChildKind.swift b/Sources/DifferentiaUnit.DictionaryType.swift similarity index 85% rename from Sources/DifferentiaUnit.ChildKind.swift rename to Sources/DifferentiaUnit.DictionaryType.swift index ee783bf..9049563 100644 --- a/Sources/DifferentiaUnit.ChildKind.swift +++ b/Sources/DifferentiaUnit.DictionaryType.swift @@ -3,7 +3,7 @@ import Foundation extension DifferentiaUnit { - enum ChildKind { + enum DictionaryType { case dictionary case anyStruct(type: Any.Type) case anyClass(type: Any.Type) @@ -34,8 +34,8 @@ extension DifferentiaUnit { -extension DifferentiaUnit.ChildKind: Equatable { - static func == (_ lhs: DifferentiaUnit.ChildKind, _ rhs: DifferentiaUnit.ChildKind) -> Bool { +extension DifferentiaUnit.DictionaryType: Equatable { + static func == (_ lhs: DifferentiaUnit.DictionaryType, _ rhs: DifferentiaUnit.DictionaryType) -> Bool { switch (lhs, rhs) { case (.dictionary, .dictionary): return true diff --git a/Sources/DifferentiaUnit.SequenceType.swift b/Sources/DifferentiaUnit.SequenceType.swift new file mode 100644 index 0000000..75149eb --- /dev/null +++ b/Sources/DifferentiaUnit.SequenceType.swift @@ -0,0 +1,25 @@ +import Foundation + + + +extension DifferentiaUnit { + enum SequenceType { + case array + case set + } +} + + + +extension DifferentiaUnit.SequenceType: Equatable { + static func ==(lhs: DifferentiaUnit.SequenceType, rhs: DifferentiaUnit.SequenceType) -> Bool { + switch (lhs, rhs) { + case (.array, .array): + return true + case (.set, .set): + return true + default: + return false + } + } +} \ No newline at end of file diff --git a/Sources/DifferentiaUnit.swift b/Sources/DifferentiaUnit.swift index 64615c8..a957a3f 100644 --- a/Sources/DifferentiaUnit.swift +++ b/Sources/DifferentiaUnit.swift @@ -6,7 +6,8 @@ indirect enum DifferentiaUnit { case notChanged(Diffable) case inserted(Diffable) case deleted(Diffable) - case child(kind: DifferentiaUnit.ChildKind, [String: Differentia]) + case dictionaryChanged(kind: DifferentiaUnit.DictionaryType, [String: [DifferentiaUnit]]) + case sequenceChanged(kind: DifferentiaUnit.SequenceType, [DifferentiaUnit]) } @@ -20,7 +21,11 @@ extension DifferentiaUnit: Equatable { return l == r case let (.deleted(l), .deleted(r)): return l == r - case let (.child(kind: lk, ld), .child(kind: rk, rd)): + case let (.dictionaryChanged(kind: lk, ld), .dictionaryChanged(kind: rk, rd)): + return lk == rk + && DifferentiaUnitComparableDictionary.from(dictionary: ld) + == DifferentiaUnitComparableDictionary.from(dictionary: rd) + case let (.sequenceChanged(kind: lk, ld), .sequenceChanged(kind: rk, rd)): return lk == rk && ld == rd default: diff --git a/Sources/MirrorDiffKit.swift b/Sources/MirrorDiffKit.swift index 0655735..d555264 100644 --- a/Sources/MirrorDiffKit.swift +++ b/Sources/MirrorDiffKit.swift @@ -1,8 +1,12 @@ public func diff(between a: Any, and b: Any) -> String { - let result = Diffable.diff( + let diff = Diffable.diff( between: Diffable.from(any: a), and: Diffable.from(any: b) ) - return "\n\(result.description)\n" + let prettyLines = diff.flatMap { (unit) in + return unit.prettyLines + } + + return "\n\(PrettyPrinter.print(fromLines: prettyLines))\n" } \ No newline at end of file diff --git a/Sources/PrettyPrintable.swift b/Sources/PrettyPrintable.swift index d7d1ab5..4718503 100644 --- a/Sources/PrettyPrintable.swift +++ b/Sources/PrettyPrintable.swift @@ -2,16 +2,14 @@ import Foundation -protocol PrettyPrintable /*: CustomStringConvertible */ { +protocol PrettyPrintable { var prettyLines: [PrettyLine] { get } } -extension PrettyPrintable { +extension PrettyPrintable /*: CustomStringConvertible */ { var description: String { - return self.prettyLines - .map { $0.description } - .joined(separator: "\n") + return PrettyPrinter.print(fromLines: self.prettyLines) } } diff --git a/Sources/PrettyPrinter.swift b/Sources/PrettyPrinter.swift new file mode 100644 index 0000000..69ae5b8 --- /dev/null +++ b/Sources/PrettyPrinter.swift @@ -0,0 +1,7 @@ +enum PrettyPrinter { + static func print(fromLines lines: [PrettyLine]) -> String { + return lines.map { $0.description } + .joined(separator: "\n") + } +} + diff --git a/Tests/MirrorDiffKitTests/Diffable+PrettyPrintableTests.swift b/Tests/MirrorDiffKitTests/Diffable+PrettyPrintableTests.swift deleted file mode 100644 index a33981f..0000000 --- a/Tests/MirrorDiffKitTests/Diffable+PrettyPrintableTests.swift +++ /dev/null @@ -1,158 +0,0 @@ -import XCTest -@testable import MirrorDiffKit - - -class Diffable_PrettyPrintableTests: XCTestCase { - private struct TestCase { - let input: Differentia - let expected: String - } - - - func testPrettyLines() { - let testCases: [UInt: TestCase] = [ - #line: TestCase( - input: Differentia( - units: [] - ), - expected: "" - ), - #line: TestCase( - input: Differentia( - units: [ - .notChanged(.string("I'm not changed")) - ] - ), - expected: " \"I'm not changed\"" - ), - #line: TestCase( - input: Differentia( - units: [ - .deleted(.string("I'm deleted")) - ] - ), - expected: "- \"I'm deleted\"" - ), - #line: TestCase( - input: Differentia( - units: [ - .inserted(.string("I'm inserted")) - ] - ), - expected: "+ \"I'm inserted\"" - ), - #line: TestCase( - input: Differentia( - units: [ - .child(kind: .dictionary, [ - "child": Differentia(units: []) - ]) - ] - ), - expected: " []" - ), - #line: TestCase( - input: Differentia( - units: [ - .child(kind: .anyStruct(type: StructStub.Empty.self), [ - "child": Differentia(units: []) - ]) - ] - ), - expected: " struct Empty {}" - ), - #line: TestCase( - input: Differentia( - units: [ - .child(kind: .anyClass(type: ClassStub.Empty.self), [ - "child": Differentia(units: []) - ]) - ] - ), - expected: " class Empty {}" - ), - #line: TestCase( - input: Differentia( - units: [ - .child(kind: .dictionary, [ - "child": Differentia(units: [ - .notChanged(.string("I'm not changed")), - ]) - ]) - ] - ), - expected: [ - " [", - " child: \"I'm not changed\"", - " ]" - ].joined(separator: "\n") - ), - #line: TestCase( - input: Differentia( - units: [ - .child(kind: .dictionary, [ - "child": Differentia(units: [ - .deleted(.string("I'm deleted")), - ]) - ]) - ] - ), - expected: [ - " [", - " - child: \"I'm deleted\"", - " ]" - ].joined(separator: "\n") - ), - #line: TestCase( - input: Differentia( - units: [ - .child(kind: .dictionary, [ - "child": Differentia(units: [ - .inserted(.string("I'm inserted")), - ]) - ]) - ] - ), - expected: [ - " [", - " + child: \"I'm inserted\"", - " ]" - ].joined(separator: "\n") - ), - #line: TestCase( - input: Differentia( - units: [ - .child(kind: .dictionary, [ - "child": Differentia(units: [ - .deleted(.string("I'm deleted")), - .inserted(.string("I'm inserted")), - .notChanged(.string("I'm not changed")), - ]), - ]) - ] - ), - expected: [ - " [", - " - child: \"I'm deleted\"", - " + child: \"I'm inserted\"", - " child: \"I'm not changed\"", - " ]" - ].joined(separator: "\n") - ), - ] - - - testCases.forEach { (line, testCase) in - let actual = testCase.input.description - XCTAssertEqual(actual, testCase.expected, line: line) - } - } - - - - static var allTests : [(String, (Diffable_PrettyPrintableTests) -> () throws -> Void)] { - return [ - ("testPrettyLines", self.testPrettyLines), - ] - } -} \ No newline at end of file diff --git a/Tests/MirrorDiffKitTests/DiffableSequenceTests.swift b/Tests/MirrorDiffKitTests/DiffableSequenceTests.swift index 1742ead..7cbb0e8 100644 --- a/Tests/MirrorDiffKitTests/DiffableSequenceTests.swift +++ b/Tests/MirrorDiffKitTests/DiffableSequenceTests.swift @@ -6,7 +6,7 @@ class DiffableSequenceTests: XCTestCase { private struct TestCase { let between: DiffableSequence let and: DiffableSequence - let expected: Differentia + let expected: [DifferentiaUnit] } @@ -15,7 +15,7 @@ class DiffableSequenceTests: XCTestCase { #line: TestCase( between: DiffableSequence([]), and: DiffableSequence([]), - expected: Differentia(units: []) + expected: [] ), #line: TestCase( between: DiffableSequence([ @@ -24,27 +24,27 @@ class DiffableSequenceTests: XCTestCase { and: DiffableSequence([ .string("I'm not changed"), ]), - expected: Differentia(units: [ + expected: [ .notChanged(.string("I'm not changed")), - ]) + ] ), #line: TestCase( between: DiffableSequence([]), and: DiffableSequence([ .string("I'm inserted"), ]), - expected: Differentia(units: [ + expected: [ .inserted(.string("I'm inserted")), - ]) + ] ), #line: TestCase( between: DiffableSequence([ .string("I'm deleted"), ]), and: DiffableSequence([]), - expected: Differentia(units: [ + expected: [ .deleted(.string("I'm deleted")), - ]) + ] ), #line: TestCase( between: DiffableSequence([ @@ -55,11 +55,11 @@ class DiffableSequenceTests: XCTestCase { .string("I'm not changed"), .string("I'm inserted"), ]), - expected: Differentia(units: [ + expected: [ .notChanged(.string("I'm not changed")), .deleted(.string("I'm deleted")), .inserted(.string("I'm inserted")), - ]) + ] ), #line: TestCase( between: DiffableSequence([ @@ -70,11 +70,11 @@ class DiffableSequenceTests: XCTestCase { .string("I'm inserted"), .string("I'm not changed"), ]), - expected: Differentia(units: [ + expected: [ .inserted(.string("I'm inserted")), .notChanged(.string("I'm not changed")), .deleted(.string("I'm deleted")), - ]) + ] ), #line: TestCase( between: DiffableSequence([ @@ -85,11 +85,11 @@ class DiffableSequenceTests: XCTestCase { .string("I'm inserted"), .string("I'm not changed"), ]), - expected: Differentia(units: [ + expected: [ .deleted(.string("I'm deleted")), .inserted(.string("I'm inserted")), .notChanged(.string("I'm not changed")), - ]) + ] ), #line: TestCase( between: DiffableSequence([ @@ -100,11 +100,11 @@ class DiffableSequenceTests: XCTestCase { .string("I'm not changed"), .string("I'm inserted"), ]), - expected: Differentia(units: [ + expected: [ .deleted(.string("I'm deleted")), .notChanged(.string("I'm not changed")), .inserted(.string("I'm inserted")), - ]) + ] ), #line: TestCase( between: DiffableSequence([ @@ -119,12 +119,12 @@ class DiffableSequenceTests: XCTestCase { .string("I'm not changed 3"), .string("I'm not changed 4"), ]), - expected: Differentia(units: [ + expected: [ .notChanged(.string("I'm not changed 1")), .notChanged(.string("I'm not changed 2")), .notChanged(.string("I'm not changed 3")), .notChanged(.string("I'm not changed 4")), - ]) + ] ), #line: TestCase( between: DiffableSequence([ @@ -137,13 +137,13 @@ class DiffableSequenceTests: XCTestCase { and: DiffableSequence([ .string("I'm not changed"), ]), - expected: Differentia(units: [ + expected: [ .deleted(.string("I'm deleted 1")), .deleted(.string("I'm deleted 2")), .deleted(.string("I'm deleted 3")), .deleted(.string("I'm deleted 4")), .notChanged(.string("I'm not changed")), - ]) + ] ), #line: TestCase( between: DiffableSequence([ @@ -156,13 +156,13 @@ class DiffableSequenceTests: XCTestCase { .string("I'm inserted 4"), .string("I'm not changed"), ]), - expected: Differentia(units: [ + expected: [ .inserted(.string("I'm inserted 1")), .inserted(.string("I'm inserted 2")), .inserted(.string("I'm inserted 3")), .inserted(.string("I'm inserted 4")), .notChanged(.string("I'm not changed")), - ]) + ] ), ] diff --git a/Tests/MirrorDiffKitTests/DiffableSetTests.swift b/Tests/MirrorDiffKitTests/DiffableSetTests.swift index 53f52ba..56cf718 100644 --- a/Tests/MirrorDiffKitTests/DiffableSetTests.swift +++ b/Tests/MirrorDiffKitTests/DiffableSetTests.swift @@ -8,7 +8,7 @@ class DiffableSetTests: XCTestCase { private struct TestCase { let from: DiffableSet let to: DiffableSet - let expected: Differentia + let expected: [DifferentiaUnit] } @@ -17,7 +17,7 @@ class DiffableSetTests: XCTestCase { #line: TestCase( from: DiffableSet([]), to: DiffableSet([]), - expected: Differentia(units: []) + expected: [] ), #line: TestCase( from: DiffableSet([ @@ -26,27 +26,27 @@ class DiffableSetTests: XCTestCase { to: DiffableSet([ .string("I'm not changed"), ]), - expected: Differentia(units: [ + expected: [ .notChanged(.string("I'm not changed")), - ]) + ] ), #line: TestCase( from: DiffableSet([ .string("I'm deleted"), ]), to: DiffableSet([]), - expected: Differentia(units: [ + expected: [ .deleted(.string("I'm deleted")), - ]) + ] ), #line: TestCase( from: DiffableSet([]), to: DiffableSet([ .string("I'm inserted"), ]), - expected: Differentia(units:[ + expected: [ .inserted(.string("I'm inserted")), - ]) + ] ), #line: TestCase( from: DiffableSet([ @@ -57,11 +57,11 @@ class DiffableSetTests: XCTestCase { .string("I'm not changed"), .string("I'm inserted") ]), - expected: Differentia(units:[ + expected: [ .deleted(.string("I'm deleted")), .inserted(.string("I'm inserted")), .notChanged(.string("I'm not changed")), - ]) + ] ), #line: TestCase( from: DiffableSet([ @@ -72,10 +72,10 @@ class DiffableSetTests: XCTestCase { to: DiffableSet([ .string("I'm deleted"), ]), - expected: Differentia(units:[ + expected: [ .deleted(.string("I'm deleted")), .notChanged(.string("I'm deleted")), - ]) + ] ), #line: TestCase( from: DiffableSet([ @@ -86,10 +86,10 @@ class DiffableSetTests: XCTestCase { .string("I'm inserted"), .string("I'm inserted"), ]), - expected: Differentia(units:[ + expected: [ .inserted(.string("I'm inserted")), .notChanged(.string("I'm inserted")), - ]) + ] ), ] @@ -106,7 +106,7 @@ class DiffableSetTests: XCTestCase { static var allTests : [(String, (DiffableSetTests) -> () throws -> Void)] { return [ - ("testExample", self.testDiff), + ("testDiff", self.testDiff), ] } } diff --git a/Tests/MirrorDiffKitTests/DifferentiaUnit+PrettyPrintableTests.swift b/Tests/MirrorDiffKitTests/DifferentiaUnit+PrettyPrintableTests.swift new file mode 100644 index 0000000..cc09ce7 --- /dev/null +++ b/Tests/MirrorDiffKitTests/DifferentiaUnit+PrettyPrintableTests.swift @@ -0,0 +1,174 @@ +import XCTest +@testable import MirrorDiffKit + + +class Diffable_PrettyPrintableTests: XCTestCase { + private struct TestCase { + let input: DifferentiaUnit + let expected: String + } + + + func testPrettyLines() { + let testCases: [UInt: TestCase] = [ + #line: TestCase( + input: .notChanged(.string("I'm not changed")), + expected: " \"I'm not changed\"" + ), + + #line: TestCase( + input: .deleted(.string("I'm deleted")), + expected: "- \"I'm deleted\"" + ), + + #line: TestCase( + input: .inserted(.string("I'm inserted")), + expected: "+ \"I'm inserted\"" + ), + + #line: TestCase( + input: .dictionaryChanged(kind: .dictionary, [ + "child": [], + ]), + expected: " []" + ), + + #line: TestCase( + input: .dictionaryChanged( + kind: .anyStruct(type: StructStub.Empty.self), + [ + "child": [], + ] + ), + expected: " struct Empty {}" + ), + + #line: TestCase( + input: .dictionaryChanged( + kind: .anyClass(type: ClassStub.Empty.self), + [ + "child": [], + ] + ), + expected: " class Empty {}" + ), + + #line: TestCase( + input: .dictionaryChanged( + kind: .dictionary, + [ + "child": [ + .notChanged(.string("I'm not changed")), + ], + ] + ), + expected: [ + " [", + " child: \"I'm not changed\"", + " ]" + ].joined(separator: "\n") + ), + + #line: TestCase( + input: .dictionaryChanged( + kind: .dictionary, + [ + "child": [ + .deleted(.string("I'm deleted")), + ], + ] + ), + expected: [ + " [", + " - child: \"I'm deleted\"", + " ]" + ].joined(separator: "\n") + ), + + #line: TestCase( + input: .dictionaryChanged( + kind: .dictionary, + [ + "child": [ + .inserted(.string("I'm inserted")), + ] + ] + ), + expected: [ + " [", + " + child: \"I'm inserted\"", + " ]" + ].joined(separator: "\n") + ), + + #line: TestCase( + input: .dictionaryChanged( + kind: .dictionary, + [ + "changed": [ + .deleted(.string("I'm deleted")), + .inserted(.string("I'm inserted")), + ], + "notChanged": [ + .notChanged(.string("I'm not changed")), + ], + ] + ), + expected: [ + " [", + " - changed: \"I'm deleted\"", + " + changed: \"I'm inserted\"", + " notChanged: \"I'm not changed\"", + " ]" + ].joined(separator: "\n") + ), + #line: TestCase( + input: .dictionaryChanged( + kind: .dictionary, + [ + "child": [ + .notChanged(.string("I'm not changed")), + ], + "grandChild": [ + .dictionaryChanged(kind: .dictionary, [ + "deleted": [ + .deleted(.string("I'm deleted")), + ], + "inserted": [ + .inserted(.string("I'm inserted")), + ], + "notChanged": [ + .notChanged(.string("I'm not changed")), + ], + ]), + ], + ] + ), + expected: [ + " [", + " child: \"I'm not changed\"", + " grandChild: [", + " - deleted: \"I'm deleted\"", + " + inserted: \"I'm inserted\"", + " notChanged: \"I'm not changed\"", + " ]", + " ]" + ].joined(separator: "\n") + ), + ] + + + testCases.forEach { (line, testCase) in + let actual = PrettyPrinter.print(fromLines: testCase.input.prettyLines) + XCTAssertEqual(actual, testCase.expected, line: line) + } + } + + + + static var allTests : [(String, (Diffable_PrettyPrintableTests) -> () throws -> Void)] { + return [ + ("testPrettyLines", self.testPrettyLines), + ] + } +} \ No newline at end of file diff --git a/Tests/MirrorDiffKitTests/Issue10Tests.swift b/Tests/MirrorDiffKitTests/Issue10Tests.swift new file mode 100644 index 0000000..f41d356 --- /dev/null +++ b/Tests/MirrorDiffKitTests/Issue10Tests.swift @@ -0,0 +1,70 @@ +import XCTest +@testable import MirrorDiffKit + + +class Issue10Tests: XCTestCase { + struct Example { + let data: [String] + let title: String + } + + + func testDiff() { + let a = Example( + data: [ + "I'm not changed", + "I'm not changed", + "I'm not changed", + "I'm deleted", + ], + title: "I'm not changed" + ) + + let b = Example( + data: [ + "I'm not changed", + "I'm not changed", + "I'm not changed", + "I'm inserted", + ], + title: "I'm not changed" + ) + + let actual = diff(between: a, and: b) + let expected = [ + "", + " struct Example {", + " data: [", + " \"I'm not changed\"", + " \"I'm not changed\"", + " \"I'm not changed\"", + " - \"I'm deleted\"", + " + \"I'm inserted\"", + " ]", + " title: \"I'm not changed\"", + " }", + "", + ].joined(separator: "\n") + + XCTAssertEqual(actual, expected) + + // NOTE: Print verbose info for efficient debugging. + let wasTestFailed = actual != expected + if wasTestFailed { + print("verbose:") + dump(Diffable.diff( + between: Diffable.from(any: a), + and: Diffable.from(any: b) + )) + } + } + + + + static var allTests: [(String, (Issue10Tests) -> () throws -> Void)] { + return [ + ("testDiff", self.testDiff), + ] + } +} + diff --git a/Tests/MirrorDiffKitTests/MirrorDiffKitIntegrationTests.swift b/Tests/MirrorDiffKitTests/MirrorDiffKitIntegrationTests.swift index b26c533..997c898 100644 --- a/Tests/MirrorDiffKitTests/MirrorDiffKitIntegrationTests.swift +++ b/Tests/MirrorDiffKitTests/MirrorDiffKitIntegrationTests.swift @@ -42,10 +42,12 @@ class MirrorDiffKitTests: XCTestCase { and: [0, 2, 3], is: [ "", - " 0.0", - "- 1.0", - " 2.0", - "+ 3.0", + " [", + " 0.0", + " - 1.0", + " 2.0", + " + 3.0", + " ]", "", ].joined(separator: "\n") ), @@ -166,6 +168,24 @@ class MirrorDiffKitTests: XCTestCase { "", ].joined(separator: "\n") ), + #line: TestCase( + diffBetween: [ + "changed": StructStub.OneEntry(key1: "I'm deleted"), + ], + and: [ + "changed": StructStub.OneEntry(key1: "I'm inserted"), + ], + is: [ + "", + " [", + " \"changed\": struct OneEntry {", + " - key1: \"I'm deleted\"", + " + key1: \"I'm inserted\"", + " }", + " ]", + "", + ].joined(separator: "\n") + ), ]