Skip to content

Commit

Permalink
Expose ServerInfo (#17)
Browse files Browse the repository at this point in the history
* Expose ServerInfo

* Use InitializationResponse

* Remove spaces
  • Loading branch information
FastestMolasses authored Jan 28, 2024
1 parent f8fdeae commit 94bb1bb
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 27 deletions.
74 changes: 48 additions & 26 deletions Sources/LanguageClient/InitializingServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ public actor InitializingServer {

private enum State {
case uninitialized
case initialized(ServerCapabilities)
case initialized(InitializationResponse)
case shutdown

var capabilities: ServerCapabilities? {
get {
switch self {
case .initialized(let capabilities):
return capabilities
case .initialized(let initResp):
return initResp.capabilities
case .uninitialized, .shutdown:
return nil
}
Expand All @@ -40,13 +40,22 @@ public actor InitializingServer {
}

switch self {
case .initialized:
self = .initialized(caps)
case .initialized(let initResp):
self = .initialized(initResp)
case .uninitialized, .shutdown:
break
}
}
}

var serverInfo: ServerInfo? {
switch self {
case .initialized(let initResp):
return initResp.serverInfo
case .uninitialized, .shutdown:
return nil
}
}
}

private let channel: ServerConnection
Expand Down Expand Up @@ -94,6 +103,23 @@ public actor InitializingServer {
return state.capabilities
}
}

/// Return the server's info.
///
/// This will not start the server if it isn't already running.
public var serverInfo: ServerInfo? {
get async {
do {
try await semaphore.waitUnlessCancelled()
} catch {
return nil
}

defer { semaphore.signal() }

return state.serverInfo
}
}
}

extension InitializingServer: StatefulServer {
Expand Down Expand Up @@ -158,45 +184,42 @@ extension InitializingServer: StatefulServer {

extension InitializingServer {
/// Run the initialization sequence with the server, if it has not already happened.
public func initializeIfNeeded() async throws -> ServerCapabilities {
public func initializeIfNeeded() async throws -> InitializationResponse {
switch state {
case .initialized(let caps):
return caps
case .initialized(let initResp):
return initResp
case .uninitialized, .shutdown:
try await semaphore.waitUnlessCancelled()
}

defer { semaphore.signal() }

let params = try await initializeParamsProvider()

let initResponse = try await channel.initialize(params)
let caps = initResponse.capabilities

try await channel.initialized(InitializedParams())
self.state = .initialized(initResponse)

self.state = .initialized(caps)
capabilitiesContinuation.yield(initResponse.capabilities)

capabilitiesContinuation.yield(caps)

return caps
return initResponse
}

private func handleEvent(_ event: ServerEvent) {
switch event {
case let .request(_, request):
handleRequest(request)
default:
break
}
}
switch event {
case let .request(_, request):
handleRequest(request)
default:
break
}
}

private func handleRequest(_ request: ServerRequest) {
guard case .initialized(let caps) = self.state else {
guard case .initialized(let initResp) = self.state else {
fatalError("received a request without being initialized")
}

var newCaps = caps
var newCaps = initResp.capabilities

do {
switch request {
Expand All @@ -211,9 +234,8 @@ extension InitializingServer {
print("unable to mutate server capabilities: \(error)")
}

if caps != newCaps {
self.state = .initialized(newCaps)

if initResp.capabilities != newCaps {
self.state = .initialized(InitializationResponse(capabilities: newCaps, serverInfo: initResp.serverInfo))
capabilitiesContinuation.yield(newCaps)
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/LanguageClient/RestartingServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public actor RestartingServer<WrappedServer: ServerConnection & Sendable> {
}

/// Run the initialization sequence with the server, if it has not already happened.
public func initializeIfNeeded() async throws -> ServerCapabilities {
public func initializeIfNeeded() async throws -> InitializationResponse {
try await startServerIfNeeded().initializeIfNeeded()
}

Expand Down

0 comments on commit 94bb1bb

Please sign in to comment.