From 8f988b346c3dda8c47bc1e21d42cb18015d38f0b Mon Sep 17 00:00:00 2001 From: Rien Date: Thu, 12 Jul 2018 10:50:21 +0200 Subject: [PATCH] Fixed undo error for name changes on a child --- Sources/VJson/Name.swift | 39 +++++++++++++++++++------- Sources/VJson/UndoRedo.swift | 16 +++++++++-- Tests/VJsonTests/Bugfixes.swift | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 13 deletions(-) diff --git a/Sources/VJson/Name.swift b/Sources/VJson/Name.swift index f7660ee..c0c6225 100644 --- a/Sources/VJson/Name.swift +++ b/Sources/VJson/Name.swift @@ -3,7 +3,7 @@ // File: Name.swift // Project: VJson // -// Version: 0.13.0 +// Version: 0.13.3 // // Author: Marinus van der Lugt // Company: http://balancingrock.nl @@ -50,6 +50,7 @@ // // History // +// 0.13.3 - Fixed problem with undo support for name changes of a child // 0.13.0 - Improved unicode character support. // 0.10.8 - Split off from VJson.swift // ===================================================================================================================== @@ -70,12 +71,16 @@ public extension VJson { set { if let newName = newValue?.stringToJsonString() { if newName != name { - recordUndoRedoAction() + recordUndoRedoAction(newName) name = newName } } else { - recordUndoRedoAction() - name = nil + if let parent = parent, parent.isObject { + // Cannot remove name + } else { + recordUndoRedoAction() + name = nil + } } } } @@ -90,12 +95,16 @@ public extension VJson { set { if let newName = newValue?.stringToJsonString(lut: printableJsonStringSequenceLUT) { if newName != name { - recordUndoRedoAction() + recordUndoRedoAction(newName) name = newName } } else { - recordUndoRedoAction() - name = nil + if let parent = parent, parent.isObject { + // Cannot remove name + } else { + recordUndoRedoAction() + name = nil + } } } } @@ -107,9 +116,19 @@ public extension VJson { public var nameValueRaw: String? { get { return name } - set { if name != newValue { - recordUndoRedoAction() - name = newValue + set { + if let newName = newValue { + if newName != name { + recordUndoRedoAction(newName) + name = newName + } + } else { + if let parent = parent, parent.isObject { + // Cannot remove name + } else { + recordUndoRedoAction() + name = nil + } } } } diff --git a/Sources/VJson/UndoRedo.swift b/Sources/VJson/UndoRedo.swift index 669ffec..310f01a 100644 --- a/Sources/VJson/UndoRedo.swift +++ b/Sources/VJson/UndoRedo.swift @@ -3,7 +3,7 @@ // File: UndoRedo.swift // Project: VJson // -// Version: 0.13.0 +// Version: 0.13.3 // // Author: Marinus van der Lugt // Company: http://balancingrock.nl @@ -50,6 +50,7 @@ // // History // +// 0.13.3 - Fixed problem with undo support for name changes of a child // 0.13.0 - Added escape sequences support // 0.12.5 - Made location public // 0.11.3 - Search for lowest undo manager in the VJson hierarchy. @@ -193,13 +194,22 @@ extension VJson { } - internal func recordUndoRedoAction() { + internal func recordUndoRedoAction(_ forNewName: String? = nil) { if let undoManager = undoManager { if #available(OSX 10.11, *) { - if let (root, path) = self.location() { + if let (root, lpath) = self.location() { + + var path = lpath + + // If the name will be changed, be sure to use the new name in the path + if let newName = forNewName { + if path.count >= 1 { + path[path.count - 1] = newName + } + } let clone = undoRedoClone() diff --git a/Tests/VJsonTests/Bugfixes.swift b/Tests/VJsonTests/Bugfixes.swift index 76c0664..e36fe5b 100644 --- a/Tests/VJsonTests/Bugfixes.swift +++ b/Tests/VJsonTests/Bugfixes.swift @@ -41,4 +41,53 @@ class Bugfixes: XCTestCase { XCTAssertEqual(json?.children?.items[0].nameValueRaw, "th\\uD83D\\uDE00ree") } + + func testBugfix_0_13_3() { + + // This test will fail (crash on assert) with < 0.13.3 + + let json = VJson() + json["name"] &= "content" + let child = json["name"] + XCTAssertEqual(child.nameValue, "name") + + json.undoManager = UndoManager() + + child.nameValue = "new" + XCTAssertEqual(child.nameValue, "new") + + json.undoManager?.undo() + + XCTAssertEqual(child.nameValue, "name") + + + // Extra test on removing a name from root object + + let root = VJson("content", name: "name") + + root.undoManager = UndoManager() + + XCTAssertEqual(root.nameValue, "name") + root.nameValue = nil + XCTAssertNil(root.nameValue) + + root.undoManager?.undo() + + XCTAssertEqual(root.nameValue, "name") + + + // Extra test on removing a name from a child object + + let array = VJson.array() + let element = VJson("content", name: "name") + array.append(element) + XCTAssertEqual(array[0].nameValue, "name") + array.undoManager = UndoManager() + + array[0].nameValue = nil + XCTAssertNil(array[0].nameValue) + + array.undoManager?.undo() + XCTAssertEqual(array[0].nameValue, "name") + } }