Create from Usage: Approximate unresolvable types
#KT-7722 Fixed (cherry picked from commit 917cd22)
This commit is contained in:
@@ -33,6 +33,8 @@ import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.idea.util.approximateWithResolvableType
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.idea.util.isResolvableInScope
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.idea.util.getResolvableApproximations
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
@@ -40,9 +42,9 @@ import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isFlexible
|
||||
import org.jetbrains.kotlin.utils.ifEmpty
|
||||
|
||||
class SpecifyTypeExplicitlyIntention :
|
||||
@@ -112,28 +114,7 @@ class SpecifyTypeExplicitlyIntention :
|
||||
val resolutionFacade = contextElement.getResolutionFacade()
|
||||
val bindingContext = resolutionFacade.analyze(contextElement, BodyResolveMode.PARTIAL)
|
||||
val scope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||
val types = (exprType.singletonList() + TypeUtils.getAllSupertypes(exprType))
|
||||
.filter { it.isResolvableInScope(scope, true) }
|
||||
.mapNotNull mapArgs@ {
|
||||
val resolvableArgs = it.arguments.filterTo(SmartSet.create()) { it.type.isResolvableInScope(scope, true) }
|
||||
if (resolvableArgs.containsAll(it.arguments)) return@mapArgs it
|
||||
|
||||
val newArguments = (it.arguments zip it.constructor.parameters).map {
|
||||
val (arg, param) = it
|
||||
when {
|
||||
arg in resolvableArgs -> arg
|
||||
arg.projectionKind == Variance.OUT_VARIANCE ||
|
||||
param.variance == Variance.OUT_VARIANCE -> TypeProjectionImpl(
|
||||
arg.projectionKind,
|
||||
arg.type.approximateWithResolvableType(scope, true)
|
||||
)
|
||||
else -> return@mapArgs null
|
||||
}
|
||||
}
|
||||
|
||||
it.replace(newArguments)
|
||||
}
|
||||
.ifEmpty { return null }
|
||||
val types = exprType.getResolvableApproximations(scope, true).toList().ifEmpty { return null }
|
||||
return object : ChooseValueExpression<KotlinType>(types, types.first()) {
|
||||
override fun getLookupString(element: KotlinType) = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(element)
|
||||
override fun getResult(element: KotlinType) = IdeDescriptorRenderers.SOURCE_CODE.renderType(element)
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
||||
|
||||
private val typeCandidates = HashMap<TypeInfo, List<TypeCandidate>>()
|
||||
|
||||
var placement: CallablePlacement by Delegates.notNull()
|
||||
var placement: CallablePlacement? = null
|
||||
|
||||
private val elementsToShorten = ArrayList<KtElement>()
|
||||
|
||||
|
||||
+34
-7
@@ -18,17 +18,20 @@ package org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.ClassInfo
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.idea.util.getResolvableApproximations
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@@ -86,14 +89,38 @@ abstract class TypeInfo(val variance: Variance) {
|
||||
open fun getPossibleNamesFromExpression(bindingContext: BindingContext): Array<String> = ArrayUtil.EMPTY_STRING_ARRAY
|
||||
abstract fun getPossibleTypes(builder: CallableBuilder): List<KotlinType>
|
||||
|
||||
private fun getScopeForTypeApproximation(config: CallableBuilderConfiguration, placement: CallablePlacement?): LexicalScope? {
|
||||
if (placement == null) return config.originalElement.getResolutionScope()
|
||||
|
||||
val containingElement = when (placement) {
|
||||
is CallablePlacement.NoReceiver -> {
|
||||
placement.containingElement
|
||||
}
|
||||
is CallablePlacement.WithReceiver -> {
|
||||
val receiverClassDescriptor =
|
||||
placement.receiverTypeCandidate.theType.constructor.declarationDescriptor
|
||||
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) }
|
||||
if (!config.isExtension && classDeclaration != null) classDeclaration else config.currentFile
|
||||
}
|
||||
else -> throw IllegalArgumentException("Unexpected placement: $placement")
|
||||
}
|
||||
return when (containingElement) {
|
||||
is KtClassOrObject -> (containingElement.resolveToDescriptor() as? ClassDescriptorWithResolutionScopes)?.scopeForMemberDeclarationResolution
|
||||
is KtBlockExpression -> (containingElement.statements.firstOrNull() ?: containingElement).getResolutionScope()
|
||||
is KtElement -> containingElement.getContainingKtFile().getResolutionScope()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
protected fun KotlinType?.getPossibleSupertypes(variance: Variance, callableBuilder: CallableBuilder): List<KotlinType> {
|
||||
if (this == null || ErrorUtils.containsErrorType(this)) {
|
||||
return Collections.singletonList(callableBuilder.currentFileModule.builtIns.anyType)
|
||||
}
|
||||
val single = Collections.singletonList(this)
|
||||
val scope = getScopeForTypeApproximation(callableBuilder.config, callableBuilder.placement)
|
||||
val approximations = getResolvableApproximations(scope, false)
|
||||
return when (variance) {
|
||||
Variance.IN_VARIANCE -> single + supertypes()
|
||||
else -> single
|
||||
Variance.IN_VARIANCE -> approximations.toList()
|
||||
else -> listOf(approximations.firstOrNull() ?: this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user