-
Notifications
You must be signed in to change notification settings - Fork 273
feat(amazonq): Added LSP Manifest manager related changes #5387
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
Merged
Merged
Changes from 10 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
c4aa8cb
Added Manifest Fetcher
LokeshDogga13 d1ca7d1
Addressing code review comments
LokeshDogga13 600f91a
Added unit test cases
LokeshDogga13 cad10ef
Fixing lint issues
LokeshDogga13 2607eec
Merge branch 'feature/q-lsp' into lodogga/initialChanges
LokeshDogga13 b0e9648
Addressing code review comments
LokeshDogga13 973b710
Addressing code review comments
LokeshDogga13 2641472
Merge branch 'feature/q-lsp' into lodogga/initialChanges
LokeshDogga13 fef3b06
Fixing lint issues
LokeshDogga13 539cb7e
Merge remote-tracking branch 'origin/lodogga/initialChanges' into lod…
LokeshDogga13 563ca08
Addressing code review comments
LokeshDogga13 8f44478
Fixing detektMain lint issues
LokeshDogga13 30f8dc6
Added unit test cases
LokeshDogga13 eef3e59
Merge branch 'feature/q-lsp' into lodogga/initialChanges
LokeshDogga13 bc25fb9
Updating code according to spec.
LokeshDogga13 7ac76b0
detekt
LokeshDogga13 a28dca7
Merge branch 'feature/q-lsp' into lodogga/initialChanges
LokeshDogga13 20e7451
Fixing typo
LokeshDogga13 a970509
Artifact changes
LokeshDogga13 44f5c7b
Fixing validation function
LokeshDogga13 60c4b1c
Merge branch 'feature/q-lsp' into lodogga/initialChanges
LokeshDogga13 65f6f68
Addressing code review comments
LokeshDogga13 224289d
Merge branch 'feature/q-lsp' into lodogga/initialChanges
LokeshDogga13 3e1bc1e
Fixing Detekt
LokeshDogga13 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
59 changes: 59 additions & 0 deletions
59
...tst/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ManifestFetcherTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| // 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.artifacts | ||
|
|
||
| import io.mockk.every | ||
| import io.mockk.spyk | ||
| import io.mockk.verify | ||
| import org.junit.jupiter.api.Assertions.assertEquals | ||
| import org.junit.jupiter.api.BeforeEach | ||
| import org.junit.jupiter.api.Test | ||
| import software.aws.toolkits.jetbrains.services.amazonq.project.manifest.ManifestManager | ||
|
|
||
| class ManifestFetcherTest { | ||
|
|
||
| private lateinit var manifestFetcher: ManifestFetcher | ||
| private lateinit var manifest: ManifestManager.Manifest | ||
|
|
||
| @BeforeEach | ||
| fun setup() { | ||
| manifestFetcher = ManifestFetcher() | ||
| manifest = ManifestManager.Manifest() | ||
| } | ||
|
|
||
| @Test | ||
| fun `should return null when both local and remote manifests are null`() { | ||
| val fetchLocalManifestMock = spyk<ManifestFetcher>(recordPrivateCalls = true) | ||
|
|
||
| every { fetchLocalManifestMock["fetchManifestFromLocal"]() } returns null | ||
| every { fetchLocalManifestMock["fetchManifestFromRemote"]() } returns null | ||
|
|
||
| assertEquals(fetchLocalManifestMock.fetch(), null) | ||
LokeshDogga13 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| verify { fetchLocalManifestMock["fetchManifestFromLocal"]() } | ||
| verify { fetchLocalManifestMock["fetchManifestFromRemote"]() } | ||
| } | ||
|
|
||
| @Test | ||
| fun `should return valid result from local should not execute remote method`() { | ||
| val fetchLocalManifestMock = spyk<ManifestFetcher>(recordPrivateCalls = true) | ||
|
|
||
| every { fetchLocalManifestMock["fetchManifestFromLocal"]() } returns manifest | ||
| every { fetchLocalManifestMock["fetchManifestFromRemote"]() } returns null | ||
|
|
||
| assertEquals(fetchLocalManifestMock.fetch(), manifest) | ||
| verify { fetchLocalManifestMock["fetchManifestFromLocal"]() } | ||
| } | ||
|
|
||
| @Test | ||
| fun `should return valid result from remote`() { | ||
| val fetchLocalManifestMock = spyk<ManifestFetcher>(recordPrivateCalls = true) | ||
|
|
||
| every { fetchLocalManifestMock["fetchManifestFromLocal"]() } returns null | ||
| every { fetchLocalManifestMock["fetchManifestFromRemote"]() } returns manifest | ||
|
|
||
| assertEquals(fetchLocalManifestMock.fetch(), manifest) | ||
| verify { fetchLocalManifestMock["fetchManifestFromLocal"]() } | ||
| verify { fetchLocalManifestMock["fetchManifestFromRemote"]() } | ||
| } | ||
| } | ||
20 changes: 20 additions & 0 deletions
20
...-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // 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.artifacts | ||
|
|
||
| import com.intellij.openapi.util.SystemInfo | ||
| import java.nio.file.Path | ||
| import java.nio.file.Paths | ||
|
|
||
| fun getToolkitsCommonCachePath(): Path = when { | ||
LokeshDogga13 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| SystemInfo.isWindows -> { | ||
| Paths.get(System.getenv("APPDATA")) | ||
LokeshDogga13 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| SystemInfo.isMac -> { | ||
| Paths.get(System.getProperty("user.home"), "Library", "Caches") | ||
| } | ||
| else -> { | ||
| Paths.get(System.getProperty("user.home"), ".cache") | ||
| } | ||
| } | ||
100 changes: 100 additions & 0 deletions
100
...ity/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ManifestFetcher.kt
LokeshDogga13 marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| // 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.artifacts | ||
|
|
||
| import com.intellij.openapi.util.text.StringUtil | ||
| import com.intellij.util.io.DigestUtil | ||
| import software.aws.toolkits.core.utils.exists | ||
| import software.aws.toolkits.core.utils.getLogger | ||
| import software.aws.toolkits.core.utils.readText | ||
| import software.aws.toolkits.jetbrains.core.getETagFromUrl | ||
| import software.aws.toolkits.jetbrains.core.getTextFromUrl | ||
| import software.aws.toolkits.jetbrains.core.saveFileFromUrl | ||
| import software.aws.toolkits.jetbrains.services.amazonq.project.manifest.ManifestManager | ||
| import java.nio.file.Path | ||
|
|
||
| class ManifestFetcher { | ||
|
||
|
|
||
| private val lspManifestUrl = "https://aws-toolkit-language-servers.amazonaws.com/codewhisperer/0/manifest.json" | ||
| private val manifestManager = ManifestManager() | ||
| private val lspManifestFilePath: Path = getToolkitsCommonCachePath().resolve("aws").resolve("toolkits").resolve("language-servers") | ||
| .resolve("lsp-manifest.json") | ||
|
|
||
| companion object { | ||
| private val logger = getLogger<ManifestFetcher>() | ||
| } | ||
|
|
||
| /** | ||
| * Method which will be used to fetch latest manifest. | ||
| * */ | ||
| fun fetch(): ManifestManager.Manifest? { | ||
| val localManifest = fetchManifestFromLocal() | ||
| if (localManifest != null) { | ||
| return localManifest | ||
| } | ||
| val remoteManifest = fetchManifestFromRemote() ?: return null | ||
| return remoteManifest | ||
LokeshDogga13 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| private fun fetchManifestFromRemote(): ManifestManager.Manifest? { | ||
| val manifest: ManifestManager.Manifest? | ||
| try { | ||
| val manifestString = getTextFromUrl(lspManifestUrl) | ||
| manifest = manifestManager.readManifestFile(manifestString) ?: return null | ||
| } catch (e: Exception) { | ||
| logger.error("error fetching lsp manifest from remote URL ${e.message}", e) | ||
| return null | ||
| } | ||
| if (manifest.isManifestDeprecated == true) { | ||
| logger.info("Manifest is deprecated") | ||
| return null | ||
| } | ||
| updateManifestCache() | ||
| logger.info("Using manifest found from remote URL") | ||
| return manifest | ||
| } | ||
|
|
||
| private fun updateManifestCache() { | ||
| try { | ||
| saveFileFromUrl(lspManifestUrl, lspManifestFilePath) | ||
| } catch (e: Exception) { | ||
| logger.error("error occurred while saving lsp manifest to local cache ${e.message}", e) | ||
| } | ||
| } | ||
|
|
||
| private fun fetchManifestFromLocal(): ManifestManager.Manifest? { | ||
| val localETag = getManifestETagFromLocal() | ||
| val remoteETag = getManifestETagFromUrl() | ||
| // If local and remote have same ETag, we can re-use the manifest file from local to fetch artifacts. | ||
| if (localETag != null && remoteETag != null && localETag == remoteETag) { | ||
| try { | ||
| val manifestContent = lspManifestFilePath.readText() | ||
| return manifestManager.readManifestFile(manifestContent) | ||
| } catch (e: Exception) { | ||
| logger.error("error reading lsp manifest file from local ${e.message}", e) | ||
| return null | ||
| } | ||
| } | ||
| return null | ||
| } | ||
|
|
||
| private fun getManifestETagFromLocal(): String? { | ||
| if (lspManifestFilePath.exists()) { | ||
| val messageDigest = DigestUtil.md5() | ||
| DigestUtil.updateContentHash(messageDigest, lspManifestFilePath) | ||
| return StringUtil.toHexString(messageDigest.digest()) | ||
| } | ||
| return null | ||
| } | ||
|
|
||
| private fun getManifestETagFromUrl(): String? { | ||
| try { | ||
| val actualETag = getETagFromUrl(lspManifestUrl) | ||
| return actualETag.trim('"') | ||
| } catch (e: Exception) { | ||
| logger.error("error fetching ETag of lsp manifest from url.", e) | ||
| } | ||
| return null | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.