diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt index 348b7bc1971..2bac4688bec 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt @@ -524,12 +524,16 @@ internal class DescriptorRendererImpl( functionDescriptor.isInfix && (functionDescriptor.overriddenDescriptors.none { it.isInfix } || alwaysRenderModifiers) renderModifier(builder, functionDescriptor.isTailrec, "tailrec") - renderModifier(builder, functionDescriptor.isSuspend, "suspend") + renderSuspendModifier(functionDescriptor, builder) renderModifier(builder, functionDescriptor.isInline, "inline") renderModifier(builder, isInfix, "infix") renderModifier(builder, isOperator, "operator") } + private fun renderSuspendModifier(functionDescriptor: FunctionDescriptor, builder: StringBuilder) { + renderModifier(builder, functionDescriptor.isSuspend, "suspend") + } + override fun render(declarationDescriptor: DeclarationDescriptor): String { return buildString { declarationDescriptor.accept(RenderDeclarationDescriptorVisitor(), this) @@ -630,6 +634,8 @@ internal class DescriptorRendererImpl( if (includeAdditionalModifiers) { renderAdditionalModifiers(function, builder) + } else { + renderSuspendModifier(function, builder) } renderMemberKind(function, builder) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/OverridesCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/OverridesCompletion.kt index 57071cc00f3..6013f04a0c9 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/OverridesCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/OverridesCompletion.kt @@ -24,6 +24,7 @@ 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 @@ -43,8 +44,8 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType class OverridesCompletion( - private val collector: LookupElementsCollector, - private val lookupElementFactory: BasicLookupElementFactory + private val collector: LookupElementsCollector, + private val lookupElementFactory: BasicLookupElementFactory ) { private val PRESENTATION_RENDERER = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.withOptions { modifiers = emptySet() @@ -85,7 +86,9 @@ class OverridesCompletion( val baseClassIcon = KotlinDescriptorIconProvider.getIcon(baseClass, baseClassDeclaration, 0) lookupElement = object : LookupElementDecorator(lookupElement) { - override fun getLookupString() = if (declaration == null) "override" else delegate.lookupString // don't use "override" as lookup string when already in the name of declaration + override fun getLookupString() = + if (declaration == null) "override" else delegate.lookupString // don't use "override" as lookup string when already in the name of declaration + override fun getAllLookupStrings() = setOf(lookupString, delegate.lookupString) override fun renderElement(presentation: LookupElementPresentation) { @@ -122,6 +125,7 @@ class OverridesCompletion( val prototype = memberObject.generateMember(classOrObject, false) prototype.modifierList!!.replace(modifierList) val insertedMember = dummyMember.replaced(prototype) + if (memberObject.descriptor.isSuspend) insertedMember.addModifier(KtTokens.SUSPEND_KEYWORD) ShortenReferences.DEFAULT.process(insertedMember) @@ -135,8 +139,7 @@ class OverridesCompletion( context.document.deleteString(offset, atCharOffset + 1) context.editor.moveCaret(offset) - } - else { + } else { moveCaretIntoGeneratedElement(context.editor, insertedMember) } } @@ -156,8 +159,7 @@ class OverridesCompletion( if (descriptorToOverride !is PropertyDescriptor) return false return if (declaration.valOrVarKeyword?.node?.elementType == KtTokens.VAL_KEYWORD) { !descriptorToOverride.isVar - } - else { + } else { true // var can override either var or val } } diff --git a/idea/idea-completion/testData/basic/common/override/Simple.kt b/idea/idea-completion/testData/basic/common/override/Simple.kt index d858a49e856..20300e0662c 100644 --- a/idea/idea-completion/testData/basic/common/override/Simple.kt +++ b/idea/idea-completion/testData/basic/common/override/Simple.kt @@ -5,7 +5,7 @@ interface I { } class Base1 { - protected open fun bar(){} + protected open suspend fun bar(){} } open class Base2 : Base1() { @@ -16,7 +16,7 @@ class A : Base2(), I { } // EXIST: { lookupString: "override", itemText: "override" } -// EXIST: { itemText: "override fun bar() {...}", lookupString: "override", allLookupStrings: "bar, override", tailText: null, typeText: "Base1", attributes: "" } +// EXIST: { itemText: "override suspend fun bar() {...}", lookupString: "override", allLookupStrings: "bar, override", tailText: null, typeText: "Base1", attributes: "" } // EXIST: { itemText: "override fun equals(other: Any?): Boolean {...}", lookupString: "override", allLookupStrings: "equals, override", tailText: null, typeText: "Any", attributes: "" } // EXIST: { itemText: "override fun foo(p: Int) {...}", lookupString: "override", allLookupStrings: "foo, override", tailText: null, typeText: "I", attributes: "bold" } // EXIST: { itemText: "override fun hashCode(): Int {...}", lookupString: "override", allLookupStrings: "hashCode, override", tailText: null, typeText: "Any", attributes: "" } diff --git a/idea/idea-completion/testData/handlers/basic/override/Suspend.kt b/idea/idea-completion/testData/handlers/basic/override/Suspend.kt new file mode 100644 index 00000000000..d8d80ab50ca --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/override/Suspend.kt @@ -0,0 +1,9 @@ +interface I { + suspend fun foo() +} + +class A : I { + o +} + +// ELEMENT_TEXT: "override suspend fun foo() {...}" diff --git a/idea/idea-completion/testData/handlers/basic/override/Suspend.kt.after b/idea/idea-completion/testData/handlers/basic/override/Suspend.kt.after new file mode 100644 index 00000000000..45b73a9b9cb --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/override/Suspend.kt.after @@ -0,0 +1,11 @@ +interface I { + suspend fun foo() +} + +class A : I { + override suspend fun foo() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} + +// ELEMENT_TEXT: "override suspend fun foo() {...}" diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java index f9c7f3cc877..bbb5f8df90e 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java @@ -582,6 +582,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("Suspend.kt") + public void testSuspend() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/Suspend.kt"); + doTest(fileName); + } + @TestMetadata("TypeFunctionName.kt") public void testTypeFunctionName() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/override/TypeFunctionName.kt");