Skip to content

Commit 5abb4b0

Browse files
samgst-amazonleigaol
authored andcommitted
feat(amazonq): implement TextDocumentService message handler (aws#5380)
initial framework for TextDocumentService message implementations
1 parent 7fca93f commit 5abb4b0

File tree

3 files changed

+434
-0
lines changed

3 files changed

+434
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import software.aws.toolkits.jetbrains.isDeveloperMode
4646
import software.aws.toolkits.jetbrains.services.amazonq.lsp.auth.DefaultAuthCredentialsService
4747
import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryptionManager
4848
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.createExtendedClientMetadata
49+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.textdocument.TextDocumentServiceHandler
4950
import software.aws.toolkits.jetbrains.services.amazonq.lsp.util.WorkspaceFolderUtil.createWorkspaceFolders
5051
import software.aws.toolkits.jetbrains.services.amazonq.lsp.workspace.WorkspaceServiceHandler
5152
import software.aws.toolkits.jetbrains.services.telemetry.ClientMetadata
@@ -300,6 +301,7 @@ private class AmazonQServerInstance(private val project: Project, private val cs
300301
}
301302

302303
DefaultAuthCredentialsService(project, encryptionManager, this)
304+
TextDocumentServiceHandler(project, this)
303305
WorkspaceServiceHandler(project, this)
304306
}
305307

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.amazonq.lsp.textdocument
5+
6+
import com.intellij.openapi.Disposable
7+
import com.intellij.openapi.editor.Document
8+
import com.intellij.openapi.fileEditor.FileDocumentManager
9+
import com.intellij.openapi.fileEditor.FileDocumentManagerListener
10+
import com.intellij.openapi.fileEditor.FileEditorManager
11+
import com.intellij.openapi.fileEditor.FileEditorManagerListener
12+
import com.intellij.openapi.project.Project
13+
import com.intellij.openapi.vfs.VirtualFile
14+
import com.intellij.openapi.vfs.VirtualFileManager
15+
import com.intellij.openapi.vfs.newvfs.BulkFileListener
16+
import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent
17+
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
18+
import org.eclipse.lsp4j.DidChangeTextDocumentParams
19+
import org.eclipse.lsp4j.DidCloseTextDocumentParams
20+
import org.eclipse.lsp4j.DidOpenTextDocumentParams
21+
import org.eclipse.lsp4j.DidSaveTextDocumentParams
22+
import org.eclipse.lsp4j.TextDocumentContentChangeEvent
23+
import org.eclipse.lsp4j.TextDocumentIdentifier
24+
import org.eclipse.lsp4j.TextDocumentItem
25+
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier
26+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
27+
import software.aws.toolkits.jetbrains.utils.pluginAwareExecuteOnPooledThread
28+
29+
class TextDocumentServiceHandler(
30+
private val project: Project,
31+
serverInstance: Disposable,
32+
) : FileDocumentManagerListener,
33+
FileEditorManagerListener,
34+
BulkFileListener {
35+
36+
init {
37+
// didOpen & didClose events
38+
project.messageBus.connect(serverInstance).subscribe(
39+
FileEditorManagerListener.FILE_EDITOR_MANAGER,
40+
this
41+
)
42+
43+
// didChange events
44+
project.messageBus.connect(serverInstance).subscribe(
45+
VirtualFileManager.VFS_CHANGES,
46+
this
47+
)
48+
49+
// didSave events
50+
project.messageBus.connect(serverInstance).subscribe(
51+
FileDocumentManagerListener.TOPIC,
52+
this
53+
)
54+
}
55+
56+
override fun beforeDocumentSaving(document: Document) {
57+
AmazonQLspService.executeIfRunning(project) { languageServer ->
58+
val file = FileDocumentManager.getInstance().getFile(document) ?: return@executeIfRunning
59+
file.toNioPath().toUri().toString().takeIf { it.isNotEmpty() }?.let { uri ->
60+
languageServer.textDocumentService.didSave(
61+
DidSaveTextDocumentParams().apply {
62+
textDocument = TextDocumentIdentifier().apply {
63+
this.uri = uri
64+
}
65+
text = document.text
66+
}
67+
)
68+
}
69+
}
70+
}
71+
72+
override fun after(events: MutableList<out VFileEvent>) {
73+
AmazonQLspService.executeIfRunning(project) { languageServer ->
74+
pluginAwareExecuteOnPooledThread {
75+
events.filterIsInstance<VFileContentChangeEvent>().forEach { event ->
76+
val document = FileDocumentManager.getInstance().getCachedDocument(event.file) ?: return@forEach
77+
event.file.toNioPath().toUri().toString().takeIf { it.isNotEmpty() }?.let { uri ->
78+
languageServer.textDocumentService.didChange(
79+
DidChangeTextDocumentParams().apply {
80+
textDocument = VersionedTextDocumentIdentifier().apply {
81+
this.uri = uri
82+
version = document.modificationStamp.toInt()
83+
}
84+
contentChanges = listOf(
85+
TextDocumentContentChangeEvent().apply {
86+
text = document.text
87+
}
88+
)
89+
}
90+
)
91+
}
92+
}
93+
}
94+
}
95+
}
96+
97+
override fun fileOpened(
98+
source: FileEditorManager,
99+
file: VirtualFile,
100+
) {
101+
AmazonQLspService.executeIfRunning(project) { languageServer ->
102+
file.toNioPath().toUri().toString().takeIf { it.isNotEmpty() }?.let { uri ->
103+
languageServer.textDocumentService.didOpen(
104+
DidOpenTextDocumentParams().apply {
105+
textDocument = TextDocumentItem().apply {
106+
this.uri = uri
107+
text = file.inputStream.readAllBytes().decodeToString()
108+
}
109+
}
110+
)
111+
}
112+
}
113+
}
114+
115+
override fun fileClosed(
116+
source: FileEditorManager,
117+
file: VirtualFile,
118+
) {
119+
AmazonQLspService.executeIfRunning(project) { languageServer ->
120+
file.toNioPath().toUri().toString().takeIf { it.isNotEmpty() }?.let { uri ->
121+
languageServer.textDocumentService.didClose(
122+
DidCloseTextDocumentParams().apply {
123+
textDocument = TextDocumentIdentifier().apply {
124+
this.uri = uri
125+
}
126+
}
127+
)
128+
}
129+
}
130+
}
131+
}

0 commit comments

Comments
 (0)