Skip to content

Commit a6fdd1d

Browse files
authored
Merge pull request #1117 from ahoppen/ahoppen/sendability
Add Sendable annotations to LanguageServerProtocol, LSPLogging and SKSupport
2 parents c699da9 + 9fcf364 commit a6fdd1d

File tree

100 files changed

+380
-337
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+380
-337
lines changed

Package.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.7
1+
// swift-tools-version:5.8
22

33
import Foundation
44
import PackageDescription
@@ -97,7 +97,8 @@ let package = Package(
9797
.target(
9898
name: "LanguageServerProtocol",
9999
dependencies: [],
100-
exclude: ["CMakeLists.txt"]
100+
exclude: ["CMakeLists.txt"],
101+
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
101102
),
102103

103104
.testTarget(
@@ -137,7 +138,7 @@ let package = Package(
137138
.product(name: "Crypto", package: "swift-crypto")
138139
],
139140
exclude: ["CMakeLists.txt"],
140-
swiftSettings: lspLoggingSwiftSettings
141+
swiftSettings: lspLoggingSwiftSettings + [.enableExperimentalFeature("StrictConcurrency")]
141142
),
142143

143144
.testTarget(
@@ -197,7 +198,8 @@ let package = Package(
197198
"LanguageServerProtocol",
198199
"LSPLogging",
199200
],
200-
exclude: ["CMakeLists.txt"]
201+
exclude: ["CMakeLists.txt"],
202+
swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]
201203
),
202204

