-
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
Changes from all commits
c4aa8cb
d1ca7d1
600f91a
cad10ef
2607eec
b0e9648
973b710
2641472
fef3b06
539cb7e
563ca08
8f44478
30f8dc6
eef3e59
bc25fb9
7ac76b0
a28dca7
20e7451
a970509
44f5c7b
60c4b1c
65f6f68
224289d
3e1bc1e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| // 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.util.io.createDirectories | ||
| import com.intellij.util.text.SemVer | ||
| import software.aws.toolkits.core.utils.deleteIfExists | ||
| import software.aws.toolkits.core.utils.error | ||
| import software.aws.toolkits.core.utils.exists | ||
| import software.aws.toolkits.core.utils.getLogger | ||
| import software.aws.toolkits.core.utils.info | ||
| import software.aws.toolkits.core.utils.warn | ||
| import software.aws.toolkits.jetbrains.core.saveFileFromUrl | ||
| import software.aws.toolkits.jetbrains.services.amazonq.project.manifest.ManifestManager | ||
| import java.nio.file.Path | ||
| import java.util.concurrent.atomic.AtomicInteger | ||
|
|
||
| class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH, private val maxDownloadAttempts: Int = MAX_DOWNLOAD_ATTEMPTS) { | ||
|
Check warning on line 19 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| companion object { | ||
| private val DEFAULT_ARTIFACT_PATH = getToolkitsCommonCacheRoot().resolve("aws").resolve("toolkits").resolve("language-servers") | ||
| private val logger = getLogger<ArtifactHelper>() | ||
|
Check warning on line 23 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| private const val MAX_DOWNLOAD_ATTEMPTS = 3 | ||
| } | ||
| private val currentAttempt = AtomicInteger(0) | ||
|
Check warning on line 26 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| fun removeDelistedVersions(delistedVersions: List<ManifestManager.Version>) { | ||
| val localFolders = getSubFolders(lspArtifactsPath) | ||
|
Check warning on line 29 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| delistedVersions.forEach { delistedVersion -> | ||
|
Check warning on line 31 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| val versionToDelete = delistedVersion.serverVersion ?: return@forEach | ||
|
|
||
| localFolders | ||
| .filter { folder -> folder.fileName.toString() == versionToDelete } | ||
| .forEach { folder -> | ||
| try { | ||
| folder.toFile().deleteRecursively() | ||
| logger.info { "Successfully deleted deListed version: ${folder.fileName}" } | ||
| } catch (e: Exception) { | ||
| logger.error(e) { "Failed to delete deListed version ${folder.fileName}: ${e.message}" } | ||
|
Check warning on line 41 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| } | ||
| } | ||
| } | ||
|
Check warning on line 45 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| fun deleteOlderLspArtifacts(manifestVersionRanges: ArtifactManager.SupportedManifestVersionRange) { | ||
| val localFolders = getSubFolders(lspArtifactsPath) | ||
|
Check warning on line 48 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| val validVersions = localFolders | ||
| .mapNotNull { localFolder -> | ||
|
Check warning on line 51 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| SemVer.parseFromText(localFolder.fileName.toString())?.let { semVer -> | ||
| if (semVer in manifestVersionRanges.startVersion..manifestVersionRanges.endVersion) { | ||
| localFolder to semVer | ||
|
Check warning on line 54 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } else { | ||
| null | ||
| } | ||
| } | ||
|
Check warning on line 58 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| .sortedByDescending { (_, semVer) -> semVer } | ||
|
Check warning on line 60 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| // Keep the latest 2 versions, delete others | ||
| validVersions.drop(2).forEach { (folder, _) -> | ||
| try { | ||
| folder.toFile().deleteRecursively() | ||
| logger.info { "Deleted older LSP artifact: ${folder.fileName}" } | ||
| } catch (e: Exception) { | ||
| logger.error(e) { "Failed to delete older LSP artifact: ${folder.fileName}" } | ||
|
Check warning on line 68 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| } | ||
| } | ||
|
Check warning on line 71 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| fun getExistingLspArtifacts(versions: List<ManifestManager.Version>, target: ManifestManager.VersionTarget?): Boolean { | ||
| if (versions.isEmpty() || target?.contents == null) return false | ||
|
|
||
| val localLSPPath = lspArtifactsPath.resolve(versions.first().serverVersion.toString()) | ||
|
Check warning on line 76 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| if (!localLSPPath.exists()) return false | ||
|
|
||
| val hasInvalidFiles = target.contents.any { content -> | ||
|
Check warning on line 79 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| content.filename?.let { filename -> | ||
| val filePath = localLSPPath.resolve(filename) | ||
|
Check warning on line 81 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| !filePath.exists() || !validateFileHash(filePath, content.hashes?.firstOrNull()) | ||
| } ?: false | ||
|
Check warning on line 83 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
|
|
||
| if (hasInvalidFiles) { | ||
| try { | ||
| localLSPPath.toFile().deleteRecursively() | ||
| logger.info { "Deleted mismatched LSP artifacts at: $localLSPPath" } | ||
| } catch (e: Exception) { | ||
| logger.error(e) { "Failed to delete mismatched LSP artifacts at: $localLSPPath" } | ||
|
Check warning on line 91 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| } | ||
| return !hasInvalidFiles | ||
| } | ||
|
|
||
| fun tryDownloadLspArtifacts(versions: List<ManifestManager.Version>, target: ManifestManager.VersionTarget?) { | ||
| val temporaryDownloadPath = lspArtifactsPath.resolve("temp") | ||
| val downloadPath = lspArtifactsPath.resolve(versions.first().serverVersion.toString()) | ||
|
Check warning on line 99 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| while (currentAttempt.get() < maxDownloadAttempts) { | ||
| currentAttempt.incrementAndGet() | ||
| logger.info { "Attempt ${currentAttempt.get()} of $maxDownloadAttempts to download LSP artifacts" } | ||
|
Check warning on line 103 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| try { | ||
|
Check warning on line 105 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| if (downloadLspArtifacts(temporaryDownloadPath, target)) { | ||
| moveFilesFromSourceToDestination(temporaryDownloadPath, downloadPath) | ||
| logger.info { "Successfully downloaded and moved LSP artifacts to $downloadPath" } | ||
| return | ||
|
Check warning on line 109 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| } catch (e: Exception) { | ||
| logger.error(e) { "Failed to download/move LSP artifacts on attempt ${currentAttempt.get()}" } | ||
| temporaryDownloadPath.toFile().deleteRecursively() | ||
|
Check warning on line 113 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| if (currentAttempt.get() >= maxDownloadAttempts) { | ||
| throw LspException("Failed to download LSP artifacts after $maxDownloadAttempts attempts", LspException.ErrorCode.DOWNLOAD_FAILED) | ||
|
Check warning on line 116 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| } | ||
| } | ||
| } | ||
|
Check warning on line 120 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| private fun downloadLspArtifacts(downloadPath: Path, target: ManifestManager.VersionTarget?): Boolean { | ||
| if (target == null || target.contents.isNullOrEmpty()) { | ||
| logger.warn { "No target contents available for download" } | ||
| return false | ||
|
Check warning on line 125 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| try { | ||
| downloadPath.createDirectories() | ||
| target.contents.forEach { content -> | ||
|
Check warning on line 129 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| if (content.url == null || content.filename == null) { | ||
| logger.warn { "Missing URL or filename in content" } | ||
| return@forEach | ||
|
Check warning on line 132 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| val filePath = downloadPath.resolve(content.filename) | ||
|
Check warning on line 134 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| val contentHash = content.hashes?.firstOrNull() ?: run { | ||
| logger.warn { "No hash available for ${content.filename}" } | ||
| return@forEach | ||
|
Check warning on line 137 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| downloadAndValidateFile(content.url, filePath, contentHash) | ||
| } | ||
| validateDownloadedFiles(downloadPath, target.contents) | ||
| } catch (e: Exception) { | ||
| logger.error(e) { "Failed to download LSP artifacts: ${e.message}" } | ||
| downloadPath.toFile().deleteRecursively() | ||
| return false | ||
|
Check warning on line 145 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| return true | ||
|
Check warning on line 147 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
|
|
||
| private fun downloadAndValidateFile(url: String, filePath: Path, expectedHash: String) { | ||
| try { | ||
|
Check warning on line 151 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| if (!filePath.exists()) { | ||
| logger.info { "Downloading file: ${filePath.fileName}" } | ||
| saveFileFromUrl(url, filePath) | ||
|
Check warning on line 154 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| if (!validateFileHash(filePath, expectedHash)) { | ||
| logger.warn { "Hash mismatch for ${filePath.fileName}, re-downloading" } | ||
| filePath.deleteIfExists() | ||
| saveFileFromUrl(url, filePath) | ||
|
Check warning on line 159 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| if (!validateFileHash(filePath, expectedHash)) { | ||
| throw LspException("Hash mismatch after re-download for ${filePath.fileName}", LspException.ErrorCode.HASH_MISMATCH) | ||
|
Check warning on line 161 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| } | ||
| } catch (e: Exception) { | ||
| throw IllegalStateException("Failed to download/validate file: ${filePath.fileName}", e) | ||
|
Check warning on line 165 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| } | ||
|
Check warning on line 167 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
|
|
||
| private fun validateFileHash(filePath: Path, expectedHash: String?): Boolean { | ||
| if (expectedHash == null) return false | ||
| val contentHash = generateSHA384Hash(filePath) | ||
| return "sha384:$contentHash" == expectedHash | ||
|
Check warning on line 172 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
|
|
||
| private fun validateDownloadedFiles(downloadPath: Path, contents: List<ManifestManager.TargetContent>) { | ||
| val missingFiles = contents | ||
| .mapNotNull { it.filename } | ||
| .filter { filename -> | ||
|
Check warning on line 178 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| !downloadPath.resolve(filename).exists() | ||
| } | ||
| if (missingFiles.isNotEmpty()) { | ||
| val errorMessage = "Missing required files: ${missingFiles.joinToString(", ")}" | ||
| logger.error { errorMessage } | ||
| throw LspException(errorMessage, LspException.ErrorCode.DOWNLOAD_FAILED) | ||
|
Check warning on line 184 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| } | ||
|
Check warning on line 186 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactHelper.kt
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| // 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.util.text.SemVer | ||
| import org.assertj.core.util.VisibleForTesting | ||
| import software.aws.toolkits.core.utils.error | ||
| import software.aws.toolkits.core.utils.getLogger | ||
| import software.aws.toolkits.core.utils.info | ||
| import software.aws.toolkits.jetbrains.services.amazonq.project.manifest.ManifestManager | ||
|
|
||
| class ArtifactManager { | ||
|
|
||
| data class SupportedManifestVersionRange( | ||
| val startVersion: SemVer, | ||
| val endVersion: SemVer, | ||
|
Check warning on line 17 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| ) | ||
| data class LSPVersions( | ||
| val deListedVersions: List<ManifestManager.Version>, | ||
| val inRangeVersions: List<ManifestManager.Version>, | ||
|
Check warning on line 21 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| ) | ||
|
|
||
| private val manifestFetcher: ManifestFetcher | ||
| private val artifactHelper: ArtifactHelper | ||
| private val manifestVersionRanges: SupportedManifestVersionRange | ||
|
|
||
| // Primary constructor with config | ||
| constructor( | ||
| manifestFetcher: ManifestFetcher = ManifestFetcher(), | ||
| artifactFetcher: ArtifactHelper = ArtifactHelper(), | ||
|
Check warning on line 31 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| manifestRange: SupportedManifestVersionRange?, | ||
| ) { | ||
|
Check warning on line 33 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| manifestVersionRanges = manifestRange ?: DEFAULT_VERSION_RANGE | ||
| this.manifestFetcher = manifestFetcher | ||
| this.artifactHelper = artifactFetcher | ||
| } | ||
|
Check warning on line 37 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
|
|
||
| // Secondary constructor with no parameters | ||
| constructor() : this(ManifestFetcher(), ArtifactHelper(), null) | ||
|
Check warning on line 40 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
Check warningCode scanning / QDJVMC Unused symbol Warning
Constructor is never used
|
||
|
|
||
| companion object { | ||
| private val DEFAULT_VERSION_RANGE = SupportedManifestVersionRange( | ||
| startVersion = SemVer("3.0.0", 3, 0, 0), | ||
| endVersion = SemVer("4.0.0", 4, 0, 0) | ||
|
Check warning on line 45 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| ) | ||
| private val logger = getLogger<ArtifactManager>() | ||
|
Check warning on line 47 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| } | ||
|
|
||
| fun fetchArtifact() { | ||
Check warningCode scanning / QDJVMC Unused symbol Warning
Function "fetchArtifact" is never used
|
||
| val manifest = manifestFetcher.fetch() ?: throw LspException( | ||
| "Language Support is not available, as manifest is missing.", | ||
| LspException.ErrorCode.MANIFEST_FETCH_FAILED | ||
|
Check warning on line 53 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| ) | ||
| val lspVersions = getLSPVersionsFromManifestWithSpecifiedRange(manifest) | ||
|
Check warning on line 55 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
|
|
||
| this.artifactHelper.removeDelistedVersions(lspVersions.deListedVersions) | ||
|
Check warning on line 57 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
|
|
||
| if (lspVersions.inRangeVersions.isEmpty()) { | ||
| // No versions are found which are in the given range. | ||
| throw LspException("Language server versions not found in manifest.", LspException.ErrorCode.NO_COMPATIBLE_LSP_VERSION) | ||
|
Check warning on line 61 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| } | ||
|
|
||
| // If there is an LSP Manifest with the same version | ||
| val target = getTargetFromLspManifest(lspVersions.inRangeVersions) | ||
|
Check warning on line 65 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
|
|
||
| // Get Local LSP files and check if we can re-use existing LSP Artifacts | ||
| if (!this.artifactHelper.getExistingLspArtifacts(lspVersions.inRangeVersions, target)) { | ||
| this.artifactHelper.tryDownloadLspArtifacts(lspVersions.inRangeVersions, target) | ||
|
Check warning on line 69 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| } | ||
|
|
||
| this.artifactHelper.deleteOlderLspArtifacts(manifestVersionRanges) | ||
| } | ||
|
Check warning on line 73 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
|
|
||
| @VisibleForTesting | ||
| internal fun getLSPVersionsFromManifestWithSpecifiedRange(manifest: ManifestManager.Manifest): LSPVersions { | ||
| if (manifest.versions.isNullOrEmpty()) return LSPVersions(emptyList(), emptyList()) | ||
|
|
||
| val (deListed, inRange) = manifest.versions.mapNotNull { version -> | ||
|
Check warning on line 79 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| version.serverVersion?.let { serverVersion -> | ||
| SemVer.parseFromText(serverVersion)?.let { semVer -> | ||
| when { | ||
|
Check warning on line 82 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| version.isDelisted != false -> Pair(version, true) // Is deListed | ||
| semVer in manifestVersionRanges.startVersion..manifestVersionRanges.endVersion -> Pair(version, false) // Is in range | ||
| else -> null | ||
| } | ||
| } | ||
| } | ||
| }.partition { it.second } | ||
|
Check warning on line 89 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
|
|
||
| return LSPVersions( | ||
| deListedVersions = deListed.map { it.first }, | ||
| inRangeVersions = inRange.map { it.first }.sortedByDescending { (_, semVer) -> semVer } | ||
|
Check warning on line 93 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| ) | ||
| } | ||
|
|
||
| private fun getTargetFromLspManifest(versions: List<ManifestManager.Version>): ManifestManager.VersionTarget { | ||
| val currentOS = getCurrentOS() | ||
| val currentArchitecture = getCurrentArchitecture() | ||
|
Check warning on line 99 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
|
|
||
| val currentTarget = versions.first().targets?.find { target -> | ||
| target.platform == currentOS && target.arch == currentArchitecture | ||
| } | ||
| if (currentTarget == null) { | ||
| logger.error { "Failed to obtain target for $currentOS and $currentArchitecture" } | ||
| throw LspException("Target not found in the current Version: ${versions.first().serverVersion}", LspException.ErrorCode.TARGET_NOT_FOUND) | ||
|
Check warning on line 106 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| } | ||
| logger.info { "Target found in the current Version: ${versions.first().serverVersion}" } | ||
| return currentTarget | ||
|
Check warning on line 109 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/ArtifactManager.kt
|
||
| } | ||
| } | ||
| 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 | ||
|
|
||
| class LspException(message: String, private val errorCode: ErrorCode, cause: Throwable? = null) : Exception(message, cause) { | ||
|
Check warning on line 6 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspException.kt
|
||
|
|
||
| enum class ErrorCode { | ||
| MANIFEST_FETCH_FAILED, | ||
| DOWNLOAD_FAILED, | ||
| HASH_MISMATCH, | ||
| TARGET_NOT_FOUND, | ||
| NO_COMPATIBLE_LSP_VERSION, | ||
| } | ||
|
Check warning on line 14 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspException.kt
|
||
|
|
||
| override fun toString(): String = buildString { | ||
| append("LSP Error [$errorCode]: $message") | ||
|
Check warning on line 17 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspException.kt
|
||
| cause?.let { append(", Cause: ${it.message}") } | ||
| } | ||
|
Check warning on line 19 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspException.kt
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| // 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 com.intellij.openapi.util.text.StringUtil | ||
| import com.intellij.util.io.DigestUtil | ||
| import com.intellij.util.system.CpuArch | ||
| import java.nio.file.Files | ||
| import java.nio.file.Path | ||
| import java.nio.file.Paths | ||
| import java.nio.file.StandardCopyOption | ||
| import java.security.MessageDigest | ||
| import kotlin.io.path.isDirectory | ||
| import kotlin.io.path.listDirectoryEntries | ||
|
|
||
| fun getToolkitsCommonCacheRoot(): Path = when { | ||
|
Check warning on line 18 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
| SystemInfo.isWindows -> { | ||
| Paths.get(System.getenv("LOCALAPPDATA")) | ||
|
Check warning on line 20 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
| } | ||
| SystemInfo.isMac -> { | ||
| Paths.get(System.getProperty("user.home"), "Library", "Caches") | ||
|
Check warning on line 23 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
| } | ||
| else -> { | ||
| Paths.get(System.getProperty("user.home"), ".cache") | ||
|
Check warning on line 26 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
| } | ||
| } | ||
|
Check warning on line 28 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
|
|
||
| fun getCurrentOS(): String = when { | ||
|
Check warning on line 30 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
|
||
| SystemInfo.isWindows -> "windows" | ||
| SystemInfo.isMac -> "darwin" | ||
| else -> "linux" | ||
| } | ||
|
Check warning on line 34 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
|
|
||
| fun getCurrentArchitecture() = when (CpuArch.CURRENT) { | ||
| CpuArch.X86_64 -> "x64" | ||
| CpuArch.ARM64 -> "arm64" | ||
| else -> "unknown" | ||
| } | ||
|
Check warning on line 40 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
|
|
||
| fun generateMD5Hash(filePath: Path): String { | ||
| val messageDigest = DigestUtil.md5() | ||
| DigestUtil.updateContentHash(messageDigest, filePath) | ||
| return StringUtil.toHexString(messageDigest.digest()) | ||
|
Check warning on line 45 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
| } | ||
|
|
||
| fun generateSHA384Hash(filePath: Path): String { | ||
| val messageDigest = MessageDigest.getInstance("SHA-384") | ||
| DigestUtil.updateContentHash(messageDigest, filePath) | ||
| return StringUtil.toHexString(messageDigest.digest()) | ||
|
Check warning on line 51 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
| } | ||
|
|
||
| fun getSubFolders(basePath: Path): List<Path> = try { | ||
| basePath.listDirectoryEntries() | ||
| .filter { it.isDirectory() } | ||
| } catch (e: Exception) { | ||
| emptyList() | ||
| } | ||
|
Check warning on line 59 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
|
|
||
| fun moveFilesFromSourceToDestination(sourceDir: Path, targetDir: Path) { | ||
| try { | ||
| Files.createDirectories(targetDir.parent) | ||
| Files.move(sourceDir, targetDir, StandardCopyOption.REPLACE_EXISTING) | ||
| } catch (e: Exception) { | ||
| throw IllegalStateException("Failed to move files from $sourceDir to $targetDir", e) | ||
|
Check warning on line 66 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
| } | ||
| } | ||
|
Check warning on line 68 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/artifacts/LspUtils.kt
|
||
Uh oh!
There was an error while loading. Please reload this page.