Skip to content

Commit 4fbb75f

Browse files
committed
feat(amazonq): expose lsp server capabilities to consumers of AmazonQLspService
For certain capabilities, the client implementation needs to be aware of what resources the server is interested in. In the case of `WorkspaceEdit`, we need to expose the filters returned by the server in the initialization handshake. ```json "fileOperations": { "didCreate": { "filters": [ { "pattern": { "glob": "**/*.{ts,js,py,java}", "matches": "file" } }, { "pattern": { "glob": "**/*", "matches": "folder" } } ] }, "didRename": { "filters": [ { "pattern": { "glob": "**/*.{ts,js,py,java}", "matches": "file" } }, { "pattern": { "glob": "**/*", "matches": "folder" } } ] }, "didDelete": { "filters": [ { "pattern": { "glob": "**/*.{ts,js,py,java}", "matches": "file" } }, { "pattern": { "glob": "**/*", "matches": "folder" } } ] } } ```
1 parent bd4dd63 commit 4fbb75f

File tree

1 file changed

+16
-13
lines changed
  • plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp

1 file changed

+16
-13
lines changed

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ import com.intellij.openapi.util.Key
2121
import com.intellij.util.io.await
2222
import kotlinx.coroutines.CoroutineScope
2323
import kotlinx.coroutines.Deferred
24-
import kotlinx.coroutines.Job
2524
import kotlinx.coroutines.TimeoutCancellationException
2625
import kotlinx.coroutines.async
27-
import kotlinx.coroutines.launch
2826
import kotlinx.coroutines.runBlocking
2927
import kotlinx.coroutines.sync.Mutex
3028
import kotlinx.coroutines.sync.withLock
@@ -33,7 +31,7 @@ import org.eclipse.lsp4j.ClientCapabilities
3331
import org.eclipse.lsp4j.ClientInfo
3432
import org.eclipse.lsp4j.FileOperationsWorkspaceCapabilities
3533
import org.eclipse.lsp4j.InitializeParams
36-
import org.eclipse.lsp4j.InitializedParams
34+
import org.eclipse.lsp4j.InitializeResult
3735
import org.eclipse.lsp4j.SynchronizationCapabilities
3836
import org.eclipse.lsp4j.TextDocumentClientCapabilities
3937
import org.eclipse.lsp4j.WorkspaceClientCapabilities
@@ -95,6 +93,8 @@ internal class LSPProcessListener : ProcessListener {
9593
@Service(Service.Level.PROJECT)
9694
class AmazonQLspService(private val project: Project, private val cs: CoroutineScope) : Disposable {
9795
private var instance: Deferred<AmazonQServerInstance>
96+
val capabilities
97+
get() = instance.getCompleted().initializeResult.getCompleted().capabilities
9898

9999
// dont allow lsp commands if server is restarting
100100
private val mutex = Mutex(false)
@@ -110,7 +110,7 @@ class AmazonQLspService(private val project: Project, private val cs: CoroutineS
110110
Disposer.register(this@AmazonQLspService, it)
111111
}
112112
// wait for handshake to complete
113-
instance.initializer.join()
113+
instance.initializeResult.join()
114114

115115
instance
116116
}
@@ -140,7 +140,7 @@ class AmazonQLspService(private val project: Project, private val cs: CoroutineS
140140

141141
try {
142142
val i = it.await()
143-
if (i.initializer.isActive) {
143+
if (i.initializeResult.isActive) {
144144
// not initialized
145145
return
146146
}
@@ -154,17 +154,17 @@ class AmazonQLspService(private val project: Project, private val cs: CoroutineS
154154
instance = start()
155155
}
156156

157-
suspend fun<T> execute(runnable: suspend (AmazonQLanguageServer) -> T): T {
157+
suspend fun<T> execute(runnable: suspend AmazonQLspService.(AmazonQLanguageServer) -> T): T {
158158
val lsp = withTimeout(10.seconds) {
159159
val holder = mutex.withLock { instance }.await()
160-
holder.initializer.join()
160+
holder.initializeResult.join()
161161

162162
holder.languageServer
163163
}
164164
return runnable(lsp)
165165
}
166166

167-
fun<T> executeSync(runnable: suspend (AmazonQLanguageServer) -> T): T =
167+
fun<T> executeSync(runnable: suspend AmazonQLspService.(AmazonQLanguageServer) -> T): T =
168168
runBlocking(cs.coroutineContext) {
169169
execute(runnable)
170170
}
@@ -173,7 +173,7 @@ class AmazonQLspService(private val project: Project, private val cs: CoroutineS
173173
private val LOG = getLogger<AmazonQLspService>()
174174
fun getInstance(project: Project) = project.service<AmazonQLspService>()
175175

176-
fun <T> executeIfRunning(project: Project, runnable: (AmazonQLanguageServer) -> T): T? =
176+
fun <T> executeIfRunning(project: Project, runnable: AmazonQLspService.(AmazonQLanguageServer) -> T): T? =
177177
project.serviceIfCreated<AmazonQLspService>()?.executeSync(runnable)
178178
}
179179
}
@@ -189,7 +189,7 @@ private class AmazonQServerInstance(private val project: Project, private val cs
189189
@Suppress("ForbiddenVoid")
190190
private val launcherFuture: Future<Void>
191191
private val launcherHandler: KillableProcessHandler
192-
val initializer: Job
192+
val initializeResult: Deferred<InitializeResult>
193193

194194
private fun createClientCapabilities(): ClientCapabilities =
195195
ClientCapabilities().apply {
@@ -244,7 +244,8 @@ private class AmazonQServerInstance(private val project: Project, private val cs
244244

245245
init {
246246
val cmd = GeneralCommandLine(
247-
"amazon-q-lsp",
247+
"/opt/homebrew/opt/node@20/bin/node",
248+
"/Users/richali/idetools/language-servers/app/aws-lsp-codewhisperer-runtimes/out/token-standalone.js",
248249
"--stdio",
249250
"--set-credentials-encryption-key",
250251
)
@@ -281,7 +282,7 @@ private class AmazonQServerInstance(private val project: Project, private val cs
281282

282283
launcherFuture = launcher.startListening()
283284

284-
initializer = cs.launch {
285+
initializeResult = cs.async {
285286
// encryption info must be sent within 5s or Flare process will exit
286287
encryptionManager.writeInitializationPayload(launcherHandler.process.outputStream)
287288

@@ -300,8 +301,10 @@ private class AmazonQServerInstance(private val project: Project, private val cs
300301
// then if this succeeds then we can allow the client to send requests
301302
if (initializeResult == null) {
302303
launcherHandler.destroyProcess()
304+
error("LSP initialization failed")
303305
}
304-
languageServer.initialized(InitializedParams())
306+
307+
initializeResult
305308
}
306309
}
307310

0 commit comments

Comments
 (0)