From 1a635e404b238688944f78472221c7cd75d2a767 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 12 Feb 2025 12:03:17 -0800 Subject: [PATCH 1/3] Revert "feat(amazonq): Prefetch next inline recommendation (#5290)" This reverts commit 805cb399c5baf865bc811ed76c5ee5ed943a5a62. --- .../credentials/CodeWhispererClientAdaptor.kt | 6 - .../popup/CodeWhispererPopupListener.kt | 4 +- .../popup/CodeWhispererPopupManager.kt | 4 - .../service/CodeWhispererService.kt | 149 +----------------- .../CodeWhispererTelemetryService.kt | 14 -- .../CodeWhispererSettingsTest.kt | 10 +- .../CodeWhispererTelemetryTest.kt | 25 ++- .../codewhisperer/CodeWhispererTestBase.kt | 12 +- 8 files changed, 25 insertions(+), 199 deletions(-) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/credentials/CodeWhispererClientAdaptor.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/credentials/CodeWhispererClientAdaptor.kt index f81e18a56a8..e2e55b86430 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/credentials/CodeWhispererClientAdaptor.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/credentials/CodeWhispererClientAdaptor.kt @@ -77,10 +77,6 @@ interface CodeWhispererClientAdaptor : Disposable { firstRequest: GenerateCompletionsRequest, ): Sequence - fun generateCompletions( - firstRequest: GenerateCompletionsRequest, - ): GenerateCompletionsResponse - fun createUploadUrl( request: CreateUploadUrlRequest, ): CreateUploadUrlResponse @@ -327,8 +323,6 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW yield(response) } while (!nextToken.isNullOrEmpty()) } - override fun generateCompletions(firstRequest: GenerateCompletionsRequest): GenerateCompletionsResponse = - bearerClient().generateCompletions(firstRequest) override fun createUploadUrl(request: CreateUploadUrlRequest): CreateUploadUrlResponse = bearerClient().createUploadUrl(request) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupListener.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupListener.kt index 891d0303deb..f452de9a00d 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupListener.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupListener.kt @@ -7,7 +7,6 @@ import com.intellij.openapi.ui.popup.JBPopupListener import com.intellij.openapi.ui.popup.LightweightWindowEvent import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus -import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererServiceNew import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService import java.time.Duration @@ -28,8 +27,7 @@ class CodeWhispererPopupListener(private val states: InvocationContext) : JBPopu recommendationContext, CodeWhispererPopupManager.getInstance().sessionContext, event.isOk, - CodeWhispererInvocationStatus.getInstance().popupStartTimestamp?.let { Duration.between(it, Instant.now()) }, - CodeWhispererService.getInstance().getNextInvocationContext() + CodeWhispererInvocationStatus.getInstance().popupStartTimestamp?.let { Duration.between(it, Instant.now()) } ) CodeWhispererInvocationStatus.getInstance().setDisplaySessionActive(false) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupManager.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupManager.kt index 245f9cdc453..4402b684d99 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupManager.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/popup/CodeWhispererPopupManager.kt @@ -68,7 +68,6 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.Co import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererScrollListener import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.addIntelliSenseAcceptListener import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus -import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService import software.aws.toolkits.jetbrains.services.codewhisperer.toolwindow.CodeWhispererCodeReferenceManager import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererColorUtil.POPUP_DIM_HEX @@ -453,9 +452,6 @@ class CodeWhispererPopupManager { CodeWhispererEditorManager.getInstance().updateEditorWithRecommendation(states, sessionContext) } closePopup(states.popup) - if (sessionContext.selectedIndex == 0) { - CodeWhispererService.getInstance().promoteNextInvocationIfAvailable() - } } } ) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt index 0773910bb03..4f500ea14a4 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt @@ -16,7 +16,6 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.VisualPosition import com.intellij.openapi.project.Project import com.intellij.openapi.ui.popup.JBPopup -import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.openapi.util.Disposer import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiFile @@ -25,7 +24,6 @@ import com.intellij.util.messages.Topic import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Deferred import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.async import kotlinx.coroutines.delay import kotlinx.coroutines.isActive @@ -100,7 +98,6 @@ import java.util.concurrent.TimeUnit class CodeWhispererService(private val cs: CoroutineScope) : Disposable { private val codeInsightSettingsFacade = CodeInsightsSettingsFacade() private var refreshFailure: Int = 0 - private var nextInvocationContext: InvocationContext? = null init { Disposer.register(this, codeInsightSettingsFacade) @@ -212,118 +209,7 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable { invokeCodeWhispererInBackground(requestContext) } - internal suspend fun invokeCodeWhispererInBackground( - requestContext: RequestContext, - currStates: InvocationContext? = null, - ): Job { - // current states != null means that it's prefetch - if (currStates != null) { - val firstValidRecommendation = currStates.recommendationContext.details - .firstOrNull { - !it.isDiscarded && it.recommendation.content().isNotEmpty() - } ?: return SupervisorJob().apply { complete() } - val job = cs.launch(getCoroutineBgContext()) { - val latencyContext = LatencyContext().apply { - codewhispererPreprocessingStart = System.nanoTime() - codewhispererEndToEndStart = System.nanoTime() - } - - val nextCaretPosition = CaretPosition( - line = requestContext.caretPosition.line + firstValidRecommendation.recommendation.content().count { it == '\n' }, - offset = requestContext.caretPosition.offset + firstValidRecommendation.recommendation.content().length - ) - - val nextFileContextInfo = requestContext.fileContextInfo.copy( - caretContext = requestContext.fileContextInfo.caretContext.copy( - leftFileContext = requestContext.fileContextInfo.caretContext.leftFileContext + firstValidRecommendation.recommendation.content() - ) - ) - - val nextRequestContext = requestContext.copy( - caretPosition = nextCaretPosition, - fileContextInfo = nextFileContextInfo, - latencyContext = latencyContext - ) - val newVisualPosition = withContext(EDT) { - runReadAction { - nextRequestContext.editor.offsetToVisualPosition(nextRequestContext.caretPosition.offset) - } - } - try { - val nextResponse = CodeWhispererClientAdaptor - .getInstance(nextRequestContext.project) - .generateCompletions( - buildCodeWhispererRequest( - nextRequestContext.fileContextInfo, - nextRequestContext.awaitSupplementalContext(), - nextRequestContext.customizationArn - ) - ) - val startTime = System.nanoTime() - nextRequestContext.latencyContext.codewhispererPreprocessingEnd = System.nanoTime() - nextRequestContext.latencyContext.paginationAllCompletionsStart = System.nanoTime() - CodeWhispererInvocationStatus.getInstance().setInvocationStart() - nextResponse.let { - val endTime = System.nanoTime() - val latency = TimeUnit.NANOSECONDS.toMillis(endTime - startTime).toDouble() - val requestId = nextResponse.responseMetadata().requestId() - val sessionId = nextResponse.sdkHttpResponse().headers().getOrDefault(KET_SESSION_ID, listOf(requestId))[0] - - nextRequestContext.latencyContext.apply { - codewhispererPostprocessingStart = System.nanoTime() - paginationFirstCompletionTime = (endTime - codewhispererEndToEndStart).toDouble() - firstRequestId = requestId - } - - CodeWhispererInvocationStatus.getInstance().setInvocationSessionId(sessionId) - - val nextResponseContext = ResponseContext(sessionId) - CodeWhispererTelemetryService.getInstance().sendServiceInvocationEvent( - nextResponse.responseMetadata().requestId(), - nextRequestContext, - nextResponseContext, - nextResponse.completions().size, - invocationSuccess = true, - latency, - null - ) - val validatedResponse = validateResponse(it) - val detailContexts = withContext(EDT) { - runReadAction { - CodeWhispererRecommendationManager.getInstance().buildDetailContext( - nextRequestContext, - "", - validatedResponse.completions(), - validatedResponse.responseMetadata().requestId() - ) - } - } - val nextRecommendationContext = RecommendationContext(detailContexts, "", "", newVisualPosition) - val newPopup = withContext(EDT) { - JBPopupFactory.getInstance().createMessage("Dummy popup") - } - - // send userDecision and trigger decision when next recommendation haven't been seen - if (currStates.popup.isDisposed) { - CodeWhispererTelemetryService.getInstance().sendUserDecisionEventForAll( - nextRequestContext, - nextResponseContext, - nextRecommendationContext, - SessionContext(), - false - ) - } else { - nextInvocationContext = InvocationContext(nextRequestContext, nextResponseContext, nextRecommendationContext, newPopup) - } - LOG.debug { "Prefetched next invocation stored in nextInvocationContext" } - } - } catch (ex: Exception) { - LOG.warn { "Failed to prefetch next codewhisperer invocation: ${ex.message}" } - } - } - return job - } - + internal suspend fun invokeCodeWhispererInBackground(requestContext: RequestContext): Job { val popup = withContext(EDT) { CodeWhispererPopupManager.getInstance().initPopup().also { Disposer.register(it) { CodeWhispererInvocationStatus.getInstance().finishInvocation() } @@ -605,9 +491,6 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable { CodeWhispererPopupManager.getInstance().cancelPopup(popup) return null } - cs.launch(getCoroutineBgContext()) { - invokeCodeWhispererInBackground(requestContext, nextStates) - } } else { // subsequent responses nextStates = updateStates(currStates, response) @@ -739,34 +622,6 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable { CodeWhispererPopupManager.getInstance().changeStates(states, 0, recommendationAdded) } - fun promoteNextInvocationIfAvailable() { - val nextStates = nextInvocationContext ?: run { - LOG.debug { "No nextInvocationContext found, nothing to promote." } - return - } - nextInvocationContext?.popup?.let { Disposer.dispose(it) } - nextInvocationContext = null - - cs.launch { - val newPopup = CodeWhispererPopupManager.getInstance().initPopup() - val updatedNextStates = nextStates.copy(popup = newPopup).also { - addPopupChildDisposables(it.requestContext.project, it.requestContext.editor, it.popup) - Disposer.register(newPopup, it) - } - CodeWhispererPopupManager.getInstance().initPopupListener(updatedNextStates) - withContext(EDT) { - CodeWhispererPopupManager.getInstance().changeStates( - updatedNextStates, - 0, - recommendationAdded = false - ) - } - invokeCodeWhispererInBackground(updatedNextStates.requestContext, updatedNextStates) - } - - LOG.debug { "Promoted nextInvocationContext to current session and displayed next recommendation." } - } - private fun sendDiscardedUserDecisionEventForAll( requestContext: RequestContext, responseContext: ResponseContext, @@ -940,8 +795,6 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable { override fun dispose() {} - fun getNextInvocationContext(): InvocationContext? = nextInvocationContext - companion object { private val LOG = getLogger() private const val MAX_REFRESH_ATTEMPT = 3 diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/telemetry/CodeWhispererTelemetryService.kt b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/telemetry/CodeWhispererTelemetryService.kt index a7308247f3b..7a1033e1d8e 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/telemetry/CodeWhispererTelemetryService.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/telemetry/CodeWhispererTelemetryService.kt @@ -457,7 +457,6 @@ class CodeWhispererTelemetryService { sessionContext: SessionContext, hasUserAccepted: Boolean, popupShownTime: Duration? = null, - nextInvocationContext: InvocationContext? = null, ) { val detailContexts = recommendationContext.details val decisions = mutableListOf() @@ -505,19 +504,6 @@ class CodeWhispererTelemetryService { previousUserTriggerDecisions.add(this) // we need this as well because AutotriggerService will reset the queue periodically CodeWhispererAutoTriggerService.getInstance().addPreviousDecision(this) - // send possible next session event if current action is reject and next popup haven't shown up - if (CodewhispererSuggestionState.from(this.toString()) == CodewhispererSuggestionState.Reject) { - nextInvocationContext?.let { - sendUserDecisionEventForAll( - it.requestContext, - it.responseContext, - it.recommendationContext, - SessionContext(), - false, - nextInvocationContext = null - ) - } - } } } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererSettingsTest.kt b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererSettingsTest.kt index 56a7be6df94..63bc70ae2b8 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererSettingsTest.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererSettingsTest.kt @@ -4,6 +4,7 @@ package software.aws.toolkits.jetbrains.services.codewhisperer import com.intellij.analysis.problemsView.toolWindow.ProblemsView +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.service import com.intellij.openapi.wm.RegisterToolWindowTask import com.intellij.openapi.wm.ToolWindow @@ -19,12 +20,14 @@ import org.junit.Ignore import org.junit.Test import org.mockito.kotlin.any import org.mockito.kotlin.never +import org.mockito.kotlin.spy import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import software.aws.toolkits.jetbrains.core.ToolWindowHeadlessManagerImpl import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererLoginType import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.CodeWhispererExploreActionState import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.isCodeWhispererEnabled +import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService import software.aws.toolkits.jetbrains.services.codewhisperer.status.CodeWhispererStatusBarWidgetFactory import software.aws.toolkits.jetbrains.services.codewhisperer.toolwindow.CodeWhispererCodeReferenceToolWindowFactory import software.aws.toolkits.jetbrains.settings.CodeWhispererConfiguration @@ -34,11 +37,14 @@ import kotlin.test.fail class CodeWhispererSettingsTest : CodeWhispererTestBase() { + private lateinit var codewhispererServiceSpy: CodeWhispererService private lateinit var toolWindowHeadlessManager: ToolWindowHeadlessManagerImpl @Before override fun setUp() { super.setUp() + codewhispererServiceSpy = spy(codewhispererService) + ApplicationManager.getApplication().replaceService(CodeWhispererService::class.java, codewhispererServiceSpy, disposableRule.disposable) // Create a mock ToolWindowManager with working implementation of setAvailable() and isAvailable() toolWindowHeadlessManager = object : ToolWindowHeadlessManagerImpl(projectRule.project) { @@ -80,7 +86,7 @@ class CodeWhispererSettingsTest : CodeWhispererTestBase() { whenever(stateManager.checkActiveCodeWhispererConnectionType(projectRule.project)).thenReturn(CodeWhispererLoginType.Logout) assertThat(isCodeWhispererEnabled(projectRule.project)).isFalse invokeCodeWhispererService() - verify(codewhispererService, never()).showRecommendationsInPopup(any(), any(), any()) + verify(codewhispererServiceSpy, never()).showRecommendationsInPopup(any(), any(), any()) } @Test @@ -89,7 +95,7 @@ class CodeWhispererSettingsTest : CodeWhispererTestBase() { assertThat(stateManager.isAutoEnabled()).isFalse runInEdtAndWait { projectRule.fixture.type(':') - verify(codewhispererService, never()).showRecommendationsInPopup(any(), any(), any()) + verify(codewhispererServiceSpy, never()).showRecommendationsInPopup(any(), any(), any()) } } diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTelemetryTest.kt b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTelemetryTest.kt index 20253bfed8f..47a1f3eb754 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTelemetryTest.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTelemetryTest.kt @@ -105,9 +105,11 @@ class CodeWhispererTelemetryTest : CodeWhispererTestBase() { @Test fun `test pre-setup failure will send service invocation event with failed status`() { - doAnswer { throw Exception() } - .whenever(codewhispererService) - .getRequestContext(any(), any(), any(), any(), any()) + val codewhispererServiceSpy = spy(codewhispererService) { + onGeneric { getRequestContext(any(), any(), any(), any(), any()) } + .doAnswer { throw Exception() } + } + ApplicationManager.getApplication().replaceService(CodeWhispererService::class.java, codewhispererServiceSpy, disposableRule.disposable) invokeCodeWhispererService() @@ -162,8 +164,7 @@ class CodeWhispererTelemetryTest : CodeWhispererTestBase() { // 1 serviceInvocation + 1 userModification + 1 userDecision for accepted + // (count - 1) userDecisions for ignored verify(batcher, atLeast(2 + count)).enqueue(capture()) - // one service invocation for current recommendation and one for next recommendation - assertEventsContainsFieldsAndCount(allValues, serviceInvocation, 2) + assertEventsContainsFieldsAndCount(allValues, serviceInvocation, 1) assertEventsContainsFieldsAndCount( allValues, userModification, @@ -193,12 +194,10 @@ class CodeWhispererTelemetryTest : CodeWhispererTestBase() { val count = pythonResponse.completions().size argumentCaptor().apply { verify(batcher, atLeast(1 + count)).enqueue(capture()) - // send 2 invocation events for current and next recommendation session, - // one reject and at least (count -1) Unseen events assertEventsContainsFieldsAndCount( allValues, serviceInvocation, - 2, + 1, "result" to Result.Succeeded.toString(), ) assertEventsContainsFieldsAndCount( @@ -212,7 +211,6 @@ class CodeWhispererTelemetryTest : CodeWhispererTestBase() { userDecision, count - 1, codewhispererSuggestionState to CodewhispererSuggestionState.Unseen.toString(), - atLeast = true ) } } @@ -220,14 +218,13 @@ class CodeWhispererTelemetryTest : CodeWhispererTestBase() { @Test fun `test invoking CodeWhisperer will send service invocation event with succeeded status`() { - // serviceInvocation event will be sent for current session and preloaded next session withCodeWhispererServiceInvokedAndWait { argumentCaptor().apply { verify(batcher, atLeastOnce()).enqueue(capture()) assertEventsContainsFieldsAndCount( allValues, serviceInvocation, - 2, + 1, "result" to Result.Succeeded.toString(), ) } @@ -276,13 +273,12 @@ class CodeWhispererTelemetryTest : CodeWhispererTestBase() { val prefixNotMatchCount = pythonResponse.completions().count { !it.content().startsWith(userInput) } - // serviceInvocation event will be sent for current session and preloaded next session argumentCaptor().apply { verify(batcher, atLeast(1 + prefixNotMatchCount)).enqueue(capture()) assertEventsContainsFieldsAndCount( allValues, serviceInvocation, - 2, + 1, "result" to Result.Succeeded.toString(), ) assertEventsContainsFieldsAndCount( @@ -363,14 +359,13 @@ class CodeWhispererTelemetryTest : CodeWhispererTestBase() { @Test fun `test invoking CodeWhisperer will send service invocation event with sessionId and requestId from response`() { - // serviceInvocation event will be sent for current session and preloaded next session withCodeWhispererServiceInvokedAndWait { states -> val metricCaptor = argumentCaptor() verify(batcher, atLeastOnce()).enqueue(metricCaptor.capture()) assertEventsContainsFieldsAndCount( metricCaptor.allValues, serviceInvocation, - 2, + 1, "codewhispererSessionId" to states.responseContext.sessionId, "codewhispererRequestId" to states.recommendationContext.details[0].requestId, ) diff --git a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTestBase.kt b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTestBase.kt index 6adb57070cd..aa0dd9f2270 100644 --- a/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTestBase.kt +++ b/plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTestBase.kt @@ -27,7 +27,6 @@ import org.mockito.kotlin.spy import org.mockito.kotlin.stub import org.mockito.kotlin.timeout import org.mockito.kotlin.verify -import org.mockito.kotlin.whenever import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntimeClient import software.amazon.awssdk.services.codewhispererruntime.model.GenerateCompletionsRequest import software.amazon.awssdk.services.codewhispererruntime.paginators.GenerateCompletionsIterable @@ -127,10 +126,7 @@ open class CodeWhispererTestBase { stateManager = spy(CodeWhispererExplorerActionManager.getInstance()) recommendationManager = CodeWhispererRecommendationManager.getInstance() - codewhispererService = spy(CodeWhispererService.getInstance()) - ApplicationManager.getApplication().replaceService(CodeWhispererService::class.java, codewhispererService, disposableRule.disposable) - doNothing().whenever(codewhispererService).promoteNextInvocationIfAvailable() - + codewhispererService = CodeWhispererService.getInstance() editorManager = CodeWhispererEditorManager.getInstance() settingsManager = CodeWhispererSettings.getInstance() @@ -242,12 +238,13 @@ open class CodeWhispererTestBase { } fun addUserInputAfterInvocation(userInput: String) { + val codewhispererServiceSpy = spy(codewhispererService) val triggerTypeCaptor = argumentCaptor() val editorCaptor = argumentCaptor() val projectCaptor = argumentCaptor() val psiFileCaptor = argumentCaptor() val latencyContextCaptor = argumentCaptor() - codewhispererService.stub { + codewhispererServiceSpy.stub { onGeneric { getRequestContext( triggerTypeCaptor.capture(), @@ -257,7 +254,7 @@ open class CodeWhispererTestBase { latencyContextCaptor.capture() ) }.doAnswer { - val requestContext = codewhispererService.getRequestContext( + val requestContext = codewhispererServiceSpy.getRequestContext( triggerTypeCaptor.firstValue, editorCaptor.firstValue, projectCaptor.firstValue, @@ -268,5 +265,6 @@ open class CodeWhispererTestBase { requestContext }.thenCallRealMethod() } + ApplicationManager.getApplication().replaceService(CodeWhispererService::class.java, codewhispererServiceSpy, disposableRule.disposable) } } From 8f96431f106b6618793d7e1d3d68a93adbbbe94e Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 12 Feb 2025 16:45:02 -0800 Subject: [PATCH 2/3] add changelog --- .../removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changes/next-release/removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json diff --git a/.changes/next-release/removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json b/.changes/next-release/removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json new file mode 100644 index 00000000000..cbfd12f93df --- /dev/null +++ b/.changes/next-release/removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json @@ -0,0 +1,4 @@ +{ + "type" : "removal", + "description" : "Reverted prefetch logic to enable more stable inline completion." +} \ No newline at end of file From c35d2af2b4f9272637515ac81b3e2fec6b6e0607 Mon Sep 17 00:00:00 2001 From: Richard Li <742829+rli@users.noreply.github.com> Date: Wed, 12 Feb 2025 16:53:37 -0800 Subject: [PATCH 3/3] Update .changes/next-release/removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json --- .../removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changes/next-release/removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json b/.changes/next-release/removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json index cbfd12f93df..9155cbd3cf9 100644 --- a/.changes/next-release/removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json +++ b/.changes/next-release/removal-758edd1c-4ebd-49c6-8ad8-0ec59a5d9f0b.json @@ -1,4 +1,4 @@ { "type" : "removal", - "description" : "Reverted prefetch logic to enable more stable inline completion." + "description" : "Amazon Q: Revert prefetch logic to enable more stable inline completion." } \ No newline at end of file