Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
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 @@ -22,7 +22,6 @@ import software.amazon.awssdk.services.codewhispererruntime.model.GetCodeFixJobR
import software.amazon.awssdk.services.codewhispererruntime.model.GetTestGenerationResponse
import software.amazon.awssdk.services.codewhispererruntime.model.IdeCategory
import software.amazon.awssdk.services.codewhispererruntime.model.InlineChatUserDecision
import software.amazon.awssdk.services.codewhispererruntime.model.ListAvailableCustomizationsRequest
import software.amazon.awssdk.services.codewhispererruntime.model.ListCodeAnalysisFindingsRequest
import software.amazon.awssdk.services.codewhispererruntime.model.ListCodeAnalysisFindingsResponse
import software.amazon.awssdk.services.codewhispererruntime.model.ListFeatureEvaluationsResponse
Expand All @@ -35,8 +34,6 @@ import software.amazon.awssdk.services.codewhispererruntime.model.StartTestGener
import software.amazon.awssdk.services.codewhispererruntime.model.SuggestionState
import software.amazon.awssdk.services.codewhispererruntime.model.TargetCode
import software.amazon.awssdk.services.codewhispererruntime.model.UserIntent
import software.aws.toolkits.core.utils.debug
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.jetbrains.services.amazonq.codeWhispererUserContext
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomization
Expand Down Expand Up @@ -78,8 +75,6 @@ interface CodeWhispererClientAdaptor {

fun getCodeFixJob(request: GetCodeFixJobRequest): GetCodeFixJobResponse

fun listAvailableCustomizations(): List<CodeWhispererCustomization>

fun startTestGeneration(uploadId: String, targetCode: List<TargetCode>, userInput: String): StartTestGenerationResponse

fun getTestGeneration(jobId: String, jobGroupName: String): GetTestGenerationResponse
Expand Down Expand Up @@ -281,28 +276,6 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW

override fun getCodeFixJob(request: GetCodeFixJobRequest): GetCodeFixJobResponse = bearerClient().getCodeFixJob(request)

// DO NOT directly use this method to fetch customizations, use wrapper [CodeWhispererModelConfigurator.listCustomization()] instead
override fun listAvailableCustomizations(): List<CodeWhispererCustomization> =
bearerClient().listAvailableCustomizationsPaginator(
ListAvailableCustomizationsRequest.builder().profileArn(QRegionProfileManager.getInstance().activeProfile(project)?.arn).build()
)
.stream()
.toList()
.flatMap { resp ->
LOG.debug {
"listAvailableCustomizations: requestId: ${resp.responseMetadata().requestId()}, customizations: ${
resp.customizations().map { it.name() }
}"
}
resp.customizations().map {
CodeWhispererCustomization(
arn = it.arn(),
name = it.name(),
description = it.description()
)
}
}

override fun startTestGeneration(uploadId: String, targetCode: List<TargetCode>, userInput: String): StartTestGenerationResponse =
bearerClient().startTestGeneration { builder ->
builder.uploadId(uploadId)
Expand Down Expand Up @@ -799,10 +772,6 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
requestBuilder.userContext(codeWhispererUserContext())
requestBuilder.profileArn(QRegionProfileManager.getInstance().activeProfile(project)?.arn)
}

companion object {
private val LOG = getLogger<CodeWhispererClientAdaptorImpl>()
}
}

