@@ -38,6 +38,7 @@ import com.intellij.ui.util.preferredHeight
3838import icons.AwsIcons
3939import kotlinx.coroutines.CancellationException
4040import kotlinx.coroutines.CoroutineScope
41+ import kotlinx.coroutines.NonCancellable
4142import kotlinx.coroutines.channels.Channel
4243import kotlinx.coroutines.flow.receiveAsFlow
4344import kotlinx.coroutines.future.await
@@ -132,6 +133,7 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
132133
133134 // not needed for current implementation, will need this when we support concurrent triggers, so leave it here
134135 private val activeTriggerSessions = mutableMapOf<Int , InlineCompletionSessionContext >()
136+ private val previousTriggerSessions = mutableMapOf<Int , InlineCompletionSessionContext >()
135137
136138 fun qToolTip (
137139 title : String ,
@@ -261,6 +263,7 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
261263 }
262264
263265 override fun onInvalidated (event : InlineCompletionEventType .Invalidated ) {
266+ // CodeWhispererInvocationStatus.getInstance().setIsInvokingQInline(session, false)
264267 updateDisplayIndex(session)
265268 super .onInvalidated(event)
266269 }
@@ -401,9 +404,9 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
401404 return TriggerTypeInfo (triggerType, automatedTriggerType)
402405 }
403406
404- override suspend fun getSuggestion (request : InlineCompletionRequest ): InlineCompletionSuggestion {
407+ override suspend fun getSuggestion (request : InlineCompletionRequest ): InlineCompletionSuggestion = withContext( NonCancellable ) {
405408 val editor = request.editor
406- val project = editor.project ? : return InlineCompletionSuggestion .Empty
409+ val project = editor.project ? : return @withContext InlineCompletionSuggestion .Empty
407410
408411 // try to refresh automatically if possible, otherwise ask user to login again
409412 if (isQExpired(project)) {
@@ -414,13 +417,13 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
414417 }
415418
416419 if (shouldReauth) {
417- return InlineCompletionSuggestion .Empty
420+ return @withContext InlineCompletionSuggestion .Empty
418421 }
419422 }
420423
421424 val document = editor.document
422- val handler = InlineCompletion .getHandlerOrNull(editor) ? : return InlineCompletionSuggestion .Empty
423- val session = InlineCompletionSession .getOrNull(editor) ? : return InlineCompletionSuggestion .Empty
425+ val handler = InlineCompletion .getHandlerOrNull(editor) ? : return @withContext InlineCompletionSuggestion .Empty
426+ val session = InlineCompletionSession .getOrNull(editor) ? : return @withContext InlineCompletionSuggestion .Empty
424427 val triggerSessionId = triggerSessionId++
425428 val latencyContext = LatencyContext (codewhispererEndToEndStart = System .nanoTime())
426429 val triggerTypeInfo = getTriggerTypeInfo(request)
@@ -431,14 +434,6 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
431434 CodeWhispererInvocationStatus .getInstance().setIsInvokingQInline(session, false )
432435 }
433436
434- // this is only available in 2024.3+
435- if (request.event.isDeletion()) {
436- logInline(triggerSessionId) {
437- " Skip inline completion when deleting"
438- }
439- return InlineCompletionSuggestion .Empty
440- }
441-
442437 val sessionContext = InlineCompletionSessionContext (triggerOffset = request.endOffset, diagnostics = diagnostics)
443438
444439 // Pagination workaround: Always return exactly 5 variants
@@ -490,17 +485,38 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
490485 it.channel.close()
491486 }
492487 if (session.context.isDisposed) {
488+ previousTriggerSessions[triggerSessionId] = sessionContext
493489 logInline(triggerSessionId) {
494490 " Current display session already disposed by a new trigger before pagination finishes, exiting"
495491 }
492+ return @withContext InlineCompletionSuggestion .Empty
496493 }
497494
498- return object : InlineCompletionSuggestion {
499- override suspend fun getVariants (): List <InlineCompletionVariant > =
500- sessionContext.itemContexts.map { itemContext ->
501- itemContext.data.putUserData(KEY_Q_INLINE_ITEM_CONTEXT , itemContext)
502- InlineCompletionVariant .build(data = itemContext.data, elements = itemContext.channel.receiveAsFlow())
495+ return @withContext object : InlineCompletionSuggestion {
496+ override suspend fun getVariants (): List <InlineCompletionVariant > {
497+ // also need to build valid elements from last session
498+ val result = mutableListOf<InlineCompletionVariant >()
499+ previousTriggerSessions.forEach { (t, u) ->
500+ logInline(triggerSessionId) {
501+ " Adding results from previous trigger $t for the current display session"
502+ }
503+ result.addAll(
504+ u.itemContexts.map { itemContext ->
505+ itemContext.data.putUserData(KEY_Q_INLINE_ITEM_CONTEXT , itemContext)
506+ InlineCompletionVariant .build(data = itemContext.data, elements = itemContext.channel.receiveAsFlow())
507+ }
508+ )
503509 }
510+ previousTriggerSessions.clear()
511+
512+ result.addAll(
513+ sessionContext.itemContexts.map { itemContext ->
514+ itemContext.data.putUserData(KEY_Q_INLINE_ITEM_CONTEXT , itemContext)
515+ InlineCompletionVariant .build(data = itemContext.data, elements = itemContext.channel.receiveAsFlow())
516+ }
517+ )
518+ return result
519+ }
504520 }
505521 } catch (e: Exception ) {
506522 logInline(triggerSessionId, e) {
@@ -509,7 +525,7 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
509525 if (e is CancellationException ) {
510526 throw e
511527 }
512- return InlineCompletionSuggestion .Empty
528+ return @withContext InlineCompletionSuggestion .Empty
513529 }
514530 }
515531
@@ -537,7 +553,8 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
537553 }
538554
539555 logInline(triggerSessionId) {
540- " Received ${nextPageResult.items.size} items from pagination with token: ${nextToken?.left} "
556+ " Received ${nextPageResult.items.size} items from pagination with current token: ${nextToken?.left} , " +
557+ " next token: ${nextPageResult.partialResultToken?.left} "
541558 }
542559
543560 // Update channels in order with new items from pagination
@@ -587,7 +604,9 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
587604 sessionContext.itemContexts[channelIndex].isDiscarded = discarded
588605 val success = existingChannel.trySend(InlineCompletionGrayTextElement (displayText))
589606 logInline(triggerSessionId) {
590- " Adding paginated item '${newItem.itemId} ' to channel $channelIndex , success: ${success.isSuccess} , discarded: $discarded "
607+ " Adding paginated item '${newItem.itemId} ' to channel $channelIndex , " +
608+ " original first line context: ${newItem.insertText.lines()[0 ]} , " +
609+ " success: ${success.isSuccess} , discarded: $discarded "
591610 }
592611 sessionContext.counter++
593612 }
@@ -638,7 +657,7 @@ class QInlineCompletionProvider(private val cs: CoroutineScope) : InlineCompleti
638657 if (QRegionProfileManager .getInstance().hasValidConnectionButNoActiveProfile(project)) return false
639658 if (event.isManualCall()) return true
640659 if (! CodeWhispererExplorerActionManager .getInstance().isAutoEnabled()) return false
641-
660+ if (request.event.isDeletion()) return false
642661 return true
643662 }
644663}
0 commit comments