Skip to content

Commit d71e9e4

Browse files
committed
Capture stderr from clangd and forward it to the logger
Previously, we were forwarding clangd’s stderr to sourcekit-lsp’s stderr. We should pipe it through the logger so that it ends up in OSLog on Darwin.
1 parent 7772f07 commit d71e9e4

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

Sources/SourceKitLSP/Clang/ClangLanguageServer.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,27 @@ extension NSLock {
3232
}
3333
}
3434

35+
/// Gathers data from clangd's stderr pipe. When it has accumulated a full line, writes the the line to the logger.
36+
fileprivate class ClangdStderrLogForwarder {
37+
private var buffer = Data()
38+
39+
func handle(_ newData: Data) {
40+
self.buffer += newData
41+
if newData.contains(UInt8(ascii: "\n")) {
42+
self.flushBuffer()
43+
}
44+
}
45+
46+
private func flushBuffer() {
47+
guard let newlineIndex = self.buffer.firstIndex(of: UInt8(ascii: "\n")) else {
48+
return
49+
}
50+
let logger = Logger(subsystem: subsystem, category: "clangd-stderr")
51+
logger.info("\(String(data: self.buffer[...newlineIndex], encoding: .utf8) ?? "<invalid UTF-8>")")
52+
buffer = buffer[buffer.index(after: newlineIndex)...]
53+
}
54+
}
55+
3556
/// A thin wrapper over a connection to a clangd server providing build setting handling.
3657
///
3758
/// In addition, it also intercepts notifications and replies from clangd in order to do things
@@ -203,6 +224,17 @@ actor ClangLanguageServerShim: ToolchainLanguageServer, MessageHandler {
203224

204225
process.standardOutput = clangdToUs
205226
process.standardInput = usToClangd
227+
let logForwarder = ClangdStderrLogForwarder()
228+
let stderrHandler = Pipe()
229+
stderrHandler.fileHandleForReading.readabilityHandler = { fileHandle in
230+
let newData = fileHandle.readData(ofLength: 1)
231+
if newData.count == 0 {
232+
stderrHandler.fileHandleForReading.readabilityHandler = nil
233+
} else {
234+
logForwarder.handle(newData)
235+
}
236+
}
237+
process.standardError = stderrHandler
206238
process.terminationHandler = { [weak self] process in
207239
logger.log(
208240
level: process.terminationReason == .exit ? .default : .error,

0 commit comments

Comments
 (0)