Skip to content

Commit cf19900

Browse files
authored
Swap BuildSystem to remove build settings method (#183)
Remove `settings(for:)` from the BuildSystem API in favor of the change callback - With the `settings(for:)` method removed, we instead block on a callback from the `BuildSystemManager` which itself handles the primary build system callback in conjunction with the fallback system - We queue up notifications / requests that reference documents until we receive the callback. - Remove language from FileBuildSettings as it is no longer needed, Swift-specific working dir fixes are now in SwiftCompileCommand - registerForChangeNotifications should inform its delegate asynchronously instead of immediately
1 parent 5cc5413 commit cf19900

28 files changed

+847
-382
lines changed

Sources/LanguageServerProtocol/Message.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,14 @@ extension NotificationType {
6767
}
6868
}
6969

70-
/// A `textDocument/*` request, which takes a text document identifier indicating which document it
71-
/// operates in or on.
70+
/// A `textDocument/*` notification, which takes a text document identifier
71+
/// indicating which document it operates in or on.
72+
public protocol TextDocumentNotification: NotificationType {
73+
var textDocument: TextDocumentIdentifier { get }
74+
}
75+
76+
/// A `textDocument/*` request, which takes a text document identifier
77+
/// indicating which document it operates in or on.
7278
public protocol TextDocumentRequest: RequestType {
7379
var textDocument: TextDocumentIdentifier { get }
7480
}

