FIR IDE: implement override completion

This commit is contained in:
Ilya Kirillov
2021-05-10 20:27:18 +02:00
committed by TeamCityServer
parent ae212f36f5
commit 8983bde73e
42 changed files with 244 additions and 68 deletions
@@ -16,34 +16,21 @@
package org.jetbrains.kotlin.idea.completion
import com.intellij.codeInsight.completion.InsertionContext
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementDecorator
import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.icons.AllIcons
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.ui.RowIcon
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.KotlinDescriptorIconProvider
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.completion.handlers.indexOfSkippingSpace
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
import org.jetbrains.kotlin.idea.core.moveCaret
import org.jetbrains.kotlin.idea.core.moveCaretIntoGeneratedElement
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMembersHandler
import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import javax.swing.Icon
class OverridesCompletion(
private val collector: LookupElementsCollector,
@@ -96,10 +83,9 @@ class OverridesCompletion(
baseClassName,
baseClassIcon,
isConstructorParameter,
classOrObject,
memberObject.descriptor.isSuspend,
memberObject::generateMember,
ShortenReferences.DEFAULT::process,
generateMember = { memberObject.generateMember(classOrObject, copyDoc = false) },
shortenReferences = ShortenReferences.DEFAULT::process,
)
lookupElement.assignPriority(if (isImplement) ItemPriority.IMPLEMENT else ItemPriority.OVERRIDE)
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface Interface {
var field: Int
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface Interface {
var field: Int
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
fun foo(p: Int)
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
fun foo(p: Int)
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
val someVal: String?
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
val someVal: String?
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
var someVar: String
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
var someVar: String
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
class A {
@Deprecated("")
o<caret>
@@ -1,3 +1,4 @@
// FIR_COMPARISON
class A {
@Deprecated("")
override fun equals(other: Any?): Boolean {
@@ -1,3 +1,4 @@
// FIR_COMPARISON
class A {
@Deprecated("") // it is deprecated
public o<caret>
@@ -1,3 +1,4 @@
// FIR_COMPARISON
class A {
@Deprecated("") // it is deprecated
public override fun equals(other: Any?): Boolean {
@@ -1,3 +1,4 @@
// FIR_COMPARISON
class A {
o<caret>
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
class A {
override fun equals(other: Any?): Boolean {
<caret><selection>return super.equals(other)</selection>
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
val someVal: java.io.File?
}
@@ -1,5 +1,6 @@
import java.io.File
// FIR_COMPARISON
interface I {
val someVal: java.io.File?
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
suspend fun foo()
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
suspend fun foo()
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
class A {
equ<caret>
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
class A {
override fun equals(other: Any?): Boolean {
<caret><selection>return super.equals(other)</selection>
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
protected var someVar: java.io.File?
}
@@ -1,5 +1,6 @@
import java.io.File
// FIR_COMPARISON
interface I {
protected var someVar: java.io.File?
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
val someVal: java.io.File?
}
@@ -1,5 +1,6 @@
import java.io.File
// FIR_COMPARISON
interface I {
val someVal: java.io.File?
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
val p: Int
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
val p: Int
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
val p: Int
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface I {
val p: Int
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
package ppp
interface I {
@@ -1,3 +1,4 @@
// FIR_COMPARISON
package ppp
interface I {
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface Interface {
fun funA()
}
@@ -1,3 +1,4 @@
// FIR_COMPARISON
interface Interface {
fun funA()
}
@@ -55,21 +55,15 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
val keywordContributor = FirKeywordCompletionContributor(basicContext)
if (positionContext is FirUnknownPositionContext) {
// TODO unify when LL API will be able to handle more context for completion
keywordContributor.completeDefaultKeywordsWithoutResolve(positionContext.position, expression = null)
} else {
FirPositionCompletionContextDetector.analyseInContext(basicContext, positionContext) {
with(keywordContributor) { completeKeywords(positionContext) }
when (positionContext) {
is FirNameReferencePositionContext -> with(
KotlinWithNameReferenceCompletionProvider(basicContext, indexHelper)
) {
addCompletions(positionContext)
}
is FirUnknownPositionContext -> {
// TODO remove when hack when LL API will be able to handle more context for completion
}
FirPositionCompletionContextDetector.analyseInContext(basicContext, positionContext) {
with(keywordContributor) { completeKeywords(positionContext) }
when (positionContext) {
is FirNameReferencePositionContext -> with(
KotlinWithNameReferenceCompletionProvider(basicContext, indexHelper)
) {
addCompletions(positionContext)
}
is FirUnknownPositionContext -> {
}
}
}
@@ -137,7 +131,6 @@ private class KotlinWithNameReferenceCompletionProvider(
basicContext: FirBasicCompletionContext,
private val indexHelper: IndexHelper
) : FirCompletionContributorBase(basicContext) {
private val lookupElementFactory = KotlinFirLookupElementFactory()
private val typeNamesProvider = TypeNamesProvider(indexHelper)
private val scopeNameFilter: KtScopeNameFilter =
@@ -198,13 +191,13 @@ private class KotlinWithNameReferenceCompletionProvider(
.getClassifierSymbols(scopeNameFilter)
.filter { visibilityChecker.isVisible(it) }
classesFromScopes.forEach { addSymbolToCompletion(result, expectedType, it) }
classesFromScopes.forEach { addSymbolToCompletion(expectedType, it) }
val kotlinClassesFromIndices = indexHelper.getKotlinClasses(scopeNameFilter, psiFilter = { it !is KtEnumEntry })
kotlinClassesFromIndices.asSequence()
.map { it.getSymbol() as KtClassifierSymbol }
.filter { visibilityChecker.isVisible(it) }
.forEach { addSymbolToCompletion(result, expectedType, it) }
.forEach { addSymbolToCompletion(expectedType, it) }
}
private fun KtAnalysisSession.collectDotCompletion(
@@ -220,11 +213,11 @@ private class KotlinWithNameReferenceCompletionProvider(
val nonExtensionMembers = possibleReceiverScope.collectNonExtensions(visibilityChecker)
val extensionNonMembers = implicitScopes.collectSuitableExtensions(extensionChecker, visibilityChecker)
nonExtensionMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
extensionNonMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
nonExtensionMembers.forEach { addSymbolToCompletion(expectedType, it) }
extensionNonMembers.forEach { addSymbolToCompletion(expectedType, it) }
collectTopLevelExtensionsFromIndices(listOf(typeOfPossibleReceiver), extensionChecker, visibilityChecker)
.forEach { addSymbolToCompletion(result, expectedType, it) }
.forEach { addSymbolToCompletion(expectedType, it) }
}
private fun KtAnalysisSession.collectDefaultCompletion(
@@ -238,19 +231,19 @@ private class KotlinWithNameReferenceCompletionProvider(
val availableNonExtensions = implicitScopes.collectNonExtensions(visibilityChecker)
val extensionsWhichCanBeCalled = implicitScopes.collectSuitableExtensions(extensionChecker, visibilityChecker)
availableNonExtensions.forEach { addSymbolToCompletion(result, expectedType, it) }
extensionsWhichCanBeCalled.forEach { addSymbolToCompletion(result, expectedType, it) }
availableNonExtensions.forEach { addSymbolToCompletion(expectedType, it) }
extensionsWhichCanBeCalled.forEach { addSymbolToCompletion(expectedType, it) }
if (shouldCompleteTopLevelCallablesFromIndex) {
val topLevelCallables = indexHelper.getTopLevelCallables(scopeNameFilter)
topLevelCallables.asSequence()
.map { it.getSymbol() as KtCallableSymbol }
.filter { visibilityChecker.isVisible(it) }
.forEach { addSymbolToCompletion(result, expectedType, it) }
.forEach { addSymbolToCompletion(expectedType, it) }
}
collectTopLevelExtensionsFromIndices(implicitReceiversTypes, extensionChecker, visibilityChecker)
.forEach { addSymbolToCompletion(result, expectedType, it) }
.forEach { addSymbolToCompletion(expectedType, it) }
collectTypesCompletion(implicitScopes, expectedType, visibilityChecker)
}
@@ -9,6 +9,7 @@ import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.completion.PrefixMatcher
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.completion.KotlinFirLookupElementFactory
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtFile
@@ -21,6 +22,7 @@ internal class FirBasicCompletionContext(
val fakeKtFile: KtFile,
val project: Project,
val targetPlatform: TargetPlatform,
val lookupElementFactory: KotlinFirLookupElementFactory = KotlinFirLookupElementFactory(),
) {
companion object {
fun createFromParameters(parameters: CompletionParameters, result: CompletionResultSet): FirBasicCompletionContext? {
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.completion.context
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.analyse
import org.jetbrains.kotlin.idea.frontend.api.analyseInFakeAnalysisSession
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.references.mainReference
@@ -60,7 +61,7 @@ internal object FirPositionCompletionContextDetector {
action
)
is FirUnknownPositionContext -> {
// TODO
analyse(basicContext.originalKtFile, action)
}
}
}
@@ -29,9 +29,7 @@ internal abstract class FirCompletionContributorBase(protected val basicContext:
protected val fakeKtFile: KtFile get() = basicContext.fakeKtFile
protected val project: Project get() = basicContext.project
protected val targetPlatform: TargetPlatform get() = basicContext.targetPlatform
protected val lookupElementFactory = KotlinFirLookupElementFactory()
protected val lookupElementFactory: KotlinFirLookupElementFactory get() = basicContext.lookupElementFactory
protected fun KtAnalysisSession.addSymbolToCompletion(expectedType: KtType?, symbol: KtSymbol) {
if (symbol !is KtNamedSymbol) return
@@ -26,6 +26,8 @@ internal class FirKeywordCompletionContributor(basicContext: FirBasicCompletionC
override fun getLanguageVersionSetting(module: Module) = LanguageVersionSettingsImpl.DEFAULT // TODO
})
private val resolveDependentCompletionKeywordHandlers = ResolveDependentCompletionKeywordHandlers(basicContext)
fun KtAnalysisSession.completeKeywords(
positionContext: FirPositionCompletionContext
) {
@@ -43,10 +45,10 @@ internal class FirKeywordCompletionContributor(basicContext: FirBasicCompletionC
}
fun KtAnalysisSession.completeWithResolve(position: PsiElement, expression: KtExpression?) {
complete(position, expression) { lookupElement, keyword ->
complete(position) { lookupElement, keyword ->
val lookups = DefaultCompletionKeywordHandlers.defaultHandlers.getHandlerForKeyword(keyword)
?.createLookups(parameters, expression, lookupElement, project)
?: ResolveDependentCompletionKeywordHandlers.handlers.getHandlerForKeyword(keyword)?.run {
?: resolveDependentCompletionKeywordHandlers.handlers.getHandlerForKeyword(keyword)?.run {
createLookups(parameters, expression, lookupElement, project)
}
?: listOf(lookupElement)
@@ -54,16 +56,7 @@ internal class FirKeywordCompletionContributor(basicContext: FirBasicCompletionC
}
}
fun completeDefaultKeywordsWithoutResolve(position: PsiElement, expression: KtExpression?) {
complete(position, expression) { lookupElement, keyword ->
val lookups = DefaultCompletionKeywordHandlers.defaultHandlers.getHandlerForKeyword(keyword)
?.createLookups(parameters, expression, lookupElement, project)
?: listOf(lookupElement)
result.addAllElements(lookups)
}
}
private inline fun complete(position: PsiElement, expression: KtExpression?, crossinline complete: (LookupElement, String) -> Unit) {
private inline fun complete(position: PsiElement, crossinline complete: (LookupElement, String) -> Unit) {
keywordCompletion.complete(position, prefixMatcher, targetPlatform.isJvm()) { lookupElement ->
val keyword = lookupElement.lookupString
complete(lookupElement, keyword)
@@ -71,10 +64,9 @@ internal class FirKeywordCompletionContributor(basicContext: FirBasicCompletionC
}
}
private object ResolveDependentCompletionKeywordHandlers {
private class ResolveDependentCompletionKeywordHandlers(basicContext: FirBasicCompletionContext) {
val handlers = CompletionKeywordHandlers(
ReturnKeywordHandler,
OverrideKeywordHandler,
OverrideKeywordHandler(basicContext),
)
}
}
@@ -0,0 +1,173 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.completion.contributors.keywords
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project
import com.intellij.ui.RowIcon
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.idea.completion.*
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
import org.jetbrains.kotlin.idea.core.overrideImplement.*
import org.jetbrains.kotlin.idea.core.overrideImplement.KtClassMember
import org.jetbrains.kotlin.idea.core.overrideImplement.KtGenerateMembersHandler
import org.jetbrains.kotlin.idea.core.overrideImplement.KtOverrideMembersHandler
import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.analyse
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithModality
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtIconProvider.getIcon
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.nameOrAnonymous
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.idea.frontend.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.tokens.hackyAllowRunningOnEdt
import org.jetbrains.kotlin.idea.util.application.runWriteAction
internal class OverrideKeywordHandler(
private val basicContext: FirBasicCompletionContext
) : CompletionKeywordHandler<KtAnalysisSession>(KtTokens.OVERRIDE_KEYWORD) {
@OptIn(ExperimentalStdlibApi::class)
override fun KtAnalysisSession.createLookups(
parameters: CompletionParameters,
expression: KtExpression?,
lookup: LookupElement,
project: Project
): Collection<LookupElement> {
val result = mutableListOf(lookup)
val position = parameters.position
val isConstructorParameter = position.getNonStrictParentOfType<KtPrimaryConstructor>() != null
val classOrObject = position.getNonStrictParentOfType<KtClassOrObject>() ?: return result
val members = collectMembers(classOrObject, isConstructorParameter)
for (member in members) {
result += createLookupElementToGenerateSingleOverrideMember(member, classOrObject, isConstructorParameter, project)
}
return result
}
private fun KtAnalysisSession.collectMembers(classOrObject: KtClassOrObject, isConstructorParameter: Boolean): List<KtClassMember> {
val allMembers = KtOverrideMembersHandler().collectMembersToGenerate(classOrObject)
return if (isConstructorParameter) {
allMembers.mapNotNull { member ->
if (member.memberInfo.isProperty) {
member.copy(bodyType = BodyType.FROM_TEMPLATE, preferConstructorParameter = true)
} else null
}
} else allMembers.toList()
}
private fun KtAnalysisSession.createLookupElementToGenerateSingleOverrideMember(
member: KtClassMember,
classOrObject: KtClassOrObject,
isConstructorParameter: Boolean,
project: Project
): OverridesCompletionLookupElementDecorator {
val memberSymbol = member.symbol
check(memberSymbol is KtNamedSymbol)
val text = getSymbolTextForLookupElement(memberSymbol)
val baseIcon = getIcon(memberSymbol)
val isImplement = (memberSymbol as? KtSymbolWithModality)?.modality == Modality.ABSTRACT
val additionalIcon = if (isImplement) AllIcons.Gutter.ImplementingMethod else AllIcons.Gutter.OverridingMethod
val icon = RowIcon(baseIcon, additionalIcon)
val baseClass = classOrObject.getClassOrObjectSymbol()
val baseClassIcon = getIcon(baseClass)
val isSuspendFunction = (memberSymbol as? KtFunctionSymbol)?.isSuspend == true
val baseClassName = baseClass.nameOrAnonymous.asString()
val memberPointer = memberSymbol.createPointer()
val baseLookupElement = with(basicContext.lookupElementFactory) { createLookupElement(memberSymbol) }
?: error("Lookup element should be available for override completion")
return OverridesCompletionLookupElementDecorator(
baseLookupElement,
declaration = null,
text,
isImplement,
icon,
baseClassName,
baseClassIcon,
isConstructorParameter,
isSuspendFunction,
generateMember = {
generateMemberInNewAnalysisSession(classOrObject, memberPointer, member, project)
},
shortenReferences = { element ->
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
val shortenings = hackyAllowRunningOnEdt {
analyse(classOrObject) {
collectPossibleReferenceShortenings(element.containingKtFile, element.textRange)
}
}
runWriteAction {
shortenings.invokeShortening()
}
}
)
}
private fun KtAnalysisSession.getSymbolTextForLookupElement(memberSymbol: KtCallableSymbol): String = buildString {
append(KtTokens.OVERRIDE_KEYWORD.value)
.append(" ")
.append(memberSymbol.render(renderingOptionsForLookupElementRendering))
if (memberSymbol is KtFunctionSymbol) {
append(" {...}")
}
}
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
private fun generateMemberInNewAnalysisSession(
classOrObject: KtClassOrObject,
memberPointer: KtSymbolPointer<KtCallableSymbol>,
member: KtClassMember,
project: Project
) = hackyAllowRunningOnEdt {
analyse(classOrObject) {
val memberInCorrectAnalysisSession = createCopyInCurrentAnalysisSession(memberPointer, member)
generateMember(
project,
memberInCorrectAnalysisSession,
classOrObject,
copyDoc = false,
mode = MemberGenerateMode.OVERRIDE
)
}
}
//todo temporary hack until KtSymbolPointer is properly implemented
private fun KtAnalysisSession.createCopyInCurrentAnalysisSession(
memberPointer: KtSymbolPointer<KtCallableSymbol>,
member: KtClassMember
) = KtClassMember(
KtClassMemberInfo(
memberPointer.restoreSymbol()
?: error("Cannot restore symbol from $memberPointer"),
member.memberInfo.memberText,
member.memberInfo.memberIcon,
member.memberInfo.containingSymbolText,
member.memberInfo.containingSymbolIcon,
),
member.bodyType,
member.preferConstructorParameter,
)
companion object {
private val renderingOptionsForLookupElementRendering =
KtGenerateMembersHandler.renderOption.copy(
renderUnitReturnType = false,
renderDeclarationHeader = true
)
}
}
@@ -43,8 +43,8 @@ internal data class KtClassMemberInfo(
val isProperty: Boolean get() = symbol is KtPropertySymbol
}
internal class KtClassMember(
private val memberInfo: KtClassMemberInfo,
internal data class KtClassMember(
val memberInfo: KtClassMemberInfo,
val bodyType: BodyType,
val preferConstructorParameter: Boolean
) : MemberChooserObjectBase(
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.idea.frontend.api.tokens.hackyAllowRunningOnEdt
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.KtClassOrObject
internal class KtOverrideMembersHandler : KtGenerateMembersHandler() {
internal open class KtOverrideMembersHandler : KtGenerateMembersHandler() {
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
override fun collectMembersToGenerate(classOrObject: KtClassOrObject): Collection<KtClassMember> {
return hackyAllowRunningOnEdt {
@@ -29,7 +29,7 @@ internal class KtOverrideMembersHandler : KtGenerateMembersHandler() {
}
}
private fun KtAnalysisSession.collectMembers(classOrObject: KtClassOrObject): List<KtClassMember> {
fun KtAnalysisSession.collectMembers(classOrObject: KtClassOrObject): List<KtClassMember> {
val classOrObjectSymbol = classOrObject.getClassOrObjectSymbol()
return getOverridableMembers(classOrObjectSymbol).map { (symbol, bodyType, containingSymbol) ->
KtClassMember(
@@ -30,9 +30,8 @@ class OverridesCompletionLookupElementDecorator(
private val baseClassName: String,
private val baseClassIcon: Icon?,
private val isConstructorParameter: Boolean,
private val classOrObject: KtClassOrObject,
private val isSuspend: Boolean,
private val generateMember: (targetClass: KtClassOrObject, copyDoc: Boolean) -> KtCallableDeclaration,
private val generateMember: () -> KtCallableDeclaration,
private val shortenReferences: (KtElement) -> Unit,
) : LookupElementDecorator<LookupElement>(lookupElement) {
override fun getLookupString() =
@@ -85,7 +84,7 @@ class OverridesCompletionLookupElementDecorator(
// keep original modifiers
val modifierList = KtPsiFactory(context.project).createModifierList(dummyMember.modifierList!!.text)
val prototype = generateMember(classOrObject, false)
val prototype = generateMember()
prototype.modifierList!!.replace(modifierList)
val insertedMember = dummyMember.replaced(prototype)
if (isSuspend) insertedMember.addModifier(KtTokens.SUSPEND_KEYWORD)