Pull Up: Approximate anonymous object type with its direct supertype

This commit is contained in:
Alexey Sedunov
2015-09-08 20:53:05 +03:00
parent 4d0cbf83d3
commit 49f0101b70
4 changed files with 32 additions and 10 deletions
@@ -28,10 +28,13 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames.JETBRAINS_NULLABLE_ANNO
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.psi.JetCallableDeclaration
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.getClassifier
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.substitute
import org.jetbrains.kotlin.types.typeUtil.supertypes
@@ -94,3 +97,11 @@ public fun JetType.approximateWithResolvableType(scope: LexicalScope?, checkType
return supertypes().firstOrNull { it.isResolvableInScope(scope, checkTypeParameters) }
?: KotlinBuiltIns.getInstance().getAnyType()
}
public fun JetType.anonymousObjectSuperTypeOrNull(): JetType? {
val classDescriptor = constructor.declarationDescriptor
if (classDescriptor != null && DescriptorUtils.isAnonymousObject(classDescriptor)) {
return immediateSupertypes().firstOrNull() ?: KotlinBuiltIns.getInstance().anyType
}
return null
}
@@ -33,11 +33,13 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.JetType
fun JetCallableDeclaration.setType(type: JetType) {
fun JetCallableDeclaration.setType(type: JetType, shortenReferences: Boolean = true) {
if (type.isError()) return
val typeReference = JetPsiFactory(getProject()).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
setTypeReference(typeReference)
ShortenReferences.DEFAULT.process(getTypeReference()!!)
if (shortenReferences) {
ShortenReferences.DEFAULT.process(getTypeReference()!!)
}
}
fun JetCallableDeclaration.setReceiverType(type: JetType) {
@@ -30,12 +30,15 @@ import org.jetbrains.kotlin.asJava.getRepresentativeLightMethod
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.JetLanguage
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
import org.jetbrains.kotlin.idea.core.refactoring.createJavaField
import org.jetbrains.kotlin.idea.core.refactoring.createJavaMethod
import org.jetbrains.kotlin.idea.intentions.setType
import org.jetbrains.kotlin.idea.refactoring.safeDelete.removeOverrideModifier
import org.jetbrains.kotlin.idea.util.anonymousObjectSuperTypeOrNull
import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiUnifier
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.*
@@ -49,10 +52,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getExplicitReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.source.getPsi
import java.util.ArrayList
import java.util.Comparator
import java.util.LinkedHashMap
import java.util.LinkedHashSet
import java.util.*
class KotlinPullUpHelper(
private val javaData: PullUpData,
@@ -365,9 +365,16 @@ class KotlinPullUpHelper(
private fun moveToJavaClass(member: JetNamedDeclaration, substitutor: PsiSubstitutor) {
if (!(data.targetClass is PsiClass && member.canMoveMemberToJavaClass(data.targetClass))) return
// TODO: Drop after PsiTypes in light elements are properly generated
if (member is JetCallableDeclaration && member.typeReference == null) {
val returnType = (data.memberDescriptors[member] as CallableDescriptor).returnType ?: KotlinBuiltIns.getInstance().anyType
returnType.anonymousObjectSuperTypeOrNull()?.let { member.setType(it, false) }
}
val project = member.project
val lightMethod = member.getRepresentativeLightMethod() ?: return
val elementFactory = JavaPsiFacade.getElementFactory(project)
val lightMethod = member.getRepresentativeLightMethod()!!
val movedMember: PsiMember = when (member) {
is JetProperty -> {
val newType = substitutor.substitute(lightMethod.returnType)
@@ -22,7 +22,9 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.intentions.setType
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.anonymousObjectSuperTypeOrNull
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.*
@@ -112,12 +114,12 @@ fun makeAbstract(member: JetCallableDeclaration,
type = KotlinBuiltIns.getInstance().nullableAnyType
}
else {
type = substitutor.substitute(type, Variance.INVARIANT) ?: KotlinBuiltIns.getInstance().nullableAnyType
type = substitutor.substitute(type.anonymousObjectSuperTypeOrNull() ?: type, Variance.INVARIANT)
?: KotlinBuiltIns.getInstance().nullableAnyType
}
if (member is JetProperty || !type.isUnit()) {
val typeRef = JetPsiFactory(targetClass).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
member.setTypeReference(typeRef)
member.setType(type, false)
}
}