Make HeuristicSignatures an IDE service

This commit is contained in:
Pavel V. Talanov
2015-07-30 19:21:55 +03:00
parent 87f826d1b8
commit f98cb74d53
3 changed files with 41 additions and 38 deletions
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.getService
import org.jetbrains.kotlin.idea.completion.smart.TypesWithContainsDetector
import org.jetbrains.kotlin.idea.core.IterableTypesDetection
import org.jetbrains.kotlin.idea.core.IterableTypesDetector
import org.jetbrains.kotlin.idea.caches.resolve.ideService
import org.jetbrains.kotlin.idea.core.mapArgumentsToParameters
import org.jetbrains.kotlin.idea.util.FuzzyType
import org.jetbrains.kotlin.idea.util.fuzzyReturnType
@@ -319,7 +320,8 @@ class ExpectedInfos(
if (alreadyHasStar) continue
val parameterType = if (useHeuristicSignatures)
HeuristicSignatures.correctedParameterType(descriptor, parameter, moduleDescriptor, project) ?: parameter.getType()
resolutionFacade.ideService<HeuristicSignatures>(moduleDescriptor).
correctedParameterType(descriptor, parameter) ?: parameter.getType()
else
parameter.getType()
@@ -524,7 +526,7 @@ class ExpectedInfos(
val leftOperandType = binaryExpression.left?.let { bindingContext.getType(it) } ?: return null
val scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, expressionWithType)!!
val detector = TypesWithContainsDetector(scope, leftOperandType, binaryExpression.project, moduleDescriptor)
val detector = TypesWithContainsDetector(scope, leftOperandType, resolutionFacade.ideService<HeuristicSignatures>(binaryExpression))
val byTypeFilter = object : ByTypeFilter {
override fun matchingSubstitutor(descriptorType: FuzzyType): TypeSubstitutor? {
@@ -34,43 +34,23 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.types.*
import java.util.HashMap
public object HeuristicSignatures {
private val signatures = HashMap<Pair<FqName, Name>, List<String>>()
init {
registerSignature("kotlin.Collection", "contains", "E")
registerSignature("kotlin.Collection", "containsAll", "kotlin.Collection<E>")
registerSignature("kotlin.MutableCollection", "remove", "E")
registerSignature("kotlin.MutableCollection", "removeAll", "kotlin.Collection<E>")
registerSignature("kotlin.MutableCollection", "retainAll", "kotlin.Collection<E>")
registerSignature("kotlin.List", "indexOf", "E")
registerSignature("kotlin.List", "lastIndexOf", "E")
registerSignature("kotlin.Map", "get", "K")
registerSignature("kotlin.Map", "containsKey", "K")
registerSignature("kotlin.Map", "containsValue", "V")
registerSignature("kotlin.MutableMap", "remove", "K")
}
private fun registerSignature(
classFqName: String,
name: String,
vararg parameterTypes: String) {
signatures[FqName(classFqName) to Name.identifier(name)] = parameterTypes.toList()
}
public fun correctedParameterType(function: FunctionDescriptor, parameter: ValueParameterDescriptor, moduleDescriptor: ModuleDescriptor, project: Project): JetType? {
public class HeuristicSignatures(
private val moduleDescriptor: ModuleDescriptor,
private val project: Project
) {
public fun correctedParameterType(function: FunctionDescriptor, parameter: ValueParameterDescriptor): JetType? {
val parameterIndex = function.getValueParameters().indexOf(parameter)
assert(parameterIndex >= 0)
return correctedParameterType(function, parameterIndex, moduleDescriptor, project)
return correctedParameterType(function, parameterIndex)
}
private fun correctedParameterType(function: FunctionDescriptor, parameterIndex: Int, moduleDescriptor: ModuleDescriptor, project: Project): JetType? {
private fun correctedParameterType(function: FunctionDescriptor, parameterIndex: Int): JetType? {
val ownerType = function.getDispatchReceiverParameter()?.getType() ?: return null
val superFunctions = function.getOverriddenDescriptors()
if (superFunctions.isNotEmpty()) {
for (superFunction in superFunctions) {
val correctedType = correctedParameterType(superFunction, parameterIndex, moduleDescriptor, project) ?: continue
val correctedType = correctedParameterType(superFunction, parameterIndex) ?: continue
val typeSubstitutor = SubstitutionUtils.buildDeepSubstitutor(ownerType)
return typeSubstitutor.safeSubstitute(correctedType, Variance.INVARIANT)
}
@@ -84,14 +64,14 @@ public object HeuristicSignatures {
val typeStr = parameterTypes[parameterIndex]
val typeParameters = ownerClass.getTypeConstructor().getParameters()
val type = typeFromText(typeStr, typeParameters, moduleDescriptor, project)
val type = typeFromText(typeStr, typeParameters)
val substitutor = IndexedParametersSubstitution(ownerClass.typeConstructor, ownerType.arguments).buildSubstitutor()
return substitutor.substitute(type, Variance.INVARIANT)
}
}
private fun typeFromText(text: String, typeParameters: Collection<TypeParameterDescriptor>, moduleDescriptor: ModuleDescriptor, project: Project): JetType {
private fun typeFromText(text: String, typeParameters: Collection<TypeParameterDescriptor>): JetType {
val typeRef = JetPsiFactory(project).createType(text)
val container = createContainerForMacros(project, moduleDescriptor)
val rootPackagesScope = SubpackagesScope(moduleDescriptor, FqName.ROOT)
@@ -107,4 +87,29 @@ public object HeuristicSignatures {
override fun getClassifier(name: Name, location: LookupLocation) = paramsByName[name]
}
companion object {
private val signatures = HashMap<Pair<FqName, Name>, List<String>>()
init {
registerSignature("kotlin.Collection", "contains", "E")
registerSignature("kotlin.Collection", "containsAll", "kotlin.Collection<E>")
registerSignature("kotlin.MutableCollection", "remove", "E")
registerSignature("kotlin.MutableCollection", "removeAll", "kotlin.Collection<E>")
registerSignature("kotlin.MutableCollection", "retainAll", "kotlin.Collection<E>")
registerSignature("kotlin.List", "indexOf", "E")
registerSignature("kotlin.List", "lastIndexOf", "E")
registerSignature("kotlin.Map", "get", "K")
registerSignature("kotlin.Map", "containsKey", "K")
registerSignature("kotlin.Map", "containsValue", "V")
registerSignature("kotlin.MutableMap", "remove", "K")
}
private fun registerSignature(
classFqName: String,
name: String,
vararg parameterTypes: String) {
signatures[FqName(classFqName) to Name.identifier(name)] = parameterTypes.toList()
}
}
}
@@ -16,10 +16,8 @@
package org.jetbrains.kotlin.idea.completion.smart
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.idea.completion.HeuristicSignatures
import org.jetbrains.kotlin.idea.util.FuzzyType
@@ -35,10 +33,8 @@ import java.util.HashMap
class TypesWithContainsDetector(
private val scope: JetScope,
private val argumentType: JetType,
private val project: Project,
private val moduleDescriptor: ModuleDescriptor
private val heuristicSignatures: HeuristicSignatures
) {
private val cache = HashMap<FuzzyType, Boolean>()
private val containsName = Name.identifier("contains")
private val booleanType = KotlinBuiltIns.getInstance().getBooleanType()
@@ -60,7 +56,7 @@ class TypesWithContainsDetector(
private fun isGoodContainsFunction(function: FunctionDescriptor, freeTypeParams: Collection<TypeParameterDescriptor>): Boolean {
if (!TypeUtils.equalTypes(function.getReturnType()!!, booleanType)) return false
val parameter = function.getValueParameters().singleOrNull() ?: return false
val parameterType = HeuristicSignatures.correctedParameterType(function, parameter, moduleDescriptor, project) ?: parameter.getType()
val parameterType = heuristicSignatures.correctedParameterType(function, parameter) ?: parameter.getType()
val fuzzyParameterType = FuzzyType(parameterType, function.getTypeParameters() + freeTypeParams)
return fuzzyParameterType.checkIsSuperTypeOf(argumentType) != null
}