Completion: fixed filtering shadowed declarations for generic functions

This commit is contained in:
Valentin Kipyatkov
2015-07-06 22:16:13 +03:00
parent 3f74cc6351
commit 4dc7081dc4
13 changed files with 154 additions and 38 deletions
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.scopes.ChainedScope
import org.jetbrains.kotlin.resolve.scopes.ExplicitImportsScope
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.util.descriptorsEqualWithSubstitution
import java.util.ArrayList
import java.util.HashSet
@@ -168,8 +169,12 @@ public class ShadowedDeclarationsFilter(
CompositeChecker(listOf()), SymbolUsageValidator.Empty, AdditionalTypeChecker.Composite(listOf()), false)
val callResolver = createContainerForMacros(project, moduleDescriptor).callResolver
val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context)
val resultingDescriptors = results.getResultingCalls().map { it.getResultingDescriptor() }.toSet()
val filtered = descriptors.filter { it in resultingDescriptors }
val resultingDescriptors = results.getResultingCalls().map { it.getResultingDescriptor() }
val resultingOriginals = resultingDescriptors.mapTo(HashSet<DeclarationDescriptor>()) { it.getOriginal() }
val filtered = descriptors.filter { candidateDescriptor ->
candidateDescriptor.getOriginal() in resultingOriginals /* optimization */
&& resultingDescriptors.any { descriptorsEqualWithSubstitution(it, candidateDescriptor) }
}
return if (filtered.isNotEmpty()) filtered else descriptors /* something went wrong, none of our declarations among resolve candidates, let's not filter anything */
}
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.util
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.checker.JetTypeChecker
import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
public fun descriptorsEqualWithSubstitution(descriptor1: DeclarationDescriptor?, descriptor2: DeclarationDescriptor?): Boolean {
if (descriptor1 == descriptor2) return true
if (descriptor1 == null || descriptor2 == null) return false
if (descriptor1.getOriginal() != descriptor2.getOriginal()) return false
if (descriptor1 !is CallableDescriptor) return true
descriptor2 as CallableDescriptor
val typeChecker = JetTypeChecker.withAxioms(object: JetTypeChecker.TypeConstructorEquality {
override fun equals(a: TypeConstructor, b: TypeConstructor): Boolean {
val typeParam1 = a.getDeclarationDescriptor() as? TypeParameterDescriptor
val typeParam2 = b.getDeclarationDescriptor() as? TypeParameterDescriptor
if (typeParam1 != null
&& typeParam2 != null
&& typeParam1.getContainingDeclaration() == descriptor1
&& typeParam2.getContainingDeclaration() == descriptor2) {
return typeParam1.getIndex() == typeParam2.getIndex()
}
return a == b
}
})
if (!typeChecker.equalTypesOrNulls(descriptor1.getReturnType(), descriptor2.getReturnType())) return false
val parameters1 = descriptor1.getValueParameters()
val parameters2 = descriptor2.getValueParameters()
if (parameters1.size() != parameters2.size()) return false
for ((param1, param2) in parameters1.zip(parameters2)) {
if (!typeChecker.equalTypes(param1.getType(), param2.getType())) return false
}
return true
}