Correct completion after "super."
#KT-8406 Fixed
This commit is contained in:
+9
-9
@@ -44,6 +44,7 @@ import java.util.*
|
|||||||
class ReferenceVariantsHelper(
|
class ReferenceVariantsHelper(
|
||||||
private val bindingContext: BindingContext,
|
private val bindingContext: BindingContext,
|
||||||
private val resolutionFacade: ResolutionFacade,
|
private val resolutionFacade: ResolutionFacade,
|
||||||
|
private val moduleDescriptor: ModuleDescriptor,
|
||||||
private val visibilityFilter: (DeclarationDescriptor) -> Boolean
|
private val visibilityFilter: (DeclarationDescriptor) -> Boolean
|
||||||
) {
|
) {
|
||||||
fun getReferenceVariants(
|
fun getReferenceVariants(
|
||||||
@@ -151,6 +152,7 @@ class ReferenceVariantsHelper(
|
|||||||
|
|
||||||
is CallTypeAndReceiver.DEFAULT -> receiverExpression = null
|
is CallTypeAndReceiver.DEFAULT -> receiverExpression = null
|
||||||
is CallTypeAndReceiver.DOT -> receiverExpression = callTypeAndReceiver.receiver
|
is CallTypeAndReceiver.DOT -> receiverExpression = callTypeAndReceiver.receiver
|
||||||
|
is CallTypeAndReceiver.SUPER_MEMBERS -> receiverExpression = callTypeAndReceiver.receiver
|
||||||
is CallTypeAndReceiver.SAFE -> receiverExpression = callTypeAndReceiver.receiver
|
is CallTypeAndReceiver.SAFE -> receiverExpression = callTypeAndReceiver.receiver
|
||||||
is CallTypeAndReceiver.INFIX -> receiverExpression = callTypeAndReceiver.receiver
|
is CallTypeAndReceiver.INFIX -> receiverExpression = callTypeAndReceiver.receiver
|
||||||
is CallTypeAndReceiver.OPERATOR -> return emptyList()
|
is CallTypeAndReceiver.OPERATOR -> return emptyList()
|
||||||
@@ -179,15 +181,7 @@ class ReferenceVariantsHelper(
|
|||||||
listOf(useReceiverType)
|
listOf(useReceiverType)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val expressionType = bindingContext.getType(receiverExpression)
|
callTypeAndReceiver.receiverTypes(bindingContext, contextElement, moduleDescriptor, resolutionFacade, predictableSmartCastsOnly = false)!!
|
||||||
if (expressionType != null && !expressionType.isError()) {
|
|
||||||
val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
|
|
||||||
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, bindingContext, containingDeclaration, dataFlowInfo)
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptors.processAll(implicitReceiverTypes, explicitReceiverTypes, resolutionScope, callType, kindFilter, nameFilter)
|
descriptors.processAll(implicitReceiverTypes, explicitReceiverTypes, resolutionScope, callType, kindFilter, nameFilter)
|
||||||
@@ -201,6 +195,12 @@ class ReferenceVariantsHelper(
|
|||||||
descriptors.addAll(resolutionScope.collectDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter))
|
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
|
return descriptors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.util
|
package org.jetbrains.kotlin.idea.util
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
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.bindingContextUtil.getDataFlowInfo
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
|
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.DescriptorKindExclude
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
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
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||||
|
|
||||||
public sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: DescriptorKindFilter) {
|
public sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: DescriptorKindFilter) {
|
||||||
@@ -42,6 +46,8 @@ public sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: D
|
|||||||
|
|
||||||
object SAFE : CallType<KtExpression>(DescriptorKindFilter.ALL)
|
object SAFE : CallType<KtExpression>(DescriptorKindFilter.ALL)
|
||||||
|
|
||||||
|
object SUPER_MEMBERS : CallType<KtSuperExpression>(DescriptorKindFilter.CALLABLES exclude DescriptorKindExclude.Extensions exclude AbstractMembersExclude)
|
||||||
|
|
||||||
object INFIX : CallType<KtExpression>(DescriptorKindFilter.FUNCTIONS exclude NonInfixExclude)
|
object INFIX : CallType<KtExpression>(DescriptorKindFilter.FUNCTIONS exclude NonInfixExclude)
|
||||||
|
|
||||||
object OPERATOR : CallType<KtExpression>(DescriptorKindFilter.FUNCTIONS exclude NonOperatorExclude)
|
object OPERATOR : CallType<KtExpression>(DescriptorKindFilter.FUNCTIONS exclude NonOperatorExclude)
|
||||||
@@ -90,6 +96,14 @@ public sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: D
|
|||||||
|
|
||||||
override val fullyExcludedDescriptorKinds: Int get() = 0
|
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<TReceiver : KtElement?, TCallType : CallType<TReceiver>>(
|
public sealed class CallTypeAndReceiver<TReceiver : KtElement?, TCallType : CallType<TReceiver>>(
|
||||||
@@ -100,6 +114,7 @@ public sealed class CallTypeAndReceiver<TReceiver : KtElement?, TCallType : Call
|
|||||||
object DEFAULT : CallTypeAndReceiver<Nothing?, CallType.DEFAULT>(CallType.DEFAULT, null)
|
object DEFAULT : CallTypeAndReceiver<Nothing?, CallType.DEFAULT>(CallType.DEFAULT, null)
|
||||||
class DOT(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.DOT>(CallType.DOT, receiver)
|
class DOT(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.DOT>(CallType.DOT, receiver)
|
||||||
class SAFE(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.SAFE>(CallType.SAFE, receiver)
|
class SAFE(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.SAFE>(CallType.SAFE, receiver)
|
||||||
|
class SUPER_MEMBERS(receiver: KtSuperExpression) : CallTypeAndReceiver<KtSuperExpression, CallType.SUPER_MEMBERS>(CallType.SUPER_MEMBERS, receiver)
|
||||||
class INFIX(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.INFIX>(CallType.INFIX, receiver)
|
class INFIX(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.INFIX>(CallType.INFIX, receiver)
|
||||||
class OPERATOR(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.OPERATOR>(CallType.OPERATOR, receiver)
|
class OPERATOR(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.OPERATOR>(CallType.OPERATOR, receiver)
|
||||||
class CALLABLE_REFERENCE(receiver: KtTypeReference?) : CallTypeAndReceiver<KtTypeReference?, CallType.CALLABLE_REFERENCE>(CallType.CALLABLE_REFERENCE, receiver)
|
class CALLABLE_REFERENCE(receiver: KtTypeReference?) : CallTypeAndReceiver<KtTypeReference?, CallType.CALLABLE_REFERENCE>(CallType.CALLABLE_REFERENCE, receiver)
|
||||||
@@ -159,6 +174,10 @@ public sealed class CallTypeAndReceiver<TReceiver : KtElement?, TCallType : Call
|
|||||||
return CallTypeAndReceiver.DEFAULT
|
return CallTypeAndReceiver.DEFAULT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (receiverExpression is KtSuperExpression) {
|
||||||
|
return CallTypeAndReceiver.SUPER_MEMBERS(receiverExpression)
|
||||||
|
}
|
||||||
|
|
||||||
return when (parent) {
|
return when (parent) {
|
||||||
is KtCallExpression -> {
|
is KtCallExpression -> {
|
||||||
if ((parent.parent as KtQualifiedExpression).operationSign == KtTokens.SAFE_ACCESS)
|
if ((parent.parent as KtQualifiedExpression).operationSign == KtTokens.SAFE_ACCESS)
|
||||||
@@ -186,7 +205,7 @@ public sealed class CallTypeAndReceiver<TReceiver : KtElement?, TCallType : Call
|
|||||||
|
|
||||||
public fun CallTypeAndReceiver<*, *>.receiverTypes(
|
public fun CallTypeAndReceiver<*, *>.receiverTypes(
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
position: KtExpression,
|
contextElement: PsiElement,
|
||||||
moduleDescriptor: ModuleDescriptor,
|
moduleDescriptor: ModuleDescriptor,
|
||||||
resolutionFacade: ResolutionFacade,
|
resolutionFacade: ResolutionFacade,
|
||||||
predictableSmartCastsOnly: Boolean
|
predictableSmartCastsOnly: Boolean
|
||||||
@@ -205,6 +224,18 @@ public fun CallTypeAndReceiver<*, *>.receiverTypes(
|
|||||||
is CallTypeAndReceiver.OPERATOR -> receiverExpression = receiver
|
is CallTypeAndReceiver.OPERATOR -> receiverExpression = receiver
|
||||||
is CallTypeAndReceiver.DELEGATE -> 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<ClassDescriptor>() ?: return emptyList()
|
||||||
|
return classDescriptor.typeConstructor.supertypesWithAny()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
is CallTypeAndReceiver.IMPORT_DIRECTIVE,
|
is CallTypeAndReceiver.IMPORT_DIRECTIVE,
|
||||||
is CallTypeAndReceiver.PACKAGE_DIRECTIVE,
|
is CallTypeAndReceiver.PACKAGE_DIRECTIVE,
|
||||||
is CallTypeAndReceiver.TYPE,
|
is CallTypeAndReceiver.TYPE,
|
||||||
@@ -220,11 +251,11 @@ public fun CallTypeAndReceiver<*, *>.receiverTypes(
|
|||||||
expressionType?.let { listOf(ExpressionReceiver(receiverExpression, expressionType)) } ?: return emptyList()
|
expressionType?.let { listOf(ExpressionReceiver(receiverExpression, expressionType)) } ?: return emptyList()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val resolutionScope = position.getResolutionScope(bindingContext, resolutionFacade)
|
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||||
resolutionScope.getImplicitReceiversWithInstance().map { it.value }
|
resolutionScope.getImplicitReceiversWithInstance().map { it.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataFlowInfo = bindingContext.getDataFlowInfo(position)
|
val dataFlowInfo = bindingContext.getDataFlowInfo(contextElement)
|
||||||
|
|
||||||
return receiverValues.flatMap { receiverValue ->
|
return receiverValues.flatMap { receiverValue ->
|
||||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public class ShadowedDeclarationsFilter(
|
|||||||
is CallTypeAndReceiver.DEFAULT -> null
|
is CallTypeAndReceiver.DEFAULT -> null
|
||||||
is CallTypeAndReceiver.DOT -> callTypeAndReceiver.receiver
|
is CallTypeAndReceiver.DOT -> callTypeAndReceiver.receiver
|
||||||
is CallTypeAndReceiver.SAFE -> callTypeAndReceiver.receiver
|
is CallTypeAndReceiver.SAFE -> callTypeAndReceiver.receiver
|
||||||
|
is CallTypeAndReceiver.SUPER_MEMBERS -> callTypeAndReceiver.receiver
|
||||||
is CallTypeAndReceiver.INFIX -> callTypeAndReceiver.receiver
|
is CallTypeAndReceiver.INFIX -> callTypeAndReceiver.receiver
|
||||||
is CallTypeAndReceiver.TYPE, is CallTypeAndReceiver.ANNOTATION -> null // need filtering of classes with the same FQ-name
|
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
|
else -> return null // TODO: support shadowed declarations filtering for callable references
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
|
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
|
import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
|
||||||
|
|
||||||
public fun descriptorsEqualWithSubstitution(descriptor1: DeclarationDescriptor?, descriptor2: DeclarationDescriptor?): Boolean {
|
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
|
&& OverridingUtil.DEFAULT.isOverridableBy(it as CallableDescriptor, signature).getResult() == OVERRIDABLE
|
||||||
} as? CallableMemberDescriptor
|
} as? CallableMemberDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun TypeConstructor.supertypesWithAny(): Collection<KotlinType> {
|
||||||
|
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
|
||||||
|
}
|
||||||
+2
-7
@@ -45,9 +45,9 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.renderer.render
|
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.DescriptorKindExclude
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.util.supertypesWithAny
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -474,15 +474,10 @@ class BasicCompletionSession(
|
|||||||
override fun doComplete() {
|
override fun doComplete() {
|
||||||
val classOrObject = position.parents.firstIsInstanceOrNull<KtClassOrObject>() ?: return
|
val classOrObject = position.parents.firstIsInstanceOrNull<KtClassOrObject>() ?: return
|
||||||
val classDescriptor = resolutionFacade.resolveToDescriptor(classOrObject) as ClassDescriptor
|
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 }
|
.map { it.constructor.declarationDescriptor as? ClassDescriptor }
|
||||||
.filterNotNull()
|
.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) {
|
if (callTypeAndReceiver.receiver != null) {
|
||||||
val referenceVariantsSet = referenceVariants!!.imported.toSet()
|
val referenceVariantsSet = referenceVariants!!.imported.toSet()
|
||||||
superClasses = superClasses.filter { it in referenceVariantsSet }
|
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 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 callTypeAndReceiver: CallTypeAndReceiver<*, *>
|
||||||
protected val receiverTypes: Collection<KotlinType>?
|
protected val receiverTypes: Collection<KotlinType>?
|
||||||
@@ -298,11 +298,6 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
excludeNonInitializedVariable = false,
|
excludeNonInitializedVariable = false,
|
||||||
useReceiverType = runtimeReceiver?.type)
|
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()
|
var notImportedExtensions: Collection<CallableDescriptor> = emptyList()
|
||||||
if (callTypeAndReceiver.shouldCompleteCallableExtensions()) {
|
if (callTypeAndReceiver.shouldCompleteCallableExtensions()) {
|
||||||
val nameFilter: (String) -> Boolean = { prefixMatcher.prefixMatches(it) }
|
val nameFilter: (String) -> Boolean = { prefixMatcher.prefixMatches(it) }
|
||||||
@@ -316,6 +311,11 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
|||||||
notImportedExtensions = pair.second
|
notImportedExtensions = pair.second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val shadowedDeclarationsFilter = if (runtimeReceiver != null)
|
||||||
|
ShadowedDeclarationsFilter(bindingContext, resolutionFacade, position, runtimeReceiver)
|
||||||
|
else
|
||||||
|
ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, position, callTypeAndReceiver)
|
||||||
|
|
||||||
if (shadowedDeclarationsFilter != null) {
|
if (shadowedDeclarationsFilter != null) {
|
||||||
variants = shadowedDeclarationsFilter.filter(variants)
|
variants = shadowedDeclarationsFilter.filter(variants)
|
||||||
notImportedExtensions = shadowedDeclarationsFilter.filterNonImported(notImportedExtensions, variants)
|
notImportedExtensions = shadowedDeclarationsFilter.filterNonImported(notImportedExtensions, variants)
|
||||||
|
|||||||
+2
-2
@@ -40,7 +40,7 @@ class InsertHandlerProvider(
|
|||||||
return when (descriptor) {
|
return when (descriptor) {
|
||||||
is FunctionDescriptor -> {
|
is FunctionDescriptor -> {
|
||||||
when (callType) {
|
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 needTypeArguments = needTypeArguments(descriptor)
|
||||||
val parameters = descriptor.valueParameters
|
val parameters = descriptor.valueParameters
|
||||||
when (parameters.size()) {
|
when (parameters.size()) {
|
||||||
@@ -62,7 +62,7 @@ class InsertHandlerProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is CallType.INFIX -> KotlinFunctionInsertHandler.Infix
|
CallType.INFIX -> KotlinFunctionInsertHandler.Infix
|
||||||
|
|
||||||
else -> KotlinFunctionInsertHandler.OnlyName
|
else -> KotlinFunctionInsertHandler.OnlyName
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -60,7 +60,7 @@ class LookupElementFactory(
|
|||||||
public fun createStandardLookupElementsForDescriptor(descriptor: DeclarationDescriptor, useReceiverTypes: Boolean): Collection<LookupElement> {
|
public fun createStandardLookupElementsForDescriptor(descriptor: DeclarationDescriptor, useReceiverTypes: Boolean): Collection<LookupElement> {
|
||||||
val result = SmartList<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)
|
var lookupElement = createLookupElement(descriptor, useReceiverTypes, parametersAndTypeGrayed = !isNormalCall && callType != CallType.INFIX)
|
||||||
result.add(lookupElement)
|
result.add(lookupElement)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ class SmartCompletion(
|
|||||||
|
|
||||||
is CallTypeAndReceiver.DOT,
|
is CallTypeAndReceiver.DOT,
|
||||||
is CallTypeAndReceiver.SAFE,
|
is CallTypeAndReceiver.SAFE,
|
||||||
|
is CallTypeAndReceiver.SUPER_MEMBERS,
|
||||||
is CallTypeAndReceiver.INFIX,
|
is CallTypeAndReceiver.INFIX,
|
||||||
is CallTypeAndReceiver.CALLABLE_REFERENCE ->
|
is CallTypeAndReceiver.CALLABLE_REFERENCE ->
|
||||||
expression.parent as KtExpression
|
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
|
package org.jetbrains.kotlin.idea.completion.test
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonNull
|
import com.google.gson.JsonNull
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
@@ -157,7 +158,12 @@ public object ExpectedCompletionUtils {
|
|||||||
for (proposalStr in InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, *prefixes)) {
|
for (proposalStr in InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, *prefixes)) {
|
||||||
if (proposalStr.startsWith("{")) {
|
if (proposalStr.startsWith("{")) {
|
||||||
val parser = JsonParser()
|
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))
|
proposals.add(CompletionProposal(json as JsonObject))
|
||||||
}
|
}
|
||||||
else if (proposalStr.startsWith("\"") && proposalStr.endsWith("\"")) {
|
else if (proposalStr.startsWith("\"") && proposalStr.endsWith("\"")) {
|
||||||
|
|||||||
+18
@@ -631,6 +631,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("RecieverMembersFromExtAccessor.kt")
|
||||||
public void testRecieverMembersFromExtAccessor() throws Exception {
|
public void testRecieverMembersFromExtAccessor() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/RecieverMembersFromExtAccessor.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/RecieverMembersFromExtAccessor.kt");
|
||||||
@@ -685,6 +691,18 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("TopLevelClassCompletionInQualifiedCall.kt")
|
||||||
public void testTopLevelClassCompletionInQualifiedCall() throws Exception {
|
public void testTopLevelClassCompletionInQualifiedCall() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/TopLevelClassCompletionInQualifiedCall.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/TopLevelClassCompletionInQualifiedCall.kt");
|
||||||
|
|||||||
+18
@@ -631,6 +631,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("RecieverMembersFromExtAccessor.kt")
|
||||||
public void testRecieverMembersFromExtAccessor() throws Exception {
|
public void testRecieverMembersFromExtAccessor() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/RecieverMembersFromExtAccessor.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/RecieverMembersFromExtAccessor.kt");
|
||||||
@@ -685,6 +691,18 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("TopLevelClassCompletionInQualifiedCall.kt")
|
||||||
public void testTopLevelClassCompletionInQualifiedCall() throws Exception {
|
public void testTopLevelClassCompletionInQualifiedCall() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/TopLevelClassCompletionInQualifiedCall.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/TopLevelClassCompletionInQualifiedCall.kt");
|
||||||
|
|||||||
+6
@@ -479,6 +479,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("ThisConstructorArgument.kt")
|
||||||
public void testThisConstructorArgument() throws Exception {
|
public void testThisConstructorArgument() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/ThisConstructorArgument.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/ThisConstructorArgument.kt");
|
||||||
|
|||||||
+6
@@ -143,6 +143,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("SuperTypeArg.kt")
|
||||||
public void testSuperTypeArg() throws Exception {
|
public void testSuperTypeArg() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/SuperTypeArg.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/SuperTypeArg.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user