Make completion for overriding functions respect suspend modifier

Fixes #KT-22200
This commit is contained in:
Kirill Rakhman
2018-01-09 21:52:18 +01:00
committed by Alexander Udalov
parent 8bc020f31b
commit b567817d1f
6 changed files with 44 additions and 10 deletions
@@ -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)
@@ -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>(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
}
}
@@ -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: "" }
@@ -0,0 +1,9 @@
interface I {
suspend fun foo()
}
class A : I {
o<caret>
}
// ELEMENT_TEXT: "override suspend fun foo() {...}"
@@ -0,0 +1,11 @@
interface I {
suspend fun foo()
}
class A : I {
override suspend fun foo() {
<caret><selection>TODO("not implemented") //To change body of created functions use File | Settings | File Templates.</selection>
}
}
// ELEMENT_TEXT: "override suspend fun foo() {...}"
@@ -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");