@@ -193,52 +193,56 @@ package actor SourceKitD {
193
193
let dlopenModes : DLOpenFlags = [ . lazy, . local, . first]
194
194
#endif
195
195
let dlhandle = try dlopen ( path. filePath, mode: dlopenModes)
196
- do {
197
- try self . init (
198
- dlhandle: dlhandle,
199
- path: path,
200
- pluginPaths: pluginPaths,
201
- initialize: initialize
202
- )
203
- } catch {
204
- try ? dlhandle. close ( )
205
- throw error
206
- }
196
+ try self . init (
197
+ dlhandle: dlhandle,
198
+ path: path,
199
+ pluginPaths: pluginPaths,
200
+ initialize: initialize
201
+ )
207
202
}
208
203
204
+ /// Create a `SourceKitD` instance from an existing `DLHandle`. `SourceKitD` takes over ownership of the `DLHandler`
205
+ /// and will close it when the `SourceKitD` instance gets deinitialized or if the initializer throws.
209
206
package init ( dlhandle: DLHandle , path: URL , pluginPaths: PluginPaths ? , initialize: Bool ) throws {
210
- self . path = path
211
- self . dylib = dlhandle
212
- let api = try sourcekitd_api_functions_t ( dlhandle)
213
- self . api = api
214
-
215
- // We load the plugin-related functions eagerly so the members are initialized and we don't have data races on first
216
- // access to eg. `pluginApi`. But if one of the functions is missing, we will only emit that error when that family
217
- // of functions is being used. For example, it is expected that the plugin functions are not available in
218
- // SourceKit-LSP.
219
- self . ideApiResult = Result ( catching: { try sourcekitd_ide_api_functions_t ( dlhandle) } )
220
- self . pluginApiResult = Result ( catching: { try sourcekitd_plugin_api_functions_t ( dlhandle) } )
221
- self . servicePluginApiResult = Result ( catching: { try sourcekitd_service_plugin_api_functions_t ( dlhandle) } )
222
-
223
- if let pluginPaths {
224
- api. register_plugin_path ? ( pluginPaths. clientPlugin. path, pluginPaths. servicePlugin. path)
225
- }
226
- if initialize {
227
- self . api. initialize ( )
228
- }
207
+ do {
208
+ self . path = path
209
+ self . dylib = dlhandle
210
+ let api = try sourcekitd_api_functions_t ( dlhandle)
211
+ self . api = api
212
+
213
+ // We load the plugin-related functions eagerly so the members are initialized and we don't have data races on first
214
+ // access to eg. `pluginApi`. But if one of the functions is missing, we will only emit that error when that family
215
+ // of functions is being used. For example, it is expected that the plugin functions are not available in
216
+ // SourceKit-LSP.
217
+ self . ideApiResult = Result ( catching: { try sourcekitd_ide_api_functions_t ( dlhandle) } )
218
+ self . pluginApiResult = Result ( catching: { try sourcekitd_plugin_api_functions_t ( dlhandle) } )
219
+ self . servicePluginApiResult = Result ( catching: { try sourcekitd_service_plugin_api_functions_t ( dlhandle) } )
229
220
230
- if initialize {
231
- self . api. set_notification_handler { [ weak self] rawResponse in
232
- guard let self, let rawResponse else { return }
233
- let response = SKDResponse ( rawResponse, sourcekitd: self )
234
- self . notificationHandlingQueue. async {
235
- let handlers = await self . notificationHandlers. compactMap ( \. value)
221
+ if let pluginPaths {
222
+ api. register_plugin_path ? ( pluginPaths. clientPlugin. path, pluginPaths. servicePlugin. path)
223
+ }
224
+ if initialize {
225
+ self . api. initialize ( )
226
+ }
227
+
228
+ if initialize {
229
+ self . api. set_notification_handler { [ weak self] rawResponse in
230
+ guard let self, let rawResponse else { return }
231
+ let response = SKDResponse ( rawResponse, sourcekitd: self )
232
+ self . notificationHandlingQueue. async {
233
+ let handlers = await self . notificationHandlers. compactMap ( \. value)
236
234
237
- for handler in handlers {
238
- handler. notification ( response)
235
+ for handler in handlers {
236
+ handler. notification ( response)
237
+ }
239
238
}
240
239
}
241
240
}
241
+ } catch {
242
+ orLog ( " Closing dlhandle after opening sourcekitd failed " ) {
243
+ try ? dlhandle. close ( )
244
+ }
245
+ throw error
242
246
}
243
247
}
244
248
0 commit comments