Correct completion after "super."
#KT-8406 Fixed
This commit is contained in:
+2
-7
@@ -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<KtClassOrObject>() ?: 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 }
|
||||
|
||||
@@ -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<KotlinType>?
|
||||
@@ -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<CallableDescriptor> = 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)
|
||||
|
||||
+2
-2
@@ -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
|
||||
}
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ class LookupElementFactory(
|
||||
public fun createStandardLookupElementsForDescriptor(descriptor: DeclarationDescriptor, useReceiverTypes: Boolean): Collection<LookupElement> {
|
||||
val result = SmartList<LookupElement>()
|
||||
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Base>.<caret>
|
||||
}
|
||||
|
||||
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
|
||||
@@ -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.<caret>
|
||||
}
|
||||
|
||||
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: "" }
|
||||
@@ -0,0 +1,17 @@
|
||||
interface I {
|
||||
fun abstractFun()
|
||||
val abstractVal: Int
|
||||
fun nonAbstractFun(){}
|
||||
}
|
||||
|
||||
class A : I {
|
||||
override fun abstractFun() {
|
||||
super.<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// ABSENT: abstractFun
|
||||
// ABSENT: abstractVal
|
||||
// EXIST: { itemText: "nonAbstractFun", attributes: "bold" }
|
||||
// EXIST: { itemText: "equals", attributes: "bold" }
|
||||
// EXIST: { itemText: "hashCode", attributes: "bold" }
|
||||
@@ -0,0 +1,11 @@
|
||||
open class Base {
|
||||
open fun foo(p: Int){}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
override fun foo(p: Int) {
|
||||
super.<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// ELEMENT: foo
|
||||
@@ -0,0 +1,11 @@
|
||||
open class Base {
|
||||
open fun foo(p: Int){}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
override fun foo(p: Int) {
|
||||
super.foo(<caret>)
|
||||
}
|
||||
}
|
||||
|
||||
// ELEMENT: foo
|
||||
@@ -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.<caret>
|
||||
}
|
||||
|
||||
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
|
||||
+7
-1
@@ -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("\"")) {
|
||||
|
||||
+18
@@ -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");
|
||||
|
||||
+18
@@ -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");
|
||||
|
||||
+6
@@ -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");
|
||||
|
||||
+6
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user