From c9b19701041ed412da03902e426df7d3d205a2da Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Thu, 12 Dec 2024 15:27:59 +0000 Subject: [PATCH 1/4] Replace NSNumber with JMESNumber --- .swift-format | 63 +++++++ Sources/JMESPath/Expression.swift | 9 +- Sources/JMESPath/Functions.swift | 76 +++++---- Sources/JMESPath/Lexer.swift | 4 +- Sources/JMESPath/Number.swift | 193 ++++++++++++++++++++++ Sources/JMESPath/Variable.swift | 29 ++-- Tests/JMESPathTests/ComplianceTests.swift | 24 ++- Tests/JMESPathTests/MirrorTests.swift | 14 +- 8 files changed, 347 insertions(+), 65 deletions(-) create mode 100644 .swift-format create mode 100644 Sources/JMESPath/Number.swift diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..bb3dcff --- /dev/null +++ b/.swift-format @@ -0,0 +1,63 @@ +{ + "version" : 1, + "indentation" : { + "spaces" : 4 + }, + "tabWidth" : 4, + "fileScopedDeclarationPrivacy" : { + "accessLevel" : "private" + }, + "spacesAroundRangeFormationOperators" : false, + "indentConditionalCompilationBlocks" : false, + "indentSwitchCaseLabels" : false, + "lineBreakAroundMultilineExpressionChainComponents" : false, + "lineBreakBeforeControlFlowKeywords" : false, + "lineBreakBeforeEachArgument" : true, + "lineBreakBeforeEachGenericRequirement" : true, + "lineLength" : 150, + "maximumBlankLines" : 1, + "respectsExistingLineBreaks" : true, + "prioritizeKeepingFunctionOutputTogether" : true, + "multiElementCollectionTrailingCommas" : true, + "rules" : { + "AllPublicDeclarationsHaveDocumentation" : false, + "AlwaysUseLiteralForEmptyCollectionInit" : false, + "AlwaysUseLowerCamelCase" : false, + "AmbiguousTrailingClosureOverload" : true, + "BeginDocumentationCommentWithOneLineSummary" : false, + "DoNotUseSemicolons" : true, + "DontRepeatTypeInStaticProperties" : true, + "FileScopedDeclarationPrivacy" : true, + "FullyIndirectEnum" : true, + "GroupNumericLiterals" : true, + "IdentifiersMustBeASCII" : true, + "NeverForceUnwrap" : false, + "NeverUseForceTry" : false, + "NeverUseImplicitlyUnwrappedOptionals" : false, + "NoAccessLevelOnExtensionDeclaration" : true, + "NoAssignmentInExpressions" : true, + "NoBlockComments" : true, + "NoCasesWithOnlyFallthrough" : true, + "NoEmptyTrailingClosureParentheses" : true, + "NoLabelsInCasePatterns" : true, + "NoLeadingUnderscores" : false, + "NoParensAroundConditions" : true, + "NoVoidReturnOnFunctionSignature" : true, + "OmitExplicitReturns" : true, + "OneCasePerLine" : true, + "OneVariableDeclarationPerLine" : true, + "OnlyOneTrailingClosureArgument" : true, + "OrderedImports" : true, + "ReplaceForEachWithForLoop" : true, + "ReturnVoidInsteadOfEmptyTuple" : true, + "UseEarlyExits" : false, + "UseExplicitNilCheckInConditions" : false, + "UseLetInEveryBoundCaseVariable" : false, + "UseShorthandTypeNames" : true, + "UseSingleLinePropertyGetter" : false, + "UseSynthesizedInitializer" : false, + "UseTripleSlashForDocumentationComments" : true, + "UseWhereClausesInForLoops" : false, + "ValidateDocumentationComments" : false + } +} diff --git a/Sources/JMESPath/Expression.swift b/Sources/JMESPath/Expression.swift index 0009f7a..43141ef 100644 --- a/Sources/JMESPath/Expression.swift +++ b/Sources/JMESPath/Expression.swift @@ -23,7 +23,7 @@ public struct JMESExpression: JMESSendable { /// - Throws: JMESPathError /// - Returns: Search result public func search(json: Data, as: Value.Type = Value.self, runtime: JMESRuntime = .init()) throws -> Value? { - return try self.search(json: json, runtime: runtime) as? Value + try self.search(json: json, runtime: runtime) as? Value } /// Search JSON @@ -35,7 +35,7 @@ public struct JMESExpression: JMESSendable { /// - Throws: JMESPathError /// - Returns: Search result public func search(json: String, as: Value.Type = Value.self, runtime: JMESRuntime = .init()) throws -> Value? { - return try self.search(json: json, runtime: runtime) as? Value + try self.search(json: json, runtime: runtime) as? Value } /// Search Swift type @@ -47,7 +47,8 @@ public struct JMESExpression: JMESSendable { /// - Throws: JMESPathError /// - Returns: Search result public func search(object: Any, as: Value.Type = Value.self, runtime: JMESRuntime = .init()) throws -> Value? { - return try self.search(object: object, runtime: runtime) as? Value + let value = try self.search(object: object, runtime: runtime) + return value as? Value } /// Search JSON @@ -82,7 +83,7 @@ public struct JMESExpression: JMESSendable { /// - Throws: JMESPathError /// - Returns: Search result public func search(object: Any, runtime: JMESRuntime = .init()) throws -> Any? { - return try runtime.interpret(JMESVariable(from: object), ast: self.ast).collapse() + try runtime.interpret(JMESVariable(from: object), ast: self.ast).collapse() } private init(_ ast: Ast) { diff --git a/Sources/JMESPath/Functions.swift b/Sources/JMESPath/Functions.swift index f0368bb..545e1bf 100644 --- a/Sources/JMESPath/Functions.swift +++ b/Sources/JMESPath/Functions.swift @@ -50,8 +50,7 @@ public struct FunctionSignature { /// - Parameter args: Array of arguments /// - Throws: JMESPathError.runtime func validateArgs(_ args: [JMESVariable]) throws { - guard args.count == self.inputs.count || - (args.count > self.inputs.count && self.varArg != nil) + guard args.count == self.inputs.count || (args.count > self.inputs.count && self.varArg != nil) else { throw JMESPathError.runtime("Invalid number of arguments, expected \(self.inputs.count), got \(args.count)") } @@ -76,13 +75,13 @@ extension JMESVariable { func isType(_ type: FunctionSignature.ArgumentType) -> Bool { switch (self, type) { case (_, .any), - (.string, .string), - (.null, .null), - (.number, .number), - (.boolean, .boolean), - (.array, .array), - (.object, .object), - (.expRef, .expRef): + (.string, .string), + (.null, .null), + (.number, .number), + (.boolean, .boolean), + (.array, .array), + (.object, .object), + (.expRef, .expRef): return true case (.array(let array), .typedArray(let elementType)): @@ -128,7 +127,7 @@ public protocol JMESFunction { /// Protocl for JMESPath function that takes a single number protocol NumberFunction: JMESFunction { - static func evaluate(_ number: NSNumber) -> JMESVariable + static func evaluate(_ number: JMESNumber) -> JMESVariable } extension NumberFunction { @@ -166,8 +165,8 @@ extension ArrayFunction { /// Returns the absolute value of the provided argument. The signature indicates that a number is returned, and that the /// input argument must resolve to a number, otherwise a invalid-type error is triggered. struct AbsFunction: NumberFunction { - static func evaluate(_ number: NSNumber) -> JMESVariable { - return .number(.init(value: abs(number.doubleValue))) + static func evaluate(_ number: JMESNumber) -> JMESVariable { + .number(number.abs()) } } @@ -177,22 +176,22 @@ struct AvgFunction: ArrayFunction { static var signature: FunctionSignature { .init(inputs: .typedArray(.number)) } static func evaluate(_ array: JMESArray) -> JMESVariable { guard array.count > 0 else { return .null } - let total = array.reduce(0.0) { + let total = array.reduce(JMESNumber(0)) { if case .number(let number) = JMESVariable(from: $1) { - return $0 + number.doubleValue + return $0 + number } else { preconditionFailure() } } - return .number(.init(value: total / Double(array.count))) + return .number(total / JMESNumber(Double(array.count))) } } /// `number ceil(number $value)` /// Returns the next highest integer value by rounding up if necessary. struct CeilFunction: NumberFunction { - static func evaluate(_ number: NSNumber) -> JMESVariable { - return .number(.init(value: ceil(number.doubleValue))) + static func evaluate(_ number: JMESNumber) -> JMESVariable { + .number(number.ceil()) } } @@ -236,8 +235,8 @@ struct EndsWithFunction: JMESFunction { /// `number floor(number $value)` /// Returns the next lowest integer value by rounding down if necessary. struct FloorFunction: NumberFunction { - static func evaluate(_ number: NSNumber) -> JMESVariable { - return .number(.init(value: floor(number.doubleValue))) + static func evaluate(_ number: JMESNumber) -> JMESVariable { + .number(number.floor()) } } @@ -289,11 +288,11 @@ struct LengthFunction: JMESFunction { static func evaluate(args: [JMESVariable], runtime: JMESRuntime) -> JMESVariable { switch args[0] { case .array(let array): - return .number(.init(value: array.count)) + return .number(.init(array.count)) case .object(let object): - return .number(.init(value: object.count)) + return .number(.init(object.count)) case .string(let string): - return .number(.init(value: string.count)) + return .number(.init(string.count)) default: preconditionFailure() } @@ -342,7 +341,7 @@ struct MaxFunction: JMESFunction { case .number(var max): for element in array.dropFirst() { if case .number(let number) = JMESVariable(from: element) { - if number.compare(max) == .orderedDescending { + if number > max { max = number } } @@ -389,7 +388,7 @@ struct MaxByFunction: JMESFunction { for element in array.dropFirst() { let value = try runtime.interpret(JMESVariable(from: element), ast: ast) if case .number(let number) = value { - if number.compare(maxValue) == .orderedDescending { + if number > maxValue { maxValue = number maxElement = element } @@ -430,7 +429,7 @@ struct MinFunction: JMESFunction { case .number(var min): for element in array { if case .number(let number) = JMESVariable(from: element) { - if number.compare(min) == .orderedAscending { + if number < min { min = number } } @@ -477,7 +476,7 @@ struct MinByFunction: JMESFunction { for element in array.dropFirst() { let value = try runtime.interpret(JMESVariable(from: element), ast: ast) if case .number(let number) = value { - if number.compare(minValue) == .orderedAscending { + if number < minValue { minValue = number minElement = element } @@ -603,7 +602,9 @@ struct SortByFunction: JMESFunction { let restOfTheValues = try array.dropFirst().map { element -> ValueAndSortKey in let sortValue = try runtime.interpret(JMESVariable(from: element), ast: ast) guard sortValue.isSameType(as: firstSortValue) else { - throw JMESPathError.runtime("Sort arguments all have to be the same type, expected \(firstSortValue.getType()), instead got \(sortValue.getType())") + throw JMESPathError.runtime( + "Sort arguments all have to be the same type, expected \(firstSortValue.getType()), instead got \(sortValue.getType())" + ) } return .init(value: element, sortValue: sortValue) } @@ -636,14 +637,21 @@ struct StartsWithFunction: JMESFunction { struct SumFunction: ArrayFunction { static var signature: FunctionSignature { .init(inputs: .typedArray(.number)) } static func evaluate(_ array: JMESArray) -> JMESVariable { - let total = array.reduce(0.0) { - if case .number(let number) = JMESVariable(from: $1) { - return $0 + number.doubleValue - } else { - preconditionFailure() + guard let first = array.first.map({ JMESVariable(from: $0) }) else { return .number(.init(0)) } + switch first { + case .number(let number): + let total = array.dropFirst().reduce(number) { + if case .number(let number) = JMESVariable(from: $1) { + return $0 + number + } else { + preconditionFailure() + } } + return .number(total) + + default: + preconditionFailure() } - return .number(.init(value: total)) } } @@ -709,7 +717,7 @@ struct ToStringFunction: JMESFunction { struct TypeFunction: JMESFunction { static var signature: FunctionSignature { .init(inputs: .any) } static func evaluate(args: [JMESVariable], runtime: JMESRuntime) throws -> JMESVariable { - return .string(args[0].getType()) + .string(args[0].getType()) } } diff --git a/Sources/JMESPath/Lexer.swift b/Sources/JMESPath/Lexer.swift index 5e959a3..9961a59 100644 --- a/Sources/JMESPath/Lexer.swift +++ b/Sources/JMESPath/Lexer.swift @@ -1,5 +1,3 @@ -import Foundation - /// Lexer object /// /// Parses raw text to create an array of tokens @@ -216,6 +214,6 @@ internal class Lexer { } private func reachedEnd() -> Bool { - return self.index == self.text.endIndex + self.index == self.text.endIndex } } diff --git a/Sources/JMESPath/Number.swift b/Sources/JMESPath/Number.swift new file mode 100644 index 0000000..c8d6728 --- /dev/null +++ b/Sources/JMESPath/Number.swift @@ -0,0 +1,193 @@ +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif canImport(WinSDK) +import WinSDK +#elseif canImport(Bionic) +import Bionic +#else +#error("Unsupported platform") +#endif + +/// Number type that can store integer or floating point +public struct JMESNumber: Sendable, Equatable { + fileprivate enum _Internal { + case int(Int) + case double(Double) + } + + fileprivate var value: _Internal + + init(_ int: some BinaryInteger) { + self.value = .int(numericCast(int)) + } + + init(_ double: some BinaryFloatingPoint) { + self.value = .double(Double(double)) + } +} + +private func _ceil(_ value: Double) -> Double { + ceil(value) +} +private func _floor(_ value: Double) -> Double { + floor(value) +} +extension JMESNumber { + func collapse() -> Any { + switch self.value { + case .int(let int): + int + case .double(let double): + double + } + + } + + func abs() -> JMESNumber { + switch self.value { + case .int(let int): + .init(Swift.abs(int)) + case .double(let double): + .init(Swift.abs(double)) + } + } + + func floor() -> JMESNumber { + switch self.value { + case .int: + self + case .double(let double): + .init(_floor(double)) + } + } + + func ceil() -> JMESNumber { + switch self.value { + case .int: + self + case .double(let double): + .init(_ceil(double)) + } + } + + public static func == (_ lhs: JMESNumber, _ rhs: JMESNumber) -> Bool { + switch (lhs.value, rhs.value) { + case (.int(let lhs), .int(let rhs)): + lhs == rhs + case (.int(let lhs), .double(let rhs)): + Double(lhs) == rhs + case (.double(let lhs), .double(let rhs)): + lhs == rhs + case (.double(let lhs), .int(let rhs)): + lhs == Double(rhs) + } + } + + static prefix func - (_ value: JMESNumber) -> JMESNumber { + switch value.value { + case .int(let int): + .init(-int) + case .double(let double): + .init(-double) + } + } + + static func + (_ lhs: JMESNumber, _ rhs: JMESNumber) -> JMESNumber { + switch (lhs.value, rhs.value) { + case (.int(let lhs), .int(let rhs)): + .init(lhs + rhs) + case (.int(let lhs), .double(let rhs)): + .init(Double(lhs) + rhs) + case (.double(let lhs), .double(let rhs)): + .init(lhs + rhs) + case (.double(let lhs), .int(let rhs)): + .init(lhs + Double(rhs)) + } + } + + static func - (_ lhs: JMESNumber, _ rhs: JMESNumber) -> JMESNumber { + switch (lhs.value, rhs.value) { + case (.int(let lhs), .int(let rhs)): + .init(lhs - rhs) + case (.int(let lhs), .double(let rhs)): + .init(Double(lhs) - rhs) + case (.double(let lhs), .double(let rhs)): + .init(lhs - rhs) + case (.double(let lhs), .int(let rhs)): + .init(lhs - Double(rhs)) + } + } + + static func * (_ lhs: JMESNumber, _ rhs: JMESNumber) -> JMESNumber { + switch (lhs.value, rhs.value) { + case (.int(let lhs), .int(let rhs)): + .init(lhs * rhs) + case (.int(let lhs), .double(let rhs)): + .init(Double(lhs) * rhs) + case (.double(let lhs), .double(let rhs)): + .init(lhs * rhs) + case (.double(let lhs), .int(let rhs)): + .init(lhs * Double(rhs)) + } + } + + static func / (_ lhs: JMESNumber, _ rhs: JMESNumber) -> JMESNumber { + switch (lhs.value, rhs.value) { + case (.int(let lhs), .int(let rhs)): + .init(lhs / rhs) + case (.int(let lhs), .double(let rhs)): + .init(Double(lhs) / rhs) + case (.double(let lhs), .double(let rhs)): + .init(lhs / rhs) + case (.double(let lhs), .int(let rhs)): + .init(lhs / Double(rhs)) + } + } + + static func > (_ lhs: JMESNumber, _ rhs: JMESNumber) -> Bool { + switch (lhs.value, rhs.value) { + case (.int(let lhs), .int(let rhs)): + lhs > rhs + case (.int(let lhs), .double(let rhs)): + Double(lhs) > rhs + case (.double(let lhs), .double(let rhs)): + lhs > rhs + case (.double(let lhs), .int(let rhs)): + lhs > Double(rhs) + } + } + + static func >= (_ lhs: JMESNumber, _ rhs: JMESNumber) -> Bool { + switch (lhs.value, rhs.value) { + case (.int(let lhs), .int(let rhs)): + lhs >= rhs + case (.int(let lhs), .double(let rhs)): + Double(lhs) >= rhs + case (.double(let lhs), .double(let rhs)): + lhs >= rhs + case (.double(let lhs), .int(let rhs)): + lhs >= Double(rhs) + } + } + + static func < (_ lhs: JMESNumber, _ rhs: JMESNumber) -> Bool { + !(lhs >= rhs) + } + + static func <= (_ lhs: JMESNumber, _ rhs: JMESNumber) -> Bool { + !(lhs > rhs) + } +} + +extension JMESNumber: CustomStringConvertible { + public var description: String { + switch value { + case .int(let int): int.description + case .double(let double): double.description + } + } +} diff --git a/Sources/JMESPath/Variable.swift b/Sources/JMESPath/Variable.swift index b4863b3..ddeee24 100644 --- a/Sources/JMESPath/Variable.swift +++ b/Sources/JMESPath/Variable.swift @@ -11,7 +11,7 @@ public protocol JMESPropertyWrapper { public enum JMESVariable { case null case string(String) - case number(NSNumber) + case number(JMESNumber) case boolean(Bool) case array(JMESArray) case object(JMESObject) @@ -23,13 +23,17 @@ public enum JMESVariable { switch any { case let string as String: self = .string(string) + case let integer as any BinaryInteger: + self = .number(.init(integer)) + case let float as any BinaryFloatingPoint: + self = .number(.init(float)) case let number as NSNumber: // both booleans and integer/float point types can be converted to a `NSNumber` // We have to check to see the type id to see if it is a boolean if type(of: number) == Self.nsNumberBoolType { self = .boolean(number.boolValue) } else { - self = .number(number) + self = .number(.init(number.doubleValue)) } case let array as [Any]: self = .array(array) @@ -83,7 +87,7 @@ public enum JMESVariable { /// create JMESVariable from json public static func fromJson(_ json: String) throws -> Self { - return try self.fromJson(Data(json.utf8)) + try self.fromJson(Data(json.utf8)) } /// create JMESVariable from json @@ -97,7 +101,7 @@ public enum JMESVariable { switch self { case .null: return nil case .string(let string): return string - case .number(let number): return number + case .number(let number): return number.collapse() case .boolean(let bool): return bool case .array(let array): return array case .object(let map): return map @@ -118,7 +122,9 @@ public enum JMESVariable { case .array(let array): guard let jsonData = try? JSONSerialization.data( - withJSONObject: array, options: [.fragmentsAllowed]) + withJSONObject: array, + options: [.fragmentsAllowed] + ) else { return nil } @@ -126,7 +132,9 @@ public enum JMESVariable { case .object(let object): guard let jsonData = try? JSONSerialization.data( - withJSONObject: object, options: [.fragmentsAllowed]) + withJSONObject: object, + options: [.fragmentsAllowed] + ) else { return nil } @@ -209,10 +217,10 @@ public enum JMESVariable { default: if case .number(let lhs) = self, case .number(let rhs) = value { switch comparator { - case .lessThan: return lhs.doubleValue < rhs.doubleValue - case .lessThanOrEqual: return lhs.doubleValue <= rhs.doubleValue - case .greaterThan: return lhs.doubleValue > rhs.doubleValue - case .greaterThanOrEqual: return lhs.doubleValue >= rhs.doubleValue + case .lessThan: return lhs < rhs + case .lessThanOrEqual: return lhs <= rhs + case .greaterThan: return lhs > rhs + case .greaterThanOrEqual: return lhs >= rhs default: break } @@ -268,6 +276,7 @@ public enum JMESVariable { } fileprivate static var nsNumberBoolType = type(of: NSNumber(value: true)) + fileprivate static var nsNumberIntType = type(of: NSNumber(value: Int(1))) } extension JMESVariable: Equatable { diff --git a/Tests/JMESPathTests/ComplianceTests.swift b/Tests/JMESPathTests/ComplianceTests.swift index aaa9fd5..ae8e157 100644 --- a/Tests/JMESPathTests/ComplianceTests.swift +++ b/Tests/JMESPathTests/ComplianceTests.swift @@ -10,7 +10,7 @@ import JMESPath import XCTest #if os(Linux) || os(Windows) - import FoundationNetworking +import FoundationNetworking #endif public struct AnyDecodable: Decodable { @@ -43,13 +43,15 @@ extension AnyDecodable { self.init(dictionary.mapValues { $0.value }) } else { throw DecodingError.dataCorruptedError( - in: container, debugDescription: "AnyDecodable value cannot be decoded") + in: container, + debugDescription: "AnyDecodable value cannot be decoded" + ) } } } /// Verify implementation against formal standard for Mustache. -/// https://github.com/mustache/spec +/// https://github.com/jmespath/jmespath.test final class ComplianceTests: XCTestCase { struct ComplianceTest: Decodable { struct Case: Decodable { @@ -107,12 +109,16 @@ final class ComplianceTests: XCTestCase { let resultJson: String? = try result.map { let data = try JSONSerialization.data( - withJSONObject: $0, options: [.fragmentsAllowed, .sortedKeys]) + withJSONObject: $0, + options: [.fragmentsAllowed, .sortedKeys] + ) return String(decoding: data, as: Unicode.UTF8.self) } if let value = try expression.search(object: self.given.value) { let valueData = try JSONSerialization.data( - withJSONObject: value, options: [.fragmentsAllowed, .sortedKeys]) + withJSONObject: value, + options: [.fragmentsAllowed, .sortedKeys] + ) let valueJson = String(decoding: valueData, as: Unicode.UTF8.self) XCTAssertEqual(resultJson, valueJson) } else { @@ -127,7 +133,9 @@ final class ComplianceTests: XCTestCase { func output(_ c: Case, expected: String?, result: String?) { if expected != result { let data = try! JSONSerialization.data( - withJSONObject: self.given.value, options: [.fragmentsAllowed, .sortedKeys]) + withJSONObject: self.given.value, + options: [.fragmentsAllowed, .sortedKeys] + ) let givenJson = String(decoding: data, as: Unicode.UTF8.self) if let comment = c.comment { print("Comment: \(comment)") @@ -150,9 +158,9 @@ final class ComplianceTests: XCTestCase { func testCompliance(url: URL, ignoring: [String] = []) async throws { #if compiler(>=6.0) - let (data, _) = try await URLSession.shared.data(from: url, delegate: nil) + let (data, _) = try await URLSession.shared.data(from: url, delegate: nil) #else - let data = try Data(contentsOf: url) + let data = try Data(contentsOf: url) #endif let tests = try JSONDecoder().decode([ComplianceTest].self, from: data) diff --git a/Tests/JMESPathTests/MirrorTests.swift b/Tests/JMESPathTests/MirrorTests.swift index f8fc6c9..c138b91 100644 --- a/Tests/JMESPathTests/MirrorTests.swift +++ b/Tests/JMESPathTests/MirrorTests.swift @@ -1,6 +1,7 @@ -@testable import JMESPath import XCTest +@testable import JMESPath + final class MirrorTests: XCTestCase { func testInterpreter(_ expression: String, data: Any, result: Value) { do { @@ -47,6 +48,7 @@ final class MirrorTests: XCTestCase { let a: [Int] } let test = TestArray(a: [1, 2, 3, 4, 5]) + self.testInterpreter("a", data: test, result: test.a) self.testInterpreter("a[2]", data: test, result: 3) self.testInterpreter("a[-2]", data: test, result: 4) self.testInterpreter("a[1]", data: test, result: 2) @@ -79,7 +81,7 @@ final class MirrorTests: XCTestCase { func testCustomReflectableArray() { struct TestObject: CustomReflectable { let a: [Int] - var customMirror: Mirror { return Mirror(reflecting: self.a) } + var customMirror: Mirror { Mirror(reflecting: self.a) } } let test = TestObject(a: [1, 2, 3, 4]) self.testInterpreter("[2]", data: test, result: 3) @@ -88,7 +90,7 @@ final class MirrorTests: XCTestCase { func testCustomReflectableDictionary() { struct TestObject: CustomReflectable { let d: [String: String] - var customMirror: Mirror { return Mirror(reflecting: self.d) } + var customMirror: Mirror { Mirror(reflecting: self.d) } } let test = TestObject(d: ["test": "one", "test2": "two", "test3": "three"]) self.testInterpreter("test2", data: test, result: "two") @@ -97,16 +99,16 @@ final class MirrorTests: XCTestCase { func testPropertyWrapper() { @propertyWrapper struct Wrap: JMESPropertyWrapper { var value: T - var customMirror: Mirror { return Mirror(reflecting: self.value) } + var customMirror: Mirror { Mirror(reflecting: self.value) } init(wrappedValue: T) { self.value = wrappedValue } var wrappedValue: T { - get { return value } + get { value } set { value = newValue } } - var anyValue: Any { return value } + var anyValue: Any { value } } struct TestObject { @Wrap var test: String From 477c53f8b14f27ef7d76f4c5c694856be8e3f336 Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Thu, 12 Dec 2024 15:28:23 +0000 Subject: [PATCH 2/4] Remove old swiftformat file --- .swiftformat | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 .swiftformat diff --git a/.swiftformat b/.swiftformat deleted file mode 100644 index 82d81a1..0000000 --- a/.swiftformat +++ /dev/null @@ -1,23 +0,0 @@ -# Minimum swiftformat version ---minversion 0.47.4 - -# Swift version ---swiftversion 5.1 - -# file options ---exclude .build - -# rules ---disable redundantReturn, extensionAccessControl - -# format options ---ifdef no-indent ---nospaceoperators ...,..< ---patternlet inline ---self insert ---stripunusedargs unnamed-only - -#--maxwidth 150 ---wraparguments before-first ---wrapparameters before-first ---wrapcollections before-first From 8797cee691716fcfb86429cfca4a9260a5efad1c Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Thu, 12 Dec 2024 15:35:54 +0000 Subject: [PATCH 3/4] Update CI swift versions --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1ee8f2..36861d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ on: jobs: macos: - runs-on: macOS-13 + runs-on: macOS-14 steps: - name: Checkout uses: actions/checkout@v4 @@ -36,10 +36,9 @@ jobs: strategy: matrix: tag: - - swift:5.8 - swift:5.9 - swift:5.10 - - swiftlang/swift:nightly-6.0-jammy + - swift:6.0 container: image: ${{ matrix.tag }} steps: From 27f86f2578bade9363b2b74871dd4ed51b7336c9 Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Thu, 12 Dec 2024 15:36:44 +0000 Subject: [PATCH 4/4] Use swift 6.0 in windows CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36861d7..80bd35d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: steps: - uses: compnerd/gha-setup-swift@main with: - branch: swift-5.10-release - tag: 5.10-RELEASE + branch: swift-6.0-release + tag: 6.0-RELEASE - uses: actions/checkout@v4 - run: swift test \ No newline at end of file