Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
## Main

## 6.0.0

##### Breaking

* YamlError.duplicatedKeysInMapping changed the types of its associated values
to conform to Sendable.
[Adora Lynch](https://github.com/lynchsft)

##### Enhancements

* Yams conforms to Swift 6 language mode with full concurrency checking
[Adora Lynch](https://github.com/lynchsft)

##### Bug Fixes

* None.

## 5.3.1

##### Breaking

* None.

## 5.4.0

##### Breaking
Expand Down
31 changes: 31 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// swift-tools-version:6.0
import PackageDescription

let package = Package(
name: "Yams",
products: [
.library(name: "Yams", targets: ["Yams"])
],
dependencies: [],
targets: [
.target(
name: "CYaml",
exclude: ["CMakeLists.txt"],
cSettings: [.define("YAML_DECLARE_STATIC")]
),
.target(
name: "Yams",
dependencies: ["CYaml"],
exclude: ["CMakeLists.txt"],
cSettings: [.define("YAML_DECLARE_STATIC")]
),
.testTarget(
name: "YamsTests",
dependencies: ["Yams"],
exclude: ["CMakeLists.txt"],
resources: [
.copy("Fixtures/SourceKitten#289/debug.yaml"),
]
)
]
)
14 changes: 7 additions & 7 deletions Sources/Yams/Constructor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ public final class Constructor {

extension Constructor {
/// The default `Constructor` to be used with APIs where none is explicitly provided.
public static let `default` = Constructor()
public static var `default`: Constructor { .init() }

/// The default `Tag.Name` to `Node.Scalar` map.
public static let defaultScalarMap: ScalarMap = [
public static var defaultScalarMap: ScalarMap { [
// Failsafe Schema
.str: String.construct,
// JSON Schema
Expand All @@ -82,24 +82,24 @@ extension Constructor {
// http://yaml.org/type/index.html
.binary: Data.construct,
.timestamp: Date.construct
]
] }

/// The default `Tag.Name` to `Node.Mapping` map.
public static let defaultMappingMap: MappingMap = [
public static var defaultMappingMap: MappingMap { [
.map: [AnyHashable: Any].construct_mapping,
// http://yaml.org/type/index.html
.set: Set<AnyHashable>.construct_set
// .merge is supported in `[AnyHashable: Any].construct_mapping`.
// .value is supported in `String.construct` and `[AnyHashable: Any].construct_mapping`.
]
] }

/// The default `Tag.Name` to `Node.Sequence` map.
public static let defaultSequenceMap: SequenceMap = [
public static var defaultSequenceMap: SequenceMap { [
.seq: [Any].construct_seq,
// http://yaml.org/type/index.html
.omap: [Any].construct_omap,
.pairs: [Any].construct_pairs
]
] }
}

// MARK: - ScalarConstructible
Expand Down
6 changes: 3 additions & 3 deletions Sources/Yams/Encoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -344,12 +344,12 @@ struct _YAMLCodingKey: CodingKey { // swiftlint:disable:this type_name
// MARK: -

private extension Node {
static let null = Node("null", Tag(.null))
static let unused = Node("", .unused)
static var null: Node { Node("null", Tag(.null)) }
static var unused: Node { Node("", .unused) }
}

private extension Tag {
static let unused = Tag(.unused)
static var unused: Tag { Tag(.unused) }
}

private extension Tag.Name {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Yams/Mark.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//

/// The pointer position.
public struct Mark {
public struct Mark: Sendable {
/// Line number starting from 1.
public let line: Int
/// Column number starting from 1. libYAML counts columns in `UnicodeScalar`.
Expand Down
12 changes: 9 additions & 3 deletions Sources/Yams/Parser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public final class Parser {
/// The default encoding, determined at run time based on the String type's native encoding.
/// This can be overridden by setting `YAMS_DEFAULT_ENCODING` to either `UTF8` or `UTF16`.
/// This value is case insensitive.
public static var `default`: Encoding = {
public static var `default`: Encoding {
let key = "YAMS_DEFAULT_ENCODING"
if let yamsEncoding = ProcessInfo.processInfo.environment[key],
let encoding = Encoding(rawValue: yamsEncoding.lowercased()) {
Expand All @@ -142,7 +142,7 @@ public final class Parser {
return encoding
}
return key.utf8.withContiguousStorageIfAvailable({ _ in true }) != nil ? .utf8 : .utf16
}()
}

/// The equivalent `Swift.Encoding` value for `self`.
public var swiftStringEncoding: String.Encoding {
Expand Down Expand Up @@ -397,7 +397,13 @@ private extension Parser {
private func checkDuplicates(mappingKeys: [Node]) throws {
let duplicates: [Node: [Node]] = Dictionary(grouping: mappingKeys) { $0 }.filter { $1.count > 1 }
guard duplicates.isEmpty else {
throw YamlError.duplicatedKeysInMapping(duplicates: duplicates, yaml: yaml)
let sortedKeys = duplicates.keys.sorted()
let firstKey = sortedKeys.first!
let firstMark = firstKey.mark ?? .init(line: 0, column: 0)
let duplicates = sortedKeys.map { $0.string ?? "<uncovertable>" }
throw YamlError.duplicatedKeysInMapping(duplicates: duplicates,
context: .init(text: yaml,
mark: firstMark))
}
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/Yams/Resolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import Foundation

/// Class used to resolve nodes to tags based on customizable rules.
public final class Resolver {
public final class Resolver: Sendable {
/// Rule describing how to resolve tags from regex patterns.
public struct Rule {
public struct Rule: Sendable {
/// The tag name this rule applies to.
public let tag: Tag.Name
fileprivate let regexp: NSRegularExpression
Expand Down
2 changes: 1 addition & 1 deletion Sources/Yams/Tag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
/// Tags describe the the _type_ of a Node.
public final class Tag {
/// Tag name.
public struct Name: RawRepresentable, Hashable {
public struct Name: RawRepresentable, Hashable, Sendable {
/// This `Tag.Name`'s raw string value.
public let rawValue: String
/// Create a `Tag.Name` with a raw string value.
Expand Down
21 changes: 1 addition & 20 deletions Sources/Yams/YamlAnchorProviding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,5 @@ public protocol YamlAnchorCoding: YamlAnchorProviding {
}

internal extension Node {
static let anchorKeyNode: Self = .scalar(.init(YamlAnchorFunctionNameProvider().getName()))
}

private final class YamlAnchorFunctionNameProvider: YamlAnchorProviding {

fileprivate var functionName: StaticString?

var yamlAnchor: Anchor? {
functionName = #function
return nil
}

func getName() -> StaticString {
_ = yamlAnchor
return functionName!
}

func getName() -> String {
String(describing: getName() as StaticString)
}
static var anchorKeyNode: Self { .scalar(.init("yamlAnchor")) }
}
24 changes: 9 additions & 15 deletions Sources/Yams/YamlError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ public enum YamlError: Error {
///
/// - parameter duplicates: A dictionary keyed by the duplicated node value, with all nodes that duplicate the value
/// - parameter yaml: YAML String which the problem occured while reading.
case duplicatedKeysInMapping(duplicates: [Node: [Node]], yaml: String)
case duplicatedKeysInMapping(duplicates: [String], context: Context)

/// The error context.
public struct Context: CustomStringConvertible {
public struct Context: CustomStringConvertible, Sendable {
/// Context text.
public let text: String
/// Context position.
Expand Down Expand Up @@ -187,20 +187,14 @@ extension YamlError: CustomStringConvertible {
return problem
case .dataCouldNotBeDecoded(encoding: let encoding):
return "String could not be decoded from data using '\(encoding)' encoding"
case let .duplicatedKeysInMapping(duplicates, yaml):
return duplicates.duplicatedKeyErrorDescription(yaml: yaml)
}
}
}
case let .duplicatedKeysInMapping(duplicates, context):
let duplicateKeys = duplicates.sorted().map { "'\($0)'" }.joined(separator: ", ")
return """
Parser: expected all keys to be unique but found the following duplicated key(s): \(duplicateKeys).
Context:
\(context.description)
"""

private extension Dictionary where Key == Node, Value == [Node] {
func duplicatedKeyErrorDescription(yaml: String) -> String {
var error = "error: parser: expected all keys to be unique but found the following duplicated key(s):"
for key in self.keys.sorted() {
let duplicatedNodes = self[key]!
let marks = duplicatedNodes.compactMap { $0.mark }
error += "\n\(key.any) (\(marks)):\n\(marks.map { $0.snippet(from: yaml) }.joined(separator: "\n"))"
}
return error
}
}
21 changes: 1 addition & 20 deletions Sources/Yams/YamlTagProviding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,5 @@ public protocol YamlTagCoding: YamlTagProviding {
}

internal extension Node {
static let tagKeyNode: Self = .scalar(.init(YamlTagFunctionNameProvider().getName()))
}

private final class YamlTagFunctionNameProvider: YamlTagProviding {

fileprivate var functionName: StaticString?

var yamlTag: Tag? {
functionName = #function
return nil
}

func getName() -> StaticString {
_ = yamlTag
return functionName!
}

func getName() -> String {
String(describing: getName() as StaticString)
}
static var tagKeyNode: Self { .scalar(.init("yamlTag")) }
}
2 changes: 1 addition & 1 deletion Tests/YamsTests/ConstructorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
import XCTest
import Yams

class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length
final class ConstructorTests: XCTestCase, @unchecked Sendable { // swiftlint:disable:this type_body_length
// Samples come from PyYAML.

func testBinary() throws {
Expand Down
2 changes: 1 addition & 1 deletion Tests/YamsTests/EmitterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import XCTest
import Yams

class EmitterTests: XCTestCase {
final class EmitterTests: XCTestCase, @unchecked Sendable {

func testScalar() throws {
var node: Node = "key"
Expand Down
2 changes: 1 addition & 1 deletion Tests/YamsTests/EncoderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Yams
// swiftlint:disable identifier_name line_length

/// Tests are copied from https://github.com/apple/swift/blob/main/test/stdlib/TestJSONEncoder.swift
class EncoderTests: XCTestCase { // swiftlint:disable:this type_body_length
final class EncoderTests: XCTestCase, @unchecked Sendable { // swiftlint:disable:this type_body_length
// MARK: - Encoding Top-Level Empty Types
func testEncodingTopLevelEmptyStruct() {
let empty = EmptyStruct()
Expand Down
2 changes: 1 addition & 1 deletion Tests/YamsTests/MarkTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import XCTest
import Yams

class MarkTests: XCTestCase {
final class MarkTests: XCTestCase, @unchecked Sendable {
func testLocatableDeprecationMessageForSwiftLint() throws {
let deprecatedRulesIdentifiers = [("variable_name", "identifier_name")].map { (Node($0.0), $0.1) }
func deprecatedMessage(from rule: Node) -> String? {
Expand Down
2 changes: 1 addition & 1 deletion Tests/YamsTests/NodeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
import XCTest
import Yams

class NodeTests: XCTestCase {
final class NodeTests: XCTestCase, @unchecked Sendable {

func testExpressibleByArrayLiteral() {
let sequence: Node = [
Expand Down
10 changes: 8 additions & 2 deletions Tests/YamsTests/PerformanceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ import Foundation
import XCTest
import Yams

class PerformanceTests: XCTestCase {
final class PerformanceTests: XCTestCase, @unchecked Sendable {
private let fixturesDirectory: String = {
if ProcessInfo.processInfo.environment["TEST_WORKSPACE"] != nil {
return "Tests/YamsTests/Fixtures/"
}
return URL(fileURLWithPath: #file).deletingLastPathComponent().path + "/Fixtures/"
let baseURL: URL
#if swift(>=6.0)
baseURL = URL(fileURLWithPath: #filePath)
#else
baseURL = URL(fileURLWithPath: #file)
#endif
return baseURL.deletingLastPathComponent().path + "/Fixtures/"
}()
let expectedImports = ["/SourceKitten/.build/debug"]
let expectedOtherArguments = [
Expand Down
2 changes: 1 addition & 1 deletion Tests/YamsTests/RepresenterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
import XCTest
import Yams

class RepresenterTests: XCTestCase {
final class RepresenterTests: XCTestCase, @unchecked Sendable {
func testBool() throws {
XCTAssertEqual(try Node(true), "true")
XCTAssertEqual(try Node(false), "false")
Expand Down
2 changes: 1 addition & 1 deletion Tests/YamsTests/ResolverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import XCTest
import Yams

class ResolverTests: XCTestCase {
final class ResolverTests: XCTestCase, @unchecked Sendable {

func testBasic() {
let resolver = Resolver.basic
Expand Down
2 changes: 1 addition & 1 deletion Tests/YamsTests/SpecTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
import XCTest
import Yams

class SpecTests: XCTestCase { // swiftlint:disable:this type_body_length
final class SpecTests: XCTestCase, @unchecked Sendable { // swiftlint:disable:this type_body_length

func testEmptyString() throws {
XCTAssertNil(try Yams.load(yaml: ""))
Expand Down
2 changes: 1 addition & 1 deletion Tests/YamsTests/StringTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import XCTest
@testable import Yams

class StringTests: XCTestCase {
final class StringTests: XCTestCase, @unchecked Sendable {
// column 1 2 3 4 5 6 7 8 9 10 11
// line 1 L I N E 1 _ 6 7 あ \n
// line 2 L I N E 2 _ 7 8 9 0 \n
Expand Down
Loading
Loading