Skip to content

Commit 02c6062

Browse files
committed
Automatically initialize the SourceKit-LSP server when creating a TestSoruceKitLSPClient
Sending the `InitializeRequest` was always unnecessarily verbose. If we automatically initialize the server when creating the test client, the code becomes sufficiently concise that we can set up the client + server in the test method itself and no longer need the `setUp` methods, making the tests easier to read.
1 parent e141933 commit 02c6062

17 files changed

+229
-440
lines changed

Sources/SKTestSupport/SKSwiftPMTestWorkspace.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,14 @@ public final class SKSwiftPMTestWorkspace {
6262
toolchain: Toolchain,
6363
testClient: TestSourceKitLSPClient? = nil
6464
) async throws {
65-
self.testClient = testClient ?? TestSourceKitLSPClient()
65+
self.testClient =
66+
if let testClient {
67+
testClient
68+
} else {
69+
// Don't initialize the LSP server because we wire up all the properties that `InitializeRequest` would set
70+
// manually below.
71+
try await TestSourceKitLSPClient(initialize: false)
72+
}
6673

6774
self.projectDir = URL(
6875
fileURLWithPath: try resolveSymlinks(AbsolutePath(validating: projectDir.path)).pathString

Sources/SKTestSupport/SKTibsTestWorkspace.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,14 @@ public final class SKTibsTestWorkspace {
5151
clientCapabilities: ClientCapabilities,
5252
testClient: TestSourceKitLSPClient? = nil
5353
) async throws {
54-
self.testClient = testClient ?? TestSourceKitLSPClient()
54+
self.testClient =
55+
if let testClient {
56+
testClient
57+
} else {
58+
// Don't initialize the LSP server because we wire up all the properties that `InitializeRequest` would set
59+
// manually below.
60+
try await TestSourceKitLSPClient(initialize: false)
61+
}
5562
self.tibsWorkspace = try TibsTestWorkspace(
5663
immutableProjectDir: immutableProjectDir,
5764
persistentBuildDir: persistentBuildDir,
@@ -70,7 +77,14 @@ public final class SKTibsTestWorkspace {
7077
clientCapabilities: ClientCapabilities,
7178
testClient: TestSourceKitLSPClient? = nil
7279
) async throws {
73-
self.testClient = testClient ?? TestSourceKitLSPClient()
80+
self.testClient =
81+
if let testClient {
82+
testClient
83+
} else {
84+
// Don't initialize the LSP server because we wire up all the properties that `InitializeRequest` would set
85+
// manually below.
86+
try await TestSourceKitLSPClient(initialize: false)
87+
}
7488

7589
self.tibsWorkspace = try TibsTestWorkspace(
7690
projectDir: projectDir,

Sources/SKTestSupport/TestSourceKitLSPClient.swift

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,22 @@ public final class TestSourceKitLSPClient: MessageHandler {
6262
private var requestHandlers: [Any] = []
6363

6464
/// - Parameters:
65+
/// - serverOptions: The equivalent of the command line options with which sourcekit-lsp should be started
6566
/// - useGlobalModuleCache: If `false`, the server will use its own module
6667
/// cache in an empty temporary directory instead of the global module cache.
67-
public init(serverOptions: SourceKitServer.Options = .testDefault, useGlobalModuleCache: Bool = true) {
68+
/// - initialize: Whether an `InitializeRequest` should be automatically sent to the SourceKit-LSP server.
69+
/// `true` by default
70+
/// - initializationOptions: Initialization options to pass to the SourceKit-LSP server.
71+
/// - capabilities: The test client's capabilities.
72+
/// - workspaceFolders: Workspace folders to open.
73+
public init(
74+
serverOptions: SourceKitServer.Options = .testDefault,
75+
useGlobalModuleCache: Bool = true,
76+
initialize: Bool = true,
77+
initializationOptions: LSPAny? = nil,
78+
capabilities: ClientCapabilities = ClientCapabilities(),
79+
workspaceFolders: [WorkspaceFolder]? = nil
80+
) async throws {
6881
if !useGlobalModuleCache {
6982
moduleCache = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString)
7083
} else {
@@ -92,6 +105,20 @@ public final class TestSourceKitLSPClient: MessageHandler {
92105
)
93106

94107
self.serverToClientConnection.start(handler: WeakMessageHandler(self))
108+
109+
if initialize {
110+
_ = try await self.send(
111+
InitializeRequest(
112+
processId: nil,
113+
rootPath: nil,
114+
rootURI: nil,
115+
initializationOptions: initializationOptions,
116+
capabilities: capabilities,
117+
trace: .off,
118+
workspaceFolders: workspaceFolders
119+
)
120+
)
121+
}
95122
}
96123

97124
deinit {

Tests/SourceKitLSPTests/BuildSystemTests.swift

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ final class BuildSystemTests: XCTestCase {
9494

9595
override func setUp() async throws {
9696
haveClangd = ToolchainRegistry.shared.toolchains.contains { $0.clangd != nil }
97-
testClient = TestSourceKitLSPClient()
97+
testClient = try await TestSourceKitLSPClient()
9898
buildSystem = TestBuildSystem()
9999

100100
let server = testClient.server
@@ -112,18 +112,6 @@ final class BuildSystemTests: XCTestCase {
112112

113113
await server.setWorkspaces([workspace])
114114
await workspace.buildSystemManager.setDelegate(server)
115-
116-
_ = try await testClient.send(
117-
InitializeRequest(
118-
processId: nil,
119-
rootPath: nil,
120-
rootURI: nil,
121-
initializationOptions: nil,
122-
capabilities: ClientCapabilities(workspace: nil, textDocument: nil),
123-
trace: .off,
124-
workspaceFolders: nil
125-
)
126-
)
127115
}
128116

129117
override func tearDown() {

Tests/SourceKitLSPTests/DocumentColorTests.swift

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,11 @@ import SourceKitLSP
1717
import XCTest
1818

1919
final class DocumentColorTests: XCTestCase {
20-
/// The mock client used to communicate with the SourceKit-LSP server.
21-
///
22-
/// - Note: Set before each test run in `setUp`.
23-
private var testClient: TestSourceKitLSPClient! = nil
24-
25-
override func setUp() async throws {
26-
testClient = TestSourceKitLSPClient()
27-
let documentCapabilities = TextDocumentClientCapabilities()
28-
_ = try await testClient.send(
29-
InitializeRequest(
30-
processId: nil,
31-
rootPath: nil,
32-
rootURI: nil,
33-
initializationOptions: nil,
34-
capabilities: ClientCapabilities(workspace: nil, textDocument: documentCapabilities),
35-
trace: .off,
36-
workspaceFolders: nil
37-
)
38-
)
39-
}
40-
41-
override func tearDown() {
42-
testClient = nil
43-
}
44-
4520
// MARK: - Helpers
4621

4722
private func performDocumentColorRequest(text: String) async throws -> [ColorInformation] {
23+
let testClient = try await TestSourceKitLSPClient()
24+
4825
let uri = DocumentURI.for(.swift)
4926

5027
testClient.openDocument(text, uri: uri)
@@ -58,6 +35,8 @@ final class DocumentColorTests: XCTestCase {
5835
color: Color,
5936
range: Range<Position>
6037
) async throws -> [ColorPresentation] {
38+
let testClient = try await TestSourceKitLSPClient()
39+
6140
let uri = DocumentURI.for(.swift)
6241

6342
testClient.openDocument(text, uri: uri)

Tests/SourceKitLSPTests/DocumentSymbolTests.swift

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,10 @@ import SourceKitLSP
1717
import XCTest
1818

1919
final class DocumentSymbolTests: XCTestCase {
20-
typealias DocumentSymbolCapabilities = TextDocumentClientCapabilities.DocumentSymbol
21-
22-
/// The mock client used to communicate with the SourceKit-LSP server.
23-
///
24-
/// - Note: Set before each test run in `setUp`.
25-
private var testClient: TestSourceKitLSPClient! = nil
26-
27-
override func setUp() async throws {
28-
testClient = TestSourceKitLSPClient()
29-
var documentCapabilities = TextDocumentClientCapabilities()
30-
documentCapabilities.documentSymbol = DocumentSymbolCapabilities()
31-
_ = try await testClient.send(
32-
InitializeRequest(
33-
processId: nil,
34-
rootPath: nil,
35-
rootURI: nil,
36-
initializationOptions: nil,
37-
capabilities: ClientCapabilities(workspace: nil, textDocument: documentCapabilities),
38-
trace: .off,
39-
workspaceFolders: nil
40-
)
41-
)
42-
}
43-
44-
override func tearDown() {
45-
testClient = nil
46-
}
47-
4820
// MARK: - Helpers
4921

5022
private func performDocumentSymbolRequest(text: String) async throws -> DocumentSymbolResponse {
23+
let testClient = try await TestSourceKitLSPClient()
5124
let uri = DocumentURI.for(.swift)
5225

5326
testClient.openDocument(text, uri: uri)

Tests/SourceKitLSPTests/ExecuteCommandTests.swift

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,6 @@ import SourceKitLSP
1717
import XCTest
1818

1919
final class ExecuteCommandTests: XCTestCase {
20-
21-
/// The mock client used to communicate with the SourceKit-LSP server.
22-
///
23-
/// - Note: Set before each test run in `setUp`.
24-
private var testClient: TestSourceKitLSPClient! = nil
25-
26-
override func tearDown() {
27-
testClient = nil
28-
}
29-
30-
override func setUp() async throws {
31-
testClient = TestSourceKitLSPClient()
32-
_ = try await self.testClient.send(
33-
InitializeRequest(
34-
processId: nil,
35-
rootPath: nil,
36-
rootURI: nil,
37-
initializationOptions: nil,
38-
capabilities: ClientCapabilities(workspace: nil, textDocument: nil),
39-
trace: .off,
40-
workspaceFolders: nil
41-
)
42-
)
43-
}
44-
45-
// MARK: - Tests
46-
4720
func testLocationSemanticRefactoring() async throws {
4821
guard let ws = try await staticSourceKitTibsWorkspace(name: "SemanticRefactor") else { return }
4922
let loc = ws.testLoc("sr:string")

Tests/SourceKitLSPTests/InlayHintTests.swift

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,10 @@ import SourceKitLSP
1717
import XCTest
1818

1919
final class InlayHintTests: XCTestCase {
20-
/// The mock client used to communicate with the SourceKit-LSP server.
21-
///
22-
/// - Note: Set before each test run in `setUp`.
23-
private var testClient: TestSourceKitLSPClient! = nil
24-
25-
override func setUp() async throws {
26-
testClient = TestSourceKitLSPClient()
27-
_ = try await testClient.send(
28-
InitializeRequest(
29-
processId: nil,
30-
rootPath: nil,
31-
rootURI: nil,
32-
initializationOptions: nil,
33-
capabilities: ClientCapabilities(workspace: nil, textDocument: nil),
34-
trace: .off,
35-
workspaceFolders: nil
36-
)
37-
)
38-
}
39-
40-
override func tearDown() {
41-
testClient = nil
42-
}
43-
4420
// MARK: - Helpers
4521

4622
func performInlayHintRequest(text: String, range: Range<Position>? = nil) async throws -> [InlayHint] {
23+
let testClient = try await TestSourceKitLSPClient()
4724
let uri = DocumentURI.for(.swift)
4825

4926
testClient.openDocument(text, uri: uri)

Tests/SourceKitLSPTests/LocalClangTests.swift

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,45 +28,18 @@ final class LocalClangTests: XCTestCase {
2828
/// - Note: Set before each test run in `setUp`.
2929
private var haveClangd: Bool = false
3030

31-
/// The mock client used to communicate with the SourceKit-LSP server.
32-
///
33-
/// - Note: Set before each test run in `setUp`.
34-
private var testClient: TestSourceKitLSPClient! = nil
35-
3631
override func setUp() async throws {
3732
haveClangd = ToolchainRegistry.shared.toolchains.contains { $0.clangd != nil }
3833
if LocalClangTests.requireClangd && !haveClangd {
3934
XCTFail("cannot find clangd in toolchain")
4035
}
41-
42-
testClient = TestSourceKitLSPClient()
43-
let documentSymbol = TextDocumentClientCapabilities.DocumentSymbol(
44-
dynamicRegistration: nil,
45-
symbolKind: nil,
46-
hierarchicalDocumentSymbolSupport: true
47-
)
48-
let textDocument = TextDocumentClientCapabilities(documentSymbol: documentSymbol)
49-
_ = try await self.testClient.send(
50-
InitializeRequest(
51-
processId: nil,
52-
rootPath: nil,
53-
rootURI: nil,
54-
initializationOptions: nil,
55-
capabilities: ClientCapabilities(workspace: nil, textDocument: textDocument),
56-
trace: .off,
57-
workspaceFolders: nil
58-
)
59-
)
60-
}
61-
62-
override func tearDown() {
63-
testClient = nil
6436
}
6537

6638
// MARK: - Tests
6739

6840
func testSymbolInfo() async throws {
6941
guard haveClangd else { return }
42+
let testClient = try await TestSourceKitLSPClient()
7043
let uri = DocumentURI.for(.cpp)
7144

7245
let locations = testClient.openDocument(
@@ -142,6 +115,7 @@ final class LocalClangTests: XCTestCase {
142115

143116
func testFoldingRange() async throws {
144117
guard haveClangd else { return }
118+
let testClient = try await TestSourceKitLSPClient()
145119
let uri = DocumentURI.for(.cpp)
146120

147121
testClient.openDocument(
@@ -169,6 +143,17 @@ final class LocalClangTests: XCTestCase {
169143

170144
func testDocumentSymbols() async throws {
171145
guard haveClangd else { return }
146+
let testClient = try await TestSourceKitLSPClient(
147+
capabilities: ClientCapabilities(
148+
textDocument: TextDocumentClientCapabilities(
149+
documentSymbol: TextDocumentClientCapabilities.DocumentSymbol(
150+
dynamicRegistration: nil,
151+
symbolKind: nil,
152+
hierarchicalDocumentSymbolSupport: true
153+
)
154+
)
155+
)
156+
)
172157
let uri = DocumentURI.for(.cpp)
173158

174159
testClient.openDocument(

0 commit comments

Comments
 (0)