diff --git a/platform/analysis-api/api-dump-unreviewed.txt b/platform/analysis-api/api-dump-unreviewed.txt index e4d5cd213b6b..783c44f901f6 100644 --- a/platform/analysis-api/api-dump-unreviewed.txt +++ b/platform/analysis-api/api-dump-unreviewed.txt @@ -916,6 +916,11 @@ com.intellij.codeInsight.lookup.LookupListener - lookupCanceled(com.intellij.codeInsight.lookup.LookupEvent):V - lookupShown(com.intellij.codeInsight.lookup.LookupEvent):V - uiRefreshed():V +a:com.intellij.codeInsight.lookup.SuspendingLookupElementRenderer +- com.intellij.codeInsight.lookup.LookupElementRenderer +- ():V +- f:renderElement(com.intellij.codeInsight.lookup.LookupElement,com.intellij.codeInsight.lookup.LookupElementPresentation):V +- a:renderElementSuspending(com.intellij.codeInsight.lookup.LookupElement,com.intellij.codeInsight.lookup.LookupElementPresentation,kotlin.coroutines.Continuation):java.lang.Object a:com.intellij.codeInsight.lookup.TailTypeDecorator - com.intellij.codeInsight.lookup.LookupElementDecorator - (com.intellij.codeInsight.lookup.LookupElement):V diff --git a/platform/analysis-api/src/com/intellij/codeInsight/lookup/SuspendingLookupElementRenderer.kt b/platform/analysis-api/src/com/intellij/codeInsight/lookup/SuspendingLookupElementRenderer.kt new file mode 100644 index 000000000000..c555d06ddf66 --- /dev/null +++ b/platform/analysis-api/src/com/intellij/codeInsight/lookup/SuspendingLookupElementRenderer.kt @@ -0,0 +1,16 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.codeInsight.lookup + +import com.intellij.openapi.progress.runBlockingCancellable + +abstract class SuspendingLookupElementRenderer : LookupElementRenderer() { + /** + * Render LookupElement in a coroutine. There is no guarantee that the element is valid. + * The method will usually be called without a read lock. + */ + abstract suspend fun renderElementSuspending(element: T, presentation: LookupElementPresentation) + + final override fun renderElement(element: T, presentation: LookupElementPresentation) { + runBlockingCancellable { renderElementSuspending(element, presentation) } + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/AsyncRendering.kt b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/AsyncRendering.kt index fee6652518f5..70efe8ef3fbd 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/AsyncRendering.kt +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/AsyncRendering.kt @@ -6,6 +6,7 @@ package com.intellij.codeInsight.lookup.impl import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementPresentation import com.intellij.codeInsight.lookup.LookupElementRenderer +import com.intellij.codeInsight.lookup.SuspendingLookupElementRenderer import com.intellij.openapi.application.readAction import com.intellij.openapi.util.Key import com.intellij.util.indexing.DumbModeAccessType @@ -42,11 +43,14 @@ internal class AsyncRendering(private val lookup: LookupImpl) { val job = lookup.coroutineScope.launch(limitedDispatcher) { val job = coroutineContext.job - readAction { - if (element.isValid) { - renderInBackground(element, renderer) + if (renderer is SuspendingLookupElementRenderer) { + renderInBackgroundSuspending(element, renderer) + } else + readAction { + if (element.isValid) { + renderInBackground(element, renderer) + } } - } synchronized(LAST_COMPUTATION) { element.replace(LAST_COMPUTATION, job, null) } @@ -65,4 +69,15 @@ internal class AsyncRendering(private val lookup: LookupImpl) { rememberPresentation(element, presentation) lookup.cellRenderer.scheduleUpdateLookupWidthFromVisibleItems() } + + private suspend fun renderInBackgroundSuspending(element: LookupElement, renderer: SuspendingLookupElementRenderer) { + val presentation = LookupElementPresentation() + renderer.renderElementSuspending(element, presentation) + + presentation.freeze() + rememberPresentation(element, presentation) + lookup.cellRenderer.scheduleUpdateLookupWidthFromVisibleItems() + } + + }