private fun CodewhispererSuggestionState.toCodeWhispererSdkType() = when {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhisperer
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.getTelemetryOptOutPreference
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.notifyErrorCodeWhispererUsageLimit
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.promptReAuth
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CustomizationConstants
import software.aws.toolkits.jetbrains.services.codewhisperer.util.FileContextProvider
import software.aws.toolkits.jetbrains.settings.CodeWhispererSettings
import software.aws.toolkits.jetbrains.utils.isInjectedText
Expand Down Expand Up @@ -333,7 +334,7 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
val displayMessage: String

if (
CodeWhispererConstants.Customization.invalidCustomizationExceptionPredicate(e) ||
CustomizationConstants.invalidCustomizationExceptionPredicate(e) ||
e is ResourceNotFoundException
) {
(e as CodeWhispererRuntimeException)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhisperer
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.getTelemetryOptOutPreference
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.notifyErrorCodeWhispererUsageLimit
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.promptReAuth
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CustomizationConstants
import software.aws.toolkits.jetbrains.services.codewhisperer.util.FileContextProvider
import software.aws.toolkits.jetbrains.settings.CodeWhispererSettings
import software.aws.toolkits.jetbrains.utils.isInjectedText
Expand Down Expand Up @@ -360,7 +361,7 @@ class CodeWhispererServiceNew(private val cs: CoroutineScope) : Disposable {
val displayMessage: String

if (
CodeWhispererConstants.Customization.invalidCustomizationExceptionPredicate(e) ||
CustomizationConstants.invalidCustomizationExceptionPredicate(e) ||
e is ResourceNotFoundException
) {
(e as CodeWhispererRuntimeException)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.intellij.openapi.options.SearchableConfigurable
import com.intellij.openapi.options.ex.Settings
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.ui.emptyText
import com.intellij.ui.components.ActionLink
import com.intellij.ui.components.fields.ExpandableTextField
Expand All @@ -23,6 +24,7 @@
import com.intellij.util.execution.ParametersListUtil
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManagerListener
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererLoginType
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.CodeWhispererExplorerActionManager
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.isCodeWhispererEnabled
Expand Down Expand Up @@ -284,6 +286,20 @@
}
}
}
}.also {
val newCallbacks = it.applyCallbacks.toMutableMap()
.also { map ->
val list = map.getOrPut(null) { mutableListOf() } as MutableList<() -> Unit>
list.add {
ProjectManager.getInstance().openProjects.forEach {
if (it.isDisposed) {

Check notice on line 295 in plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/settings/CodeWhispererConfigurable.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Nested lambda has shadowed implicit parameter

Implicit parameter 'it' of enclosing lambda is shadowed
return@forEach
}
AmazonQLspService.didChangeConfiguration(it)

Check notice on line 298 in plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/settings/CodeWhispererConfigurable.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Nested lambda has shadowed implicit parameter

Implicit parameter 'it' of enclosing lambda is shadowed
}
}
}
it.applyCallbacks = newCallbacks
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import com.intellij.openapi.editor.markup.EffectType
import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.ui.JBColor
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.codewhispererruntime.model.AccessDeniedException
import software.amazon.awssdk.services.codewhispererruntime.model.CodeWhispererRuntimeException
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeScanResponse
import software.aws.toolkits.jetbrains.services.codewhisperer.language.languages.CodeWhispererJava
import software.aws.toolkits.telemetry.CodewhispererGettingStartedTask
Expand Down Expand Up @@ -59,7 +57,6 @@ object CodeWhispererConstants {
val scanResultsKey = DataKey.create<CodeScanResponse>("amazonq.codescan.result")
val scanScopeKey = DataKey.create<CodeAnalysisScope>("amazonq.codescan.scope")

const val Q_CUSTOM_LEARN_MORE_URI = "https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/customizations.html"
const val Q_SUPPORTED_LANG_URI = "https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/q-language-ide-support.html"
const val CODEWHISPERER_CODE_SCAN_LEARN_MORE_URI = "https://docs.aws.amazon.com/codewhisperer/latest/userguide/security-scans.html"
const val CODEWHISPERER_ONBOARDING_DOCUMENTATION_URI = "https://docs.aws.amazon.com/codewhisperer/latest/userguide/features.html"
Expand Down Expand Up @@ -157,27 +154,6 @@ object CodeWhispererConstants {
val Sigv4ClientRegion = Region.US_EAST_1
}

object Customization {
private const val noAccessToCustomizationMessage = "Your account is not authorized to use CodeWhisperer Enterprise."
private const val invalidCustomizationMessage = "You are not authorized to access"

val noAccessToCustomizationExceptionPredicate: (e: Exception) -> Boolean = { e ->
if (e !is CodeWhispererRuntimeException) {
false
} else {
e is AccessDeniedException && (e.message?.contains(noAccessToCustomizationMessage, ignoreCase = true) ?: false)
}
}

val invalidCustomizationExceptionPredicate: (e: Exception) -> Boolean = { e ->
if (e !is CodeWhispererRuntimeException) {
false
} else {
e is AccessDeniedException && (e.message?.contains(invalidCustomizationMessage, ignoreCase = true) ?: false)
}
}
}

object CrossFile {
const val CHUNK_SIZE = 60
const val NUMBER_OF_LINE_IN_CHUNK = 50
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,10 @@ import software.amazon.awssdk.services.codewhispererruntime.model.CodeAnalysisSt
import software.amazon.awssdk.services.codewhispererruntime.model.CompletionType
import software.amazon.awssdk.services.codewhispererruntime.model.CreateUploadUrlRequest
import software.amazon.awssdk.services.codewhispererruntime.model.CreateUploadUrlResponse
import software.amazon.awssdk.services.codewhispererruntime.model.Customization
import software.amazon.awssdk.services.codewhispererruntime.model.GenerateCompletionsRequest
import software.amazon.awssdk.services.codewhispererruntime.model.GetCodeAnalysisRequest
import software.amazon.awssdk.services.codewhispererruntime.model.GetCodeAnalysisResponse
import software.amazon.awssdk.services.codewhispererruntime.model.IdeCategory
import software.amazon.awssdk.services.codewhispererruntime.model.ListAvailableCustomizationsRequest
import software.amazon.awssdk.services.codewhispererruntime.model.ListAvailableCustomizationsResponse
import software.amazon.awssdk.services.codewhispererruntime.model.ListCodeAnalysisFindingsRequest
import software.amazon.awssdk.services.codewhispererruntime.model.ListCodeAnalysisFindingsResponse
import software.amazon.awssdk.services.codewhispererruntime.model.ListFeatureEvaluationsRequest
Expand All @@ -51,7 +48,6 @@ import software.amazon.awssdk.services.codewhispererruntime.model.StartCodeAnaly
import software.amazon.awssdk.services.codewhispererruntime.model.StartCodeAnalysisResponse
import software.amazon.awssdk.services.codewhispererruntime.model.SuggestionState
import software.amazon.awssdk.services.codewhispererruntime.paginators.GenerateCompletionsIterable
import software.amazon.awssdk.services.codewhispererruntime.paginators.ListAvailableCustomizationsIterable
import software.amazon.awssdk.services.ssooidc.SsoOidcClient
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
Expand Down Expand Up @@ -158,48 +154,6 @@ class CodeWhispererClientAdaptorTest {
.isInstanceOf(CodeWhispererRuntimeClient::class.java)
}

@Test
fun `listCustomizations`() {
val sdkIterable = ListAvailableCustomizationsIterable(bearerClient, ListAvailableCustomizationsRequest.builder().build())
val mockResponse1 = ListAvailableCustomizationsResponse.builder()
.customizations(
listOf(
Customization.builder().name("custom-1").arn("arn-1").build(),
Customization.builder().name("custom-2").arn("arn-2").build()
)
)
.nextToken("token-1")
.responseMetadata(metadata)
.sdkHttpResponse(sdkHttpResponse)
.build() as ListAvailableCustomizationsResponse

val mockResponse2 = ListAvailableCustomizationsResponse.builder()
.customizations(
listOf(
Customization.builder().name("custom-3").arn("arn-3").build(),
)
)
.nextToken("")
.responseMetadata(metadata)
.sdkHttpResponse(sdkHttpResponse)
.build() as ListAvailableCustomizationsResponse

bearerClient.stub { client ->
on { client.listAvailableCustomizations(any<ListAvailableCustomizationsRequest>()) } doReturnConsecutively listOf(mockResponse1, mockResponse2)
on { client.listAvailableCustomizationsPaginator(any<ListAvailableCustomizationsRequest>()) } doReturn sdkIterable
}

val actual = sut.listAvailableCustomizations()
assertThat(actual).hasSize(3)
assertThat(actual).isEqualTo(
listOf(
CodeWhispererCustomization(name = "custom-1", arn = "arn-1"),
CodeWhispererCustomization(name = "custom-2", arn = "arn-2"),
CodeWhispererCustomization(name = "custom-3", arn = "arn-3")
)
)
}

@Test
fun `generateCompletionsPaginator - bearer`() {
val request = pythonRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ class CodeWhispererModelConfiguratorTest {
"</option>" +
"</component>"

assertThat(actual).isEqualTo(expected)
assertThat(actual).isEqualToIgnoringWhitespace(expected)
}

@Test
Expand Down Expand Up @@ -574,11 +574,6 @@ class CodeWhispererModelConfiguratorTest {

assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization)

val fakeCustomizations = listOf(
CodeWhispererCustomization("oldArn", "oldName", "oldDescription")
)
mockClintAdaptor.stub { on { listAvailableCustomizations() } doReturn fakeCustomizations }

ApplicationManager.getApplication().messageBus
.syncPublisher(QRegionProfileSelectedListener.TOPIC)
.onProfileSelected(projectRule.project, null)
Expand All @@ -593,10 +588,6 @@ class CodeWhispererModelConfiguratorTest {
val oldCustomization = CodeWhispererCustomization("oldArn", "oldName", "oldDescription")
sut.switchCustomization(projectRule.project, oldCustomization)
assertThat(sut.activeCustomization(projectRule.project)).isEqualTo(oldCustomization)
val fakeCustomizations = listOf(
CodeWhispererCustomization("newArn", "newName", "newDescription")
)
mockClintAdaptor.stub { on { listAvailableCustomizations() } doReturn fakeCustomizations }

val latch = CountDownLatch(1)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package migration.software.aws.toolkits.jetbrains.services.codewhisperer.customization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package software.aws.toolkits.jetbrains.services.amazonq.lsp

import com.intellij.notification.NotificationType
import com.intellij.openapi.project.Project
import migration.software.aws.toolkits.jetbrains.settings.AwsSettings
import org.eclipse.lsp4j.ConfigurationParams
import org.eclipse.lsp4j.MessageActionItem
import org.eclipse.lsp4j.MessageParams
Expand All @@ -18,6 +19,7 @@ import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.ChatCommunicationManager
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.ConnectionMetadata
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.SsoProfileData
import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererModelConfigurator
import software.aws.toolkits.jetbrains.settings.CodeWhispererSettings
import java.util.concurrent.CompletableFuture

Expand Down Expand Up @@ -79,14 +81,31 @@ class AmazonQLanguageClientImpl(private val project: Project) : AmazonQLanguageC

return CompletableFuture.completedFuture(
buildList {
val qSettings = CodeWhispererSettings.getInstance()
params.items.forEach {
when (it.section) {
AmazonQLspConstants.LSP_CW_CONFIGURATION_KEY -> {
add(
CodeWhispererLspConfiguration(
shouldShareData = CodeWhispererSettings.getInstance().isMetricOptIn(),
shouldShareCodeReferences = CodeWhispererSettings.getInstance().isIncludeCodeWithReference(),
shouldEnableWorkspaceContext = CodeWhispererSettings.getInstance().isWorkspaceContextEnabled()
shouldShareData = qSettings.isMetricOptIn(),
shouldShareCodeReferences = qSettings.isIncludeCodeWithReference(),
// server context
shouldEnableWorkspaceContext = qSettings.isWorkspaceContextEnabled()
)
)
}
AmazonQLspConstants.LSP_Q_CONFIGURATION_KEY -> {
add(
AmazonQLspConfiguration(
optOutTelemetry = AwsSettings.getInstance().isTelemetryEnabled,
customization = CodeWhispererModelConfigurator.getInstance().activeCustomization(project)?.arn,
// local context
enableLocalIndexing = qSettings.isProjectContextEnabled(),
indexWorkerThreads = qSettings.getProjectContextIndexThreadCount(),
enableGpuAcceleration = qSettings.isProjectContextGpu(),
localIndexing = LocalIndexingConfiguration(
maxIndexSizeMB = qSettings.getProjectContextIndexMaxSize()
)
)
)
}
Expand Down
Loading
Loading