203205
.testTarget(

Sources/LSPLogging/NonDarwinLogging.swift

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public enum LogConfig {
4545
///
4646
/// For documentation of the different log levels see
4747
/// https://developer.apple.com/documentation/os/oslogtype.
48-
public enum NonDarwinLogLevel: Comparable, CustomStringConvertible {
48+
public enum NonDarwinLogLevel: Comparable, CustomStringConvertible, Sendable {
4949
case debug
5050
case info
5151
case `default`
@@ -102,7 +102,7 @@ public enum NonDarwinLogLevel: Comparable, CustomStringConvertible {
102102
///
103103
/// For documentation of the different privacy levels see
104104
/// https://developer.apple.com/documentation/os/oslogprivacy.
105-
public enum NonDarwinLogPrivacy: Comparable {
105+
public enum NonDarwinLogPrivacy: Comparable, Sendable {
106106
case `public`
107107
case `private`
108108
case sensitive
@@ -132,16 +132,16 @@ public enum NonDarwinLogPrivacy: Comparable {
132132
/// sourcekit-lsp.
133133
///
134134
/// This is used on platforms that don't have OSLog.
135-
public struct NonDarwinLogInterpolation: StringInterpolationProtocol {
136-
private enum LogPiece {
135+
public struct NonDarwinLogInterpolation: StringInterpolationProtocol, Sendable {
136+
private enum LogPiece: Sendable {
137137
/// A segment of the log message that will always be displayed.
138138
case string(String)
139139

140140
/// A segment of the log message that might need to be redacted if the
141141
/// privacy level is lower than `privacy`.
142142
case possiblyRedacted(
143-
description: () -> String,
144-
redactedDescription: () -> String,
143+
description: @Sendable () -> String,
144+
redactedDescription: @Sendable () -> String,
145145
privacy: NonDarwinLogPrivacy
146146
)
147147
}
@@ -158,8 +158,8 @@ public struct NonDarwinLogInterpolation: StringInterpolationProtocol {
158158
}
159159

160160
private mutating func append(
161-
description: @autoclosure @escaping () -> String,
162-
redactedDescription: @autoclosure @escaping () -> String,
161+
description: @autoclosure @escaping @Sendable () -> String,
162+
redactedDescription: @autoclosure @escaping @Sendable () -> String,
163163
privacy: NonDarwinLogPrivacy
164164
) {
165165
if privacy == .public {
@@ -181,13 +181,15 @@ public struct NonDarwinLogInterpolation: StringInterpolationProtocol {
181181
}
182182

183183
@_disfavoredOverload // Prefer to use the StaticString overload when possible.
184-
public mutating func appendInterpolation(_ message: CustomStringConvertible, privacy: NonDarwinLogPrivacy = .private)
185-
{
184+
public mutating func appendInterpolation(
185+
_ message: some CustomStringConvertible & Sendable,
186+
privacy: NonDarwinLogPrivacy = .private
187+
) {
186188
append(description: message.description, redactedDescription: "<private>", privacy: privacy)
187189
}
188190

189191
public mutating func appendInterpolation(
190-
_ message: CustomLogStringConvertibleWrapper,
192+
_ message: some CustomLogStringConvertibleWrapper & Sendable,
191193
privacy: NonDarwinLogPrivacy = .private
192194
) {
193195
append(description: message.description, redactedDescription: message.redactedDescription, privacy: privacy)
@@ -198,7 +200,7 @@ public struct NonDarwinLogInterpolation: StringInterpolationProtocol {
198200
}
199201

200202
/// Builds the string that represents the log message, masking all interpolation
201-
/// segments whose privacy level is greater thatn `logPrivacyLevel`.
203+
/// segments whose privacy level is greater that `logPrivacyLevel`.
202204
fileprivate func string(for logPrivacyLevel: NonDarwinLogPrivacy) -> String {
203205
var result = ""
204206
for piece in pieces {
@@ -221,7 +223,7 @@ public struct NonDarwinLogInterpolation: StringInterpolationProtocol {
221223
/// sourcekit-lsp.
222224
///
223225
/// This is used on platforms that don't have OSLog.
224-
public struct NonDarwinLogMessage: ExpressibleByStringInterpolation, ExpressibleByStringLiteral {
226+
public struct NonDarwinLogMessage: ExpressibleByStringInterpolation, ExpressibleByStringLiteral, Sendable {
225227
fileprivate let value: NonDarwinLogInterpolation
226228

227229
public init(stringInterpolation: NonDarwinLogInterpolation) {
@@ -257,12 +259,12 @@ private let loggingQueue: DispatchQueue = DispatchQueue(label: "loggingQueue", q
257259
///
258260
/// This logger is used to log messages to stderr on platforms where OSLog is
259261
/// not available.
260-
public struct NonDarwinLogger {
262+
public struct NonDarwinLogger: Sendable {
261263
private let subsystem: String
262264
private let category: String
263265
private let logLevel: NonDarwinLogLevel
264266
private let privacyLevel: NonDarwinLogPrivacy
265-
private let logHandler: (String) -> Void
267+
private let logHandler: @Sendable (String) -> Void
266268

267269
/// - Parameters:
268270
/// - subsystem: See os.Logger
@@ -277,7 +279,7 @@ public struct NonDarwinLogger {
277279
category: String,
278280
logLevel: NonDarwinLogLevel? = nil,
279281
privacyLevel: NonDarwinLogPrivacy? = nil,
280-
logHandler: @escaping (String) -> Void = { fputs($0 + "\n", stderr) }
282+
logHandler: @escaping @Sendable (String) -> Void = { fputs($0 + "\n", stderr) }
281283
) {
282284
self.subsystem = subsystem
283285
self.category = category
@@ -292,7 +294,7 @@ public struct NonDarwinLogger {
292294
/// program to finish as quickly as possible.
293295
public func log(
294296
level: NonDarwinLogLevel,
295-
_ message: @autoclosure @escaping () -> NonDarwinLogMessage
297+
_ message: @autoclosure @escaping @Sendable () -> NonDarwinLogMessage
296298
) {
297299
guard level >= self.logLevel else { return }
298300
let date = Date()

Sources/LSPTestSupport/TestJSONRPCConnection.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ extension String: @retroactive ResponseType {}
196196
#endif
197197

198198
public struct EchoRequest: RequestType {
199-
public static var method: String = "test_server/echo"
199+
public static let method: String = "test_server/echo"
200200
public typealias Response = String
201201

202202
public var string: String
@@ -207,7 +207,7 @@ public struct EchoRequest: RequestType {
207207
}
208208

209209
public struct EchoError: RequestType {
210-
public static var method: String = "test_server/echo_error"
210+
public static let method: String = "test_server/echo_error"
211211
public typealias Response = VoidResponse
212212

213213
public var code: ErrorCode?
@@ -220,7 +220,7 @@ public struct EchoError: RequestType {
220220
}
221221

222222
public struct EchoNotification: NotificationType {
223-
public static var method: String = "test_server/echo_note"
223+
public static let method: String = "test_server/echo_note"
224224

225225
public var string: String
226226

Sources/LanguageServerProtocol/Connection.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import Dispatch
1414

1515
/// An abstract connection, allow messages to be sent to a (potentially remote) `MessageHandler`.
16-
public protocol Connection: AnyObject {
16+
public protocol Connection: AnyObject, Sendable {
1717

1818
/// Send a notification without a reply.
1919
func send(_ notification: some NotificationType)
@@ -61,7 +61,9 @@ public protocol MessageHandler: AnyObject {
6161
/// conn.send(...) // handled by server
6262
/// conn.close()
6363
/// ```
64-
public final class LocalConnection {
64+
///
65+
/// - Note: Unchecked sendable conformance because shared state is guarded by `queue`.
66+
public final class LocalConnection: @unchecked Sendable {
6567

6668
enum State {
6769
case ready, started, closed

Sources/LanguageServerProtocol/CustomCodable.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public struct CustomCodable<CustomCoder: CustomCodableWrapper> {
5151
}
5252
}
5353

54+
extension CustomCodable: Sendable where CustomCoder.WrappedValue: Sendable {}
55+
5456
extension CustomCodable: Codable {
5557
public init(from decoder: Decoder) throws {
5658
self.wrappedValue = try CustomCoder(from: decoder).wrappedValue

Sources/LanguageServerProtocol/Error.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
public typealias LSPResult<T> = Swift.Result<T, ResponseError>
1515

1616
/// Error code suitable for use between language server and client.
17-
public struct ErrorCode: RawRepresentable, Codable, Hashable {
17+
public struct ErrorCode: RawRepresentable, Codable, Hashable, Sendable {
1818

1919
public var rawValue: Int
2020

@@ -100,9 +100,9 @@ public struct ResponseError: Error, Codable, Hashable {
100100
extension ResponseError {
101101
// MARK: Convenience properties for common errors.
102102

103-
public static var cancelled: ResponseError = ResponseError(code: .cancelled, message: "request cancelled by client")
103+
public static let cancelled: ResponseError = ResponseError(code: .cancelled, message: "request cancelled by client")
104104

105-
public static var serverCancelled: ResponseError = ResponseError(
105+
public static let serverCancelled: ResponseError = ResponseError(
106106
code: .serverCancelled,
107107
message: "request cancelled by server"
108108
)
@@ -136,7 +136,7 @@ public struct MessageDecodingError: Error, Hashable {
136136
/// If it was possible to recover the request id, it is stored here. This can be used e.g. to reply with a `ResponseError` to invalid requests.
137137
public var id: RequestID?
138138

139-
public enum MessageKind {
139+
public enum MessageKind: Sendable {
140140
case request
141141
case response
142142
case notification

Sources/LanguageServerProtocol/Message.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import Dispatch
1414

15-
public protocol MessageType: Codable {}
15+
public protocol MessageType: Codable, Sendable {}
1616

1717
/// `RequestType` with no associated type or same-type requirements. Most users should prefer
1818
/// `RequestType`.

Sources/LanguageServerProtocol/MessageRegistry.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
public final class MessageRegistry {
13+
public final class MessageRegistry: Sendable {
1414

1515
public static let lspProtocol: MessageRegistry =
1616
MessageRegistry(requests: builtinRequests, notifications: builtinNotifications)

Sources/LanguageServerProtocol/Notifications/CancelWorkDoneProgressNotification.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
public struct CancelWorkDoneProgressNotification: NotificationType {
14-
public static var method: String = "window/workDoneProgress/cancel"
14+
public static let method: String = "window/workDoneProgress/cancel"
1515

1616
public var token: ProgressToken
1717

Sources/LanguageServerProtocol/Notifications/DidChangeFileNotifications.swift

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

1313
public struct DidCreateFilesNotification: NotificationType {
14-
public static var method: String = "workspace/didCreateFiles"
14+
public static let method: String = "workspace/didCreateFiles"
1515

1616
/// An array of all files/folders created in this operation.
1717
public var files: [FileCreate]
@@ -22,7 +22,7 @@ public struct DidCreateFilesNotification: NotificationType {
2222
}
2323

2424
public struct DidRenameFilesNotification: NotificationType {
25-
public static var method: String = "workspace/didRenameFiles"
25+
public static let method: String = "workspace/didRenameFiles"
2626

2727
/// An array of all files/folders renamed in this operation. When a folder
2828
/// is renamed, only the folder will be included, and not its children.
@@ -34,7 +34,7 @@ public struct DidRenameFilesNotification: NotificationType {
3434
}
3535

3636
public struct DidDeleteFilesNotification: NotificationType {
37-
public static var method: String = "workspace/didDeleteFiles"
37+
public static let method: String = "workspace/didDeleteFiles"
3838

3939
/// An array of all files/folders created in this operation.
4040
public var files: [FileDelete]

0 commit comments

Comments
 (0)