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 275a7fb56a7..0ba086b8268 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 @@ -51,36 +51,37 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit import java.util.* class ReferenceVariantsHelper( - private val bindingContext: BindingContext, - private val resolutionFacade: ResolutionFacade, - private val moduleDescriptor: ModuleDescriptor, - private val visibilityFilter: (DeclarationDescriptor) -> Boolean, - private val notProperties: Set = setOf() + private val bindingContext: BindingContext, + private val resolutionFacade: ResolutionFacade, + private val moduleDescriptor: ModuleDescriptor, + private val visibilityFilter: (DeclarationDescriptor) -> Boolean, + private val notProperties: Set = setOf() ) { fun getReferenceVariants( - expression: KtSimpleNameExpression, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean, - filterOutJavaGettersAndSetters: Boolean = true, - filterOutShadowed: Boolean = true, - excludeNonInitializedVariable: Boolean = true, - useReceiverType: KotlinType? = null - ): Collection - = getReferenceVariants(expression, CallTypeAndReceiver.detect(expression), - kindFilter, nameFilter, filterOutJavaGettersAndSetters, filterOutShadowed, excludeNonInitializedVariable, useReceiverType) + expression: KtSimpleNameExpression, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean, + filterOutJavaGettersAndSetters: Boolean = true, + filterOutShadowed: Boolean = true, + excludeNonInitializedVariable: Boolean = true, + useReceiverType: KotlinType? = null + ): Collection = getReferenceVariants( + expression, CallTypeAndReceiver.detect(expression), + kindFilter, nameFilter, filterOutJavaGettersAndSetters, filterOutShadowed, excludeNonInitializedVariable, useReceiverType + ) fun getReferenceVariants( - contextElement: PsiElement, - callTypeAndReceiver: CallTypeAndReceiver<*, *>, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean, - filterOutJavaGettersAndSetters: Boolean = true, - filterOutShadowed: Boolean = true, - excludeNonInitializedVariable: Boolean = true, - useReceiverType: KotlinType? = null + contextElement: PsiElement, + callTypeAndReceiver: CallTypeAndReceiver<*, *>, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean, + filterOutJavaGettersAndSetters: Boolean = true, + filterOutShadowed: Boolean = true, + excludeNonInitializedVariable: Boolean = true, + useReceiverType: KotlinType? = null ): Collection { - var variants: Collection - = getReferenceVariantsNoVisibilityFilter(contextElement, kindFilter, nameFilter, callTypeAndReceiver, useReceiverType) + var variants: Collection = + getReferenceVariantsNoVisibilityFilter(contextElement, kindFilter, nameFilter, callTypeAndReceiver, useReceiverType) .filter { !resolutionFacade.frontendService().isHiddenInResolution(it) && visibilityFilter(it) } if (filterOutShadowed) { @@ -100,7 +101,7 @@ class ReferenceVariantsHelper( return variants } - fun filterOutJavaGettersAndSetters(variants: Collection): Collection { + fun filterOutJavaGettersAndSetters(variants: Collection): Collection { val accessorMethodsToRemove = HashSet() val filteredVariants = variants.filter { it !is SyntheticJavaPropertyDescriptor || !it.suppressedByNotPropertyList(notProperties) } @@ -119,7 +120,10 @@ class ReferenceVariantsHelper( } // filters out variable inside its initializer - fun excludeNonInitializedVariable(variants: Collection, contextElement: PsiElement): Collection { + fun excludeNonInitializedVariable( + variants: Collection, + contextElement: PsiElement + ): Collection { for (element in contextElement.parentsWithSelf) { val parent = element.parent if (parent is KtVariableDeclaration && element == parent.initializer) { @@ -131,11 +135,11 @@ class ReferenceVariantsHelper( } private fun getReferenceVariantsNoVisibilityFilter( - contextElement: PsiElement, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean, - callTypeAndReceiver: CallTypeAndReceiver<*, *>, - useReceiverType: KotlinType? + contextElement: PsiElement, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean, + callTypeAndReceiver: CallTypeAndReceiver<*, *>, + useReceiverType: KotlinType? ): Collection { val callType = callTypeAndReceiver.callType @@ -205,20 +209,30 @@ class ReferenceVariantsHelper( val explicitReceiverTypes = if (useReceiverType != null) { listOf(useReceiverType) - } - else { - callTypeAndReceiver.receiverTypes(bindingContext, contextElement, moduleDescriptor, resolutionFacade, stableSmartCastsOnly = false)!! + } else { + callTypeAndReceiver.receiverTypes( + bindingContext, + contextElement, + moduleDescriptor, + resolutionFacade, + stableSmartCastsOnly = false + )!! } descriptors.processAll(implicitReceiverTypes, explicitReceiverTypes, resolutionScope, callType, kindFilter, nameFilter) - } - else { + } else { assert(useReceiverType == null) { "'useReceiverType' parameter is not supported for implicit receiver" } descriptors.processAll(implicitReceiverTypes, implicitReceiverTypes, resolutionScope, callType, kindFilter, nameFilter) // add non-instance members - descriptors.addAll(resolutionScope.collectDescriptorsFiltered(filterWithoutExtensions, nameFilter, changeNamesForAliased = true)) + descriptors.addAll( + resolutionScope.collectDescriptorsFiltered( + filterWithoutExtensions, + nameFilter, + changeNamesForAliased = true + ) + ) descriptors.addAll(resolutionScope.collectAllFromMeAndParent { scope -> scope.collectSyntheticStaticMembersAndConstructors(resolutionFacade, kindFilter, nameFilter) }) @@ -226,7 +240,9 @@ class ReferenceVariantsHelper( 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) + if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) it.overriddenDescriptors else listOf( + it + ) } } @@ -234,27 +250,26 @@ class ReferenceVariantsHelper( } private fun getVariantsForUserType( - receiverExpression: KtExpression?, - contextElement: PsiElement, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + receiverExpression: KtExpression?, + contextElement: PsiElement, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean ): Collection { if (receiverExpression != null) { val qualifier = bindingContext[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList() return qualifier.staticScope.collectStaticMembers(resolutionFacade, kindFilter, nameFilter) - } - else { + } else { val scope = contextElement.getResolutionScope(bindingContext, resolutionFacade) return scope.collectDescriptorsFiltered(kindFilter, nameFilter, changeNamesForAliased = true) } } private fun getVariantsForCallableReference( - callTypeAndReceiver: CallTypeAndReceiver.CALLABLE_REFERENCE, - contextElement: PsiElement, - useReceiverType: KotlinType?, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + callTypeAndReceiver: CallTypeAndReceiver.CALLABLE_REFERENCE, + contextElement: PsiElement, + useReceiverType: KotlinType?, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean ): Collection { val descriptors = LinkedHashSet() @@ -266,59 +281,69 @@ class ReferenceVariantsHelper( val explicitReceiverTypes = if (useReceiverType != null) { listOf(useReceiverType) - } - else { - callTypeAndReceiver.receiverTypes(bindingContext, contextElement, moduleDescriptor, resolutionFacade, stableSmartCastsOnly = false)!! + } else { + callTypeAndReceiver.receiverTypes( + bindingContext, + contextElement, + moduleDescriptor, + resolutionFacade, + stableSmartCastsOnly = false + )!! } val constructorFilter = { descriptor: ClassDescriptor -> if (isStatic) true else descriptor.isInner } descriptors.addNonExtensionMembers(explicitReceiverTypes, kindFilter, nameFilter, constructorFilter) - descriptors.addScopeAndSyntheticExtensions(resolutionScope, explicitReceiverTypes, CallType.CALLABLE_REFERENCE, kindFilter, nameFilter) + descriptors.addScopeAndSyntheticExtensions( + resolutionScope, + explicitReceiverTypes, + CallType.CALLABLE_REFERENCE, + kindFilter, + nameFilter + ) if (isStatic) { explicitReceiverTypes - .mapNotNull { (it.constructor.declarationDescriptor as? ClassDescriptor)?.staticScope } - .flatMapTo(descriptors) { it.collectStaticMembers(resolutionFacade, kindFilter, nameFilter) } + .mapNotNull { (it.constructor.declarationDescriptor as? ClassDescriptor)?.staticScope } + .flatMapTo(descriptors) { it.collectStaticMembers(resolutionFacade, kindFilter, nameFilter) } } - } - else { + } else { // process non-instance members and class constructors descriptors.addNonExtensionCallablesAndConstructors( - resolutionScope, - kindFilter, nameFilter, constructorFilter = { !it.isInner }, - classesOnly = false + resolutionScope, + kindFilter, nameFilter, constructorFilter = { !it.isInner }, + classesOnly = false ) } return descriptors } private fun getVariantsForImportOrPackageDirective( - receiverExpression: KtExpression?, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + receiverExpression: KtExpression?, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean ): Collection { if (receiverExpression != null) { val qualifier = bindingContext[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList() val staticDescriptors = qualifier.staticScope.collectStaticMembers(resolutionFacade, kindFilter, nameFilter) - val objectDescriptor = (qualifier as? ClassQualifier)?.descriptor?.takeIf { it.kind == ClassKind.OBJECT } ?: return staticDescriptors + val objectDescriptor = + (qualifier as? ClassQualifier)?.descriptor?.takeIf { it.kind == ClassKind.OBJECT } ?: return staticDescriptors return staticDescriptors + objectDescriptor.defaultType.memberScope.getDescriptorsFiltered(kindFilter, nameFilter) - } - else { + } else { val rootPackage = resolutionFacade.moduleDescriptor.getPackage(FqName.ROOT) return rootPackage.memberScope.getDescriptorsFiltered(kindFilter, nameFilter) } } private fun MutableSet.processAll( - implicitReceiverTypes: Collection, - receiverTypes: Collection, - resolutionScope: LexicalScope, - callType: CallType<*>, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + implicitReceiverTypes: Collection, + receiverTypes: Collection, + resolutionScope: LexicalScope, + callType: CallType<*>, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean ) { addNonExtensionMembers(receiverTypes, kindFilter, nameFilter, constructorFilter = { it.isInner }) addMemberExtensions(implicitReceiverTypes, receiverTypes, callType, kindFilter, nameFilter) @@ -326,11 +351,11 @@ class ReferenceVariantsHelper( } private fun MutableSet.addMemberExtensions( - dispatchReceiverTypes: Collection, - extensionReceiverTypes: Collection, - callType: CallType<*>, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + dispatchReceiverTypes: Collection, + extensionReceiverTypes: Collection, + callType: CallType<*>, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean ) { val memberFilter = kindFilter exclude DescriptorKindExclude.NonExtensions for (dispatchReceiverType in dispatchReceiverTypes) { @@ -341,35 +366,36 @@ class ReferenceVariantsHelper( } private fun MutableSet.addNonExtensionMembers( - receiverTypes: Collection, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean, - constructorFilter: (ClassDescriptor) -> Boolean + receiverTypes: Collection, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean, + constructorFilter: (ClassDescriptor) -> Boolean ) { for (receiverType in receiverTypes) { addNonExtensionCallablesAndConstructors( - receiverType.memberScope.memberScopeAsImportingScope(), - kindFilter, nameFilter, constructorFilter, - false + receiverType.memberScope.memberScopeAsImportingScope(), + kindFilter, nameFilter, constructorFilter, + false ) receiverType.constructor.supertypes.forEach { addNonExtensionCallablesAndConstructors( - it.memberScope.memberScopeAsImportingScope(), - kindFilter, nameFilter, constructorFilter, - true + it.memberScope.memberScopeAsImportingScope(), + kindFilter, nameFilter, constructorFilter, + true ) } } } private fun MutableSet.addNonExtensionCallablesAndConstructors( - scope: HierarchicalScope, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean, - constructorFilter: (ClassDescriptor) -> Boolean, - classesOnly: Boolean + scope: HierarchicalScope, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean, + constructorFilter: (ClassDescriptor) -> Boolean, + classesOnly: Boolean ) { - var filterToUse = DescriptorKindFilter(kindFilter.kindMask and DescriptorKindFilter.CALLABLES.kindMask).exclude(DescriptorKindExclude.Extensions) + var filterToUse = + DescriptorKindFilter(kindFilter.kindMask and DescriptorKindFilter.CALLABLES.kindMask).exclude(DescriptorKindExclude.Extensions) // should process classes if we need constructors if (filterToUse.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) { @@ -381,19 +407,18 @@ class ReferenceVariantsHelper( if (descriptor.modality == Modality.ABSTRACT || descriptor.modality == Modality.SEALED) continue if (!constructorFilter(descriptor)) continue descriptor.constructors.filterTo(this) { kindFilter.accepts(it) } - } - else if (!classesOnly && kindFilter.accepts(descriptor)) { + } else if (!classesOnly && kindFilter.accepts(descriptor)) { this.add(descriptor) } } } private fun MutableSet.addScopeAndSyntheticExtensions( - scope: LexicalScope, - receiverTypes: Collection, - callType: CallType<*>, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + scope: LexicalScope, + receiverTypes: Collection, + callType: CallType<*>, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean ) { if (kindFilter.excludes.contains(DescriptorKindExclude.Extensions)) return if (receiverTypes.isEmpty()) return @@ -402,14 +427,17 @@ class ReferenceVariantsHelper( if (kindFilter.accepts(extensionOrSyntheticMember) && nameFilter(extensionOrSyntheticMember.name)) { if (extensionOrSyntheticMember.isExtension) { addAll(extensionOrSyntheticMember.substituteExtensionIfCallable(receiverTypes, callType)) - } - else { + } else { add(extensionOrSyntheticMember) } } } - for (descriptor in scope.collectDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.NonExtensions, nameFilter, changeNamesForAliased = true)) { + for (descriptor in scope.collectDescriptorsFiltered( + kindFilter exclude DescriptorKindExclude.NonExtensions, + nameFilter, + changeNamesForAliased = true + )) { // todo: sometimes resolution scope here is LazyJavaClassMemberScope. see ea.jetbrains.com/browser/ea_problems/72572 process(descriptor as CallableDescriptor) } @@ -433,19 +461,23 @@ class ReferenceVariantsHelper( } private fun MemberScope.collectStaticMembers( - resolutionFacade: ResolutionFacade, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + resolutionFacade: ResolutionFacade, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean ): Collection { - return getDescriptorsFiltered(kindFilter, nameFilter) + collectSyntheticStaticMembersAndConstructors(resolutionFacade, kindFilter, nameFilter) + return getDescriptorsFiltered(kindFilter, nameFilter) + collectSyntheticStaticMembersAndConstructors( + resolutionFacade, + kindFilter, + nameFilter + ) } fun ResolutionScope.collectSyntheticStaticMembersAndConstructors( - resolutionFacade: ResolutionFacade, - kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean + resolutionFacade: ResolutionFacade, + kindFilter: DescriptorKindFilter, + nameFilter: (Name) -> Boolean ): List { val syntheticScopes = resolutionFacade.getFrontendService(SyntheticScopes::class.java) return (syntheticScopes.collectSyntheticStaticFunctions(this) + syntheticScopes.collectSyntheticConstructors(this)) - .filter { kindFilter.accepts(it) && nameFilter(it.name) } + .filter { kindFilter.accepts(it) && nameFilter(it.name) } }