Skip to content

Commit 1c3e5bb

Browse files
committed
Communicate the path of sourcekitd that the plugin was loaded from to the plugin
1 parent b78c91c commit 1c3e5bb

File tree

7 files changed

+116
-72
lines changed

7 files changed

+116
-72
lines changed

Sources/SourceKitD/DynamicallyLoadedSourceKitD.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,18 @@ package actor DynamicallyLoadedSourceKitD: SourceKitD {
111111
)
112112
}
113113

114-
private init(dylib path: URL, pluginPaths: PluginPaths?) throws {
114+
package init(dylib path: URL, pluginPaths: PluginPaths?, initialize: Bool = true) throws {
115115
#if os(Windows)
116116
let dlopenModes: DLOpenFlags = []
117117
#else
118118
let dlopenModes: DLOpenFlags = [.lazy, .local, .first]
119119
#endif
120-
let dlhandle = try dlopen(path.filePath, mode: [])
120+
let dlhandle = try dlopen(path.filePath, mode: dlopenModes)
121121
try self.init(
122122
dlhandle: dlhandle,
123123
path: path,
124124
pluginPaths: pluginPaths,
125-
initialize: true
125+
initialize: initialize
126126
)
127127
}
128128

Sources/SourceKitD/dlopen.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ package final class DLHandle: Sendable {
3434
#endif
3535
}
3636

37-
#if !os(Windows)
38-
package static let rtldDefault = DLHandle(rawValue: Handle(handle: UnsafeMutableRawPointer(bitPattern: -2)!))
39-
#endif
40-
4137
fileprivate let rawValue: ThreadSafeBox<Handle?>
4238

4339
fileprivate init(rawValue: Handle) {

Sources/SwiftSourceKitClientPlugin/ClientPlugin.swift

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import Foundation
1314
import SourceKitD
15+
import SwiftExtensionsForPlugin
1416
import SwiftSourceKitPluginCommon
1517

1618
#if compiler(>=6)
@@ -19,12 +21,46 @@ public import Csourcekitd
1921
import Csourcekitd
2022
#endif
2123

24+
/// Legacy plugin initialization logic in which sourcekitd does not inform the plugin about the sourcekitd path it was
25+
/// loaded from.
2226
@_cdecl("sourcekitd_plugin_initialize")
2327
public func sourcekitd_plugin_initialize(_ params: sourcekitd_api_plugin_initialize_params_t) {
24-
let skd = DynamicallyLoadedSourceKitD.relativeToPlugin
25-
let customBufferStart = skd.pluginApi.plugin_initialize_custom_buffer_start(params)
28+
#if canImport(Darwin)
29+
var dlInfo = Dl_info()
30+
dladdr(#dsohandle, &dlInfo)
31+
let path = String(cString: dlInfo.dli_fname)
32+
var url = URL(fileURLWithPath: path, isDirectory: false)
33+
while url.pathExtension != "framework" && url.lastPathComponent != "/" {
34+
url.deleteLastPathComponent()
35+
}
36+
url =
37+
url
38+
.deletingLastPathComponent()
39+
.appendingPathComponent("sourcekitd.framework")
40+
.appendingPathComponent("sourcekitd")
41+
try! url.filePath.withCString { sourcekitdPath in
42+
sourcekitd_plugin_initialize_2(params, sourcekitdPath)
43+
}
44+
#else
45+
fatalError("sourcekitd_plugin_initialize is not supported on non-Darwin platforms")
46+
#endif
47+
}
48+
49+
@_cdecl("sourcekitd_plugin_initialize_2")
50+
public func sourcekitd_plugin_initialize_2(
51+
_ params: sourcekitd_api_plugin_initialize_params_t,
52+
_ sourcekitdPath: UnsafePointer<CChar>
53+
) {
54+
DynamicallyLoadedSourceKitD.forPlugin = try! DynamicallyLoadedSourceKitD(
55+
dylib: URL(fileURLWithPath: String(cString: sourcekitdPath)),
56+
pluginPaths: nil,
57+
initialize: false
58+
)
59+
let sourcekitd = DynamicallyLoadedSourceKitD.forPlugin
60+
61+
let customBufferStart = sourcekitd.pluginApi.plugin_initialize_custom_buffer_start(params)
2662
let arrayBuffKind = customBufferStart
27-
skd.pluginApi.plugin_initialize_register_custom_buffer(
63+
sourcekitd.pluginApi.plugin_initialize_register_custom_buffer(
2864
params,
2965
arrayBuffKind,
3066
CompletionResultsArray.arrayFuncs.rawValue

Sources/SwiftSourceKitPlugin/Plugin.swift

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,42 @@ final class RequestHandler: Sendable {
143143
}
144144
}
145145

146+
/// Legacy plugin initialization logic in which sourcekitd does not inform the plugin about the sourcekitd path it was
147+
/// loaded from.
146148
@_cdecl("sourcekitd_plugin_initialize")
147149
public func sourcekitd_plugin_initialize(_ params: sourcekitd_api_plugin_initialize_params_t) {
148-
let sourcekitd = DynamicallyLoadedSourceKitD.relativeToPlugin
150+
#if canImport(Darwin)
151+
var dlInfo = Dl_info()
152+
dladdr(#dsohandle, &dlInfo)
153+
let path = String(cString: dlInfo.dli_fname)
154+
var url = URL(fileURLWithPath: path, isDirectory: false)
155+
while url.pathExtension != "framework" && url.lastPathComponent != "/" {
156+
url.deleteLastPathComponent()
157+
}
158+
url =
159+
url
160+
.deletingLastPathComponent()
161+
.appendingPathComponent("sourcekitd.framework")
162+
.appendingPathComponent("sourcekitd")
163+
try! url.filePath.withCString { sourcekitdPath in
164+
sourcekitd_plugin_initialize_2(params, sourcekitdPath)
165+
}
166+
#else
167+
fatalError("sourcekitd_plugin_initialize is not supported on non-Darwin platforms")
168+
#endif
169+
}
170+
171+
@_cdecl("sourcekitd_plugin_initialize_2")
172+
public func sourcekitd_plugin_initialize_2(
173+
_ params: sourcekitd_api_plugin_initialize_params_t,
174+
_ sourcekitdPath: UnsafePointer<CChar>
175+
) {
176+
DynamicallyLoadedSourceKitD.forPlugin = try! DynamicallyLoadedSourceKitD(
177+
dylib: URL(fileURLWithPath: String(cString: parentLibraryPath)),
178+
pluginPaths: nil,
179+
initialize: false
180+
)
181+
let sourcekitd = DynamicallyLoadedSourceKitD.forPlugin
149182

150183
let completionResultsBufferKind = sourcekitd.pluginApi.plugin_initialize_custom_buffer_start(params)
151184
let isClientOnly = sourcekitd.pluginApi.plugin_initialize_is_client_only(params)

Sources/SwiftSourceKitPluginCommon/CompletionResultsArray.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ package struct CompletionResultsArray {
126126
}
127127

128128
package static let arrayFuncs: VariantFunctions = {
129-
let sourcekitd = DynamicallyLoadedSourceKitD.relativeToPlugin
129+
let sourcekitd = DynamicallyLoadedSourceKitD.forPlugin
130130
let funcs = sourcekitd.pluginApi.variant_functions_create()!
131131
sourcekitd.pluginApi.variant_functions_set_get_type(funcs, { _ in SOURCEKITD_API_VARIANT_TYPE_ARRAY })
132132
sourcekitd.pluginApi.variant_functions_set_array_get_count(funcs, { arrayGetCount($0) })
@@ -156,7 +156,7 @@ package struct CompletionResultsArray {
156156
}
157157
}
158158

159-
let sourcekitd = DynamicallyLoadedSourceKitD.relativeToPlugin
159+
let sourcekitd = DynamicallyLoadedSourceKitD.forPlugin
160160
let keys = sourcekitd.keys
161161

162162
let results = CompletionResultsArray(dict)
@@ -199,7 +199,7 @@ package struct CompletionResultsArray {
199199
}
200200

201201
static let dictionaryFuncs: VariantFunctions = {
202-
let sourcekitd = DynamicallyLoadedSourceKitD.relativeToPlugin
202+
let sourcekitd = DynamicallyLoadedSourceKitD.forPlugin
203203
let funcs = sourcekitd.pluginApi.variant_functions_create()!
204204
sourcekitd.pluginApi.variant_functions_set_get_type(funcs, { _ in SOURCEKITD_API_VARIANT_TYPE_DICTIONARY })
205205
sourcekitd.pluginApi.variant_functions_set_dictionary_apply(funcs, { dictionaryApply($0, $1, $2) })

Sources/SwiftSourceKitPluginCommon/DynamicallyLoadedSourceKitD+relativeToPlugin.swift

Lines changed: 0 additions & 58 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
import SKLogging
15+
import SwiftExtensions
16+
17+
#if compiler(>=6)
18+
package import SourceKitD
19+
#else
20+
import SourceKitD
21+
#endif
22+
23+
extension DynamicallyLoadedSourceKitD {
24+
private static nonisolated(unsafe) var _forPlugin: SourceKitD?
25+
package static var forPlugin: SourceKitD {
26+
get {
27+
guard let _forPlugin else {
28+
fatalError("forPlugin must only be accessed after it was set in sourcekitd_plugin_initialize_2")
29+
}
30+
return _forPlugin
31+
}
32+
set {
33+
precondition(_forPlugin == nil, "DynamicallyLoadedSourceKitD.forPlugin must not be set twice")
34+
_forPlugin = newValue
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)