From f9f13a41058758ba6e7d29520307fec4abeeccc8 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Thu, 20 Nov 2025 09:47:21 +0100 Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20use=20`Optional.map`=20or=20`Op?= =?UTF-8?q?tional.flatMap`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace usages of `Optional.map` and `Optional.flatMap` by if expressions or other expressions. I personally find `Optional.map` to be hard to read because `map` implies mapping a collection to me. Usually the alternative constructs seem clearer to me. --- .../SwiftPMBuildServer.swift | 28 ++++++++++++++----- Sources/Diagnose/ReduceCommand.swift | 7 ++++- Sources/Diagnose/ReduceFrontendCommand.swift | 7 ++++- .../UpdateIndexStoreTaskDescription.swift | 17 +++++++++-- .../SourceKitD/SKDResponseDictionary.swift | 5 +++- Sources/SwiftLanguageService/Diagnostic.swift | 9 ++++-- .../SwiftLanguageService/SemanticTokens.swift | 4 +-- .../SwiftLanguageService.swift | 8 +++++- .../SwiftTestingScanner.swift | 7 ++++- .../SyntaxHighlightingTokenParser.swift | 9 ++++-- .../SKDRequestDictionaryReader.swift | 8 ++++-- .../BackgroundIndexingTests.swift | 2 +- .../SwiftInterfaceTests.swift | 12 +++----- 13 files changed, 90 insertions(+), 33 deletions(-) diff --git a/Sources/BuildServerIntegration/SwiftPMBuildServer.swift b/Sources/BuildServerIntegration/SwiftPMBuildServer.swift index bc3f10270..18096b67e 100644 --- a/Sources/BuildServerIntegration/SwiftPMBuildServer.swift +++ b/Sources/BuildServerIntegration/SwiftPMBuildServer.swift @@ -215,19 +215,29 @@ package actor SwiftPMBuildServer: BuiltInBuildServer { let hostSDK = try SwiftSDK.hostSwiftSDK(AbsolutePath(validating: destinationToolchainBinDir.filePath)) let hostSwiftPMToolchain = try UserToolchain(swiftSDK: hostSDK) + let triple: Triple? = + if let triple = options.swiftPMOrDefault.triple { + try Triple(triple) + } else { + nil + } + let swiftSDKsDirectory: AbsolutePath? = + if let swiftSDKsDirectory = options.swiftPMOrDefault.swiftSDKsDirectory { + try AbsolutePath(validating: swiftSDKsDirectory, relativeTo: absProjectRoot) + } else { + nil + } let destinationSDK = try SwiftSDK.deriveTargetSwiftSDK( hostSwiftSDK: hostSDK, hostTriple: hostSwiftPMToolchain.targetTriple, customToolsets: options.swiftPMOrDefault.toolsets?.map { try AbsolutePath(validating: $0, relativeTo: absProjectRoot) } ?? [], - customCompileTriple: options.swiftPMOrDefault.triple.map { try Triple($0) }, + customCompileTriple: triple, swiftSDKSelector: options.swiftPMOrDefault.swiftSDK, store: SwiftSDKBundleStore( swiftSDKsDirectory: localFileSystem.getSharedSwiftSDKsDirectory( - explicitDirectory: options.swiftPMOrDefault.swiftSDKsDirectory.map { - try AbsolutePath(validating: $0, relativeTo: absProjectRoot) - } + explicitDirectory: swiftSDKsDirectory ), hostToolchainBinDir: hostSwiftPMToolchain.swiftCompilerPath.parentDirectory, fileSystem: localFileSystem, @@ -320,9 +330,13 @@ package actor SwiftPMBuildServer: BuiltInBuildServer { disableSandbox: options.swiftPMOrDefault.disableSandbox ?? false ) - self.traitConfiguration = TraitConfiguration( - enabledTraits: options.swiftPMOrDefault.traits.flatMap(Set.init) - ) + let enabledTraits: Set? = + if let traits = options.swiftPMOrDefault.traits { + Set(traits) + } else { + nil + } + self.traitConfiguration = TraitConfiguration(enabledTraits: enabledTraits) packageLoadingQueue.async { await orLog("Initial package loading") { diff --git a/Sources/Diagnose/ReduceCommand.swift b/Sources/Diagnose/ReduceCommand.swift index 0f1c14ab2..291b232b4 100644 --- a/Sources/Diagnose/ReduceCommand.swift +++ b/Sources/Diagnose/ReduceCommand.swift @@ -50,7 +50,12 @@ package struct ReduceCommand: AsyncParsableCommand { ) var predicate: String? - private var nsPredicate: NSPredicate? { predicate.map { NSPredicate(format: $0) } } + private var nsPredicate: NSPredicate? { + guard let predicate else { + return nil + } + return NSPredicate(format: predicate) + } #else private var nsPredicate: NSPredicate? { nil } #endif diff --git a/Sources/Diagnose/ReduceFrontendCommand.swift b/Sources/Diagnose/ReduceFrontendCommand.swift index a779237f7..8c642ddd9 100644 --- a/Sources/Diagnose/ReduceFrontendCommand.swift +++ b/Sources/Diagnose/ReduceFrontendCommand.swift @@ -40,7 +40,12 @@ package struct ReduceFrontendCommand: AsyncParsableCommand { ) var predicate: String? - private var nsPredicate: NSPredicate? { predicate.map { NSPredicate(format: $0) } } + private var nsPredicate: NSPredicate? { + guard let predicate else { + return nil + } + return NSPredicate(format: predicate) + } #else private var nsPredicate: NSPredicate? { nil } #endif diff --git a/Sources/SemanticIndex/UpdateIndexStoreTaskDescription.swift b/Sources/SemanticIndex/UpdateIndexStoreTaskDescription.swift index af170b2fb..de05c035c 100644 --- a/Sources/SemanticIndex/UpdateIndexStoreTaskDescription.swift +++ b/Sources/SemanticIndex/UpdateIndexStoreTaskDescription.swift @@ -521,7 +521,7 @@ package struct UpdateIndexStoreTaskDescription: IndexTaskDescription { indexFiles: indexFiles, buildSettings: buildSettings, processArguments: args, - workingDirectory: buildSettings.workingDirectory.map(AbsolutePath.init(validating:)) + workingDirectory: buildSettings.workingDirectoryPath ) case .singleFile(let file, let buildSettings): // We only end up in this case if the file's build settings didn't contain `-index-unit-output-path` and the build @@ -532,7 +532,7 @@ package struct UpdateIndexStoreTaskDescription: IndexTaskDescription { indexFiles: [file.mainFile], buildSettings: buildSettings, processArguments: args, - workingDirectory: buildSettings.workingDirectory.map(AbsolutePath.init(validating:)) + workingDirectory: buildSettings.workingDirectoryPath ) } } @@ -556,7 +556,7 @@ package struct UpdateIndexStoreTaskDescription: IndexTaskDescription { indexFiles: [uri], buildSettings: buildSettings, processArguments: args, - workingDirectory: buildSettings.workingDirectory.map(AbsolutePath.init(validating:)) + workingDirectory: buildSettings.workingDirectoryPath ) } @@ -780,3 +780,14 @@ fileprivate extension Process { } } } + +fileprivate extension FileBuildSettings { + var workingDirectoryPath: AbsolutePath? { + get throws { + guard let workingDirectory else { + return nil + } + return try AbsolutePath(validating: workingDirectory) + } + } +} diff --git a/Sources/SourceKitD/SKDResponseDictionary.swift b/Sources/SourceKitD/SKDResponseDictionary.swift index cbb248c3e..f8dc57d06 100644 --- a/Sources/SourceKitD/SKDResponseDictionary.swift +++ b/Sources/SourceKitD/SKDResponseDictionary.swift @@ -36,7 +36,10 @@ package final class SKDResponseDictionary: Sendable { } package subscript(key: sourcekitd_api_uid_t) -> String? { - return sourcekitd.api.variant_dictionary_get_string(dict, key).map(String.init(cString:)) + guard let cString = sourcekitd.api.variant_dictionary_get_string(dict, key) else { + return nil + } + return String(cString: cString) } package subscript(key: sourcekitd_api_uid_t) -> Int? { diff --git a/Sources/SwiftLanguageService/Diagnostic.swift b/Sources/SwiftLanguageService/Diagnostic.swift index e69028b5b..5d9553683 100644 --- a/Sources/SwiftLanguageService/Diagnostic.swift +++ b/Sources/SwiftLanguageService/Diagnostic.swift @@ -442,8 +442,13 @@ extension DiagnosticStage { case sourcekitd.values.semaDiagStage: self = .sema default: - let desc = sourcekitd.api.uid_get_string_ptr(uid).map { String(cString: $0) } - logger.fault("Unknown diagnostic stage \(desc ?? "nil", privacy: .public)") + let uidDescription = + if let cString = sourcekitd.api.uid_get_string_ptr(uid) { + String(cString: cString) + } else { + "" + } + logger.fault("Unknown diagnostic stage \(uidDescription, privacy: .public)") return nil } } diff --git a/Sources/SwiftLanguageService/SemanticTokens.swift b/Sources/SwiftLanguageService/SemanticTokens.swift index b9fe22a2d..fed733ee4 100644 --- a/Sources/SwiftLanguageService/SemanticTokens.swift +++ b/Sources/SwiftLanguageService/SemanticTokens.swift @@ -62,8 +62,8 @@ extension SwiftLanguageService { let semanticTokens = await orLog("Loading semantic tokens") { try await semanticHighlightingTokens(for: snapshot) } let range = - if let range = range.flatMap({ snapshot.byteSourceRange(of: $0) }) { - range + if let range { + snapshot.byteSourceRange(of: range) } else { await tree.range } diff --git a/Sources/SwiftLanguageService/SwiftLanguageService.swift b/Sources/SwiftLanguageService/SwiftLanguageService.swift index 5e647d20f..85ba16c67 100644 --- a/Sources/SwiftLanguageService/SwiftLanguageService.swift +++ b/Sources/SwiftLanguageService/SwiftLanguageService.swift @@ -651,11 +651,17 @@ extension SwiftLanguageService { // Check that the document wasn't modified while we were getting diagnostics. This could happen because we are // calling `publishDiagnosticsIfNeeded` outside of `messageHandlingQueue` and thus a concurrent edit is // possible while we are waiting for the sourcekitd request to return a result. + let latestVersionString = + if let version = latestSnapshotID?.version { + String(version) + } else { + "" + } logger.log( """ Document was modified while loading diagnostics. \ Loaded diagnostics for \(snapshot.id.version, privacy: .public), \ - latest snapshot is \((latestSnapshotID?.version).map(String.init) ?? "", privacy: .public) + latest snapshot is \(latestVersionString, privacy: .public) """ ) throw CancellationError() diff --git a/Sources/SwiftLanguageService/SwiftTestingScanner.swift b/Sources/SwiftLanguageService/SwiftTestingScanner.swift index 93717cfb5..1d96613ab 100644 --- a/Sources/SwiftLanguageService/SwiftTestingScanner.swift +++ b/Sources/SwiftLanguageService/SwiftTestingScanner.swift @@ -232,7 +232,12 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor { let suiteAttribute = node.attributes .compactMap { $0.as(AttributeSyntax.self) } .first { $0.isNamed("Suite", inModuleNamed: "Testing") } - let attributeData = suiteAttribute.map(TestingAttributeData.init(attribute:)) + let attributeData: TestingAttributeData? = + if let suiteAttribute { + TestingAttributeData(attribute: suiteAttribute) + } else { + nil + } if attributeData?.isHidden ?? false { return .skipChildren diff --git a/Sources/SwiftLanguageService/SyntaxHighlightingTokenParser.swift b/Sources/SwiftLanguageService/SyntaxHighlightingTokenParser.swift index b221cb7fd..eae1a8aba 100644 --- a/Sources/SwiftLanguageService/SyntaxHighlightingTokenParser.swift +++ b/Sources/SwiftLanguageService/SyntaxHighlightingTokenParser.swift @@ -203,8 +203,13 @@ struct SyntaxHighlightingTokenParser { values.stringInterpolation ] if !ignoredKinds.contains(uid) { - let name = api.uid_get_string_ptr(uid).map(String.init(cString:)) - logger.error("Unknown token kind: \(name ?? "?", privacy: .public)") + let name = + if let cString = api.uid_get_string_ptr(uid) { + String(cString: cString) + } else { + "" + } + logger.error("Unknown token kind: \(name, privacy: .public)") } return nil } diff --git a/Sources/SwiftSourceKitPlugin/SKDRequestDictionaryReader.swift b/Sources/SwiftSourceKitPlugin/SKDRequestDictionaryReader.swift index 1a9d2f508..395177dd4 100644 --- a/Sources/SwiftSourceKitPlugin/SKDRequestDictionaryReader.swift +++ b/Sources/SwiftSourceKitPlugin/SKDRequestDictionaryReader.swift @@ -73,9 +73,11 @@ final class SKDRequestDictionaryReader: Sendable, CustomStringConvertible { } subscript(key: sourcekitd_api_uid_t) -> String? { - return sourcekitd.servicePluginApi.request_dictionary_get_string(sourcekitd_api_object_t(dict), key).map( - String.init(cString:) - ) + guard let cString = sourcekitd.servicePluginApi.request_dictionary_get_string(sourcekitd_api_object_t(dict), key) + else { + return nil + } + return String(cString: cString) } subscript(key: sourcekitd_api_uid_t) -> Int64? { diff --git a/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift b/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift index f6c871c38..d8adcbf20 100644 --- a/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift +++ b/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift @@ -957,7 +957,7 @@ final class BackgroundIndexingTests: SourceKitLSPTestCase { let result = try await project.testClient.send( RenameRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"], newName: "height") ) - XCTAssertEqual((result?.changes?.keys).map(Set.init), [uri, try project.uri(for: "Client.swift")]) + XCTAssertEqual(Set(try XCTUnwrap(result?.changes?.keys)), [uri, try project.uri(for: "Client.swift")]) } func testDontPreparePackageManifest() async throws { diff --git a/Tests/SourceKitLSPTests/SwiftInterfaceTests.swift b/Tests/SourceKitLSPTests/SwiftInterfaceTests.swift index 0484a83ba..c2cd89f93 100644 --- a/Tests/SourceKitLSPTests/SwiftInterfaceTests.swift +++ b/Tests/SourceKitLSPTests/SwiftInterfaceTests.swift @@ -34,7 +34,7 @@ final class SwiftInterfaceTests: SourceKitLSPTestCase { ) let location = try XCTUnwrap(resp?.locations?.only) XCTAssertTrue(location.uri.pseudoPath.hasSuffix("Foundation.swiftinterface")) - let fileContents = try XCTUnwrap(location.uri.fileURL.flatMap({ try String(contentsOf: $0, encoding: .utf8) })) + let fileContents = try XCTUnwrap(String(contentsOf: try XCTUnwrap(location.uri.fileURL), encoding: .utf8)) // Smoke test that the generated Swift Interface contains Swift code XCTAssert( fileContents.hasPrefix("import "), @@ -173,7 +173,7 @@ final class SwiftInterfaceTests: SourceKitLSPTestCase { ) let location = try XCTUnwrap(response?.locations?.only) XCTAssertTrue(location.uri.pseudoPath.hasSuffix("MyLibrary.swiftinterface")) - let fileContents = try XCTUnwrap(location.uri.fileURL.flatMap({ try String(contentsOf: $0, encoding: .utf8) })) + let fileContents = try XCTUnwrap(String(contentsOf: try XCTUnwrap(location.uri.fileURL), encoding: .utf8)) XCTAssertTrue( fileContents.contains( """ @@ -420,13 +420,9 @@ private func assertSystemSwiftInterface( ) ) let location = try XCTUnwrap(definition?.locations?.only) - XCTAssert( - (location.uri.fileURL?.lastPathComponent).map(swiftInterfaceFiles.contains) ?? false, - "Path '\(location.uri.pseudoPath)' did not match any of \(String(reflecting: swiftInterfaceFiles))", - line: line - ) + assertContains(swiftInterfaceFiles, try XCTUnwrap(location.uri.fileURL?.lastPathComponent), line: line) // load contents of swiftinterface - let contents = try XCTUnwrap(location.uri.fileURL.flatMap({ try String(contentsOf: $0, encoding: .utf8) })) + let contents = try XCTUnwrap(String(contentsOf: try XCTUnwrap(location.uri.fileURL), encoding: .utf8)) let lineTable = LineTable(contents) let destinationLine = try XCTUnwrap(lineTable.line(at: location.range.lowerBound.line)) .trimmingCharacters(in: .whitespaces)