ParameterName annotation on type argument used to hold parameter name

This commit is contained in:
Valentin Kipyatkov
2016-09-14 19:37:44 +03:00
parent 3bd39df587
commit 59269ef1ae
37 changed files with 158 additions and 140 deletions
@@ -100,7 +100,7 @@ class InsertHandlerProvider(
if (type.isFunctionType && getValueParametersCountFromFunctionType(type) <= 1) {
// do not rely on inference from input of function type with one or no arguments - use only return type of functional type
addPotentiallyInferred(getReturnTypeFromFunctionType(type))
addPotentiallyInferred(type.getReturnTypeFromFunctionType())
return
}
@@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.builtins.extractParameterNameFromFunctionTypeArgument
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
@@ -33,8 +34,6 @@ import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
import org.jetbrains.kotlin.idea.core.fuzzyType
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.renderer.render
@@ -42,8 +41,6 @@ import org.jetbrains.kotlin.resolve.calls.util.getValueParametersCountFromFuncti
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjection
import org.jetbrains.kotlin.types.getParameterNamesFromFunctionType
import org.jetbrains.kotlin.utils.addToStdlib.check
fun insertLambdaTemplate(context: InsertionContext, placeholderRange: TextRange, lambdaType: KotlinType) {
val explicitParameterTypes = needExplicitParameterTypes(context, placeholderRange, lambdaType)
@@ -74,10 +71,10 @@ fun insertLambdaTemplate(context: InsertionContext, placeholderRange: TextRange,
fun lambdaPresentation(lambdaType: KotlinType?): String {
if (lambdaType == null) return "{...}"
val (parameterTypes, parameterNames) = functionParameterTypesAndNames(lambdaType)
val parametersPresentation = parameterNames
.mapIndexed { index, name ->
name.check { !it.isSpecial } ?: IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(parameterTypes[index])
val parameterTypes = functionParameterTypes(lambdaType)
val parametersPresentation = parameterTypes
.map {
it.extractParameterNameFromFunctionTypeArgument() ?: IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(it)
}
.joinToString(", ")
return "{ $parametersPresentation -> ... }"
@@ -104,7 +101,7 @@ private fun needExplicitParameterTypes(context: InsertionContext, placeholderRan
}
private fun buildTemplate(lambdaType: KotlinType, explicitParameterTypes: Boolean, project: Project): Template {
val (parameterTypes, parameterNames) = functionParameterTypesAndNames(lambdaType)
val parameterTypes = functionParameterTypes(lambdaType)
val manager = TemplateManager.getInstance(project)
@@ -118,7 +115,7 @@ private fun buildTemplate(lambdaType: KotlinType, explicitParameterTypes: Boolea
template.addTextSegment(", ")
}
//TODO: check for names in scope
val parameterName = parameterNames[i].check { !it.isSpecial }?.render()
val parameterName = parameterType.extractParameterNameFromFunctionTypeArgument()?.render()
val nameExpression = if (parameterName != null) {
object : Expression() {
override fun calculateResult(context: ExpressionContext?) = TextResult(parameterName)
@@ -148,9 +145,6 @@ private fun buildTemplate(lambdaType: KotlinType, explicitParameterTypes: Boolea
return template
}
private fun functionParameterTypesAndNames(functionType: KotlinType): Pair<List<KotlinType>, List<Name>> {
val types = getValueParameterTypesFromFunctionType(functionType).map(TypeProjection::getType)
val names = functionType.getParameterNamesFromFunctionType() ?: types.map { SpecialNames.NO_NAME_PROVIDED }
assert(names.size == types.size) { "Number of names does not match number of types for $functionType"}
return types to names
private fun functionParameterTypes(functionType: KotlinType): List<KotlinType> {
return functionType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType)
}
@@ -497,7 +497,7 @@ class ExpectedInfos(
.mapNotNull { it.fuzzyType }
.filter { it.type.isFunctionType }
.map {
val returnType = getReturnTypeFromFunctionType(it.type)
val returnType = it.type.getReturnTypeFromFunctionType()
ExpectedInfo(returnType.toFuzzyType(it.freeParameters), null, Tail.RBRACE)
}
}
@@ -129,7 +129,7 @@ class FindImplicitNothingAction : AnAction() {
private fun KotlinType.isNothingOrNothingFunctionType(): Boolean {
return KotlinBuiltIns.isNothing(this) ||
(isFunctionType && getReturnTypeFromFunctionType(this).isNothingOrNothingFunctionType())
(isFunctionType && this.getReturnTypeFromFunctionType().isNothingOrNothingFunctionType())
}
override fun update(e: AnActionEvent) {
@@ -69,7 +69,7 @@ class ConvertLambdaToReferenceIntention : SelfTargetingOffsetIndependentIntentio
// For lambda parameter with receiver, conversion is not allowed
if (lambdaParameterType.isExtensionFunctionType) return false
// Special Unit case (non-Unit returning lambda is accepted here, but non-Unit returning reference is not)
lambdaMustReturnUnit = getReturnTypeFromFunctionType(lambdaParameterType).isUnit()
lambdaMustReturnUnit = lambdaParameterType.getReturnTypeFromFunctionType().isUnit()
}
}
val context = statement.analyze()
@@ -52,7 +52,7 @@ class ConvertExtensionToFunctionTypeFix(element: KtTypeReference, type: KotlinTy
append('(')
arguments.dropLast(1).map { renderer.renderType(it.type) }.joinTo(this@buildString, ", ")
append(") -> ")
append(renderer.renderType(getReturnTypeFromFunctionType(this@renderType)))
append(renderer.renderType(this@renderType.getReturnTypeFromFunctionType()))
}
companion object Factory : KotlinIntentionActionsFactory() {
@@ -47,18 +47,18 @@ object CreateFunctionFromCallableReferenceActionFactory : CreateCallableMemberFr
.guessTypes(context, resolutionFacade.moduleDescriptor)
.filter(KotlinType::isFunctionType)
.mapNotNull {
val expectedReceiverType = getReceiverTypeFromFunctionType(it)
val expectedReceiverType = it.getReceiverTypeFromFunctionType()
val receiverExpression = element.receiverExpression
val qualifierType = (context.get(BindingContext.DOUBLE_COLON_LHS, receiverExpression) as? DoubleColonLHS.Type)?.type
val receiverTypeInfo = qualifierType?.let { TypeInfo(it, Variance.IN_VARIANCE) } ?: TypeInfo.Empty
val returnTypeInfo = TypeInfo(getReturnTypeFromFunctionType(it), Variance.OUT_VARIANCE)
val returnTypeInfo = TypeInfo(it.getReturnTypeFromFunctionType(), Variance.OUT_VARIANCE)
val containers = element.getExtractionContainers(includeAll = true).ifEmpty { return@mapNotNull null }
val parameterInfos = SmartList<ParameterInfo>().apply {
if (receiverExpression == null && expectedReceiverType != null) {
add(ParameterInfo(TypeInfo(expectedReceiverType, Variance.IN_VARIANCE)))
}
getValueParameterTypesFromFunctionType(it)
it.getValueParameterTypesFromFunctionType()
.let {
if (receiverExpression != null && expectedReceiverType == null && it.isNotEmpty())
it.subList(1, it.size)