@@ -26,17 +26,27 @@ extension sourcekitd_api_keys: @unchecked Sendable {}
2626extension sourcekitd_api_requests : @unchecked Sendable { }
2727extension sourcekitd_api_values : @unchecked Sendable { }
2828
29+ public struct SourceKitDTestHooks : Sendable {
30+ public var sourcekitdRequestDidStart : ( @Sendable ( SKDRequestDictionary ) -> Void ) ?
31+
32+ public init ( sourcekitdRequestDidStart: ( @Sendable ( SKDRequestDictionary ) -> Void ) ? = nil ) {
33+ self . sourcekitdRequestDidStart = sourcekitdRequestDidStart
34+ }
35+ }
36+
2937/// Wrapper for sourcekitd, taking care of initialization, shutdown, and notification handler
3038/// multiplexing.
3139///
3240/// Users of this class should not call the api functions `initialize`, `shutdown`, or
3341/// `set_notification_handler`, which are global state managed internally by this class.
3442public actor DynamicallyLoadedSourceKitD : SourceKitD {
3543 /// The path to the sourcekitd dylib.
36- public let path : AbsolutePath
44+ private let path : AbsolutePath
3745
3846 /// The handle to the dylib.
39- let dylib : DLHandle
47+ private let dylib : DLHandle
48+
49+ public let testHooks : SourceKitDTestHooks
4050
4151 /// The sourcekitd API functions.
4252 public let api : sourcekitd_api_functions_t
@@ -55,18 +65,23 @@ public actor DynamicallyLoadedSourceKitD: SourceKitD {
5565 /// List of notification handlers that will be called for each notification.
5666 private var notificationHandlers : [ WeakSKDNotificationHandler ] = [ ]
5767
58- public static func getOrCreate( dylibPath: AbsolutePath ) async throws -> SourceKitD {
68+ /// If there is already a `sourcekitd` instance from the given return it, otherwise create a new one.
69+ ///
70+ /// `testHooks` are only considered when an instance is being created. If a sourcekitd instance at the given path
71+ /// already exists, its test hooks will be used.
72+ public static func getOrCreate( dylibPath: AbsolutePath , testHooks: SourceKitDTestHooks ) async throws -> SourceKitD {
5973 try await SourceKitDRegistry . shared
60- . getOrAdd ( dylibPath, create: { try DynamicallyLoadedSourceKitD ( dylib: dylibPath) } )
74+ . getOrAdd ( dylibPath, create: { try DynamicallyLoadedSourceKitD ( dylib: dylibPath, testHooks : testHooks ) } )
6175 }
6276
63- init ( dylib path: AbsolutePath ) throws {
77+ init ( dylib path: AbsolutePath , testHooks : SourceKitDTestHooks ) throws {
6478 self . path = path
6579 #if os(Windows)
6680 self . dylib = try dlopen ( path. pathString, mode: [ ] )
6781 #else
6882 self . dylib = try dlopen ( path. pathString, mode: [ . lazy, . local, . first] )
6983 #endif
84+ self . testHooks = testHooks
7085 self . api = try sourcekitd_api_functions_t ( self . dylib)
7186 self . keys = sourcekitd_api_keys ( api: self . api)
7287 self . requests = sourcekitd_api_requests ( api: self . api)
0 commit comments