From 8a586918147184802fe4a13ccc93ed04ecc5f5ab Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 4 Jun 2024 15:55:59 +0100 Subject: [PATCH 1/3] Fix new SwiftLint warnings non_optional_string_data_conversion and static_over_final_class --- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- ElementX/Sources/Other/Extensions/Dictionary.swift | 2 +- ElementX/Sources/Other/UserAgentBuilder.swift | 6 +++--- .../RoomScreen/RoomScreenInteractionHandler.swift | 2 +- .../Sources/Services/BugReport/BugReportService.swift | 4 ++-- .../Sources/Services/Timeline/TimelineItemProxy.swift | 2 +- ElementX/Sources/UITests/UITestsAppCoordinator.swift | 4 ++-- ElementX/Sources/UITests/UITestsSignalling.swift | 9 +++------ UnitTests/Sources/AppLock/AppLockServiceTests.swift | 10 +++++----- UnitTests/Sources/KeychainControllerTests.swift | 8 ++++---- UnitTests/Sources/LoggingTests.swift | 2 +- 11 files changed, 25 insertions(+), 28 deletions(-) diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index c8e3a48173..c73084897b 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -3,7 +3,7 @@ { "identity" : "compound-design-tokens", "kind" : "remoteSourceControl", - "location" : "https://github.com/element-hq/compound-design-tokens.git", + "location" : "https://github.com/element-hq/compound-design-tokens", "state" : { "revision" : "c3fff1f2b042295cd5f4bcf8d4fe68ec47ca4061", "version" : "1.2.0" @@ -191,7 +191,7 @@ { "identity" : "sfsafesymbols", "kind" : "remoteSourceControl", - "location" : "https://github.com/SFSafeSymbols/SFSafeSymbols.git", + "location" : "https://github.com/SFSafeSymbols/SFSafeSymbols", "state" : { "revision" : "7cca2d60925876b5953a2cf7341cd80fbeac983c", "version" : "4.1.1" diff --git a/ElementX/Sources/Other/Extensions/Dictionary.swift b/ElementX/Sources/Other/Extensions/Dictionary.swift index 4793c64636..b26a585c50 100644 --- a/ElementX/Sources/Other/Extensions/Dictionary.swift +++ b/ElementX/Sources/Other/Extensions/Dictionary.swift @@ -22,7 +22,7 @@ extension Dictionary { options: [.fragmentsAllowed, .sortedKeys]) else { return nil } - return String(data: data, encoding: .utf8) + return String(decoding: data, as: UTF8.self) } /// Returns a dictionary containing the original values keyed by the results of mapping the given closure over its keys. diff --git a/ElementX/Sources/Other/UserAgentBuilder.swift b/ElementX/Sources/Other/UserAgentBuilder.swift index 637206fe4b..09c56f30c2 100644 --- a/ElementX/Sources/Other/UserAgentBuilder.swift +++ b/ElementX/Sources/Other/UserAgentBuilder.swift @@ -21,12 +21,12 @@ import UIKit import DeviceKit #endif -final class UserAgentBuilder { - class func makeASCIIUserAgent() -> String { +enum UserAgentBuilder { + static func makeASCIIUserAgent() -> String { makeUserAgent()?.asciified() ?? "unknown" } - private class func makeUserAgent() -> String? { + static func makeUserAgent() -> String? { let clientName = InfoPlistReader.app.bundleDisplayName let clientVersion = InfoPlistReader.app.bundleShortVersionString diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift index 2c11217c87..c957c952cc 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenInteractionHandler.swift @@ -502,7 +502,7 @@ class RoomScreenInteractionHandler { } guard let audioPlayerState = audioPlayerState(for: itemID) else { - fatalError("Audio player not found for \(itemID)") + fatalError("Audio player state not found for \(itemID)") } // Ensure this one is attached diff --git a/ElementX/Sources/Services/BugReport/BugReportService.swift b/ElementX/Sources/Services/BugReport/BugReportService.swift index 09cae3a9b7..252b084581 100644 --- a/ElementX/Sources/Services/BugReport/BugReportService.swift +++ b/ElementX/Sources/Services/BugReport/BugReportService.swift @@ -175,14 +175,14 @@ class BugReportService: NSObject, BugReportServiceProtocol { let (data, response) = try await session.dataWithRetry(for: request, delegate: self) guard let httpResponse = response as? HTTPURLResponse else { - let errorDescription = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "Unknown" + let errorDescription = String(decoding: data, as: UTF8.self).trimmingCharacters(in: .whitespacesAndNewlines) MXLog.error("Failed to submit bug report: \(errorDescription)") MXLog.error("Response: \(response)") return .failure(.serverError(response, errorDescription)) } guard httpResponse.statusCode == 200 else { - let errorDescription = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "Unknown" + let errorDescription = String(decoding: data, as: UTF8.self).trimmingCharacters(in: .whitespacesAndNewlines) MXLog.error("Failed to submit bug report: \(errorDescription) (\(httpResponse.statusCode))") MXLog.error("Response: \(httpResponse)") return .failure(.httpError(httpResponse, errorDescription)) diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 371030fdf4..1b3d06711c 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -162,7 +162,7 @@ struct TimelineItemDebugInfo: Identifiable, CustomStringConvertible { return nil } - return String(data: jsonData, encoding: .utf8) + return String(decoding: jsonData, as: UTF8.self) } } diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index cfe7b31ec0..9397ecff1c 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -160,7 +160,7 @@ class MockScreen: Identifiable { let context = LAContextMock() context.biometryTypeValue = UIDevice.current.isPhone ? .faceID : .touchID // (iPhone 14 & iPad 9th gen) context.evaluatePolicyReturnValue = true - context.evaluatedPolicyDomainStateValue = "😎".data(using: .utf8) + context.evaluatedPolicyDomainStateValue = Data("😎".utf8) let appLockService = AppLockService(keychainController: keychainController, appSettings: ServiceLocator.shared.settings, @@ -215,7 +215,7 @@ class MockScreen: Identifiable { let context = LAContextMock() context.biometryTypeValue = UIDevice.current.isPhone ? .faceID : .touchID // (iPhone 14 & iPad 9th gen) context.evaluatePolicyReturnValue = true - context.evaluatedPolicyDomainStateValue = "😎".data(using: .utf8) + context.evaluatedPolicyDomainStateValue = Data("😎".utf8) let appLockService = AppLockService(keychainController: keychainController, appSettings: ServiceLocator.shared.settings, diff --git a/ElementX/Sources/UITests/UITestsSignalling.swift b/ElementX/Sources/UITests/UITestsSignalling.swift index ebe2e0dc7e..7775c8767a 100644 --- a/ElementX/Sources/UITests/UITestsSignalling.swift +++ b/ElementX/Sources/UITests/UITestsSignalling.swift @@ -146,11 +146,8 @@ enum UITestsSignalling { let encoder = JSONEncoder() encoder.outputFormatting = .sortedKeys - guard let data = try? encoder.encode(self), - let string = String(data: data, encoding: .utf8) else { - return "unknown" - } - return string + guard let data = try? encoder.encode(self) else { return "unknown" } + return String(decoding: data, as: UTF8.self) } init?(rawValue: String) { @@ -175,7 +172,7 @@ enum UITestsSignalling { /// Processes string data from the file and publishes its signal. private func processFileData(_ data: Data) { - guard let rawMessage = String(data: data, encoding: .utf8) else { return } + let rawMessage = String(decoding: data, as: UTF8.self) guard let message = Message(rawValue: rawMessage), message.mode != mode // Filter out messages sent by this client. diff --git a/UnitTests/Sources/AppLock/AppLockServiceTests.swift b/UnitTests/Sources/AppLock/AppLockServiceTests.swift index 7048bdcac6..2084aad3d8 100644 --- a/UnitTests/Sources/AppLock/AppLockServiceTests.swift +++ b/UnitTests/Sources/AppLock/AppLockServiceTests.swift @@ -185,7 +185,7 @@ class AppLockServiceTests: XCTestCase { // Given a service with the PIN code already set. let context = LAContextMock() context.biometryTypeValue = .touchID - context.evaluatedPolicyDomainStateValue = "👆".data(using: .utf8) + context.evaluatedPolicyDomainStateValue = Data("👆".utf8) service = AppLockService(keychainController: keychainController, appSettings: appSettings, context: context) guard case .success = service.setupPINCode("2023") else { XCTFail("The PIN should be valid.") @@ -217,7 +217,7 @@ class AppLockServiceTests: XCTestCase { // Given a service with the PIN code already set. let context = LAContextMock() context.biometryTypeValue = .touchID - context.evaluatedPolicyDomainStateValue = "👆".data(using: .utf8) + context.evaluatedPolicyDomainStateValue = Data("👆".utf8) service = AppLockService(keychainController: keychainController, appSettings: appSettings, context: context) let pinCode = "2023" guard case .success = service.setupPINCode(pinCode) else { @@ -234,7 +234,7 @@ class AppLockServiceTests: XCTestCase { XCTAssertTrue(service.biometricUnlockTrusted, "Biometric unlock should be trusted.") // When the user changes biometric data. - context.evaluatedPolicyDomainStateValue = "👈".data(using: .utf8) + context.evaluatedPolicyDomainStateValue = Data("👈".utf8) // Then biometric lock should remain enabled but untrusted. XCTAssertTrue(service.isEnabled, "The service should remain enabled.") @@ -256,7 +256,7 @@ class AppLockServiceTests: XCTestCase { // Given a service with the PIN code already set. let context = LAContextMock() context.biometryTypeValue = .touchID - context.evaluatedPolicyDomainStateValue = "👆".data(using: .utf8) + context.evaluatedPolicyDomainStateValue = Data("👆".utf8) service = AppLockService(keychainController: keychainController, appSettings: appSettings, context: context) guard case .success = service.setupPINCode("2023") else { XCTFail("The PIN should be valid.") @@ -285,7 +285,7 @@ class AppLockServiceTests: XCTestCase { // Given a service with the PIN code already set. let context = LAContextMock() context.biometryTypeValue = .touchID - context.evaluatedPolicyDomainStateValue = "👆".data(using: .utf8) + context.evaluatedPolicyDomainStateValue = Data("👆".utf8) service = AppLockService(keychainController: keychainController, appSettings: appSettings, context: context) guard case .success = service.setupPINCode("2023") else { XCTFail("The PIN should be valid.") diff --git a/UnitTests/Sources/KeychainControllerTests.swift b/UnitTests/Sources/KeychainControllerTests.swift index c5b4d34a84..c008579cf7 100644 --- a/UnitTests/Sources/KeychainControllerTests.swift +++ b/UnitTests/Sources/KeychainControllerTests.swift @@ -170,7 +170,7 @@ class KeychainControllerTests: XCTestCase { XCTAssertNil(keychain.pinCodeBiometricState(), "A new keychain shouldn't return biometric state.") // When setting the state. - let data: Data! = "Face ID".data(using: .utf8) + let data = Data("Face ID".utf8) try keychain.setPINCodeBiometricState(data) // Then the state should be stored. @@ -180,13 +180,13 @@ class KeychainControllerTests: XCTestCase { func testUpdatePINCodeBiometricState() throws { // Given a keychain that contains PIN code biometric state. - let data: Data! = "😃".data(using: .utf8) + let data = Data("😃".utf8) try keychain.setPINCodeBiometricState(data) XCTAssertTrue(keychain.containsPINCodeBiometricState(), "The keychain should contain the biometric state.") XCTAssertEqual(keychain.pinCodeBiometricState(), data, "The stored biometric state should match what was set.") // When setting different state. - let newData: Data! = "😎".data(using: .utf8) + let newData = Data("😎".utf8) try keychain.setPINCodeBiometricState(newData) // Then the state should be updated. @@ -197,7 +197,7 @@ class KeychainControllerTests: XCTestCase { func testRemovePINCodeBiometricState() throws { // Given a keychain that contains PIN code biometric state. - let data: Data! = "Face ID".data(using: .utf8) + let data = Data("Face ID".utf8) try keychain.setPINCodeBiometricState(data) XCTAssertTrue(keychain.containsPINCodeBiometricState(), "The keychain should contain the biometric state.") XCTAssertEqual(keychain.pinCodeBiometricState(), data, "The stored biometric state should match what was set.") diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index e479c565c2..b7571d8956 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -294,7 +294,7 @@ class LoggingTests: XCTestCase { let currentLogFile = logsFileDirectory.appending(path: "console.1.log") let fileHandle = try FileHandle(forWritingTo: currentLogFile) try fileHandle.seekToEnd() - guard let newLineData = "newline".data(using: .utf8) else { + guard let newLineData = Data("newline".utf8) else { XCTFail("Couldn't create data to write to disk.") return } From bbc772a398ab48023eecb1956caa3a9188887001 Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 4 Jun 2024 15:59:28 +0100 Subject: [PATCH 2/3] Revert Data -> String changes for upcoming rule change. This reverts part of 8a586918147184802fe4a13ccc93ed04ecc5f5ab. --- ElementX/Sources/Other/Extensions/Dictionary.swift | 2 +- .../Sources/Services/BugReport/BugReportService.swift | 4 ++-- .../Sources/Services/Timeline/TimelineItemProxy.swift | 2 +- ElementX/Sources/UITests/UITestsSignalling.swift | 9 ++++++--- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ElementX/Sources/Other/Extensions/Dictionary.swift b/ElementX/Sources/Other/Extensions/Dictionary.swift index b26a585c50..4793c64636 100644 --- a/ElementX/Sources/Other/Extensions/Dictionary.swift +++ b/ElementX/Sources/Other/Extensions/Dictionary.swift @@ -22,7 +22,7 @@ extension Dictionary { options: [.fragmentsAllowed, .sortedKeys]) else { return nil } - return String(decoding: data, as: UTF8.self) + return String(data: data, encoding: .utf8) } /// Returns a dictionary containing the original values keyed by the results of mapping the given closure over its keys. diff --git a/ElementX/Sources/Services/BugReport/BugReportService.swift b/ElementX/Sources/Services/BugReport/BugReportService.swift index 252b084581..09cae3a9b7 100644 --- a/ElementX/Sources/Services/BugReport/BugReportService.swift +++ b/ElementX/Sources/Services/BugReport/BugReportService.swift @@ -175,14 +175,14 @@ class BugReportService: NSObject, BugReportServiceProtocol { let (data, response) = try await session.dataWithRetry(for: request, delegate: self) guard let httpResponse = response as? HTTPURLResponse else { - let errorDescription = String(decoding: data, as: UTF8.self).trimmingCharacters(in: .whitespacesAndNewlines) + let errorDescription = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "Unknown" MXLog.error("Failed to submit bug report: \(errorDescription)") MXLog.error("Response: \(response)") return .failure(.serverError(response, errorDescription)) } guard httpResponse.statusCode == 200 else { - let errorDescription = String(decoding: data, as: UTF8.self).trimmingCharacters(in: .whitespacesAndNewlines) + let errorDescription = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "Unknown" MXLog.error("Failed to submit bug report: \(errorDescription) (\(httpResponse.statusCode))") MXLog.error("Response: \(httpResponse)") return .failure(.httpError(httpResponse, errorDescription)) diff --git a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift index 1b3d06711c..371030fdf4 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItemProxy.swift @@ -162,7 +162,7 @@ struct TimelineItemDebugInfo: Identifiable, CustomStringConvertible { return nil } - return String(decoding: jsonData, as: UTF8.self) + return String(data: jsonData, encoding: .utf8) } } diff --git a/ElementX/Sources/UITests/UITestsSignalling.swift b/ElementX/Sources/UITests/UITestsSignalling.swift index 7775c8767a..ebe2e0dc7e 100644 --- a/ElementX/Sources/UITests/UITestsSignalling.swift +++ b/ElementX/Sources/UITests/UITestsSignalling.swift @@ -146,8 +146,11 @@ enum UITestsSignalling { let encoder = JSONEncoder() encoder.outputFormatting = .sortedKeys - guard let data = try? encoder.encode(self) else { return "unknown" } - return String(decoding: data, as: UTF8.self) + guard let data = try? encoder.encode(self), + let string = String(data: data, encoding: .utf8) else { + return "unknown" + } + return string } init?(rawValue: String) { @@ -172,7 +175,7 @@ enum UITestsSignalling { /// Processes string data from the file and publishes its signal. private func processFileData(_ data: Data) { - let rawMessage = String(decoding: data, as: UTF8.self) + guard let rawMessage = String(data: data, encoding: .utf8) else { return } guard let message = Message(rawValue: rawMessage), message.mode != mode // Filter out messages sent by this client. From 3422dda6516dfa9c64b33cc5b3025ee7d0e631e0 Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 4 Jun 2024 16:58:34 +0100 Subject: [PATCH 3/3] Fix compile error. --- UnitTests/Sources/LoggingTests.swift | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index b7571d8956..31f1a0ccdc 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -294,12 +294,7 @@ class LoggingTests: XCTestCase { let currentLogFile = logsFileDirectory.appending(path: "console.1.log") let fileHandle = try FileHandle(forWritingTo: currentLogFile) try fileHandle.seekToEnd() - guard let newLineData = Data("newline".utf8) else { - XCTFail("Couldn't create data to write to disk.") - return - } - - try fileHandle.write(contentsOf: newLineData) + try fileHandle.write(contentsOf: Data("newline".utf8)) try fileHandle.close() // Then that file should now be the first log file.