From 45be280989a3a9d2f8197ff5378017f0a3664eec Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Mon, 3 Mar 2025 11:55:30 -0800 Subject: [PATCH 1/2] Make `SKDRequestDictionaryReader` conform to `CustomStringConvertible` --- .../SKDRequestDictionaryReader.swift | 22 ++++++++++++++++++- .../SwiftSourceKitPlugin/SKDResponse.swift | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Sources/SwiftSourceKitPlugin/SKDRequestDictionaryReader.swift b/Sources/SwiftSourceKitPlugin/SKDRequestDictionaryReader.swift index ab7f91b44..1a9d2f508 100644 --- a/Sources/SwiftSourceKitPlugin/SKDRequestDictionaryReader.swift +++ b/Sources/SwiftSourceKitPlugin/SKDRequestDictionaryReader.swift @@ -13,14 +13,34 @@ import Csourcekitd import SourceKitD +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif canImport(CRT) +import CRT +#elseif canImport(Bionic) +import Bionic +#endif + /// Provide getters to get values of a sourcekitd request dictionary. /// /// This is not part of the `SourceKitD` module because it uses `SourceKitD.servicePluginAPI` which must not be accessed /// outside of the service plugin. -final class SKDRequestDictionaryReader: Sendable { +final class SKDRequestDictionaryReader: Sendable, CustomStringConvertible { private nonisolated(unsafe) let dict: sourcekitd_api_object_t let sourcekitd: SourceKitD + var description: String { + guard let description = sourcekitd.api.request_description_copy(dict) else { + return "getting request description failed" + } + defer { free(description) } + return String(cString: description) + } + /// Creates an `SKDRequestDictionary` that essentially provides a view into the given opaque /// `sourcekitd_api_object_t`. init?(_ request: sourcekitd_api_object_t, sourcekitd: SourceKitD) { diff --git a/Sources/SwiftSourceKitPlugin/SKDResponse.swift b/Sources/SwiftSourceKitPlugin/SKDResponse.swift index 6acd8d860..d549e2642 100644 --- a/Sources/SwiftSourceKitPlugin/SKDResponse.swift +++ b/Sources/SwiftSourceKitPlugin/SKDResponse.swift @@ -74,7 +74,7 @@ final class SKDResponse: CustomStringConvertible, Sendable { } public var description: String { - let cstr = sourcekitd.api.request_description_copy(value)! + let cstr = sourcekitd.api.response_description_copy(value)! defer { free(cstr) } return String(cString: cstr) } From 12b38fe1ea13f5319ba8eb04166502200b35342e Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Mon, 3 Mar 2025 12:05:38 -0800 Subject: [PATCH 2/2] Add logging for requests handled by the SourceKit plugin --- Package.swift | 1 + Sources/SKLogging/LoggingScope.swift | 4 +++ Sources/SwiftSourceKitPlugin/Plugin.swift | 31 +++++++++++++++---- .../SourceKitDWrappers.swift | 4 +++ .../SwiftSourceKitPluginTests.swift | 1 - 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Package.swift b/Package.swift index 7909805f1..fc4558474 100644 --- a/Package.swift +++ b/Package.swift @@ -334,6 +334,7 @@ var targets: [Target] = [ swiftSettings: globalSwiftSettings + lspLoggingSwiftSettings + [ // We can't depend on swift-crypto in the plugin because we can't module-alias it due to https://github.com/swiftlang/swift-package-manager/issues/8119 .define("NO_CRYPTO_DEPENDENCY"), + .define("SKLOGGING_FOR_PLUGIN"), .unsafeFlags([ "-module-alias", "SwiftExtensions=SwiftExtensionsForPlugin", ]), diff --git a/Sources/SKLogging/LoggingScope.swift b/Sources/SKLogging/LoggingScope.swift index c056b61ad..bdd747c0a 100644 --- a/Sources/SKLogging/LoggingScope.swift +++ b/Sources/SKLogging/LoggingScope.swift @@ -21,7 +21,11 @@ package final class LoggingScope { /// The name of the current logging subsystem. package static var subsystem: String { + #if SKLOGGING_FOR_PLUGIN + return _subsystem ?? "org.swift.sourcekit-lsp.plugin" + #else return _subsystem ?? "org.swift.sourcekit-lsp" + #endif } /// The name of the current logging scope. diff --git a/Sources/SwiftSourceKitPlugin/Plugin.swift b/Sources/SwiftSourceKitPlugin/Plugin.swift index 7c41cab4b..2887df30e 100644 --- a/Sources/SwiftSourceKitPlugin/Plugin.swift +++ b/Sources/SwiftSourceKitPlugin/Plugin.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import Foundation +import SKLogging import SourceKitD import SwiftExtensions import SwiftSourceKitPluginCommon @@ -62,14 +63,31 @@ final class RequestHandler: Sendable { func produceResult( body: @escaping @Sendable () async throws -> SKDResponseDictionaryBuilder ) -> HandleRequestResult { - requestHandlingQueue.async { - do { - receiver(try await body().response) - } catch { - receiver(SKDResponse.from(error: error, sourcekitd: self.sourcekitd)) + withLoggingScope("request-\(handle?.numericValue ?? 0 % 100)") { + let start = Date() + logger.debug( + """ + Plugin received sourcekitd request (handle: \(handle?.numericValue ?? -1)) + \(dict.description) + """ + ) + requestHandlingQueue.async { + let response: SKDResponse + do { + response = try await body().response + } catch { + response = SKDResponse.from(error: error, sourcekitd: self.sourcekitd) + } + logger.debug( + """ + Finished (took \(Date().timeIntervalSince(start))s) + \(response.description) + """ + ) + receiver(response) } + return .requestHandled } - return .requestHandled } func sourcekitdProducesResult(body: @escaping @Sendable () async -> ()) -> HandleRequestResult { @@ -139,6 +157,7 @@ final class RequestHandler: Sendable { } func cancel(_ handle: RequestHandle) { + logger.debug("Cancelling request with handle \(handle.numericValue)") self.completionProvider.cancel(handle: handle) } } diff --git a/Sources/SwiftSourceKitPlugin/SourceKitDWrappers.swift b/Sources/SwiftSourceKitPlugin/SourceKitDWrappers.swift index 0c2b5c13d..4d6adfc7e 100644 --- a/Sources/SwiftSourceKitPlugin/SourceKitDWrappers.swift +++ b/Sources/SwiftSourceKitPlugin/SourceKitDWrappers.swift @@ -31,4 +31,8 @@ struct RequestHandle: Sendable { } self.handle = handle } + + var numericValue: Int { + Int(bitPattern: handle) + } } diff --git a/Tests/SwiftSourceKitPluginTests/SwiftSourceKitPluginTests.swift b/Tests/SwiftSourceKitPluginTests/SwiftSourceKitPluginTests.swift index dd2cd5b68..9f7e510f1 100644 --- a/Tests/SwiftSourceKitPluginTests/SwiftSourceKitPluginTests.swift +++ b/Tests/SwiftSourceKitPluginTests/SwiftSourceKitPluginTests.swift @@ -272,7 +272,6 @@ final class SwiftSourceKitPluginTests: XCTestCase { } func testCancellation() async throws { - try XCTSkipIf(true, "rdar://145905708") try await SkipUnless.sourcekitdSupportsPlugin() let sourcekitd = try await getSourceKitD() let path = scratchFilePath()