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.load.java.JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap 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.JetScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.getClassifier import org.jetbrains.kotlin.resolve.scopes.utils.getClassifier
import org.jetbrains.kotlin.types.* 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.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.substitute import org.jetbrains.kotlin.types.typeUtil.substitute
import org.jetbrains.kotlin.types.typeUtil.supertypes 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) } return supertypes().firstOrNull { it.isResolvableInScope(scope, checkTypeParameters) }
?: KotlinBuiltIns.getInstance().getAnyType() ?: 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.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.JetType
fun JetCallableDeclaration.setType(type: JetType) { fun JetCallableDeclaration.setType(type: JetType, shortenReferences: Boolean = true) {
if (type.isError()) return if (type.isError()) return
val typeReference = JetPsiFactory(getProject()).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type)) val typeReference = JetPsiFactory(getProject()).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
setTypeReference(typeReference) setTypeReference(typeReference)
ShortenReferences.DEFAULT.process(getTypeReference()!!) if (shortenReferences) {
ShortenReferences.DEFAULT.process(getTypeReference()!!)
}
} }
fun JetCallableDeclaration.setReceiverType(type: JetType) { 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.namedUnwrappedElement
import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.JetLanguage import org.jetbrains.kotlin.idea.JetLanguage
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
import org.jetbrains.kotlin.idea.core.refactoring.createJavaField import org.jetbrains.kotlin.idea.core.refactoring.createJavaField
import org.jetbrains.kotlin.idea.core.refactoring.createJavaMethod 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.refactoring.safeDelete.removeOverrideModifier
import org.jetbrains.kotlin.idea.util.anonymousObjectSuperTypeOrNull
import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiUnifier import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiUnifier
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.* 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.calls.resolvedCallUtil.getExplicitReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
import java.util.ArrayList import java.util.*
import java.util.Comparator
import java.util.LinkedHashMap
import java.util.LinkedHashSet
class KotlinPullUpHelper( class KotlinPullUpHelper(
private val javaData: PullUpData, private val javaData: PullUpData,
@@ -365,9 +365,16 @@ class KotlinPullUpHelper(
private fun moveToJavaClass(member: JetNamedDeclaration, substitutor: PsiSubstitutor) { private fun moveToJavaClass(member: JetNamedDeclaration, substitutor: PsiSubstitutor) {
if (!(data.targetClass is PsiClass && member.canMoveMemberToJavaClass(data.targetClass))) return 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 project = member.project
val lightMethod = member.getRepresentativeLightMethod() ?: return
val elementFactory = JavaPsiFacade.getElementFactory(project) val elementFactory = JavaPsiFacade.getElementFactory(project)
val lightMethod = member.getRepresentativeLightMethod()!!
val movedMember: PsiMember = when (member) { val movedMember: PsiMember = when (member) {
is JetProperty -> { is JetProperty -> {
val newType = substitutor.substitute(lightMethod.returnType) 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.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
import org.jetbrains.kotlin.idea.core.replaced 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.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.anonymousObjectSuperTypeOrNull
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -112,12 +114,12 @@ fun makeAbstract(member: JetCallableDeclaration,
type = KotlinBuiltIns.getInstance().nullableAnyType type = KotlinBuiltIns.getInstance().nullableAnyType
} }
else { 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()) { if (member is JetProperty || !type.isUnit()) {
val typeRef = JetPsiFactory(targetClass).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type)) member.setType(type, false)
member.setTypeReference(typeRef)
} }
} }