Reformat & cleanup: CreateCallableFromCallActionFactory
This commit is contained in:
+107
-98
@@ -49,18 +49,16 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
import java.lang.AssertionError
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
||||||
extensionsEnabled: Boolean = true
|
extensionsEnabled: Boolean = true
|
||||||
) : CreateCallableMemberFromUsageFactory<E>(extensionsEnabled) {
|
) : CreateCallableMemberFromUsageFactory<E>(extensionsEnabled) {
|
||||||
protected abstract fun doCreateCallableInfo(
|
protected abstract fun doCreateCallableInfo(
|
||||||
expression: E,
|
expression: E,
|
||||||
analysisResult: AnalysisResult,
|
analysisResult: AnalysisResult,
|
||||||
name: String,
|
name: String,
|
||||||
receiverType: TypeInfo,
|
receiverType: TypeInfo,
|
||||||
possibleContainers: List<KtElement>
|
possibleContainers: List<KtElement>
|
||||||
): CallableInfo?
|
): CallableInfo?
|
||||||
|
|
||||||
protected fun getExpressionOfInterest(diagnostic: Diagnostic): KtExpression? {
|
protected fun getExpressionOfInterest(diagnostic: Diagnostic): KtExpression? {
|
||||||
@@ -68,7 +66,8 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
if (PsiTreeUtil.getParentOfType(
|
if (PsiTreeUtil.getParentOfType(
|
||||||
diagElement,
|
diagElement,
|
||||||
KtTypeReference::class.java, KtAnnotationEntry::class.java, KtImportDirective::class.java
|
KtTypeReference::class.java, KtAnnotationEntry::class.java, KtImportDirective::class.java
|
||||||
) != null) return null
|
) != null
|
||||||
|
) return null
|
||||||
|
|
||||||
return when (diagnostic.factory) {
|
return when (diagnostic.factory) {
|
||||||
in Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS, Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND -> {
|
in Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS, Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND -> {
|
||||||
@@ -90,10 +89,10 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
val project = element.project
|
val project = element.project
|
||||||
|
|
||||||
val calleeExpr = when (element) {
|
val calleeExpr = when (element) {
|
||||||
is KtCallExpression -> element.calleeExpression
|
is KtCallExpression -> element.calleeExpression
|
||||||
is KtSimpleNameExpression -> element
|
is KtSimpleNameExpression -> element
|
||||||
else -> null
|
else -> null
|
||||||
} as? KtSimpleNameExpression ?: return null
|
} as? KtSimpleNameExpression ?: return null
|
||||||
|
|
||||||
if (calleeExpr.getReferencedNameElementType() != KtTokens.IDENTIFIER) return null
|
if (calleeExpr.getReferencedNameElementType() != KtTokens.IDENTIFIER) return null
|
||||||
|
|
||||||
@@ -102,13 +101,12 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
val receiverType = getReceiverTypeInfo(analysisResult.bindingContext, project, receiver) ?: return null
|
val receiverType = getReceiverTypeInfo(analysisResult.bindingContext, project, receiver) ?: return null
|
||||||
|
|
||||||
val possibleContainers =
|
val possibleContainers =
|
||||||
if (receiverType is TypeInfo.Empty) {
|
if (receiverType is TypeInfo.Empty) {
|
||||||
val containers = with(element.getQualifiedExpressionForSelectorOrThis().getExtractionContainers()) {
|
val containers = with(element.getQualifiedExpressionForSelectorOrThis().getExtractionContainers()) {
|
||||||
if (element is KtCallExpression) this else filter { it is KtClassBody || it is KtFile }
|
if (element is KtCallExpression) this else filter { it is KtClassBody || it is KtFile }
|
||||||
}
|
|
||||||
if (containers.isNotEmpty()) containers else return null
|
|
||||||
}
|
}
|
||||||
else Collections.emptyList()
|
if (containers.isNotEmpty()) containers else return null
|
||||||
|
} else listOf()
|
||||||
|
|
||||||
return doCreateCallableInfo(element, analysisResult, calleeExpr.getReferencedName(), receiverType, possibleContainers)
|
return doCreateCallableInfo(element, analysisResult, calleeExpr.getReferencedName(), receiverType, possibleContainers)
|
||||||
}
|
}
|
||||||
@@ -159,21 +157,22 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
if (!receiverType.isAbstract() && TypeUtils.getAllSupertypes(receiverType).all { !it.isAbstract() }) return null
|
if (!receiverType.isAbstract() && TypeUtils.getAllSupertypes(receiverType).all { !it.isAbstract() }) return null
|
||||||
|
|
||||||
return mainCallable.copy(
|
return mainCallable.copy(
|
||||||
receiverTypeInfo = receiverTypeInfo,
|
receiverTypeInfo = receiverTypeInfo,
|
||||||
possibleContainers = emptyList(),
|
possibleContainers = emptyList(),
|
||||||
modifierList = KtPsiFactory(originalExpression).createModifierList(KtTokens.ABSTRACT_KEYWORD))
|
modifierList = KtPsiFactory(originalExpression).createModifierList(KtTokens.ABSTRACT_KEYWORD)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun getCallableWithReceiverInsideExtension(
|
protected fun getCallableWithReceiverInsideExtension(
|
||||||
mainCallable: CallableInfo,
|
mainCallable: CallableInfo,
|
||||||
originalExpression: KtExpression,
|
originalExpression: KtExpression,
|
||||||
context: BindingContext,
|
context: BindingContext,
|
||||||
receiverType: TypeInfo
|
receiverType: TypeInfo
|
||||||
): CallableInfo? {
|
): CallableInfo? {
|
||||||
if (receiverType != TypeInfo.Empty) return null
|
if (receiverType != TypeInfo.Empty) return null
|
||||||
val callable = (originalExpression.getParentOfTypeAndBranch<KtFunction> { bodyExpression }
|
val callable = (originalExpression.getParentOfTypeAndBranch<KtFunction> { bodyExpression }
|
||||||
?: originalExpression.getParentOfTypeAndBranches<KtProperty> { listOf(getter, setter) })
|
?: originalExpression.getParentOfTypeAndBranches<KtProperty> { listOf(getter, setter) })
|
||||||
?: return null
|
?: return null
|
||||||
if (callable !is KtFunctionLiteral && callable.receiverTypeReference == null) return null
|
if (callable !is KtFunctionLiteral && callable.receiverTypeReference == null) return null
|
||||||
val callableDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, callable] as? CallableDescriptor ?: return null
|
val callableDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, callable] as? CallableDescriptor ?: return null
|
||||||
val extensionReceiverType = callableDescriptor.extensionReceiverParameter?.type ?: return null
|
val extensionReceiverType = callableDescriptor.extensionReceiverParameter?.type ?: return null
|
||||||
@@ -181,7 +180,7 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
return mainCallable.copy(receiverTypeInfo = newReceiverTypeInfo, possibleContainers = emptyList())
|
return mainCallable.copy(receiverTypeInfo = newReceiverTypeInfo, possibleContainers = emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class Property: CreateCallableFromCallActionFactory<KtSimpleNameExpression>() {
|
sealed class Property : CreateCallableFromCallActionFactory<KtSimpleNameExpression>() {
|
||||||
override fun getElementOfInterest(diagnostic: Diagnostic): KtSimpleNameExpression? {
|
override fun getElementOfInterest(diagnostic: Diagnostic): KtSimpleNameExpression? {
|
||||||
val refExpr = getExpressionOfInterest(diagnostic) as? KtNameReferenceExpression ?: return null
|
val refExpr = getExpressionOfInterest(diagnostic) as? KtNameReferenceExpression ?: return null
|
||||||
if (refExpr.getParentOfTypeAndBranch<KtCallableReferenceExpression> { callableReference } != null) return null
|
if (refExpr.getParentOfTypeAndBranch<KtCallableReferenceExpression> { callableReference } != null) return null
|
||||||
@@ -189,11 +188,11 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun doCreateCallableInfo(
|
override fun doCreateCallableInfo(
|
||||||
expression: KtSimpleNameExpression,
|
expression: KtSimpleNameExpression,
|
||||||
analysisResult: AnalysisResult,
|
analysisResult: AnalysisResult,
|
||||||
name: String,
|
name: String,
|
||||||
receiverType: TypeInfo,
|
receiverType: TypeInfo,
|
||||||
possibleContainers: List<KtElement>
|
possibleContainers: List<KtElement>
|
||||||
): CallableInfo? {
|
): CallableInfo? {
|
||||||
val fullCallExpr = expression.getQualifiedExpressionForSelectorOrThis()
|
val fullCallExpr = expression.getQualifiedExpressionForSelectorOrThis()
|
||||||
val varExpected = fullCallExpr.getAssignmentByLHS() != null
|
val varExpected = fullCallExpr.getAssignmentByLHS() != null
|
||||||
@@ -201,37 +200,37 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
val returnTypes = expressionForTypeGuess.guessTypes(analysisResult.bindingContext, analysisResult.moduleDescriptor)
|
val returnTypes = expressionForTypeGuess.guessTypes(analysisResult.bindingContext, analysisResult.moduleDescriptor)
|
||||||
val returnTypeInfo = TypeInfo(expressionForTypeGuess, if (varExpected) Variance.INVARIANT else Variance.OUT_VARIANCE)
|
val returnTypeInfo = TypeInfo(expressionForTypeGuess, if (varExpected) Variance.INVARIANT else Variance.OUT_VARIANCE)
|
||||||
val canBeLateinit =
|
val canBeLateinit =
|
||||||
varExpected
|
varExpected
|
||||||
&& returnTypes.any { !it.isMarkedNullable && !KotlinBuiltIns.isPrimitiveType(it) }
|
&& returnTypes.any { !it.isMarkedNullable && !KotlinBuiltIns.isPrimitiveType(it) }
|
||||||
&& fullCallExpr.parents.firstOrNull { it is KtDeclarationWithBody || it is KtClassInitializer } is KtDeclarationWithBody
|
&& fullCallExpr.parents.firstOrNull { it is KtDeclarationWithBody || it is KtClassInitializer } is KtDeclarationWithBody
|
||||||
return PropertyInfo(name, receiverType, returnTypeInfo, varExpected, possibleContainers, isLateinitPreferred = canBeLateinit)
|
return PropertyInfo(name, receiverType, returnTypeInfo, varExpected, possibleContainers, isLateinitPreferred = canBeLateinit)
|
||||||
}
|
}
|
||||||
|
|
||||||
object Default : Property() {
|
object Default : Property() {
|
||||||
override fun doCreateCallableInfo(
|
override fun doCreateCallableInfo(
|
||||||
expression: KtSimpleNameExpression,
|
expression: KtSimpleNameExpression,
|
||||||
analysisResult: AnalysisResult,
|
analysisResult: AnalysisResult,
|
||||||
name: String,
|
name: String,
|
||||||
receiverType: TypeInfo,
|
receiverType: TypeInfo,
|
||||||
possibleContainers: List<KtElement>
|
possibleContainers: List<KtElement>
|
||||||
): CallableInfo? {
|
): CallableInfo? {
|
||||||
return super.doCreateCallableInfo(
|
return super.doCreateCallableInfo(
|
||||||
expression,
|
expression,
|
||||||
analysisResult,
|
analysisResult,
|
||||||
name,
|
name,
|
||||||
receiverType,
|
receiverType,
|
||||||
possibleContainers.filterNot { it is KtClassBody && (it.parent as KtClassOrObject).isInterfaceClass() }
|
possibleContainers.filterNot { it is KtClassBody && (it.parent as KtClassOrObject).isInterfaceClass() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Abstract : Property() {
|
object Abstract : Property() {
|
||||||
override fun doCreateCallableInfo(
|
override fun doCreateCallableInfo(
|
||||||
expression: KtSimpleNameExpression,
|
expression: KtSimpleNameExpression,
|
||||||
analysisResult: AnalysisResult,
|
analysisResult: AnalysisResult,
|
||||||
name: String,
|
name: String,
|
||||||
receiverType: TypeInfo,
|
receiverType: TypeInfo,
|
||||||
possibleContainers: List<KtElement>
|
possibleContainers: List<KtElement>
|
||||||
) = super.doCreateCallableInfo(expression, analysisResult, name, receiverType, possibleContainers)?.let {
|
) = super.doCreateCallableInfo(expression, analysisResult, name, receiverType, possibleContainers)?.let {
|
||||||
getAbstractCallableInfo(it, expression)
|
getAbstractCallableInfo(it, expression)
|
||||||
}
|
}
|
||||||
@@ -239,28 +238,33 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
|
|
||||||
object ByImplicitExtensionReceiver : Property() {
|
object ByImplicitExtensionReceiver : Property() {
|
||||||
override fun doCreateCallableInfo(
|
override fun doCreateCallableInfo(
|
||||||
expression: KtSimpleNameExpression,
|
expression: KtSimpleNameExpression,
|
||||||
analysisResult: AnalysisResult,
|
analysisResult: AnalysisResult,
|
||||||
name: String,
|
name: String,
|
||||||
receiverType: TypeInfo,
|
receiverType: TypeInfo,
|
||||||
possibleContainers: List<KtElement>
|
possibleContainers: List<KtElement>
|
||||||
) = super.doCreateCallableInfo(expression, analysisResult, name, receiverType, possibleContainers)?.let {
|
) = super.doCreateCallableInfo(expression, analysisResult, name, receiverType, possibleContainers)?.let {
|
||||||
ByImplicitExtensionReceiver.getCallableWithReceiverInsideExtension(it, expression, analysisResult.bindingContext, receiverType)
|
ByImplicitExtensionReceiver.getCallableWithReceiverInsideExtension(
|
||||||
|
it,
|
||||||
|
expression,
|
||||||
|
analysisResult.bindingContext,
|
||||||
|
receiverType
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class Function: CreateCallableFromCallActionFactory<KtCallExpression>() {
|
sealed class Function : CreateCallableFromCallActionFactory<KtCallExpression>() {
|
||||||
override fun getElementOfInterest(diagnostic: Diagnostic): KtCallExpression? {
|
override fun getElementOfInterest(diagnostic: Diagnostic): KtCallExpression? {
|
||||||
return getExpressionOfInterest(diagnostic) as? KtCallExpression
|
return getExpressionOfInterest(diagnostic) as? KtCallExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doCreateCallableInfo(
|
override fun doCreateCallableInfo(
|
||||||
expression: KtCallExpression,
|
expression: KtCallExpression,
|
||||||
analysisResult: AnalysisResult,
|
analysisResult: AnalysisResult,
|
||||||
name: String,
|
name: String,
|
||||||
receiverType: TypeInfo,
|
receiverType: TypeInfo,
|
||||||
possibleContainers: List<KtElement>
|
possibleContainers: List<KtElement>
|
||||||
): CallableInfo? {
|
): CallableInfo? {
|
||||||
val parameters = expression.getParameterInfos()
|
val parameters = expression.getParameterInfos()
|
||||||
val typeParameters = expression.getTypeInfoForTypeArguments()
|
val typeParameters = expression.getTypeInfoForTypeArguments()
|
||||||
@@ -278,11 +282,11 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
|
|
||||||
object Abstract : Function() {
|
object Abstract : Function() {
|
||||||
override fun doCreateCallableInfo(
|
override fun doCreateCallableInfo(
|
||||||
expression: KtCallExpression,
|
expression: KtCallExpression,
|
||||||
analysisResult: AnalysisResult,
|
analysisResult: AnalysisResult,
|
||||||
name: String,
|
name: String,
|
||||||
receiverType: TypeInfo,
|
receiverType: TypeInfo,
|
||||||
possibleContainers: List<KtElement>
|
possibleContainers: List<KtElement>
|
||||||
) = super.doCreateCallableInfo(expression, analysisResult, name, receiverType, possibleContainers)?.let {
|
) = super.doCreateCallableInfo(expression, analysisResult, name, receiverType, possibleContainers)?.let {
|
||||||
getAbstractCallableInfo(it, expression)
|
getAbstractCallableInfo(it, expression)
|
||||||
}
|
}
|
||||||
@@ -290,42 +294,43 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
|
|
||||||
object ByImplicitExtensionReceiver : Function() {
|
object ByImplicitExtensionReceiver : Function() {
|
||||||
override fun doCreateCallableInfo(
|
override fun doCreateCallableInfo(
|
||||||
expression: KtCallExpression,
|
expression: KtCallExpression,
|
||||||
analysisResult: AnalysisResult,
|
analysisResult: AnalysisResult,
|
||||||
name: String,
|
name: String,
|
||||||
receiverType: TypeInfo,
|
receiverType: TypeInfo,
|
||||||
possibleContainers: List<KtElement>
|
possibleContainers: List<KtElement>
|
||||||
) = super.doCreateCallableInfo(expression, analysisResult, name, receiverType, possibleContainers)?.let {
|
) = super.doCreateCallableInfo(expression, analysisResult, name, receiverType, possibleContainers)?.let {
|
||||||
getCallableWithReceiverInsideExtension(it, expression, analysisResult.bindingContext, receiverType)
|
getCallableWithReceiverInsideExtension(it, expression, analysisResult.bindingContext, receiverType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Constructor: CreateCallableFromCallActionFactory<KtCallExpression>() {
|
object Constructor : CreateCallableFromCallActionFactory<KtCallExpression>() {
|
||||||
override fun getElementOfInterest(diagnostic: Diagnostic): KtCallExpression? {
|
override fun getElementOfInterest(diagnostic: Diagnostic): KtCallExpression? {
|
||||||
return getExpressionOfInterest(diagnostic) as? KtCallExpression
|
return getExpressionOfInterest(diagnostic) as? KtCallExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doCreateCallableInfo(
|
override fun doCreateCallableInfo(
|
||||||
expression: KtCallExpression,
|
expression: KtCallExpression,
|
||||||
analysisResult: AnalysisResult,
|
analysisResult: AnalysisResult,
|
||||||
name: String,
|
name: String,
|
||||||
receiverType: TypeInfo,
|
receiverType: TypeInfo,
|
||||||
possibleContainers: List<KtElement>
|
possibleContainers: List<KtElement>
|
||||||
): CallableInfo? {
|
): CallableInfo? {
|
||||||
if (expression.typeArguments.isNotEmpty()) return null
|
if (expression.typeArguments.isNotEmpty()) return null
|
||||||
|
|
||||||
val classDescriptor = expression
|
val classDescriptor = expression
|
||||||
.calleeExpression
|
.calleeExpression
|
||||||
?.getReferenceTargets(analysisResult.bindingContext)
|
?.getReferenceTargets(analysisResult.bindingContext)
|
||||||
?.mapNotNull { (it as? ConstructorDescriptor)?.containingDeclaration }
|
?.mapNotNull { (it as? ConstructorDescriptor)?.containingDeclaration }
|
||||||
?.distinct()
|
?.distinct()
|
||||||
?.singleOrNull() as? ClassDescriptor
|
?.singleOrNull() as? ClassDescriptor
|
||||||
val klass = classDescriptor?.source?.getPsi()
|
val klass = classDescriptor?.source?.getPsi()
|
||||||
if ((klass !is KtClass && klass !is PsiClass) || !klass.canRefactor()) return null
|
if ((klass !is KtClass && klass !is PsiClass) || !klass.canRefactor()) return null
|
||||||
|
|
||||||
val expectedType = analysisResult.bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expression.getQualifiedExpressionForSelectorOrThis()]
|
val expectedType =
|
||||||
?: classDescriptor.builtIns.nullableAnyType
|
analysisResult.bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expression.getQualifiedExpressionForSelectorOrThis()]
|
||||||
|
?: classDescriptor.builtIns.nullableAnyType
|
||||||
if (!classDescriptor.defaultType.isSubtypeOf(expectedType)) return null
|
if (!classDescriptor.defaultType.isSubtypeOf(expectedType)) return null
|
||||||
|
|
||||||
val parameters = expression.getParameterInfos()
|
val parameters = expression.getParameterInfos()
|
||||||
@@ -335,16 +340,20 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val FUNCTIONS = arrayOf(Function.Default,
|
val FUNCTIONS = arrayOf(
|
||||||
Function.Abstract,
|
Function.Default,
|
||||||
Function.ByImplicitExtensionReceiver,
|
Function.Abstract,
|
||||||
Constructor)
|
Function.ByImplicitExtensionReceiver,
|
||||||
val INSTANCES = arrayOf(Function.Default,
|
Constructor
|
||||||
Function.Abstract,
|
)
|
||||||
Function.ByImplicitExtensionReceiver,
|
val INSTANCES = arrayOf(
|
||||||
Constructor,
|
Function.Default,
|
||||||
Property.Default,
|
Function.Abstract,
|
||||||
Property.Abstract,
|
Function.ByImplicitExtensionReceiver,
|
||||||
Property.ByImplicitExtensionReceiver)
|
Constructor,
|
||||||
|
Property.Default,
|
||||||
|
Property.Abstract,
|
||||||
|
Property.ByImplicitExtensionReceiver
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user