13
13
@_exported import Csourcekitd
14
14
import Dispatch
15
15
import Foundation
16
- import LSPLogging
17
16
import SKSupport
18
17
19
18
/// Access to sourcekitd API, taking care of initialization, shutdown, and notification handler
@@ -42,6 +41,24 @@ public protocol SourceKitD: AnyObject {
42
41
43
42
/// Removes a previously registered notification handler.
44
43
func removeNotificationHandler( _ handler: SKDNotificationHandler )
44
+
45
+ /// Log the given request.
46
+ ///
47
+ /// This log call is issued during normal operation. It is acceptable for the logger to truncate the log message
48
+ /// to achieve good performance.
49
+ func log( request: SKDRequestDictionary )
50
+
51
+ /// Log the given request and file contents, ensuring they do not get truncated.
52
+ ///
53
+ /// This log call is used when a request has crashed. In this case we want the log to contain the entire request to be
54
+ /// able to reproduce it.
55
+ func log( crashedRequest: SKDRequestDictionary , fileContents: String ? )
56
+
57
+ /// Log the given response.
58
+ ///
59
+ /// This log call is issued during normal operation. It is acceptable for the logger to truncate the log message
60
+ /// to achieve good performance.
61
+ func log( response: SKDResponse )
45
62
}
46
63
47
64
public enum SKDError : Error , Equatable {
@@ -70,11 +87,7 @@ extension SourceKitD {
70
87
/// - fileContents: The contents of the file that the request operates on. If sourcekitd crashes, the file contents
71
88
/// will be logged.
72
89
public func send( _ req: SKDRequestDictionary , fileContents: String ? ) async throws -> SKDResponseDictionary {
73
- logRequest ( req)
74
-
75
- let signposter = logger. makeSignposter ( )
76
- let signpostID = signposter. makeSignpostID ( )
77
- let signposterState = signposter. beginInterval ( " sourcekitd-request " , id: signpostID, " Start " )
90
+ log ( request: req)
78
91
79
92
let sourcekitdResponse : SKDResponse = try await withCancellableCheckedThrowingContinuation { continuation in
80
93
var handle : sourcekitd_api_request_handle_t ? = nil
@@ -83,56 +96,26 @@ extension SourceKitD {
83
96
}
84
97
return handle
85
98
} cancel: { handle in
86
- api. cancel_request ( handle)
99
+ if let handle {
100
+ api. cancel_request ( handle)
101
+ }
87
102
}
88
103
89
- logResponse ( sourcekitdResponse)
104
+ log ( response : sourcekitdResponse)
90
105
91
106
guard let dict = sourcekitdResponse. value else {
92
- signposter. endInterval ( " sourcekitd-request " , signposterState, " Error " )
93
107
if sourcekitdResponse. error == . connectionInterrupted {
94
- let log = """
95
- Request:
96
- \( req. description)
97
-
98
- File contents:
99
- \( fileContents ?? " <nil> " )
100
- """
101
- let chunks = splitLongMultilineMessage ( message: log)
102
- for (index, chunk) in chunks. enumerated ( ) {
103
- logger. fault (
104
- """
105
- sourcekitd crashed ( \( index + 1 ) / \( chunks. count) )
106
- \( chunk)
107
- """
108
- )
109
- }
108
+ log ( crashedRequest: req, fileContents: fileContents)
110
109
}
111
110
throw sourcekitdResponse. error!
112
111
}
113
112
114
- signposter. endInterval ( " sourcekitd-request " , signposterState, " Done " )
115
113
return dict
116
114
}
117
- }
118
-
119
- private func logRequest( _ request: SKDRequestDictionary ) {
120
- logger. info (
121
- """
122
- Sending sourcekitd request:
123
- \( request. forLogging)
124
- """
125
- )
126
- }
127
115
128
- private func logResponse( _ response: SKDResponse ) {
129
- logger. log (
130
- level: ( response. error == nil || response. error == . requestCancelled) ? . debug : . error,
131
- """
132
- Received sourcekitd response:
133
- \( response. forLogging)
134
- """
135
- )
116
+ public func log( request: SKDRequestDictionary ) { }
117
+ public func log( response: SKDResponse ) { }
118
+ public func log( crashedRequest: SKDRequestDictionary , fileContents: String ? ) { }
136
119
}
137
120
138
121
/// A sourcekitd notification handler in a class to allow it to be uniquely referenced.
0 commit comments