From 1bc7a6b9e6d0c846dd039071c4be7c443f6e21da Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Sat, 6 Jul 2019 13:30:04 +0900 Subject: [PATCH 1/5] Add `testSmartQuotedString` to `EmitterTests` --- Tests/YamsTests/EmitterTests.swift | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Tests/YamsTests/EmitterTests.swift b/Tests/YamsTests/EmitterTests.swift index 8afb7572..e96c016d 100644 --- a/Tests/YamsTests/EmitterTests.swift +++ b/Tests/YamsTests/EmitterTests.swift @@ -122,6 +122,24 @@ class EmitterTests: XCTestCase { let expectedSorted = "key1: value1\nkey2: value2\nkey3: value3\n" XCTAssertEqual(yamlSorted, expectedSorted) } + + func testSmartQuotedString() throws { + let samples: [(string: String, tag: Tag.Name, expected: String, line: UInt)] = [ + ("string", .str, "string", #line), + ("true", .bool, "'true'", #line), + ("1", .int, "'1'", #line), + ("1.0", .float, "'1.0'", #line), + ("null", .null, "'null'", #line), + ("2019-07-06", .timestamp, "'2019-07-06'", #line), + ] + let resolver = Resolver.default + for (string, tag, expected, line) in samples { + let resolvedTag = resolver.resolveTag(of: Node(string)) + XCTAssertEqual(resolvedTag, tag, "Resolver resolves unexpected tag", line: line) + let yaml = try Yams.dump(object: string) + XCTAssertEqual(yaml, "\(expected)\n", line: line) + } + } } extension EmitterTests { @@ -132,7 +150,8 @@ extension EmitterTests { ("testMapping", testMapping), ("testLineBreaks", testLineBreaks), ("testAllowUnicode", testAllowUnicode), - ("testSortKeys", testSortKeys) + ("testSortKeys", testSortKeys), + ("testSmartQuotedString", testSmartQuotedString) ] } } From c8f31af423d86f154035f5f3b9d0056607bdd5c0 Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Sat, 6 Jul 2019 13:47:19 +0900 Subject: [PATCH 2/5] Add smart quoting to `String.represented()` Apply `.singleQuoted` on representing `Node.Scalar` from `String` if `Resolver.default` resolves that to other than `.str`. Fixes #197 --- Sources/Yams/Representer.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Sources/Yams/Representer.swift b/Sources/Yams/Representer.swift index 92ab078a..e4d1ade0 100644 --- a/Sources/Yams/Representer.swift +++ b/Sources/Yams/Representer.swift @@ -56,9 +56,7 @@ extension Dictionary: NodeRepresentable { } private func represent(_ value: Any) throws -> Node { - if let string = value as? String { - return Node(string) - } else if let representable = value as? NodeRepresentable { + if let representable = value as? NodeRepresentable { return try representable.represented() } throw YamlError.representer(problem: "Failed to represent \(value)") @@ -230,7 +228,8 @@ extension URL: ScalarRepresentable { extension String: ScalarRepresentable { /// This value's `Node.scalar` representation. public func represented() -> Node.Scalar { - return .init(self) + let node = Node.Scalar.init(self, .init(.implicit, .default)) + return node.resolvedTag.name == .str ? node : .init(self, .init(.str), .singleQuoted) } } From 8eb295d092007ad5c7415773a95d5014740c44b4 Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Sat, 6 Jul 2019 13:54:48 +0900 Subject: [PATCH 3/5] Update `expectedYaml` in `SpecTests.testSpecExample2_23_VariousExplicitTags()` It is more desirable behavior. --- Tests/YamsTests/SpecTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/YamsTests/SpecTests.swift b/Tests/YamsTests/SpecTests.swift index f3adeaa2..95d0c88c 100644 --- a/Tests/YamsTests/SpecTests.swift +++ b/Tests/YamsTests/SpecTests.swift @@ -703,7 +703,7 @@ class SpecTests: XCTestCase { // swiftlint:disable:this type_body_length different documents. ' - not-date: 2002-04-28 + not-date: '2002-04-28' picture: R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmleECcgggoBADs= """ From 75e89672e7f516241535fa41f79b38b48c2ea47a Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Sat, 6 Jul 2019 14:13:02 +0900 Subject: [PATCH 4/5] Add an entry to CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95d14c97..3ae898dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ * Accurately represent `Date`s with nanosecond components in Swift 4.x. [Norio Nomura](https://github.com/norio-nomura) +* Change to apply single quoted style to YAML representation of `String`, if + that contents will be resolved to other than `.str` by default `Resolver`. + [Norio Nomura](https://github.com/norio-nomura) + [#197](https://github.com/jpsim/Yams/issues/197) + ##### Bug Fixes * Fix a bug where `YAMLEncoder` would delay `Date`s by 1 second when encoding From e3b1c21d8cd818a361818e72799cad504e588c01 Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Sat, 6 Jul 2019 14:34:52 +0900 Subject: [PATCH 5/5] Fix variable name and simplify calling `Node.Scalar.init` --- Sources/Yams/Representer.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Yams/Representer.swift b/Sources/Yams/Representer.swift index e4d1ade0..e01b4972 100644 --- a/Sources/Yams/Representer.swift +++ b/Sources/Yams/Representer.swift @@ -228,8 +228,8 @@ extension URL: ScalarRepresentable { extension String: ScalarRepresentable { /// This value's `Node.scalar` representation. public func represented() -> Node.Scalar { - let node = Node.Scalar.init(self, .init(.implicit, .default)) - return node.resolvedTag.name == .str ? node : .init(self, .init(.str), .singleQuoted) + let scalar = Node.Scalar(self) + return scalar.resolvedTag.name == .str ? scalar : .init(self, Tag(.str), .singleQuoted) } }