Sources/LanguageServerProtocol/Notifications/TextSynchronizationNotifications.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public struct DidChangeTextDocumentNotification: NotificationType, Hashable {
9797
/// - reason: Whether this was user-initiated, auto-saved, etc.
9898
///
9999
/// Servers that support willSave should set the `willSave` text document sync option.
100-
public struct WillSaveTextDocumentNotification: NotificationType, Hashable {
100+
public struct WillSaveTextDocumentNotification: TextDocumentNotification, Hashable {
101101
public static let method: String = "textDocument/willSave"
102102

103103
/// The document that will be saved.
@@ -114,7 +114,7 @@ public struct WillSaveTextDocumentNotification: NotificationType, Hashable {
114114
/// - text: The content of the document at the time of save.
115115
///
116116
/// Servers that support didSave should set the `save` text document sync option.
117-
public struct DidSaveTextDocumentNotification: NotificationType, Hashable {
117+
public struct DidSaveTextDocumentNotification: TextDocumentNotification, Hashable {
118118
public static let method: String = "textDocument/didSave"
119119

120120
/// The document that was saved.

Sources/LanguageServerProtocol/Requests/ReferencesRequest.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
/// - includeDeclaration: Whether to include the declaration in the list of symbols.
2424
///
2525
/// - Returns: An array of locations, one for each reference.
26-
public struct ReferencesRequest: RequestType, Hashable {
26+
public struct ReferencesRequest: TextDocumentRequest, Hashable {
2727
public static let method: String = "textDocument/references"
2828
public typealias Response = [Location]
2929

Sources/SKCore/BuildServerBuildSystem.swift

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,36 @@ final class BuildServerHandler: LanguageServerEndpoint {
140140
}
141141

142142
func handleFileOptionsChanged(_ notification: Notification<FileOptionsChangedNotification>) {
143-
// TODO: add delegate method to include the changed settings directly
144-
self.delegate?.fileBuildSettingsChanged([notification.params.uri])
143+
let result = notification.params.updatedOptions
144+
let settings = FileBuildSettings(
145+
compilerArguments: result.options, workingDirectory: result.workingDirectory)
146+
self.delegate?.fileBuildSettingsChanged([notification.params.uri: .modified(settings)])
147+
}
148+
}
149+
150+
extension BuildServerBuildSystem {
151+
/// Exposed for *testing*.
152+
public func _settings(for uri: DocumentURI) -> FileBuildSettings? {
153+
if let response = try? self.buildServer?.sendSync(SourceKitOptions(uri: uri)) {
154+
return FileBuildSettings(
155+
compilerArguments: response.options,
156+
workingDirectory: response.workingDirectory)
157+
}
158+
return nil
145159
}
146160
}
147161

148162
extension BuildServerBuildSystem: BuildSystem {
149163

150-
/// Register the given file for build-system level change notifications, such as command
151-
/// line flag changes, dependency changes, etc.
152164
public func registerForChangeNotifications(for uri: DocumentURI, language: Language) {
153165
let request = RegisterForChanges(uri: uri, action: .register)
154166
_ = self.buildServer?.send(request, queue: requestQueue, reply: { result in
155167
if let error = result.failure {
156168
log("error registering \(uri): \(error)", level: .error)
169+
170+
// BuildServer registration failed, so tell our delegate that no build
171+
// settings are available.
172+
self.delegate?.fileBuildSettingsChanged([uri: .removedOrUnavailable])
157173
}
158174
})
159175
}
@@ -169,16 +185,6 @@ extension BuildServerBuildSystem: BuildSystem {
169185
})
170186
}
171187

172-
public func settings(for uri: DocumentURI, _ language: Language) -> FileBuildSettings? {
173-
if let response = try? self.buildServer?.sendSync(SourceKitOptions(uri: uri)) {
174-
return FileBuildSettings(
175-
compilerArguments: response.options,
176-
workingDirectory: response.workingDirectory,
177-
language: language)
178-
}
179-
return nil
180-
}
181-
182188
public func buildTargets(reply: @escaping (LSPResult<[BuildTarget]>) -> Void) {
183189
_ = self.buildServer?.send(BuildTargets(), queue: requestQueue) { response in
184190
switch response {

Sources/SKCore/BuildSystem.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,16 @@ public protocol BuildSystem: AnyObject {
3131
/// The path to put the index database, if any.
3232
var indexDatabasePath: AbsolutePath? { get }
3333

34-
/// Returns the settings for the given url and language mode, if known.
35-
func settings(for: DocumentURI, _ language: Language) -> FileBuildSettings?
36-
3734
/// Delegate to handle any build system events such as file build settings
38-
/// changing.
35+
/// initial reports as well as changes.
3936
var delegate: BuildSystemDelegate? { get set }
4037

4138
/// Register the given file for build-system level change notifications, such
4239
/// as command line flag changes, dependency changes, etc.
40+
///
41+
/// IMPORTANT: When first receiving a register request, the `BuildSystem` MUST asynchronously
42+
/// inform its delegate of any initial settings for the given file via the
43+
/// `fileBuildSettingsChanged` method, even if unavailable.
4344
func registerForChangeNotifications(for: DocumentURI, language: Language)
4445

4546
/// Unregister the given file for build-system level change notifications,

Sources/SKCore/BuildSystemDelegate.swift

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@ public protocol BuildSystemDelegate: AnyObject {
2121
/// interest.
2222
func buildTargetsChanged(_ changes: [BuildTargetEvent])
2323

24-
/// Notify the delegate that the given files' build settings have changed. If the given set is
25-
/// empty, assume that all open files are affected.
24+
/// Notify the delegate that the given files' build settings have changed.
2625
///
27-
/// The callee should request new build settings for any of the given files
28-
/// that they are interested in.
29-
func fileBuildSettingsChanged(_ changedFiles: Set<DocumentURI>)
26+
/// The delegate should cache the new build settings for any of the given
27+
/// files that they are interested in.
28+
func fileBuildSettingsChanged(
29+
_ changedFiles: [DocumentURI: FileBuildSettingsChange])
3030

31-
/// Notify the delegate that the dependencies of the given files have changed and that ASTs
32-
/// may need to be refreshed. If the given set is empty, assume that all open files are affected.
31+
/// Notify the delegate that the dependencies of the given files have changed
32+
/// and that ASTs may need to be refreshed. If the given set is empty, assume
33+
/// that all watched files are affected.
3334
///
34-
/// The callee should refresh ASTs unless it is able to determine that a refresh is not necessary.
35+
/// The callee should refresh ASTs unless it is able to determine that a
36+
/// refresh is not necessary.
3537
func filesDependenciesUpdated(_ changedFiles: Set<DocumentURI>)
3638
}

0 commit comments

Comments
 (0)