From b73c574d19e2aa5cb05638209cfe9863945d041b Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 3 Nov 2015 18:55:26 +0300 Subject: [PATCH] Correct completion after "super." #KT-8406 Fixed --- .../codeInsight/ReferenceVariantsHelper.kt | 18 +++---- .../jetbrains/kotlin/idea/util/CallType.kt | 37 +++++++++++-- .../idea/util/ShadowedDeclarationsFilter.kt | 1 + .../jetbrains/kotlin/util/descriptorUtils.kt | 10 +++- .../idea/completion/BasicCompletionSession.kt | 9 +--- .../idea/completion/CompletionSession.kt | 12 ++--- .../idea/completion/InsertHandlerProvider.kt | 4 +- .../idea/completion/LookupElementFactory.kt | 2 +- .../idea/completion/smart/SmartCompletion.kt | 1 + .../basic/common/QualifiedSuperMembers.kt | 42 +++++++++++++++ .../testData/basic/common/SuperMembers.kt | 54 +++++++++++++++++++ .../testData/basic/common/SuperMembers2.kt | 17 ++++++ .../testData/handlers/basic/SuperMethod.kt | 11 ++++ .../handlers/basic/SuperMethod.kt.after | 11 ++++ .../testData/smart/SuperMembers.kt | 37 +++++++++++++ .../test/ExpectedCompletionUtils.kt | 8 ++- .../test/JSBasicCompletionTestGenerated.java | 18 +++++++ .../test/JvmBasicCompletionTestGenerated.java | 18 +++++++ .../test/JvmSmartCompletionTestGenerated.java | 6 +++ .../BasicCompletionHandlerTestGenerated.java | 6 +++ 20 files changed, 292 insertions(+), 30 deletions(-) create mode 100644 idea/idea-completion/testData/basic/common/QualifiedSuperMembers.kt create mode 100644 idea/idea-completion/testData/basic/common/SuperMembers.kt create mode 100644 idea/idea-completion/testData/basic/common/SuperMembers2.kt create mode 100644 idea/idea-completion/testData/handlers/basic/SuperMethod.kt create mode 100644 idea/idea-completion/testData/handlers/basic/SuperMethod.kt.after create mode 100644 idea/idea-completion/testData/smart/SuperMembers.kt diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt index af8a5a9945a..0c5abad125f 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt @@ -44,6 +44,7 @@ import java.util.* class ReferenceVariantsHelper( private val bindingContext: BindingContext, private val resolutionFacade: ResolutionFacade, + private val moduleDescriptor: ModuleDescriptor, private val visibilityFilter: (DeclarationDescriptor) -> Boolean ) { fun getReferenceVariants( @@ -151,6 +152,7 @@ class ReferenceVariantsHelper( is CallTypeAndReceiver.DEFAULT -> receiverExpression = null is CallTypeAndReceiver.DOT -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.SUPER_MEMBERS -> receiverExpression = callTypeAndReceiver.receiver is CallTypeAndReceiver.SAFE -> receiverExpression = callTypeAndReceiver.receiver is CallTypeAndReceiver.INFIX -> receiverExpression = callTypeAndReceiver.receiver is CallTypeAndReceiver.OPERATOR -> return emptyList() @@ -179,15 +181,7 @@ class ReferenceVariantsHelper( listOf(useReceiverType) } else { - val expressionType = bindingContext.getType(receiverExpression) - if (expressionType != null && !expressionType.isError()) { - val receiverValue = ExpressionReceiver(receiverExpression, expressionType) - smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, bindingContext, containingDeclaration, dataFlowInfo) - - } - else { - emptyList() - } + callTypeAndReceiver.receiverTypes(bindingContext, contextElement, moduleDescriptor, resolutionFacade, predictableSmartCastsOnly = false)!! } descriptors.processAll(implicitReceiverTypes, explicitReceiverTypes, resolutionScope, callType, kindFilter, nameFilter) @@ -201,6 +195,12 @@ class ReferenceVariantsHelper( descriptors.addAll(resolutionScope.collectDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter)) } + if (callType == CallType.SUPER_MEMBERS) { // we need to unwrap fake overrides in case of "super." because ShadowedDeclarationsFilter does not work correctly + return descriptors.flatMapTo(LinkedHashSet()) { + if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) it.overriddenDescriptors else listOf(it) + } + } + return descriptors } diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt index 7d5e20a419c..9d09e86154d 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.util +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.lexer.KtTokens @@ -27,10 +28,13 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager +import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.util.supertypesWithAny +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList public sealed class CallType(val descriptorKindFilter: DescriptorKindFilter) { @@ -42,6 +46,8 @@ public sealed class CallType(val descriptorKindFilter: D object SAFE : CallType(DescriptorKindFilter.ALL) + object SUPER_MEMBERS : CallType(DescriptorKindFilter.CALLABLES exclude DescriptorKindExclude.Extensions exclude AbstractMembersExclude) + object INFIX : CallType(DescriptorKindFilter.FUNCTIONS exclude NonInfixExclude) object OPERATOR : CallType(DescriptorKindFilter.FUNCTIONS exclude NonOperatorExclude) @@ -90,6 +96,14 @@ public sealed class CallType(val descriptorKindFilter: D override val fullyExcludedDescriptorKinds: Int get() = 0 } + + private object AbstractMembersExclude : DescriptorKindExclude() { + override fun excludes(descriptor: DeclarationDescriptor) + = descriptor is CallableMemberDescriptor && descriptor.modality == Modality.ABSTRACT + + override val fullyExcludedDescriptorKinds: Int + get() = 0 + } } public sealed class CallTypeAndReceiver>( @@ -100,6 +114,7 @@ public sealed class CallTypeAndReceiver(CallType.DEFAULT, null) class DOT(receiver: KtExpression) : CallTypeAndReceiver(CallType.DOT, receiver) class SAFE(receiver: KtExpression) : CallTypeAndReceiver(CallType.SAFE, receiver) + class SUPER_MEMBERS(receiver: KtSuperExpression) : CallTypeAndReceiver(CallType.SUPER_MEMBERS, receiver) class INFIX(receiver: KtExpression) : CallTypeAndReceiver(CallType.INFIX, receiver) class OPERATOR(receiver: KtExpression) : CallTypeAndReceiver(CallType.OPERATOR, receiver) class CALLABLE_REFERENCE(receiver: KtTypeReference?) : CallTypeAndReceiver(CallType.CALLABLE_REFERENCE, receiver) @@ -159,6 +174,10 @@ public sealed class CallTypeAndReceiver { if ((parent.parent as KtQualifiedExpression).operationSign == KtTokens.SAFE_ACCESS) @@ -186,7 +205,7 @@ public sealed class CallTypeAndReceiver.receiverTypes( bindingContext: BindingContext, - position: KtExpression, + contextElement: PsiElement, moduleDescriptor: ModuleDescriptor, resolutionFacade: ResolutionFacade, predictableSmartCastsOnly: Boolean @@ -205,6 +224,18 @@ public fun CallTypeAndReceiver<*, *>.receiverTypes( is CallTypeAndReceiver.OPERATOR -> receiverExpression = receiver is CallTypeAndReceiver.DELEGATE -> receiverExpression = receiver + is CallTypeAndReceiver.SUPER_MEMBERS -> { + val qualifier = receiver.superTypeQualifier + if (qualifier != null) { + return bindingContext.getType(receiver).singletonOrEmptyList() + } + else { + val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade) + val classDescriptor = resolutionScope.ownerDescriptor.parentsWithSelf.firstIsInstanceOrNull() ?: return emptyList() + return classDescriptor.typeConstructor.supertypesWithAny() + } + } + is CallTypeAndReceiver.IMPORT_DIRECTIVE, is CallTypeAndReceiver.PACKAGE_DIRECTIVE, is CallTypeAndReceiver.TYPE, @@ -220,11 +251,11 @@ public fun CallTypeAndReceiver<*, *>.receiverTypes( expressionType?.let { listOf(ExpressionReceiver(receiverExpression, expressionType)) } ?: return emptyList() } else { - val resolutionScope = position.getResolutionScope(bindingContext, resolutionFacade) + val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade) resolutionScope.getImplicitReceiversWithInstance().map { it.value } } - val dataFlowInfo = bindingContext.getDataFlowInfo(position) + val dataFlowInfo = bindingContext.getDataFlowInfo(contextElement) return receiverValues.flatMap { receiverValue -> val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor) diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt index 0ffdfecc924..ce8698f045a 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt @@ -55,6 +55,7 @@ public class ShadowedDeclarationsFilter( is CallTypeAndReceiver.DEFAULT -> null is CallTypeAndReceiver.DOT -> callTypeAndReceiver.receiver is CallTypeAndReceiver.SAFE -> callTypeAndReceiver.receiver + is CallTypeAndReceiver.SUPER_MEMBERS -> callTypeAndReceiver.receiver is CallTypeAndReceiver.INFIX -> callTypeAndReceiver.receiver is CallTypeAndReceiver.TYPE, is CallTypeAndReceiver.ANNOTATION -> null // need filtering of classes with the same FQ-name else -> return null // TODO: support shadowed declarations filtering for callable references diff --git a/idea/ide-common/src/org/jetbrains/kotlin/util/descriptorUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/util/descriptorUtils.kt index badc7092a8d..82893a0d762 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/util/descriptorUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/util/descriptorUtils.kt @@ -20,9 +20,9 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.checker.KotlinTypeChecker -import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls public fun descriptorsEqualWithSubstitution(descriptor1: DeclarationDescriptor?, descriptor2: DeclarationDescriptor?): Boolean { @@ -68,3 +68,11 @@ public fun ClassDescriptor.findCallableMemberBySignature(signature: CallableMemb && OverridingUtil.DEFAULT.isOverridableBy(it as CallableDescriptor, signature).getResult() == OVERRIDABLE } as? CallableMemberDescriptor } + +public fun TypeConstructor.supertypesWithAny(): Collection { + val supertypes = supertypes + val noSuperClass = supertypes + .map { it.constructor.declarationDescriptor as? ClassDescriptor } + .all { it == null || it.kind == ClassKind.INTERFACE } + return if (noSuperClass) supertypes + builtIns.anyType else supertypes +} \ No newline at end of file diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt index b2b6b6e1686..221ef07b3b3 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt @@ -45,9 +45,9 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.renderer.render -import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.util.supertypesWithAny import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.util.* @@ -474,15 +474,10 @@ class BasicCompletionSession( override fun doComplete() { val classOrObject = position.parents.firstIsInstanceOrNull() ?: return val classDescriptor = resolutionFacade.resolveToDescriptor(classOrObject) as ClassDescriptor - var superClasses = classDescriptor.defaultType.constructor.supertypes + var superClasses = classDescriptor.defaultType.constructor.supertypesWithAny() .map { it.constructor.declarationDescriptor as? ClassDescriptor } .filterNotNull() - //TODO: IMO it's not good that Any is to be added manually - if (superClasses.all { it.kind == ClassKind.INTERFACE }) { - superClasses += classDescriptor.builtIns.any - } - if (callTypeAndReceiver.receiver != null) { val referenceVariantsSet = referenceVariants!!.imported.toSet() superClasses = superClasses.filter { it in referenceVariantsSet } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt index b2826c5e10b..a078ee1c528 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt @@ -126,7 +126,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC protected val isVisibleFilter: (DeclarationDescriptor) -> Boolean = { isVisibleDescriptor(it) } - protected val referenceVariantsHelper = ReferenceVariantsHelper(bindingContext, resolutionFacade, isVisibleFilter) + protected val referenceVariantsHelper = ReferenceVariantsHelper(bindingContext, resolutionFacade, moduleDescriptor, isVisibleFilter) protected val callTypeAndReceiver: CallTypeAndReceiver<*, *> protected val receiverTypes: Collection? @@ -298,11 +298,6 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC excludeNonInitializedVariable = false, useReceiverType = runtimeReceiver?.type) - val shadowedDeclarationsFilter = if (runtimeReceiver != null) - ShadowedDeclarationsFilter(bindingContext, resolutionFacade, position, runtimeReceiver) - else - ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, position, callTypeAndReceiver) - var notImportedExtensions: Collection = emptyList() if (callTypeAndReceiver.shouldCompleteCallableExtensions()) { val nameFilter: (String) -> Boolean = { prefixMatcher.prefixMatches(it) } @@ -316,6 +311,11 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC notImportedExtensions = pair.second } + val shadowedDeclarationsFilter = if (runtimeReceiver != null) + ShadowedDeclarationsFilter(bindingContext, resolutionFacade, position, runtimeReceiver) + else + ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, position, callTypeAndReceiver) + if (shadowedDeclarationsFilter != null) { variants = shadowedDeclarationsFilter.filter(variants) notImportedExtensions = shadowedDeclarationsFilter.filterNonImported(notImportedExtensions, variants) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt index 4739c6bdac8..7167587e820 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt @@ -40,7 +40,7 @@ class InsertHandlerProvider( return when (descriptor) { is FunctionDescriptor -> { when (callType) { - is CallType.DEFAULT, is CallType.DOT, is CallType.SAFE -> { + CallType.DEFAULT, CallType.DOT, CallType.SAFE, CallType.SUPER_MEMBERS -> { val needTypeArguments = needTypeArguments(descriptor) val parameters = descriptor.valueParameters when (parameters.size()) { @@ -62,7 +62,7 @@ class InsertHandlerProvider( } } - is CallType.INFIX -> KotlinFunctionInsertHandler.Infix + CallType.INFIX -> KotlinFunctionInsertHandler.Infix else -> KotlinFunctionInsertHandler.OnlyName } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt index 229f1e68b0b..56d4e56bb75 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt @@ -60,7 +60,7 @@ class LookupElementFactory( public fun createStandardLookupElementsForDescriptor(descriptor: DeclarationDescriptor, useReceiverTypes: Boolean): Collection { val result = SmartList() - val isNormalCall = callType == CallType.DEFAULT || callType == CallType.DOT || callType == CallType.SAFE + val isNormalCall = callType == CallType.DEFAULT || callType == CallType.DOT || callType == CallType.SAFE || callType == CallType.SUPER_MEMBERS var lookupElement = createLookupElement(descriptor, useReceiverTypes, parametersAndTypeGrayed = !isNormalCall && callType != CallType.INFIX) result.add(lookupElement) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt index 3dffc8e9f65..88006935bda 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt @@ -66,6 +66,7 @@ class SmartCompletion( is CallTypeAndReceiver.DOT, is CallTypeAndReceiver.SAFE, + is CallTypeAndReceiver.SUPER_MEMBERS, is CallTypeAndReceiver.INFIX, is CallTypeAndReceiver.CALLABLE_REFERENCE -> expression.parent as KtExpression diff --git a/idea/idea-completion/testData/basic/common/QualifiedSuperMembers.kt b/idea/idea-completion/testData/basic/common/QualifiedSuperMembers.kt new file mode 100644 index 00000000000..a97bbbab4a6 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/QualifiedSuperMembers.kt @@ -0,0 +1,42 @@ +import java.io.File + +interface I { + fun abstractFun() + val abstractVal: Int + fun nonAbstractFun(){} +} + +fun I.extOnI(){} +val File.extOnFile: Int get() = 1 + +open class Base : File("") { + class Nested + inner class Inner + + open fun fromBase1(): Any = 1 + open fun fromBase2(): Any = 1 +} + +abstract class A : Base(), I { + override fun fromI() { + super. + } + + override fun fromBase1(): String = "" +} + +// ABSENT: abstractFun +// ABSENT: abstractVal +// ABSENT: nonAbstractFun +// EXIST: { itemText: "equals", attributes: "" } +// EXIST: { itemText: "hashCode", attributes: "" } + +// EXIST: { itemText: "fromBase1", typeText: "Any", attributes: "bold" } +// ABSENT: { itemText: "fromBase1", typeText: "String" } +// EXIST: { itemText: "fromBase2", typeText: "Any", attributes: "bold" } + +// ABSENT: extOnI +// ABSENT: extOnFile + +// EXIST_JAVA_ONLY: { itemText: "getAbsolutePath", attributes: "" } +// ABSENT: absolutePath \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/SuperMembers.kt b/idea/idea-completion/testData/basic/common/SuperMembers.kt new file mode 100644 index 00000000000..5b0a7545b74 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/SuperMembers.kt @@ -0,0 +1,54 @@ +import java.io.File + +interface I { + fun abstractFun() + val abstractVal: Int + fun nonAbstractFun(){} +} + +fun I.extOnI(){} +val File.extOnFile: Int get() = 1 + +interface J { + fun funFromJ() + fun onLambda1(p: () -> Unit){} + fun onLambda2(p: (Int, String) -> Unit){} +} + +open class Base : File(""), J { + class Nested + inner class Inner + + open fun fromBase1(): Any = 1 + open fun fromBase2(): Any = 1 +} + +abstract class A : Base(), I { + override fun abstractFun() { + super. + } + + override fun fromBase1(): String = "" +} + +// ABSENT: abstractFun +// ABSENT: abstractVal +// EXIST: { itemText: "nonAbstractFun", attributes: "bold" } +// EXIST: { itemText: "equals", attributes: "" } +// EXIST: { itemText: "hashCode", attributes: "" } + +// EXIST: { itemText: "fromBase1", typeText: "Any", attributes: "bold" } +// ABSENT: { itemText: "fromBase1", typeText: "String" } +// EXIST: { itemText: "fromBase2", typeText: "Any", attributes: "bold" } + +// ABSENT: extOnI +// ABSENT: extOnFile + +// ABSENT: funFromJ + +// EXIST_JAVA_ONLY: { itemText: "getAbsolutePath", attributes: "" } +// ABSENT: absolutePath + +// EXIST: { itemText: "onLambda1", tailText: " {...} (p: () -> Unit)", attributes: "" } +// EXIST: { itemText: "onLambda2", tailText: "(p: (Int, String) -> Unit)", attributes: "" } +// EXIST: { itemText: "onLambda2", tailText: " { Int, String -> ... } (p: (Int, String) -> Unit)", attributes: "" } diff --git a/idea/idea-completion/testData/basic/common/SuperMembers2.kt b/idea/idea-completion/testData/basic/common/SuperMembers2.kt new file mode 100644 index 00000000000..1075a3c689f --- /dev/null +++ b/idea/idea-completion/testData/basic/common/SuperMembers2.kt @@ -0,0 +1,17 @@ +interface I { + fun abstractFun() + val abstractVal: Int + fun nonAbstractFun(){} +} + +class A : I { + override fun abstractFun() { + super. + } +} + +// ABSENT: abstractFun +// ABSENT: abstractVal +// EXIST: { itemText: "nonAbstractFun", attributes: "bold" } +// EXIST: { itemText: "equals", attributes: "bold" } +// EXIST: { itemText: "hashCode", attributes: "bold" } diff --git a/idea/idea-completion/testData/handlers/basic/SuperMethod.kt b/idea/idea-completion/testData/handlers/basic/SuperMethod.kt new file mode 100644 index 00000000000..90da7db5ec4 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/SuperMethod.kt @@ -0,0 +1,11 @@ +open class Base { + open fun foo(p: Int){} +} + +class Derived : Base() { + override fun foo(p: Int) { + super. + } +} + +// ELEMENT: foo \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/SuperMethod.kt.after b/idea/idea-completion/testData/handlers/basic/SuperMethod.kt.after new file mode 100644 index 00000000000..33f8f33224c --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/SuperMethod.kt.after @@ -0,0 +1,11 @@ +open class Base { + open fun foo(p: Int){} +} + +class Derived : Base() { + override fun foo(p: Int) { + super.foo() + } +} + +// ELEMENT: foo \ No newline at end of file diff --git a/idea/idea-completion/testData/smart/SuperMembers.kt b/idea/idea-completion/testData/smart/SuperMembers.kt new file mode 100644 index 00000000000..6ededb129da --- /dev/null +++ b/idea/idea-completion/testData/smart/SuperMembers.kt @@ -0,0 +1,37 @@ +import java.io.File + +interface I { + fun abstractFun(): Int + val abstractVal: Int + fun nonAbstractFun(): Int = 0 +} + +fun I.extOnI(): Int = 0 +val File.extOnFile: Int get() = 1 + +open class Base : File("") { + open fun fromBase1(): Any = 1 + open fun fromBase2(): Int = 1 +} + +abstract class A : Base(), I { + override fun abstractFun(): Int { + return super. + } + + override fun fromBase1(): Int = 0 +} + +// ABSENT: abstractFun +// ABSENT: abstractVal +// EXIST: { itemText: "nonAbstractFun", attributes: "bold" } +// EXIST: { itemText: "hashCode", attributes: "" } +// EXIST: { itemText: "compareTo", attributes: "" } + +// ABSENT: fromBase1 +// EXIST: { itemText: "fromBase2", attributes: "bold" } + +// ABSENT: extOnI +// ABSENT: extOnFile + +// NOTHING_ELSE \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/ExpectedCompletionUtils.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/ExpectedCompletionUtils.kt index 305b3beb55c..b0abd518fc7 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/ExpectedCompletionUtils.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/ExpectedCompletionUtils.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.idea.completion.test import com.google.common.collect.ImmutableList +import com.google.gson.JsonElement import com.google.gson.JsonNull import com.google.gson.JsonObject import com.google.gson.JsonParser @@ -157,7 +158,12 @@ public object ExpectedCompletionUtils { for (proposalStr in InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, *prefixes)) { if (proposalStr.startsWith("{")) { val parser = JsonParser() - val json = parser.parse(proposalStr) + val json: JsonElement? = try { + parser.parse(proposalStr) + } + catch(t: Throwable) { + throw RuntimeException("Error parsing '$proposalStr'", t) + } proposals.add(CompletionProposal(json as JsonObject)) } else if (proposalStr.startsWith("\"") && proposalStr.endsWith("\"")) { diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index cc20aeaf909..924fae8d84c 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -631,6 +631,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("QualifiedSuperMembers.kt") + public void testQualifiedSuperMembers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/QualifiedSuperMembers.kt"); + doTest(fileName); + } + @TestMetadata("RecieverMembersFromExtAccessor.kt") public void testRecieverMembersFromExtAccessor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/RecieverMembersFromExtAccessor.kt"); @@ -685,6 +691,18 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("SuperMembers.kt") + public void testSuperMembers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SuperMembers.kt"); + doTest(fileName); + } + + @TestMetadata("SuperMembers2.kt") + public void testSuperMembers2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SuperMembers2.kt"); + doTest(fileName); + } + @TestMetadata("TopLevelClassCompletionInQualifiedCall.kt") public void testTopLevelClassCompletionInQualifiedCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/TopLevelClassCompletionInQualifiedCall.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index 84f8bc6286d..a292a6d9cc4 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -631,6 +631,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("QualifiedSuperMembers.kt") + public void testQualifiedSuperMembers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/QualifiedSuperMembers.kt"); + doTest(fileName); + } + @TestMetadata("RecieverMembersFromExtAccessor.kt") public void testRecieverMembersFromExtAccessor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/RecieverMembersFromExtAccessor.kt"); @@ -685,6 +691,18 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("SuperMembers.kt") + public void testSuperMembers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SuperMembers.kt"); + doTest(fileName); + } + + @TestMetadata("SuperMembers2.kt") + public void testSuperMembers2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SuperMembers2.kt"); + doTest(fileName); + } + @TestMetadata("TopLevelClassCompletionInQualifiedCall.kt") public void testTopLevelClassCompletionInQualifiedCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/TopLevelClassCompletionInQualifiedCall.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java index 808954eefc1..a7013b9bdec 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java @@ -479,6 +479,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT doTest(fileName); } + @TestMetadata("SuperMembers.kt") + public void testSuperMembers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/smart/SuperMembers.kt"); + doTest(fileName); + } + @TestMetadata("ThisConstructorArgument.kt") public void testThisConstructorArgument() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/ThisConstructorArgument.kt"); 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 c8c53396886..f2620a7cb7d 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 @@ -143,6 +143,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("SuperMethod.kt") + public void testSuperMethod() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/SuperMethod.kt"); + doTest(fileName); + } + @TestMetadata("SuperTypeArg.kt") public void testSuperTypeArg() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/SuperTypeArg.kt");