Skip to content

Commit

Permalink
Fix numeric version comparisons (#5526)
Browse files Browse the repository at this point in the history
  • Loading branch information
chandlerwall authored May 1, 2024
1 parent 96db41c commit 16cb4a0
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@

#### Bug Fixes

* Fix version comparison algorithm which caused some version-dependent rules to
misbehave with Swift 5.10.
[chandlerwall](https://github.com/chandlerwall)
[#5517](https://github.com/realm/SwiftLint/issues/5517)

* Silence `discarded_notification_center_observer` rule in closures. Furthermore,
handle `get` and `set` accessors correctly and consider implicit returns.
[SimplyDanny](https://github.com/SimplyDanny)
Expand Down
20 changes: 20 additions & 0 deletions Source/SwiftLintCore/Models/SwiftVersion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,29 @@ public struct SwiftVersion: RawRepresentable, Codable, Comparable, Sendable {
self.rawValue = rawValue
}

public static func == (lhs: SwiftVersion, rhs: SwiftVersion) -> Bool {
if let lhsComparators = lhs.comparators, let rhsComparators = rhs.comparators {
return lhsComparators == rhsComparators
}
return lhs.rawValue == rhs.rawValue
}

public static func < (lhs: SwiftVersion, rhs: SwiftVersion) -> Bool {
if let lhsComparators = lhs.comparators, let rhsComparators = rhs.comparators {
return lhsComparators.lexicographicallyPrecedes(rhsComparators)
}
return lhs.rawValue < rhs.rawValue
}

private var comparators: [Int]? {
let components = rawValue.split(separator: ".").compactMap { Int($0) }
guard let major = components.first else {
return nil
}
let minor = components.dropFirst(1).first ?? 0
let patch = components.dropFirst(2).first ?? 0
return [major, minor, patch]
}
}

public extension SwiftVersion {
Expand Down
48 changes: 48 additions & 0 deletions Tests/SwiftLintFrameworkTests/SwiftVersionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,52 @@ final class SwiftVersionTests: SwiftLintTestCase {
#endif
XCTAssertEqual(SwiftVersion.current.rawValue, version)
}

func testCompareBalancedSwiftVersion() {
XCTAssertNotEqual(SwiftVersion(rawValue: "5"), SwiftVersion(rawValue: "6"))
XCTAssertTrue(SwiftVersion(rawValue: "5") < SwiftVersion(rawValue: "6"))
XCTAssertFalse(SwiftVersion(rawValue: "5") > SwiftVersion(rawValue: "6"))
XCTAssertFalse(SwiftVersion(rawValue: "6") < SwiftVersion(rawValue: "5"))

XCTAssertNotEqual(SwiftVersion(rawValue: "5.1"), SwiftVersion(rawValue: "5.2"))
XCTAssertTrue(SwiftVersion(rawValue: "5.1") < SwiftVersion(rawValue: "5.2"))
XCTAssertFalse(SwiftVersion(rawValue: "5.1") > SwiftVersion(rawValue: "5.2"))
XCTAssertFalse(SwiftVersion(rawValue: "5.2") < SwiftVersion(rawValue: "5.1"))

XCTAssertNotEqual(SwiftVersion(rawValue: "5.1.1"), SwiftVersion(rawValue: "5.1.2"))
XCTAssertTrue(SwiftVersion(rawValue: "5.1.1") < SwiftVersion(rawValue: "5.1.2"))
XCTAssertFalse(SwiftVersion(rawValue: "5.1.1") > SwiftVersion(rawValue: "5.1.2"))
XCTAssertFalse(SwiftVersion(rawValue: "5.1.2") < SwiftVersion(rawValue: "5.1.1"))
}

func testCompareUnbalancedSwiftVersion() {
XCTAssertEqual(SwiftVersion(rawValue: "5"), SwiftVersion(rawValue: "5.0"))
XCTAssertFalse(SwiftVersion(rawValue: "5") < SwiftVersion(rawValue: "5.0"))
XCTAssertFalse(SwiftVersion(rawValue: "5") > SwiftVersion(rawValue: "5.0"))

XCTAssertNotEqual(SwiftVersion(rawValue: "5.9"), SwiftVersion(rawValue: "6"))
XCTAssertTrue(SwiftVersion(rawValue: "5.9") < SwiftVersion(rawValue: "6"))
XCTAssertFalse(SwiftVersion(rawValue: "5.9") > SwiftVersion(rawValue: "6"))
XCTAssertFalse(SwiftVersion(rawValue: "6") < SwiftVersion(rawValue: "5.9"))

XCTAssertNotEqual(SwiftVersion(rawValue: "5.2"), SwiftVersion(rawValue: "5.10.3"))
XCTAssertTrue(SwiftVersion(rawValue: "5.2") < SwiftVersion(rawValue: "5.10.3"))
XCTAssertFalse(SwiftVersion(rawValue: "5.2") > SwiftVersion(rawValue: "5.10.3"))
XCTAssertFalse(SwiftVersion(rawValue: "5.10.3") < SwiftVersion(rawValue: "5.2"))
}

func testCompareProblematicSwiftVersion() {
XCTAssertEqual(SwiftVersion(rawValue: "5.010"), SwiftVersion(rawValue: "5.10"))
XCTAssertFalse(SwiftVersion(rawValue: "5.010") < SwiftVersion(rawValue: "5.10"))
XCTAssertFalse(SwiftVersion(rawValue: "5.010") > SwiftVersion(rawValue: "5.10"))

XCTAssertNotEqual(SwiftVersion(rawValue: "-10"), SwiftVersion(rawValue: "-1"))
XCTAssertTrue(SwiftVersion(rawValue: "-10") < SwiftVersion(rawValue: "-1"))

XCTAssertNotEqual(SwiftVersion(rawValue: "0"), SwiftVersion(rawValue: "10"))
XCTAssertTrue(SwiftVersion(rawValue: "0") < SwiftVersion(rawValue: "10"))

XCTAssertNotEqual(SwiftVersion(rawValue: "alpha"), SwiftVersion(rawValue: "beta"))
XCTAssertTrue(SwiftVersion(rawValue: "alpha") < SwiftVersion(rawValue: "beta"))
}
}

0 comments on commit 16cb4a0

Please sign in to comment.