From a315af9a42ea92db626a02a284786cbbe6a81e1b Mon Sep 17 00:00:00 2001 From: Marius Felkner Date: Sat, 9 Mar 2024 13:59:10 +0100 Subject: [PATCH] ADD swiftlint --- .github/workflows/{checks.yml => builds.yml} | 5 +- .github/workflows/lint.yml | 17 ++ .mise.toml | 2 + .swiftlint.yml | 220 ++++++++++++++++++ Sources/Helper/String+Regex.swift | 16 +- .../BuildMetaData+ExpressibleByLiteral.swift | 4 +- .../BuildMetaData/BuildMetaData.swift | 2 +- .../PrereleaseIdentifier+Equatable.swift | 4 +- ...leaseIdentifier+ExpressibleByLiteral.swift | 4 +- ...SemanticVersionComparable+Comparable.swift | 8 +- .../SemanticVersionComparable+Hashable.swift | 4 +- .../SemanticVersionComparable.swift | 33 ++- Sources/Version+Bundle.swift | 4 +- Sources/Version+StringInitializer.swift | 6 +- Sources/Version.swift | 18 +- .../SemanticVersionComparableTests.swift | 49 ++-- Tests/VersionCompareTests/VersionTests.swift | 92 ++++---- .../VersionCompareTests/XCTestManifests.swift | 3 +- 18 files changed, 374 insertions(+), 117 deletions(-) rename .github/workflows/{checks.yml => builds.yml} (90%) create mode 100644 .github/workflows/lint.yml create mode 100644 .mise.toml create mode 100644 .swiftlint.yml diff --git a/.github/workflows/checks.yml b/.github/workflows/builds.yml similarity index 90% rename from .github/workflows/checks.yml rename to .github/workflows/builds.yml index 263c0f6..f8f19c1 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/builds.yml @@ -1,4 +1,4 @@ -name: checks +name: builds on: push: @@ -21,7 +21,6 @@ jobs: - uses: fwal/setup-swift@v1 with: swift-version: ${{ matrix.swift }} - - - run: swift --version + - run: swift build -v - run: swift test -v \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..be570a9 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,17 @@ +name: lint + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: jdx/mise-action@v2 + - run: swiftlint --strict \ No newline at end of file diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 0000000..8326fa6 --- /dev/null +++ b/.mise.toml @@ -0,0 +1,2 @@ +[tools] +swiftlint = "0.54.0" diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..5ec20b8 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,220 @@ +excluded: + - Package.swift + - .swiftpm + - .build + +disabled_rules: + +analyzer_rules: + - capture_variable + #- explicit_self + #- typesafe_array_init + - unused_declaration + - unused_import + +# rules that are commented out are explicitly opted out unless told otherwise +opt_in_rules: + - accessibility_label_for_image + - accessibility_trait_for_button + #- anonymous_argument_in_multiline_closure + #- anyobject_protocol # deprecated + - array_init + - attributes + - balanced_xctest_lifecycle + - closure_end_indentation + - closure_spacing + - collection_alignment + - comma_inheritance + - conditional_returns_on_newline + - contains_over_filter_count + - contains_over_filter_is_empty + - contains_over_first_not_nil + - contains_over_range_nil_comparison + - convenience_type + #- direct_return + - discarded_notification_center_observer + - discouraged_assert + - discouraged_none_name + - discouraged_object_literal + #- discouraged_optional_boolean + #- discouraged_optional_collection + - empty_collection_literal + - empty_count + - empty_string + - empty_xctest_method + - enum_case_associated_values_count + #- explicit_enum_raw_value + - expiring_todo + #- explicit_acl + - explicit_enum_raw_value + - explicit_init + #- explicit_top_level_acl + - explicit_type_interface + - extension_access_modifier + - fallthrough + - fatal_error_message + - file_header + #- file_name + - file_name_no_space + #- file_types_order + - final_test_case # has been added to the source, but has not been released yet + - first_where + - flatmap_over_map_reduce + - force_unwrapping + #- function_default_parameter_at_end + - ibinspectable_in_extension + #- identical_operands + - implicit_return + - implicitly_unwrapped_optional + #- indentation_width # has conflicts with default xcode settings. use strg+i to indent correctly + #- inert_defer # deprecated + - joined_default_parameter + - last_where + #- legacy_multiple + #- legacy_objc_type # not suitable due to third party libs + - let_var_whitespace + - literal_expression_end_indentation + - local_doc_comment + - lower_acl_than_parent + - missing_docs + - modifier_order + - multiline_arguments + - multiline_arguments_brackets + - multiline_function_chains + - multiline_literal_brackets + - multiline_parameters + - multiline_parameters_brackets + #- nimble_operator + #- no_extension_access_modifier + #- no_grouping_extension + - no_magic_numbers + - non_overridable_class_declaration + - notification_center_detachment + #- nslocalizedstring_key + #- nslocalizedstring_require_bundle + - number_separator + #- object_literal + - one_declaration_per_file # has been added to the source, but has not been released yet + - opening_brace + - operator_usage_whitespace + - optional_enum_case_matching + - overridden_super_call + - override_in_extension + - pattern_matching_keywords + #- prefer_nimble + - prefer_self_in_static_references + - prefer_self_type_over_type_of_self + - prefer_zero_over_explicit_init + - prefixed_toplevel_constant + - private_swiftui_state + #- prohibited_interface_builder + #- prohibited_super_call + #- quick_discouraged_call + #- quick_discouraged_focused_test + #- quick_discouraged_pending_test + #- raw_value_for_camel_cased_codable_enum + - reduce_into + - redundant_nil_coalescing + - redundant_self_in_closure + #- redundant_type_annotation + #- required_deinit + #- required_enum_case + - return_value_from_void_function + - self_binding + - shorthand_argument # has been added to the source, but has not been released yet + - shorthand_optional_binding + - single_test_class + #- sorted_enum_cases + - sorted_first_last + #- sorted_imports # see #1295 on github, conflicts with testable, also managed with swiftformat + - static_operator + - strict_fileprivate + #- strong_iboutlet + - superfluous_else + - switch_case_on_newline + - test_case_accessibility + - toggle_bool + - trailing_closure + - type_contents_order + - unavailable_function + - unhandled_throwing_task + - unneeded_parentheses_in_closure_argument + - unowned_variable_capture + - untyped_error_in_catch + #- unused_capture_list # deprecated + #- vertical_parameter_alignment_on_call + #- vertical_whitespace_between_cases + - vertical_whitespace_closing_braces + - vertical_whitespace_opening_braces + - weak_delegate + - xct_specific_matcher + - yoda_condition + +attributes: + always_on_same_line: + - "@IBSegueAction" + - "@IBAction" + - "@NSManaged" + - "@objc" + always_on_line_above: + - "@discardableResult" + +force_cast: error + +force_try: error + +function_body_length: + warning: 150 + +legacy_hashing: error + +identifier_name: + min_length: 2 + max_length: + warning: 60 + error: 80 + excluded: + - id + +multiline_arguments: + first_argument_location: any_line + only_enforce_after_first_closure_on_first_line: true + +number_separator: + minimum_length: 5 + +overridden_super_call: + excluded: + - setUp() + - setUpWithError() + - tearDown() + - tearDownWithError() + +private_over_fileprivate: + validate_extensions: true + +trailing_whitespace: + ignores_empty_lines: true + ignores_comments: true + +type_name: + min_length: 3 + max_length: + warning: 70 + error: 80 + allowed_symbols: + - "_" + +trailing_closure: + only_single_muted_parameter: true + +cyclomatic_complexity: + ignores_case_statements: true + +function_parameter_count: + warning: 6 + error: 8 + +type_body_length: + warning: 300 + error: 400 \ No newline at end of file diff --git a/Sources/Helper/String+Regex.swift b/Sources/Helper/String+Regex.swift index fcfc3c1..dc6dee9 100644 --- a/Sources/Helper/String+Regex.swift +++ b/Sources/Helper/String+Regex.swift @@ -6,6 +6,14 @@ // internal extension String { + var isAlphaNumericString: Bool { + matches("^[a-zA-Z0-9-]+$") + } + + var isNumericString: Bool { + matches("[0-9]+$") + } + func matches(_ regex: String) -> Bool { range(of: regex, options: .regularExpression, range: nil, locale: nil) != nil } @@ -15,12 +23,4 @@ internal extension String { matches("^([0-9a-zA-Z]+)\\.([0-9a-zA-Z]+)$") || matches("^([0-9a-zA-Z]+)$") } - - var isAlphaNumericString: Bool { - matches("^[a-zA-Z0-9-]+$") - } - - var isNumericString: Bool { - matches("[0-9]+$") - } } diff --git a/Sources/SemanticVersionComparable/BuildMetaData/BuildMetaData+ExpressibleByLiteral.swift b/Sources/SemanticVersionComparable/BuildMetaData/BuildMetaData+ExpressibleByLiteral.swift index 9e8940f..4f25714 100644 --- a/Sources/SemanticVersionComparable/BuildMetaData/BuildMetaData+ExpressibleByLiteral.swift +++ b/Sources/SemanticVersionComparable/BuildMetaData/BuildMetaData+ExpressibleByLiteral.swift @@ -6,11 +6,11 @@ // extension BuildMetaData: LosslessStringConvertible { + public var description: String { value } + public init?(_ string: String) { self.init(private: string) } - - public var description: String { value } } extension BuildMetaData: ExpressibleByStringLiteral { diff --git a/Sources/SemanticVersionComparable/BuildMetaData/BuildMetaData.swift b/Sources/SemanticVersionComparable/BuildMetaData/BuildMetaData.swift index db15e3f..a18616a 100644 --- a/Sources/SemanticVersionComparable/BuildMetaData/BuildMetaData.swift +++ b/Sources/SemanticVersionComparable/BuildMetaData/BuildMetaData.swift @@ -21,7 +21,7 @@ public enum BuildMetaData: Comparable { case unknown init(private string: String) { - if let _ = Int(string) { + if Int(string) != nil { self = .digits(string) } else if string.isAlphaNumericString { self = .alphaNumeric(string) diff --git a/Sources/SemanticVersionComparable/PrereleaseIdentifier/PrereleaseIdentifier+Equatable.swift b/Sources/SemanticVersionComparable/PrereleaseIdentifier/PrereleaseIdentifier+Equatable.swift index 4bdd073..c458fe6 100644 --- a/Sources/SemanticVersionComparable/PrereleaseIdentifier/PrereleaseIdentifier+Equatable.swift +++ b/Sources/SemanticVersionComparable/PrereleaseIdentifier/PrereleaseIdentifier+Equatable.swift @@ -5,11 +5,11 @@ // Created by Marius Felkner on 12.03.21. // -extension PrereleaseIdentifier { +public extension PrereleaseIdentifier { /// Compares pre-release identifiers for equality. /// /// - Returns: `true` if pre-release identifiers are equal. - public static func == (lhs: Self, rhs: Self) -> Bool { + static func == (lhs: Self, rhs: Self) -> Bool { lhs.value == rhs.value } } diff --git a/Sources/SemanticVersionComparable/PrereleaseIdentifier/PrereleaseIdentifier+ExpressibleByLiteral.swift b/Sources/SemanticVersionComparable/PrereleaseIdentifier/PrereleaseIdentifier+ExpressibleByLiteral.swift index 2963f82..200bd4b 100644 --- a/Sources/SemanticVersionComparable/PrereleaseIdentifier/PrereleaseIdentifier+ExpressibleByLiteral.swift +++ b/Sources/SemanticVersionComparable/PrereleaseIdentifier/PrereleaseIdentifier+ExpressibleByLiteral.swift @@ -6,11 +6,11 @@ // extension PrereleaseIdentifier: LosslessStringConvertible { + public var description: String { value } + public init?(_ string: String) { self.init(private: string) } - - public var description: String { value } } extension PrereleaseIdentifier: ExpressibleByStringLiteral { diff --git a/Sources/SemanticVersionComparable/SemanticVersionComparable+Comparable.swift b/Sources/SemanticVersionComparable/SemanticVersionComparable+Comparable.swift index 7d23f1e..e7809a3 100644 --- a/Sources/SemanticVersionComparable/SemanticVersionComparable+Comparable.swift +++ b/Sources/SemanticVersionComparable/SemanticVersionComparable+Comparable.swift @@ -14,22 +14,22 @@ public extension SemanticVersionComparable { guard lhs.hasEqualVersionCore(as: rhs) else { // cast UInt to Int for each identifier to compare ordering lexicographically. missing // identifier for minor or patch versions (e. g. "1" or "2.0") are handled as zeros. - let lhsAsIntSequence = [Int(lhs.major), Int(lhs.minor ?? 0), Int(lhs.patch ?? 0)] - let rhsAsIntSequence = [Int(rhs.major), Int(rhs.minor ?? 0), Int(rhs.patch ?? 0)] + let lhsAsIntSequence: [Int] = [Int(lhs.major), Int(lhs.minor ?? 0), Int(lhs.patch ?? 0)] + let rhsAsIntSequence: [Int] = [Int(rhs.major), Int(rhs.minor ?? 0), Int(rhs.patch ?? 0)] return lhsAsIntSequence.lexicographicallyPrecedes(rhsAsIntSequence) } // non-pre-release lhs version is always >= than rhs version guard let lhspr = lhs.prerelease, - lhspr.count > 0 else { + !lhspr.isEmpty else { return false } // same goes for rhs vise versa guard let rhspr = rhs.prerelease, - rhspr.count > 0 else { + !rhspr.isEmpty else { return true } diff --git a/Sources/SemanticVersionComparable/SemanticVersionComparable+Hashable.swift b/Sources/SemanticVersionComparable/SemanticVersionComparable+Hashable.swift index caaca8b..17e9979 100644 --- a/Sources/SemanticVersionComparable/SemanticVersionComparable+Hashable.swift +++ b/Sources/SemanticVersionComparable/SemanticVersionComparable+Hashable.swift @@ -5,12 +5,12 @@ // Created by Marius Felkner on 13.03.21. // -extension SemanticVersionComparable { +public extension SemanticVersionComparable { /// Conformance to `Hashable` protocol. /// /// - Note: Since build-meta-data are not considered in ranking semantic version, it won't be considered /// here either. - public func hash(into hasher: inout Hasher) { + func hash(into hasher: inout Hasher) { hasher.combine(major) hasher.combine(minor) hasher.combine(patch) diff --git a/Sources/SemanticVersionComparable/SemanticVersionComparable.swift b/Sources/SemanticVersionComparable/SemanticVersionComparable.swift index e0a5a03..29eee7b 100644 --- a/Sources/SemanticVersionComparable/SemanticVersionComparable.swift +++ b/Sources/SemanticVersionComparable/SemanticVersionComparable.swift @@ -56,12 +56,13 @@ public extension SemanticVersionComparable { /// Lhs must be a lower version to return a valid result. Otherwise `.noUpdate` will be /// returned regardless of the difference between the two version objects. /// - /// - Parameter version: A version object that conforms to the `SemanticVersionComparable` protocol that will be compared. + /// - Parameter version: A version object that conforms to the `SemanticVersionComparable` protocol that will be + /// compared. /// /// - Returns: A `VersionCompareResult` as the severity of the update. func compare(with version: Self) -> VersionCompareResult { - let lhs = self - let rhs = version + let lhs: Self = self + let rhs: Self = version guard !lhs.hasEqualVersionCore(as: rhs) else { if lhs < rhs { @@ -75,21 +76,19 @@ public extension SemanticVersionComparable { return .noUpdate } - if - lhs.major == rhs.major, - lhs.minor == rhs.minor, - lhs.patch ?? 0 < rhs.patch ?? 0 { + if lhs.major == rhs.major, lhs.minor == rhs.minor, lhs.patch ?? 0 < rhs.patch ?? 0 { return .patch - } else if - lhs.major == rhs.major, - lhs.minor ?? 0 < rhs.minor ?? 0 { + } + + if lhs.major == rhs.major, lhs.minor ?? 0 < rhs.minor ?? 0 { return .minor - } else if - lhs.major < rhs.major { + } + + if lhs.major < rhs.major { return .major - } else { - return .noUpdate } + + return .noUpdate } /// Check if a version has an equal version core as another version. @@ -100,8 +99,8 @@ public extension SemanticVersionComparable { /// /// - Note: A version core is defined as the `MAJOR.MINOR.PATCH` part of a semantic version. func hasEqualVersionCore(as version: Self) -> Bool { - let lhsAsIntSequence = [Int(major), Int(minor ?? 0), Int(patch ?? 0)] - let rhsAsIntSequence = [Int(version.major), Int(version.minor ?? 0), Int(version.patch ?? 0)] + let lhsAsIntSequence: [Int] = [Int(major), Int(minor ?? 0), Int(patch ?? 0)] + let rhsAsIntSequence: [Int] = [Int(version.major), Int(version.minor ?? 0), Int(version.patch ?? 0)] return lhsAsIntSequence.elementsEqual(rhsAsIntSequence) } } @@ -112,7 +111,7 @@ public extension SemanticVersionComparable { /// The absolute string of the version containing the core version, pre-release identifier and build-meta-data /// formatted as `MAJOR.MINOR.PATCH-PRERELEASE+BUILD`. var absoluteString: String { - var versionString = coreString + var versionString: String = coreString if let pr = prereleaseIdentifierString { versionString = [versionString, pr].joined(separator: "-") } diff --git a/Sources/Version+Bundle.swift b/Sources/Version+Bundle.swift index 6edc9e4..b498ab4 100644 --- a/Sources/Version+Bundle.swift +++ b/Sources/Version+Bundle.swift @@ -12,7 +12,9 @@ public extension Bundle { /// /// - Note: Uses the key `CFBundleShortVersionString` for retrieving version values. var shortVersion: Version? { - guard let versionString: String = infoDictionary?["CFBundleShortVersionString"] as? String else { return nil } + guard let versionString: String = infoDictionary?["CFBundleShortVersionString"] as? String else { + return nil + } let version: Version? = Version(versionString) return version diff --git a/Sources/Version+StringInitializer.swift b/Sources/Version+StringInitializer.swift index 0b2daeb..6e8ca99 100644 --- a/Sources/Version+StringInitializer.swift +++ b/Sources/Version+StringInitializer.swift @@ -6,6 +6,8 @@ // extension Version: LosslessStringConvertible { + public var description: String { absoluteString } + /// Creates a new version from a string. /// /// - Parameter string: A string beeing parsed into a version. @@ -14,8 +16,6 @@ extension Version: LosslessStringConvertible { public init?(_ string: String) { self.init(private: string) } - - public var description: String { absoluteString } } extension Version: ExpressibleByStringLiteral { @@ -23,6 +23,7 @@ extension Version: ExpressibleByStringLiteral { /// /// - Warning: Usage is not recommended unless the given string conforms to `SemVer`. public init(stringLiteral value: StringLiteralType) { + // swiftlint:disable:next force_unwrapping self.init(private: value)! } } @@ -32,6 +33,7 @@ extension Version: ExpressibleByStringInterpolation { /// /// - Warning: Usage is not recommended unless the given string conforms to `SemVer`. public init(stringInterpolation: DefaultStringInterpolation) { + // swiftlint:disable:next force_unwrapping compiler_protocol_init self.init(private: String(stringInterpolation: stringInterpolation))! } } diff --git a/Sources/Version.swift b/Sources/Version.swift index 9b8803f..04286fb 100644 --- a/Sources/Version.swift +++ b/Sources/Version.swift @@ -101,18 +101,19 @@ public struct Version: SemanticVersionComparable { /// - Parameter string: The string representing a version. public init?(private string: String) { // split string into version with pre-release identifier and build-meta-data substrings - let versionSplitBuild = string.split(separator: "+", omittingEmptySubsequences: false) + let versionSplitBuild: [String.SubSequence] = string.split(separator: "+", omittingEmptySubsequences: false) // check if string does not contain only build-meta-data e.g. "+123" or falsely "+123+something" + let maxNumberOfSplits: Int = 2 guard !versionSplitBuild.isEmpty, - versionSplitBuild.count <= 2, + versionSplitBuild.count <= maxNumberOfSplits, let versionPrereleaseString = versionSplitBuild.first else { return nil } // split previously splitted substring into version and pre-release identifier substrings - var versionSplitPrerelease = versionPrereleaseString + var versionSplitPrerelease: [Substring.SubSequence] = versionPrereleaseString .split(separator: "-", omittingEmptySubsequences: false) // check for non-empty or invalid version string e.g. "-alpha" @@ -125,7 +126,7 @@ public struct Version: SemanticVersionComparable { // check that the version string has the correct SemVer format which are 0 and positive numbers in the form // of `x`, `x.x`or `x.x.x`. - let versionString = String(versionStringElement) + let versionString: String = String(versionStringElement) guard versionString.matchesSemVerFormat() else { return nil } @@ -154,21 +155,22 @@ public struct Version: SemanticVersionComparable { // map valid identifiers to corresponding version identifier self.major = safeIdentifiers[0] self.minor = safeIdentifiers.indices.contains(1) ? safeIdentifiers[1] : nil + // swiftlint:disable:next no_magic_numbers self.patch = safeIdentifiers.indices.contains(2) ? safeIdentifiers[2] : nil // extract pre-release identifier if available if versionSplitPrerelease.indices.contains(1) { versionSplitPrerelease.removeFirst(1) - let prereleaseSubstring = versionSplitPrerelease.joined(separator: "-") + let prereleaseSubstring: String = versionSplitPrerelease.joined(separator: "-") self.prerelease = String(prereleaseSubstring) .split(separator: ".") .map(String.init) .compactMap { if let asInt = Int($0) { - return PrereleaseIdentifier.init(integerLiteral: asInt) + return PrereleaseIdentifier(integerLiteral: asInt) } - return PrereleaseIdentifier.init($0) + return PrereleaseIdentifier($0) } // if a pre-release identifier element is initialized as .unkown, we can savely assume that the given // string is not a valid `SemVer` version string. @@ -190,7 +192,7 @@ public struct Version: SemanticVersionComparable { .split(separator: ".") .map(String.init) .compactMap { - BuildMetaData.init($0) + BuildMetaData($0) } // finding an .unkown element means that the given string is not conform to `SemVer` since it is no // alphaNumeric or a digit diff --git a/Tests/VersionCompareTests/SemanticVersionComparableTests.swift b/Tests/VersionCompareTests/SemanticVersionComparableTests.swift index a80dbdc..0aed96a 100644 --- a/Tests/VersionCompareTests/SemanticVersionComparableTests.swift +++ b/Tests/VersionCompareTests/SemanticVersionComparableTests.swift @@ -96,10 +96,12 @@ final class SemanticVersionComparableTests: XCTestCase { XCTAssertFalse(lhs < lhs) XCTAssertFalse(rhs < rhs) - // greater XCTAssertTrue(rhs > lhs, "Expected \(lhs.absoluteString) to be greater than \(rhs.absoluteString)!") - XCTAssertTrue(rhs >= lhs, "Expected \(lhs.absoluteString) to be greater than or equal to \(rhs.absoluteString)!") + XCTAssertTrue( + rhs >= lhs, + "Expected \(lhs.absoluteString) to be greater than or equal to \(rhs.absoluteString)!" + ) XCTAssertTrue(rhs >= rhs) XCTAssertTrue(lhs >= lhs) @@ -110,21 +112,21 @@ final class SemanticVersionComparableTests: XCTestCase { } func testCompatibility() { - let versionAA = Version("1.0.0") - let versionAB = Version("1.1.0") - let versionAC = Version("1.1.1") - let versionAD = Version("1.0.1") - let versionAE = Version("1.6238746") - let versionAF = Version("1") - let versionAs = [versionAA, versionAB, versionAC, versionAD, versionAE, versionAF] - - let versionBA = Version("2.0.0") - let versionBB = Version("2.1.0") - let versionBC = Version("2.1.1") - let versionBD = Version("2.0.1") - let versionBE = Version("2.3875") - let versionBF = Version("2") - let versionBs = [versionBA, versionBB, versionBC, versionBD, versionBE, versionBF] + let versionAA: Version = Version("1.0.0") + let versionAB: Version = Version("1.1.0") + let versionAC: Version = Version("1.1.1") + let versionAD: Version = Version("1.0.1") + let versionAE: Version = Version("1.6238746") + let versionAF: Version = Version("1") + let versionAs: [Version] = [versionAA, versionAB, versionAC, versionAD, versionAE, versionAF] + + let versionBA: Version = Version("2.0.0") + let versionBB: Version = Version("2.1.0") + let versionBC: Version = Version("2.1.1") + let versionBD: Version = Version("2.0.1") + let versionBE: Version = Version("2.3875") + let versionBF: Version = Version("2") + let versionBs: [Version] = [versionBA, versionBB, versionBC, versionBD, versionBE, versionBF] // compatible versionAs.forEach { first in @@ -154,6 +156,7 @@ final class SemanticVersionComparableTests: XCTestCase { } func testCompare() { + // swiftlint:disable:next large_tuple let testData: [(Version, Version, VersionCompareResult)] = [ (Version("1"), Version("2"), VersionCompareResult.major), (Version("600.123.4"), Version("601.0.1"), VersionCompareResult.major), @@ -179,10 +182,14 @@ final class SemanticVersionComparableTests: XCTestCase { ] testData.forEach { data in - let versionOne = data.0 - let versionTwo = data.1 - let compareResult = versionOne.compare(with: versionTwo) - XCTAssertTrue(compareResult == data.2, "Expected result from comparing \(data.0.absoluteString) and \(data.1.absoluteString) to be \(data.2) but is \(compareResult)!") + let versionOne: Version = data.0 + let versionTwo: Version = data.1 + let compareResult: VersionCompareResult = versionOne.compare(with: versionTwo) + XCTAssertEqual( + compareResult, + data.2, + "Expected result from comparing to be \(data.2) but is \(compareResult)!" + ) } } } diff --git a/Tests/VersionCompareTests/VersionTests.swift b/Tests/VersionCompareTests/VersionTests.swift index 513041f..e12fdc7 100644 --- a/Tests/VersionCompareTests/VersionTests.swift +++ b/Tests/VersionCompareTests/VersionTests.swift @@ -13,10 +13,11 @@ typealias ExpectedVersionString = String typealias ExpectedExtensionString = String final class VersionTests: XCTestCase { + // swiftlint:disable:next large_tuple private let validVersionData: [(ValidVersionStringLiteral, ExpectedVersionString, ExpectedExtensionString?)] = [ - ("1.0.0", "1.0.0", nil) , + ("1.0.0", "1.0.0", nil), ("1.2.3-alpha.1", "1.2.3", "alpha.1"), - ("1.0", "1.0" , nil), + ("1.0", "1.0", nil), ("1", "1", nil), ("13434", "13434", nil), ("0.123123.0", "0.123123.0", nil), @@ -93,27 +94,37 @@ final class VersionTests: XCTestCase { ] func testValidConstruction() { + // swiftlint:disable force_unwrapping validVersionData.forEach { - let version = Version($0.0) + let version: Version? = Version($0.0) XCTAssertNotNil(version, "Expected object from string `\($0.0)` not to be nil!") - XCTAssertTrue(version!.coreString == $0.1, "Expected versionCode to be \($0.1), is: \(version!.coreString)") + XCTAssertEqual(version!.coreString, $0.1, "Expected versionCode to be \($0.1), is: \(version!.coreString)") XCTAssertEqual(version!.debugDescription, version!.description) if let expectedExtension = $0.2 { - XCTAssertEqual(version!.extensionString, $0.2, "Expected extension to be \(expectedExtension), is: \(version!.extensionString ?? "nil")") + XCTAssertEqual( + version!.extensionString, + $0.2, + "Expected extension to be \(expectedExtension), is: \(version!.extensionString ?? "nil")" + ) } else { XCTAssertNil(version!.extensionString, "Expected extension to be nil!") } } + // swiftlint:enable force_unwrapping // test string literal validVersionData.forEach { // equivalent to `let version: Version = ""` - let version = Version(stringLiteral: $0.0) + let version: Version = Version(stringLiteral: $0.0) XCTAssertNotNil(version, "Expected object from string `\($0.0)` not to be nil!") - XCTAssertTrue(version.coreString == $0.1, "Expected versionCode to be \($0.1), is: \(version.coreString)") + XCTAssertEqual(version.coreString, $0.1, "Expected versionCode to be \($0.1), is: \(version.coreString)") XCTAssertEqual(version.debugDescription, version.description) if let expectedExtension = $0.2 { - XCTAssertEqual(version.extensionString, $0.2, "Expected extension to be \(expectedExtension), is: \(version.extensionString ?? "nil")") + XCTAssertEqual( + version.extensionString, + $0.2, + "Expected extension to be \(expectedExtension), is: \(version.extensionString ?? "nil")" + ) } else { XCTAssertNil(version.extensionString, "Expected extension to be nil!") } @@ -124,10 +135,14 @@ final class VersionTests: XCTestCase { // equivalent to `let version: Version = ""` let version: Version = "\($0.0)" XCTAssertNotNil(version, "Expected object from string `\($0.0)` not to be nil!") - XCTAssertTrue(version.coreString == $0.1, "Expected versionCode to be \($0.1), is: \(version.coreString)") + XCTAssertEqual(version.coreString, $0.1, "Expected versionCode to be \($0.1), is: \(version.coreString)") XCTAssertEqual(version.debugDescription, version.description) if let expectedExtension = $0.2 { - XCTAssertEqual(version.extensionString, $0.2, "Expected extension to be \(expectedExtension), is: \(version.extensionString ?? "nil")") + XCTAssertEqual( + version.extensionString, + $0.2, + "Expected extension to be \(expectedExtension), is: \(version.extensionString ?? "nil")" + ) } else { XCTAssertNil(version.extensionString, "Expected extension to be nil!") } @@ -135,27 +150,41 @@ final class VersionTests: XCTestCase { } func testMemberwiseConstruction() { - let versionA = Version(major: 1, minor: 2, patch: 3, prerelease: [.alpha]) + let versionA: Version = Version(major: 1, minor: 2, patch: 3, prerelease: [.alpha]) XCTAssertEqual(versionA.absoluteString, "1.2.3-alpha", "Expected version to be `1.2.3-alpha`, is: \(versionA)!") - let versionB = Version(major: 125) + let versionB: Version = Version(major: 125) XCTAssertEqual(versionB, "125.0.0") - let versionC = Version( + let versionC: Version = Version( major: 1, minor: 2, patch: 3, prerelease: [.alpha, "release"], - build: [.alphaNumeric("exp"), .digits("300"), "test"]) - XCTAssertEqual(versionC.absoluteString, "1.2.3-alpha.release+exp.300.test", "Expected version to be `1.2.3-alpha.release+exp.300.test`, is: \(versionC)!") + build: [ + .alphaNumeric("exp"), + .digits("300"), + "test" + ] + ) + XCTAssertEqual( + versionC.absoluteString, + "1.2.3-alpha.release+exp.300.test", + "Expected version to be `1.2.3-alpha.release+exp.300.test`, is: \(versionC)!" + ) - let versionD = Version( + let versionD: Version = Version( major: 1, minor: 2, patch: 3, prerelease: [.alphaNumeric("alpha"), .numeric(1), .beta, .releaseCandidate, .prerelease], - build: [.alphaNumeric("exp"), .digits("300"), "test"]) - XCTAssertEqual(versionD.absoluteString, "1.2.3-alpha.1.beta.rc.prerelease+exp.300.test", "Expected version to be `1.2.3-alpha.release+exp.300.test`, is: \(versionD)!") + build: [.alphaNumeric("exp"), .digits("300"), "test"] + ) + XCTAssertEqual( + versionD.absoluteString, + "1.2.3-alpha.1.beta.rc.prerelease+exp.300.test", + "Expected version to be `1.2.3-alpha.release+exp.300.test`, is: \(versionD)!" + ) } func testInvalidConstruction() { @@ -164,31 +193,6 @@ final class VersionTests: XCTestCase { } } - // FIXME: Since the pipeline will use `swift test` resulting in different bundles that were previously - // expected here this test will always fail. A new way to access a .plist file during a test - // which contains the required keys is necessary to pass the test. It is not a critcal functionality - // using a direct first party API therefor this test is disabled unless fixed. -// func testInvalidBundleVersion() { -// // the main bundle from test targets is different from actual app targets and will be invalid for use, -// // but not for testing -// XCTAssertNil(Bundle.main.shortVersion) -// XCTAssertNil(Bundle.main.version) -// } - -// func testValidBundleVersion() { -// let testBundle = Bundle(for: type(of: self)) -// let shortVersionString = testBundle.infoDictionary?["CFBundleShortVersionString"] as? String -// let buildString = testBundle.infoDictionary?["CFBundleVersion"] as? String -// let shortVersion: Version? = testBundle.shortVersion -// let version: Version? = testBundle.version -// -// XCTAssertNotNil(shortVersion) -// XCTAssertEqual(shortVersionString!, shortVersion!.absoluteString, "Expected \(shortVersion!) to be equal to \(shortVersionString!)!") -// -// XCTAssertNotNil(version) -// XCTAssertEqual("\(shortVersionString!)+\(buildString!)", version!.absoluteString, "Expected \(version!) to be equal to \(buildString!)!") -// } - func testProcessInfoVersion() { let processInfoOsVersion: OperatingSystemVersion = ProcessInfo.processInfo.operatingSystemVersion let comparableOsVersion: Version = ProcessInfo.processInfo.comparableOperatingSystemVersion @@ -201,11 +205,13 @@ final class VersionTests: XCTestCase { XCTAssertEqual( UInt(processInfoOsVersion.minorVersion), comparableOsVersion.minor, + // swiftlint:disable:next force_unwrapping "Expected \(processInfoOsVersion.minorVersion) to be equal to \(comparableOsVersion.minor!)!" ) XCTAssertEqual( UInt(processInfoOsVersion.patchVersion), comparableOsVersion.patch, + // swiftlint:disable:next force_unwrapping "Expected \(processInfoOsVersion.patchVersion) to be equal to \(comparableOsVersion.patch!)!" ) } diff --git a/Tests/VersionCompareTests/XCTestManifests.swift b/Tests/VersionCompareTests/XCTestManifests.swift index 8dbb720..48675b3 100644 --- a/Tests/VersionCompareTests/XCTestManifests.swift +++ b/Tests/VersionCompareTests/XCTestManifests.swift @@ -1,7 +1,8 @@ import XCTest #if !canImport(ObjectiveC) +// swiftlint:disable:next missing_docs public func allTests() -> [XCTestCaseEntry] { - return [] + [] } #endif