diff --git a/.bazelversion b/.bazelversion index 024b066c..bdec8e0d 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -6.2.1 +6.4.0rc2 diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index c8f72a35..492761b7 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -35,7 +35,7 @@ jobs: Linux: strategy: matrix: - tag: ['5.4', '5.5', '5.6', '5.7', '5.8'] + tag: ['5.4', '5.5', '5.6', '5.7', '5.8', '5.9'] runs-on: ubuntu-latest container: image: swift:${{ matrix.tag }}-focal diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index e202bac1..3ef1bc47 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -25,7 +25,7 @@ jobs: CMake: strategy: matrix: - xcode_version: ['14.2', '14.3'] + xcode_version: ['14.2', '14.3', '15.0'] runs-on: macos-13 env: DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode_version }}.app @@ -42,7 +42,7 @@ jobs: CMake_Linux: strategy: matrix: - tag: ['5.6', '5.7', '5.8'] + tag: ['5.6', '5.7', '5.8', '5.9'] runs-on: ubuntu-latest container: image: swift:${{ matrix.tag }} diff --git a/.github/workflows/jazzy.yml b/.github/workflows/jazzy.yml index a271cc67..1c04a156 100644 --- a/.github/workflows/jazzy.yml +++ b/.github/workflows/jazzy.yml @@ -23,9 +23,9 @@ on: jobs: Jazzy: - runs-on: macos-12 + runs-on: macos-13 env: - DEVELOPER_DIR: /Applications/Xcode_14.2.app + DEVELOPER_DIR: /Applications/Xcode_15.0.app steps: - uses: actions/checkout@v3 - name: Install SourceKitten diff --git a/.github/workflows/swiftlint.yml b/.github/workflows/swiftlint.yml index 5f892216..95355a16 100644 --- a/.github/workflows/swiftlint.yml +++ b/.github/workflows/swiftlint.yml @@ -11,7 +11,7 @@ jobs: SwiftLint: runs-on: ubuntu-latest container: - image: ghcr.io/realm/swiftlint:0.51.0 + image: ghcr.io/realm/swiftlint:0.53.0 steps: - uses: actions/checkout@v3 - name: SwiftLint diff --git a/.github/workflows/swiftlint_analyze.yml b/.github/workflows/swiftlint_analyze.yml index 5dda1d50..887e008d 100644 --- a/.github/workflows/swiftlint_analyze.yml +++ b/.github/workflows/swiftlint_analyze.yml @@ -23,7 +23,7 @@ jobs: Analyze: runs-on: macos-13 env: - DEVELOPER_DIR: /Applications/Xcode_14.3.app + DEVELOPER_DIR: /Applications/Xcode_15.0.app steps: - uses: actions/checkout@v3 - name: Generate xcodebuild.log diff --git a/.github/workflows/swiftpm.yml b/.github/workflows/swiftpm.yml index f872afa4..8fd97095 100644 --- a/.github/workflows/swiftpm.yml +++ b/.github/workflows/swiftpm.yml @@ -49,8 +49,21 @@ jobs: - run: swift -version - run: YAMS_DEFAULT_ENCODING=UTF16 swift test --parallel - run: YAMS_DEFAULT_ENCODING=UTF8 swift test --parallel + + Xcode_Ventura: + strategy: + matrix: + xcode_version: ['14.3', '15.0'] + runs-on: macos-13 + env: + DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode_version }}.app + steps: + - uses: actions/checkout@v3 + - run: swift -version + - run: YAMS_DEFAULT_ENCODING=UTF16 swift test --parallel + - run: YAMS_DEFAULT_ENCODING=UTF8 swift test --parallel - name: Code Coverage - if: matrix.xcode_version == '14.2' + if: matrix.xcode_version == '15.0' run: | swift test --enable-code-coverage xcrun llvm-cov export -format="lcov" .build/debug/YamsPackageTests.xctest/Contents/MacOS/YamsPackageTests -instr-profile .build/debug/codecov/default.profdata > coverage.lcov @@ -62,7 +75,7 @@ jobs: Linux: strategy: matrix: - tag: ['5.4', '5.5', '5.6', '5.7'] + tag: ['5.4', '5.5', '5.6', '5.7', '5.8', '5.9'] runs-on: ubuntu-latest container: image: swift:${{ matrix.tag }} diff --git a/.github/workflows/xcodebuild.yml b/.github/workflows/xcodebuild.yml index 2e064f0d..6d16628d 100644 --- a/.github/workflows/xcodebuild.yml +++ b/.github/workflows/xcodebuild.yml @@ -93,3 +93,37 @@ jobs: if: always() run: xcodebuild ${{ matrix.xcode_flags }} build -sdk watchsimulator | xcpretty shell: bash + + xcodebuild_Ventura: + strategy: + matrix: + xcode: + - version: '14.3' + - version: '15.0' + xcode_flags: ['-scheme Yams -project Yams.xcodeproj'] + runs-on: macos-13 + env: + DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode.version }}.app + steps: + - uses: actions/checkout@v3 + - run: xcodebuild -version + - name: macOS with UTF16 + if: always() + run: YAMS_DEFAULT_ENCODING=UTF16 xcodebuild ${{ matrix.xcode_flags }} test | xcpretty + shell: bash + - name: macOS with UTF8 + if: always() + run: YAMS_DEFAULT_ENCODING=UTF8 xcodebuild ${{ matrix.xcode_flags }} test | xcpretty + shell: bash + - name: iPhone Simulator + if: always() + run: xcodebuild ${{ matrix.xcode_flags }} test -sdk iphonesimulator -destination "name=iPhone 8" | xcpretty + shell: bash + - name: Apple TV Simulator + if: always() + run: xcodebuild ${{ matrix.xcode_flags }} test -sdk appletvsimulator -destination "name=Apple TV 4K (2nd generation)" | xcpretty + shell: bash + - name: watchOS Simulator + if: always() + run: xcodebuild ${{ matrix.xcode_flags }} build -sdk watchsimulator | xcpretty + shell: bash diff --git a/CHANGELOG.md b/CHANGELOG.md index a5aad8bb..4f3ecf92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,14 @@ ##### Breaking -* None. +* Change how empty strings are decoded into nullable properties. + `key: ""` previously decoded into + `struct Value: Codable { let key: String? }` as `Value(key: nil)` + whereas after this change it decodes as `Value(key: "")`. + This could be a breaking change if you were relying on the previous + semantics. + [Liam Nichols](https://github.com/liamnichols) + [#301](https://github.com/jpsim/Yams/issues/301) ##### Enhancements diff --git a/MODULE.bazel b/MODULE.bazel index e5080cca..be91d0b6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -4,7 +4,7 @@ module( compatibility_level = 1, ) -bazel_dep(name = "rules_swift", version = "1.8.0", repo_name = "build_bazel_rules_swift") +bazel_dep(name = "rules_swift", version = "1.12.0", repo_name = "build_bazel_rules_swift") -bazel_dep(name = "platforms", version = "0.0.6", dev_dependency = True) -bazel_dep(name = "rules_apple", version = "2.3.0", dev_dependency = True) +bazel_dep(name = "platforms", version = "0.0.7", dev_dependency = True) +bazel_dep(name = "rules_apple", version = "3.0.0", dev_dependency = True) diff --git a/Sources/Yams/Constructor.swift b/Sources/Yams/Constructor.swift index 29aa3c59..41b8a587 100644 --- a/Sources/Yams/Constructor.swift +++ b/Sources/Yams/Constructor.swift @@ -396,6 +396,10 @@ extension NSNull/*: ScalarConstructible*/ { /// /// - returns: An instance of `NSNull`, if one was successfully extracted from the scalar. public static func construct(from scalar: Node.Scalar) -> NSNull? { + // When constructing from a Scalar, only plain style scalars should be recognized. + // For example #"key: 'null'"# or #"key: ''"# should not be considered as null. + guard case .plain = scalar.style else { return nil } + switch scalar.string { case "", "~", "null", "Null", "NULL": return NSNull() diff --git a/Tests/YamsTests/ConstructorTests.swift b/Tests/YamsTests/ConstructorTests.swift index a04cc3cb..9f93039a 100644 --- a/Tests/YamsTests/ConstructorTests.swift +++ b/Tests/YamsTests/ConstructorTests.swift @@ -210,14 +210,16 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length english: null ~: null key --- - # This sequence has five - # entries, two have values. + # This sequence has seven + # entries, four have values. sparse: - ~ - 2nd entry - - 4th entry - Null + - 'null' + - '' """ let objects = Array(try Yams.load_all(yaml: example)) @@ -235,7 +237,9 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length "2nd entry", NSNull(), "4th entry", - NSNull() + NSNull(), + "null", + "" ] as [Any] ] ] diff --git a/Tests/YamsTests/EncoderTests.swift b/Tests/YamsTests/EncoderTests.swift index ce6d5d67..2eaa2269 100644 --- a/Tests/YamsTests/EncoderTests.swift +++ b/Tests/YamsTests/EncoderTests.swift @@ -590,14 +590,6 @@ private struct Address: Codable, Equatable { let zipCode: Int let country: String - init(street: String, city: String, state: String, zipCode: Int, country: String) { - self.street = street - self.city = city - self.state = state - self.zipCode = zipCode - self.country = country - } - static func == (_ lhs: Address, _ rhs: Address) -> Bool { return lhs.street == rhs.street && lhs.city == rhs.city && @@ -685,11 +677,6 @@ private struct Company: Codable, Equatable { let address: Address var employees: [Employee] - init(address: Address, employees: [Employee]) { - self.address = address - self.employees = employees - } - static func == (_ lhs: Company, _ rhs: Company) -> Bool { return lhs.address == rhs.address && lhs.employees == rhs.employees } diff --git a/Tests/YamsTests/NodeTests.swift b/Tests/YamsTests/NodeTests.swift index 5257e0a2..933de986 100644 --- a/Tests/YamsTests/NodeTests.swift +++ b/Tests/YamsTests/NodeTests.swift @@ -59,7 +59,7 @@ class NodeTests: XCTestCase { let scalarFloat: Node = "1.0" XCTAssertEqual(scalarFloat.float, 1.0) - let scalarNull: Node = "null" + let scalarNull = Node("null", .implicit, .plain) XCTAssertEqual(scalarNull.null, NSNull()) let scalarInt: Node = "1" diff --git a/Tests/YamsTests/TopLevelDecoderTests.swift b/Tests/YamsTests/TopLevelDecoderTests.swift index b6bdd37d..718b1b19 100644 --- a/Tests/YamsTests/TopLevelDecoderTests.swift +++ b/Tests/YamsTests/TopLevelDecoderTests.swift @@ -32,5 +32,51 @@ class TopLevelDecoderTests: XCTestCase { ) XCTAssertEqual(foo?.name, "Bird") } + + func testDecodeOptionalTypes() throws { + let yaml = """ + AAA: '' + BBB: + CCC: null + DDD: ~ + EEE: "" + json: { + "FFF": "", + "GGG": "null" + } + array: + - one + - '' + - null + - 'null' + - '~' + """ + + struct Container: Codable, Equatable { + struct JSON: Codable, Equatable { + var FFF: String? + var GGG: String? + } + + var AAA: String? + var BBB: String? + var CCC: Int? + var DDD: String? + var EEE: String? + var json: JSON + var array: [String?] + } + + let container = try YAMLDecoder().decode(Container.self, from: yaml) + + XCTAssertEqual(container.AAA, "") + XCTAssertEqual(container.BBB, nil) + XCTAssertEqual(container.CCC, nil) + XCTAssertEqual(container.DDD, nil) + XCTAssertEqual(container.EEE, "") + XCTAssertEqual(container.json.FFF, "") + XCTAssertEqual(container.json.GGG, "null") + XCTAssertEqual(container.array, ["one", "", nil, "null", "~"]) + } } #endif