Skip to content

Commit 78e102d

Browse files
committed
Split creation of the clangd shim into shim initialization and starting of clangd
This will later allow us to restart clangd while keeping the same shim.
1 parent d7f4755 commit 78e102d

File tree

1 file changed

+68
-56
lines changed

1 file changed

+68
-56
lines changed

Sources/SourceKitLSP/Clang/ClangLanguageServer.swift

Lines changed: 68 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,83 @@ import TSCBasic
2424
/// like witholding diagnostics when fallback build settings are being used.
2525
final class ClangLanguageServerShim: LanguageServer, ToolchainLanguageServer {
2626

27-
/// The connection to the clangd LSP.
28-
let clangd: Connection
27+
/// The connection to the clangd LSP. `nil` until `startClangdProcesss` has been called.
28+
var clangd: Connection!
2929

3030
/// Capabilities of the clangd LSP, if received.
3131
var capabilities: ServerCapabilities? = nil
3232

3333
/// Path to the clang binary.
3434
let clangPath: AbsolutePath?
35+
36+
/// Path to the `clangd` binary.
37+
let clangdPath: AbsolutePath
38+
39+
let clangdOptions: [String]
3540

3641
/// Resolved build settings by file. Must be accessed with the `lock`.
3742
private var buildSettingsByFile: [DocumentURI: ClangBuildSettings] = [:]
3843

3944
/// Lock protecting `buildSettingsByFile`.
40-
private var lock: Lock
45+
private var lock: Lock = Lock()
4146

4247
/// Creates a language server for the given client referencing the clang binary at the given path.
4348
public init(
44-
client: LocalConnection,
45-
clangd: Connection,
46-
clangPath: AbsolutePath?
49+
client: Connection,
50+
clangPath: AbsolutePath?,
51+
clangdPath: AbsolutePath,
52+
clangdOptions: [String]
4753
) throws {
48-
self.clangd = clangd
4954
self.clangPath = clangPath
50-
self.lock = Lock()
55+
self.clangdPath = clangdPath
56+
self.clangdOptions = clangdOptions
5157
super.init(client: client)
5258
}
59+
60+
func startClangdProcesss() throws {
61+
let usToClangd: Pipe = Pipe()
62+
let clangdToUs: Pipe = Pipe()
63+
64+
let connectionToClangd = JSONRPCConnection(
65+
protocol: MessageRegistry.lspProtocol,
66+
inFD: clangdToUs.fileHandleForReading,
67+
outFD: usToClangd.fileHandleForWriting
68+
)
69+
self.clangd = connectionToClangd
70+
71+
connectionToClangd.start(receiveHandler: self) {
72+
// FIXME: keep the pipes alive until we close the connection. This
73+
// should be fixed systemically.
74+
withExtendedLifetime((usToClangd, clangdToUs)) {}
75+
}
76+
77+
let process = Foundation.Process()
78+
79+
if #available(OSX 10.13, *) {
80+
process.executableURL = clangdPath.asURL
81+
} else {
82+
process.launchPath = clangdPath.pathString
83+
}
84+
85+
process.arguments = [
86+
"-compile_args_from=lsp", // Provide compiler args programmatically.
87+
"-background-index=false", // Disable clangd indexing, we use the build
88+
"-index=false" // system index store instead.
89+
] + clangdOptions
90+
91+
process.standardOutput = clangdToUs
92+
process.standardInput = usToClangd
93+
process.terminationHandler = { process in
94+
log("clangd exited: \(process.terminationReason) \(process.terminationStatus)")
95+
connectionToClangd.close()
96+
}
97+
98+
if #available(OSX 10.13, *) {
99+
try process.run()
100+
} else {
101+
process.launch()
102+
}
103+
}
53104

54105
public override func _registerBuiltinHandlers() {
55106
_register(ClangLanguageServerShim.publishDiagnostics)
@@ -284,60 +335,21 @@ func makeJSONRPCClangServer(
284335
toolchain: Toolchain,
285336
clangdOptions: [String]
286337
) throws -> ToolchainLanguageServer {
287-
guard let clangd = toolchain.clangd else {
338+
guard let clangdPath = toolchain.clangd else {
288339
preconditionFailure("missing clang from toolchain \(toolchain.identifier)")
289340
}
290341

291-
let usToClangd: Pipe = Pipe()
292-
let clangdToUs: Pipe = Pipe()
293-
294-
let connection = JSONRPCConnection(
295-
protocol: MessageRegistry.lspProtocol,
296-
inFD: clangdToUs.fileHandleForReading,
297-
outFD: usToClangd.fileHandleForWriting
298-
)
299-
300342
let connectionToClient = LocalConnection()
301-
343+
connectionToClient.start(handler: client)
344+
302345
let shim = try ClangLanguageServerShim(
303346
client: connectionToClient,
304-
clangd: connection,
305-
clangPath: toolchain.clang)
306-
307-
connectionToClient.start(handler: client)
308-
connection.start(receiveHandler: shim) {
309-
// FIXME: keep the pipes alive until we close the connection. This
310-
// should be fixed systemically.
311-
withExtendedLifetime((usToClangd, clangdToUs)) {}
312-
}
313-
314-
let process = Foundation.Process()
315-
316-
if #available(OSX 10.13, *) {
317-
process.executableURL = clangd.asURL
318-
} else {
319-
process.launchPath = clangd.pathString
320-
}
321-
322-
process.arguments = [
323-
"-compile_args_from=lsp", // Provide compiler args programmatically.
324-
"-background-index=false", // Disable clangd indexing, we use the build
325-
"-index=false" // system index store instead.
326-
] + clangdOptions
327-
328-
process.standardOutput = clangdToUs
329-
process.standardInput = usToClangd
330-
process.terminationHandler = { process in
331-
log("clangd exited: \(process.terminationReason) \(process.terminationStatus)")
332-
connection.close()
333-
}
334-
335-
if #available(OSX 10.13, *) {
336-
try process.run()
337-
} else {
338-
process.launch()
339-
}
340-
347+
clangPath: toolchain.clang,
348+
clangdPath: clangdPath,
349+
clangdOptions: clangdOptions
350+
)
351+
try shim.startClangdProcesss()
352+
341353
return shim
342354
}
343355

0 commit comments

Comments
 (0)