Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(amazonq): implement workspace file messages #5377

Open
wants to merge 24 commits into
base: feature/q-lsp
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
686fda2
add workspace handler
samgst-amazon Feb 13, 2025
a5250b5
break up repeat code
samgst-amazon Feb 14, 2025
0efb633
use serverInstance as messageBus disposable
samgst-amazon Feb 14, 2025
788e833
init starts listeners
samgst-amazon Feb 14, 2025
429f5e9
update listeners
samgst-amazon Feb 17, 2025
aababb6
fix init params
samgst-amazon Feb 17, 2025
c3d855a
didChangeWatchedFiles impl
samgst-amazon Feb 18, 2025
f826372
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 18, 2025
fad4467
detekt
samgst-amazon Feb 18, 2025
ffa167a
move executeIfRunning
samgst-amazon Feb 18, 2025
94c25e4
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 18, 2025
87817ea
private class
samgst-amazon Feb 18, 2025
d495450
null uri handling
samgst-amazon Feb 19, 2025
7cff72e
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 19, 2025
70b7e53
didChangeWorkspaceFolders
samgst-amazon Feb 20, 2025
eaa993a
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 24, 2025
d139dc4
detekt
samgst-amazon Feb 24, 2025
5458f0c
add tests for changeWorkspaceFolders
samgst-amazon Feb 24, 2025
0628cae
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 26, 2025
3f2a98d
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 28, 2025
401826d
fix test
samgst-amazon Feb 28, 2025
780395e
glob pattern matching
samgst-amazon Feb 28, 2025
8ee75f8
Merge branch 'feature/q-lsp' into samgst/lsp-WSmessages
samgst-amazon Feb 28, 2025
de16193
add didRename
samgst-amazon Mar 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import software.aws.toolkits.jetbrains.isDeveloperMode
import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryptionManager
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.createExtendedClientMetadata
import software.aws.toolkits.jetbrains.services.amazonq.lsp.workspace.WorkspaceServiceHandler
import software.aws.toolkits.jetbrains.services.telemetry.ClientMetadata
import java.io.IOException
import java.io.OutputStreamWriter
Expand Down Expand Up @@ -111,7 +112,7 @@
}
}

private class AmazonQServerInstance(private val project: Project, private val cs: CoroutineScope) : Disposable {

Check warning on line 115 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Constructor parameter is never used as a property

Constructor parameter is never used as a property
private val encryptionManager = JwtEncryptionManager()

private val launcher: Launcher<AmazonQLanguageServer>
Expand Down Expand Up @@ -235,6 +236,10 @@
}
languageServer.initialized(InitializedParams())
}

//may need to register listeners differently so their messageBus' don't get garbage collected
val workspaceServiceHandler = WorkspaceServiceHandler(project, languageServer)
workspaceServiceHandler.startWorkspaceServiceListeners()
}

override fun dispose() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.amazonq.lsp.workspace

import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.vfs.newvfs.BulkFileListener
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent
import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
import org.eclipse.lsp4j.CreateFilesParams
import org.eclipse.lsp4j.DeleteFilesParams
import org.eclipse.lsp4j.FileCreate
import org.eclipse.lsp4j.FileDelete
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLanguageServer
import software.aws.toolkits.jetbrains.utils.pluginAwareExecuteOnPooledThread

class WorkspaceServiceHandler(
private val project: Project,
private val languageServer: AmazonQLanguageServer,
) : Disposable {

fun startWorkspaceServiceListeners() {
startFileLifecycleListener()
}

private fun didCreateFiles(events: List<VFileEvent>){
if (events.isNotEmpty()) {
languageServer.workspaceService.didCreateFiles(
CreateFilesParams().apply {
files = events.map { event ->
FileCreate().apply {
uri = event.file?.toNioPath()?.toUri().toString()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets make a util for virtualfile -> URI because we will likely have a lot of edge cases to deal with

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if there is no file we should not emit an event

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought this would be handled by if (events.isNotEmpty()) for both messages

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess i meant if the uri is null then we shouldn't emit an event because that doesn't seem useful

}
}
}
)
}
}

private fun didDeleteFiles(events: List<VFileEvent>) {
if (events.isNotEmpty()) {
languageServer.workspaceService.didDeleteFiles(
DeleteFilesParams().apply {
files = events.map { event ->
FileDelete().apply {
uri = event.file?.toNioPath()?.toUri().toString()
}
}
}
)
}
}

private fun startFileLifecycleListener() {
project.messageBus.connect(this).subscribe(
VirtualFileManager.VFS_CHANGES,
object : BulkFileListener {
override fun after(events: List<VFileEvent>) {
// since we are using synchronous FileListener
pluginAwareExecuteOnPooledThread {
didCreateFiles(events.filterIsInstance<VFileCreateEvent>())
didDeleteFiles(events.filterIsInstance<VFileDeleteEvent>())
}
}
}
)
}

// still need to implement
//private fun didChangeWorkspaceFolders() {
// languageServer.workspaceService.didChangeWorkspaceFolders()
//}

override fun dispose() {
}
}
Loading