Skip to content

Commit aa356cb

Browse files
authored
Merge pull request #1359 from ahoppen/split-sourcekitlspserver
Split SourceKitLSPServer.swift into multiple files
2 parents 85cdd90 + 4f91a98 commit aa356cb

File tree

5 files changed

+410
-365
lines changed

5 files changed

+410
-365
lines changed

Sources/SourceKitLSP/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ add_library(SourceKitLSP STATIC
55
DocumentSnapshot+FromFileContents.swift
66
IndexProgressManager.swift
77
IndexStoreDB+MainFilesProvider.swift
8+
LanguageServerType.swift
89
LanguageService.swift
10+
MessageHandlingDependencyTracker.swift
911
Rename.swift
1012
ResponseError+Init.swift
1113
SourceKitIndexDelegate.swift
@@ -16,6 +18,7 @@ add_library(SourceKitLSP STATIC
1618
TestDiscovery.swift
1719
TextEdit+IsNoop.swift
1820
WorkDoneProgressManager.swift
21+
WorkDoneProgressState.swift
1922
Workspace.swift
2023
)
2124
target_sources(SourceKitLSP PRIVATE
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import IndexStoreDB
14+
15+
/// Exhaustive enumeration of all toolchain language servers known to SourceKit-LSP.
16+
enum LanguageServerType: Hashable {
17+
case clangd
18+
case swift
19+
20+
init?(language: Language) {
21+
switch language {
22+
case .c, .cpp, .objective_c, .objective_cpp:
23+
self = .clangd
24+
case .swift:
25+
self = .swift
26+
default:
27+
return nil
28+
}
29+
}
30+
31+
init?(symbolProvider: SymbolProviderKind?) {
32+
switch symbolProvider {
33+
case .clang: self = .clangd
34+
case .swift: self = .swift
35+
case nil: return nil
36+
}
37+
}
38+
39+
/// The `LanguageService` class used to provide functionality for this language class.
40+
var serverType: LanguageService.Type {
41+
switch self {
42+
case .clangd:
43+
return ClangLanguageService.self
44+
case .swift:
45+
return SwiftLanguageService.self
46+
}
47+
}
48+
}
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import LSPLogging
14+
import LanguageServerProtocol
15+
import SKSupport
16+
17+
/// A lightweight way of describing tasks that are created from handling LSP
18+
/// requests or notifications for the purpose of dependency tracking.
19+
enum MessageHandlingDependencyTracker: DependencyTracker {
20+
/// A task that changes the global configuration of sourcekit-lsp in any way.
21+
///
22+
/// No other tasks must execute simultaneously with this task since they
23+
/// might be relying on this task to take effect.
24+
case globalConfigurationChange
25+
26+
/// A request that depends on the state of all documents.
27+
///
28+
/// These requests wait for `documentUpdate` tasks for all documents to finish before being executed.
29+
///
30+
/// Requests that only read the semantic index and are not affected by changes to the in-memory file contents should
31+
/// `freestanding` requests.
32+
case workspaceRequest
33+
34+
/// Changes the contents of the document with the given URI.
35+
///
36+
/// Any other updates or requests to this document must wait for the
37+
/// document update to finish before being executed
38+
case documentUpdate(DocumentURI)
39+
40+
/// A request that concerns one document.
41+
///
42+
/// Any updates to this document must be processed before the document
43+
/// request can be handled. Multiple requests to the same document can be
44+
/// handled simultaneously.
45+
case documentRequest(DocumentURI)
46+
47+
/// A request that doesn't have any dependencies other than global
48+
/// configuration changes.
49+
case freestanding
50+
51+
/// Whether this request needs to finish before `other` can start executing.
52+
func isDependency(of other: MessageHandlingDependencyTracker) -> Bool {
53+
switch (self, other) {
54+
// globalConfigurationChange
55+
case (.globalConfigurationChange, _): return true
56+
case (_, .globalConfigurationChange): return true
57+
58+
// globalDocumentState
59+
case (.workspaceRequest, .workspaceRequest): return false
60+
case (.documentUpdate, .workspaceRequest): return true
61+
case (.workspaceRequest, .documentUpdate): return true
62+
case (.workspaceRequest, .documentRequest): return false
63+
case (.documentRequest, .workspaceRequest): return false
64+
65+
// documentUpdate
66+
case (.documentUpdate(let selfUri), .documentUpdate(let otherUri)):
67+
return selfUri == otherUri
68+
case (.documentUpdate(let selfUri), .documentRequest(let otherUri)):
69+
return selfUri == otherUri
70+
case (.documentRequest(let selfUri), .documentUpdate(let otherUri)):
71+
return selfUri == otherUri
72+
73+
// documentRequest
74+
case (.documentRequest, .documentRequest):
75+
return false
76+
77+
// freestanding
78+
case (.freestanding, _):
79+
return false
80+
case (_, .freestanding):
81+
return false
82+
}
83+
}
84+
85+
init(_ notification: any NotificationType) {
86+
switch notification {
87+
case is CancelRequestNotification:
88+
self = .freestanding
89+
case is CancelWorkDoneProgressNotification:
90+
self = .freestanding
91+
case is DidChangeConfigurationNotification:
92+
self = .globalConfigurationChange
93+
case let notification as DidChangeNotebookDocumentNotification:
94+
self = .documentUpdate(notification.notebookDocument.uri)
95+
case let notification as DidChangeTextDocumentNotification:
96+
self = .documentUpdate(notification.textDocument.uri)
97+
case is DidChangeWatchedFilesNotification:
98+
self = .globalConfigurationChange
99+
case is DidChangeWorkspaceFoldersNotification:
100+
self = .globalConfigurationChange
101+
case let notification as DidCloseNotebookDocumentNotification:
102+
self = .documentUpdate(notification.notebookDocument.uri)
103+
case let notification as DidCloseTextDocumentNotification:
104+
self = .documentUpdate(notification.textDocument.uri)
105+
case is DidCreateFilesNotification:
106+
self = .freestanding
107+
case is DidDeleteFilesNotification:
108+
self = .freestanding
109+
case let notification as DidOpenNotebookDocumentNotification:
110+
self = .documentUpdate(notification.notebookDocument.uri)
111+
case let notification as DidOpenTextDocumentNotification:
112+
self = .documentUpdate(notification.textDocument.uri)
113+
case is DidRenameFilesNotification:
114+
self = .freestanding
115+
case let notification as DidSaveNotebookDocumentNotification:
116+
self = .documentUpdate(notification.notebookDocument.uri)
117+
case let notification as DidSaveTextDocumentNotification:
118+
self = .documentUpdate(notification.textDocument.uri)
119+
case is ExitNotification:
120+
self = .globalConfigurationChange
121+
case is InitializedNotification:
122+
self = .globalConfigurationChange
123+
case is LogMessageNotification:
124+
self = .freestanding
125+
case is LogTraceNotification:
126+
self = .freestanding
127+
case is PublishDiagnosticsNotification:
128+
self = .freestanding
129+
case is SetTraceNotification:
130+
self = .globalConfigurationChange
131+
case is ShowMessageNotification:
132+
self = .freestanding
133+
case let notification as WillSaveTextDocumentNotification:
134+
self = .documentUpdate(notification.textDocument.uri)
135+
case is WorkDoneProgress:
136+
self = .freestanding
137+
default:
138+
logger.error(
139+
"""
140+
Unknown notification \(type(of: notification)). Treating as a freestanding notification. \
141+
This might lead to out-of-order request handling
142+
"""
143+
)
144+
self = .freestanding
145+
}
146+
}
147+
148+
init(_ request: any RequestType) {
149+
switch request {
150+
case let request as any TextDocumentRequest: self = .documentRequest(request.textDocument.uri)
151+
case is ApplyEditRequest:
152+
self = .freestanding
153+
case is BarrierRequest:
154+
self = .globalConfigurationChange
155+
case is CallHierarchyIncomingCallsRequest:
156+
self = .freestanding
157+
case is CallHierarchyOutgoingCallsRequest:
158+
self = .freestanding
159+
case is CodeActionResolveRequest:
160+
self = .freestanding
161+
case is CodeLensRefreshRequest:
162+
self = .freestanding
163+
case is CodeLensResolveRequest:
164+
self = .freestanding
165+
case is CompletionItemResolveRequest:
166+
self = .freestanding
167+
case is CreateWorkDoneProgressRequest:
168+
self = .freestanding
169+
case is DiagnosticsRefreshRequest:
170+
self = .freestanding
171+
case is DocumentLinkResolveRequest:
172+
self = .freestanding
173+
case let request as ExecuteCommandRequest:
174+
if let uri = request.textDocument?.uri {
175+
self = .documentRequest(uri)
176+
} else {
177+
self = .freestanding
178+
}
179+
case is InitializeRequest:
180+
self = .globalConfigurationChange
181+
case is InlayHintRefreshRequest:
182+
self = .freestanding
183+
case is InlayHintResolveRequest:
184+
self = .freestanding
185+
case is InlineValueRefreshRequest:
186+
self = .freestanding
187+
case is PollIndexRequest:
188+
self = .globalConfigurationChange
189+
case is RenameRequest:
190+
// Rename might touch multiple files. Make it a global configuration change so that edits to all files that might
191+
// be affected have been processed.
192+
self = .globalConfigurationChange
193+
case is RegisterCapabilityRequest:
194+
self = .globalConfigurationChange
195+
case is ShowMessageRequest:
196+
self = .freestanding
197+
case is ShutdownRequest:
198+
self = .globalConfigurationChange
199+
case is TypeHierarchySubtypesRequest:
200+
self = .freestanding
201+
case is TypeHierarchySupertypesRequest:
202+
self = .freestanding
203+
case is UnregisterCapabilityRequest:
204+
self = .globalConfigurationChange
205+
case is WillCreateFilesRequest:
206+
self = .freestanding
207+
case is WillDeleteFilesRequest:
208+
self = .freestanding
209+
case is WillRenameFilesRequest:
210+
self = .freestanding
211+
case is WorkspaceDiagnosticsRequest:
212+
self = .freestanding
213+
case is WorkspaceFoldersRequest:
214+
self = .freestanding
215+
case is WorkspaceSemanticTokensRefreshRequest:
216+
self = .freestanding
217+
case is WorkspaceSymbolResolveRequest:
218+
self = .freestanding
219+
case is WorkspaceSymbolsRequest:
220+
self = .freestanding
221+
case is WorkspaceTestsRequest:
222+
self = .workspaceRequest
223+
default:
224+
logger.error(
225+
"""
226+
Unknown request \(type(of: request)). Treating as a freestanding request. \
227+
This might lead to out-of-order request handling
228+
"""
229+
)
230+
self = .freestanding
231+
}
232+
}
233+
}

0 commit comments

Comments
 (0)