Reformat: KotlinPullUpHelper

This commit is contained in:
Mikhail Glukhikh
2018-01-30 16:30:08 +03:00
parent d88b5746c7
commit cefa17f877
@@ -61,47 +61,48 @@ import org.jetbrains.kotlin.types.Variance
import java.util.* import java.util.*
class KotlinPullUpHelper( class KotlinPullUpHelper(
private val javaData: PullUpData, private val javaData: PullUpData,
private val data: KotlinPullUpData private val data: KotlinPullUpData
) : PullUpHelper<MemberInfoBase<PsiMember>> { ) : PullUpHelper<MemberInfoBase<PsiMember>> {
private fun KtExpression.isMovable(): Boolean { private fun KtExpression.isMovable(): Boolean {
return accept( return accept(
object: KtVisitor<Boolean, Nothing?>() { object : KtVisitor<Boolean, Nothing?>() {
override fun visitKtElement(element: KtElement, arg: Nothing?): Boolean { override fun visitKtElement(element: KtElement, arg: Nothing?): Boolean {
return element.allChildren.all { (it as? KtElement)?.accept(this, arg) ?: true } return element.allChildren.all { (it as? KtElement)?.accept(this, arg) ?: true }
}
override fun visitKtFile(file: KtFile, data: Nothing?) = false
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, arg: Nothing?): Boolean {
val resolvedCall = expression.getResolvedCall(data.resolutionFacade.analyze(expression)) ?: return true
val receiver = (resolvedCall.getExplicitReceiverValue() as? ExpressionReceiver)?.expression
if (receiver != null && receiver !is KtThisExpression && receiver !is KtSuperExpression) return true
var descriptor: DeclarationDescriptor = resolvedCall.resultingDescriptor
if (descriptor is ConstructorDescriptor) {
descriptor = descriptor.containingDeclaration
} }
// todo: local functions
override fun visitKtFile(file: KtFile, data: Nothing?) = false if (descriptor is ValueParameterDescriptor) return true
if (descriptor is ClassDescriptor && !descriptor.isInner) return true
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, arg: Nothing?): Boolean { if (descriptor is MemberDescriptor) {
val resolvedCall = expression.getResolvedCall(data.resolutionFacade.analyze(expression)) ?: return true if (descriptor.source.getPsi() in propertiesToMoveInitializers) return true
val receiver = (resolvedCall.getExplicitReceiverValue() as? ExpressionReceiver)?.expression descriptor = descriptor.containingDeclaration
if (receiver != null && receiver !is KtThisExpression && receiver !is KtSuperExpression) return true
var descriptor: DeclarationDescriptor = resolvedCall.resultingDescriptor
if (descriptor is ConstructorDescriptor) {
descriptor = descriptor.containingDeclaration
}
// todo: local functions
if (descriptor is ValueParameterDescriptor) return true
if (descriptor is ClassDescriptor && !descriptor.isInner) return true
if (descriptor is MemberDescriptor) {
if (descriptor.source.getPsi() in propertiesToMoveInitializers) return true
descriptor = descriptor.containingDeclaration
}
return descriptor is PackageFragmentDescriptor
|| (descriptor is ClassDescriptor && DescriptorUtils.isSubclass(data.targetClassDescriptor, descriptor))
} }
}, return descriptor is PackageFragmentDescriptor
null || (descriptor is ClassDescriptor && DescriptorUtils.isSubclass(data.targetClassDescriptor, descriptor))
}
},
null
) )
} }
private fun getCommonInitializer( private fun getCommonInitializer(
currentInitializer: KtExpression?, currentInitializer: KtExpression?,
scope: KtBlockExpression?, scope: KtBlockExpression?,
propertyDescriptor: PropertyDescriptor, propertyDescriptor: PropertyDescriptor,
elementsToRemove: MutableSet<KtElement>): KtExpression? { elementsToRemove: MutableSet<KtElement>
): KtExpression? {
if (scope == null) return currentInitializer if (scope == null) return currentInitializer
var initializerCandidate: KtExpression? = null var initializerCandidate: KtExpression? = null
@@ -121,15 +122,13 @@ class KotlinPullUpHelper(
initializerCandidate = statement initializerCandidate = statement
elementsToRemove.add(statement) elementsToRemove.add(statement)
} } else {
else {
if (!KotlinPsiUnifier.DEFAULT.unify(statement, currentInitializer).matched) return null if (!KotlinPsiUnifier.DEFAULT.unify(statement, currentInitializer).matched) return null
initializerCandidate = currentInitializer initializerCandidate = currentInitializer
elementsToRemove.add(statement) elementsToRemove.add(statement)
} }
} } else if (!KotlinPsiUnifier.DEFAULT.unify(statement, initializerCandidate).matched) return null
else if (!KotlinPsiUnifier.DEFAULT.unify(statement, initializerCandidate).matched) return null
} }
} }
@@ -137,15 +136,17 @@ class KotlinPullUpHelper(
} }
private data class InitializerInfo( private data class InitializerInfo(
val initializer: KtExpression?, val initializer: KtExpression?,
val usedProperties: Set<KtProperty>, val usedProperties: Set<KtProperty>,
val usedParameters: Set<KtParameter>, val usedParameters: Set<KtParameter>,
val elementsToRemove: Set<KtElement> val elementsToRemove: Set<KtElement>
) )
private fun getInitializerInfo(property: KtProperty, private fun getInitializerInfo(
propertyDescriptor: PropertyDescriptor, property: KtProperty,
targetConstructor: KtElement): InitializerInfo? { propertyDescriptor: PropertyDescriptor,
targetConstructor: KtElement
): InitializerInfo? {
val sourceConstructors = targetToSourceConstructors[targetConstructor] ?: return null val sourceConstructors = targetToSourceConstructors[targetConstructor] ?: return null
val elementsToRemove = LinkedHashSet<KtElement>() val elementsToRemove = LinkedHashSet<KtElement>()
val commonInitializer = sourceConstructors.fold(null as KtExpression?) { commonInitializer, constructor -> val commonInitializer = sourceConstructors.fold(null as KtExpression?) { commonInitializer, constructor ->
@@ -181,39 +182,39 @@ class KotlinPullUpHelper(
private val propertiesToMoveInitializers = with(data) { private val propertiesToMoveInitializers = with(data) {
membersToMove membersToMove
.filterIsInstance<KtProperty>() .filterIsInstance<KtProperty>()
.filter { .filter {
val descriptor = memberDescriptors[it] as? PropertyDescriptor val descriptor = memberDescriptors[it] as? PropertyDescriptor
descriptor != null && data.sourceClassContext[BindingContext.BACKING_FIELD_REQUIRED, descriptor] ?: false descriptor != null && data.sourceClassContext[BindingContext.BACKING_FIELD_REQUIRED, descriptor] ?: false
} }
} }
private val targetToSourceConstructors = LinkedHashMap<KtElement, MutableList<KtElement>>().let { result -> private val targetToSourceConstructors = LinkedHashMap<KtElement, MutableList<KtElement>>().let { result ->
if (!data.isInterfaceTarget && data.targetClass is KtClass) { if (!data.isInterfaceTarget && data.targetClass is KtClass) {
result[data.targetClass.primaryConstructor ?: data.targetClass] = ArrayList<KtElement>() result[data.targetClass.primaryConstructor ?: data.targetClass] = ArrayList<KtElement>()
data.sourceClass.accept( data.sourceClass.accept(
object : KtTreeVisitorVoid() { object : KtTreeVisitorVoid() {
private fun processConstructorReference(expression: KtReferenceExpression, callingConstructorElement: KtElement) { private fun processConstructorReference(expression: KtReferenceExpression, callingConstructorElement: KtElement) {
val descriptor = data.resolutionFacade.analyze(expression)[BindingContext.REFERENCE_TARGET, expression] val descriptor = data.resolutionFacade.analyze(expression)[BindingContext.REFERENCE_TARGET, expression]
val constructorElement = (descriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() ?: return val constructorElement = (descriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() ?: return
if (constructorElement == data.targetClass if (constructorElement == data.targetClass
|| (constructorElement as? KtConstructor<*>)?.getContainingClassOrObject() == data.targetClass) { || (constructorElement as? KtConstructor<*>)?.getContainingClassOrObject() == data.targetClass) {
result.getOrPut(constructorElement as KtElement, { ArrayList() }).add(callingConstructorElement) result.getOrPut(constructorElement as KtElement, { ArrayList() }).add(callingConstructorElement)
}
}
override fun visitSuperTypeCallEntry(specifier: KtSuperTypeCallEntry) {
val constructorRef = specifier.calleeExpression.constructorReferenceExpression ?: return
val containingClass = specifier.getStrictParentOfType<KtClassOrObject>() ?: return
val callingConstructorElement = containingClass.primaryConstructor ?: containingClass
processConstructorReference(constructorRef, callingConstructorElement)
}
override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) {
val constructorRef = constructor.getDelegationCall().calleeExpression ?: return
processConstructorReference(constructorRef, constructor)
} }
} }
override fun visitSuperTypeCallEntry(specifier: KtSuperTypeCallEntry) {
val constructorRef = specifier.calleeExpression.constructorReferenceExpression ?: return
val containingClass = specifier.getStrictParentOfType<KtClassOrObject>() ?: return
val callingConstructorElement = containingClass.primaryConstructor ?: containingClass
processConstructorReference(constructorRef, callingConstructorElement)
}
override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) {
val constructorRef = constructor.getDelegationCall().calleeExpression ?: return
processConstructorReference(constructorRef, constructor)
}
}
) )
} }
result result
@@ -227,12 +228,12 @@ class KotlinPullUpHelper(
propertyToInitializerInfo[property] = getInitializerInfo(property, propertyDescriptor, targetConstructor) ?: continue propertyToInitializerInfo[property] = getInitializerInfo(property, propertyDescriptor, targetConstructor) ?: continue
} }
val unmovableProperties = RefactoringUtil.transitiveClosure( val unmovableProperties = RefactoringUtil.transitiveClosure(
object : RefactoringUtil.Graph<KtProperty> { object : RefactoringUtil.Graph<KtProperty> {
override fun getVertices() = propertyToInitializerInfo.keys override fun getVertices() = propertyToInitializerInfo.keys
override fun getTargets(source: KtProperty) = propertyToInitializerInfo[source]?.usedProperties override fun getTargets(source: KtProperty) = propertyToInitializerInfo[source]?.usedProperties
}, },
{ !propertyToInitializerInfo.containsKey(it) } { !propertyToInitializerInfo.containsKey(it) }
) )
propertyToInitializerInfo.keys.removeAll(unmovableProperties) propertyToInitializerInfo.keys.removeAll(unmovableProperties)
@@ -248,10 +249,10 @@ class KotlinPullUpHelper(
// Add dummy light field since PullUpProcessor won't invoke moveFieldInitializations() if no PsiFields are present // Add dummy light field since PullUpProcessor won't invoke moveFieldInitializations() if no PsiFields are present
if (dummyField == null) { if (dummyField == null) {
val factory = JavaPsiFacade.getElementFactory(newMember.project) val factory = JavaPsiFacade.getElementFactory(newMember.project)
val dummyField = object: LightField( val dummyField = object : LightField(
newMember.manager, newMember.manager,
factory.createField("dummy", PsiType.BOOLEAN), factory.createField("dummy", PsiType.BOOLEAN),
factory.createClass("Dummy") factory.createClass("Dummy")
) { ) {
// Prevent processing by JavaPullUpHelper // Prevent processing by JavaPullUpHelper
override fun getLanguage() = KotlinLanguage.INSTANCE override fun getLanguage() = KotlinLanguage.INSTANCE
@@ -272,7 +273,11 @@ class KotlinPullUpHelper(
private fun liftToProtected(declaration: KtNamedDeclaration, ignoreUsages: Boolean = false) { private fun liftToProtected(declaration: KtNamedDeclaration, ignoreUsages: Boolean = false) {
if (!declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return if (!declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) return
if (ignoreUsages || willBeUsedInSourceClass(declaration, data.sourceClass, data.membersToMove)) declaration.addModifier(KtTokens.PROTECTED_KEYWORD) if (ignoreUsages || willBeUsedInSourceClass(
declaration,
data.sourceClass,
data.membersToMove
)) declaration.addModifier(KtTokens.PROTECTED_KEYWORD)
} }
override fun setCorrectVisibility(info: MemberInfoBase<PsiMember>) { override fun setCorrectVisibility(info: MemberInfoBase<PsiMember>) {
@@ -285,19 +290,19 @@ class KotlinPullUpHelper(
if (member.hasModifier(KtTokens.PRIVATE_KEYWORD)) { if (member.hasModifier(KtTokens.PRIVATE_KEYWORD)) {
member.accept( member.accept(
object: KtVisitorVoid() { object : KtVisitorVoid() {
override fun visitNamedDeclaration(declaration: KtNamedDeclaration) { override fun visitNamedDeclaration(declaration: KtNamedDeclaration) {
when (declaration) { when (declaration) {
is KtClass -> { is KtClass -> {
liftToProtected(declaration) liftToProtected(declaration)
declaration.declarations.forEach { it.accept(this) } declaration.declarations.forEach { it.accept(this) }
} }
is KtNamedFunction, is KtProperty -> { is KtNamedFunction, is KtProperty -> {
liftToProtected(declaration, declaration == member && info.isToAbstract) liftToProtected(declaration, declaration == member && info.isToAbstract)
}
} }
} }
} }
}
) )
} }
} }
@@ -306,8 +311,10 @@ class KotlinPullUpHelper(
} }
private fun fixOverrideAndGetClashingSuper(sourceMember: KtCallableDeclaration, private fun fixOverrideAndGetClashingSuper(
targetMember: KtCallableDeclaration): KtCallableDeclaration? { sourceMember: KtCallableDeclaration,
targetMember: KtCallableDeclaration
): KtCallableDeclaration? {
val memberDescriptor = data.memberDescriptors[sourceMember] as CallableMemberDescriptor val memberDescriptor = data.memberDescriptors[sourceMember] as CallableMemberDescriptor
if (memberDescriptor.overriddenDescriptors.isEmpty()) { if (memberDescriptor.overriddenDescriptors.isEmpty()) {
@@ -329,7 +336,13 @@ class KotlinPullUpHelper(
when (data.targetClass) { when (data.targetClass) {
is KtClass -> { is KtClass -> {
data.sourceClass.removeSuperTypeListEntry(currentSpecifier) data.sourceClass.removeSuperTypeListEntry(currentSpecifier)
addSuperTypeEntry(currentSpecifier, data.targetClass, data.targetClassDescriptor, data.sourceClassContext, data.sourceToTargetClassSubstitutor) addSuperTypeEntry(
currentSpecifier,
data.targetClass,
data.targetClassDescriptor,
data.sourceClassContext,
data.sourceToTargetClassSubstitutor
)
} }
is PsiClass -> { is PsiClass -> {
@@ -337,9 +350,9 @@ class KotlinPullUpHelper(
val sourcePsiClass = data.sourceClass.toLightClass() ?: return val sourcePsiClass = data.sourceClass.toLightClass() ?: return
val superRef = sourcePsiClass.implementsList val superRef = sourcePsiClass.implementsList
?.referenceElements ?.referenceElements
?.firstOrNull { it.resolve()?.unwrapped == realMemberPsi } ?.firstOrNull { it.resolve()?.unwrapped == realMemberPsi }
?: return ?: return
val superTypeForTarget = substitutor.substitute(elementFactory.createType(superRef)) val superTypeForTarget = substitutor.substitute(elementFactory.createType(superRef))
data.sourceClass.removeSuperTypeListEntry(currentSpecifier) data.sourceClass.removeSuperTypeListEntry(currentSpecifier)
@@ -357,8 +370,7 @@ class KotlinPullUpHelper(
private fun removeOriginalMemberOrAddOverride(member: KtCallableDeclaration) { private fun removeOriginalMemberOrAddOverride(member: KtCallableDeclaration) {
if (member.isAbstract()) { if (member.isAbstract()) {
member.deleteWithCompanion() member.deleteWithCompanion()
} } else {
else {
member.addModifier(KtTokens.OVERRIDE_KEYWORD) member.addModifier(KtTokens.OVERRIDE_KEYWORD)
KtTokens.VISIBILITY_MODIFIERS.types.forEach { member.removeModifier(it as KtModifierKeywordToken) } KtTokens.VISIBILITY_MODIFIERS.types.forEach { member.removeModifier(it as KtModifierKeywordToken) }
(member as? KtNamedFunction)?.valueParameters?.forEach { it.dropDefaultValue() } (member as? KtNamedFunction)?.valueParameters?.forEach { it.dropDefaultValue() }
@@ -388,8 +400,7 @@ class KotlinPullUpHelper(
} }
if (member is KtParameter) { if (member is KtParameter) {
(member.parent as? KtParameterList)?.removeParameter(member) (member.parent as? KtParameterList)?.removeParameter(member)
} } else {
else {
member.deleteWithCompanion() member.deleteWithCompanion()
} }
newField newField
@@ -426,7 +437,7 @@ class KotlinPullUpHelper(
override fun move(info: MemberInfoBase<PsiMember>, substitutor: PsiSubstitutor) { override fun move(info: MemberInfoBase<PsiMember>, substitutor: PsiSubstitutor) {
val member = info.member.toKtDeclarationWrapperAware() ?: return val member = info.member.toKtDeclarationWrapperAware() ?: return
if ((member is KtClass || member is KtPsiClassWrapper) && info.overrides != null) { if ((member is KtClass || member is KtPsiClassWrapper) && info.overrides != null) {
moveSuperInterface(member, substitutor) moveSuperInterface(member, substitutor)
return return
} }
@@ -465,11 +476,17 @@ class KotlinPullUpHelper(
else -> false else -> false
} }
val classToAddTo = if (member.isCompanionMemberOf(data.sourceClass)) data.targetClass.getOrCreateCompanionObject() else data.targetClass val classToAddTo =
if (member.isCompanionMemberOf(data.sourceClass)) data.targetClass.getOrCreateCompanionObject() else data.targetClass
if (toAbstract) { if (toAbstract) {
if (!originalIsAbstract) { if (!originalIsAbstract) {
makeAbstract(memberCopy, data.memberDescriptors[member] as CallableMemberDescriptor, data.sourceToTargetClassSubstitutor, data.targetClass) makeAbstract(
memberCopy,
data.memberDescriptors[member] as CallableMemberDescriptor,
data.sourceToTargetClassSubstitutor,
data.targetClass
)
} }
movedMember = doAddCallableMember(memberCopy, clashingSuper, classToAddTo) movedMember = doAddCallableMember(memberCopy, clashingSuper, classToAddTo)
@@ -478,8 +495,7 @@ class KotlinPullUpHelper(
} }
removeOriginalMemberOrAddOverride(member) removeOriginalMemberOrAddOverride(member)
} } else {
else {
movedMember = doAddCallableMember(memberCopy, clashingSuper, classToAddTo) movedMember = doAddCallableMember(memberCopy, clashingSuper, classToAddTo)
if (member is KtParameter && movedMember is KtParameter) { if (member is KtParameter && movedMember is KtParameter) {
member.valOrVarKeyword?.delete() member.valOrVarKeyword?.delete()
@@ -495,18 +511,17 @@ class KotlinPullUpHelper(
val parameterIndex = movedMember.parameterIndex() val parameterIndex = movedMember.parameterIndex()
val prevParameterDescriptor = superResolvedCall.resultingDescriptor.valueParameters.getOrNull(parameterIndex - 1) val prevParameterDescriptor = superResolvedCall.resultingDescriptor.valueParameters.getOrNull(parameterIndex - 1)
val prevArgument = superResolvedCall.valueArguments[prevParameterDescriptor]?.arguments?.singleOrNull() as? KtValueArgument val prevArgument =
superResolvedCall.valueArguments[prevParameterDescriptor]?.arguments?.singleOrNull() as? KtValueArgument
val newArgumentName = if (prevArgument != null && prevArgument.isNamed()) Name.identifier(member.name!!) else null val newArgumentName = if (prevArgument != null && prevArgument.isNamed()) Name.identifier(member.name!!) else null
val newArgument = psiFactory.createArgument(psiFactory.createExpression(member.name!!), newArgumentName) val newArgument = psiFactory.createArgument(psiFactory.createExpression(member.name!!), newArgumentName)
if (prevArgument == null) { if (prevArgument == null) {
argumentList.addArgument(newArgument) argumentList.addArgument(newArgument)
} } else {
else {
argumentList.addArgumentAfter(newArgument, prevArgument) argumentList.addArgumentAfter(newArgument, prevArgument)
} }
} }
} } else {
else {
member.deleteWithCompanion() member.deleteWithCompanion()
} }
} }
@@ -532,8 +547,7 @@ class KotlinPullUpHelper(
applyMarking(movedMember, data.sourceToTargetClassSubstitutor, data.targetClassDescriptor) applyMarking(movedMember, data.sourceToTargetClassSubstitutor, data.targetClassDescriptor)
addMovedMember(movedMember) addMovedMember(movedMember)
} } finally {
finally {
clearMarking(markedElements) clearMarking(markedElements)
} }
} }
@@ -582,7 +596,10 @@ class KotlinPullUpHelper(
info.usedParameters.forEach { info.usedParameters.forEach {
val newParameter = addParameter(it) val newParameter = addParameter(it)
val originalType = data.sourceClassContext[BindingContext.VALUE_PARAMETER, it]!!.type val originalType = data.sourceClassContext[BindingContext.VALUE_PARAMETER, it]!!.type
newParameter.setType(data.sourceToTargetClassSubstitutor.substitute(originalType, Variance.INVARIANT) ?: originalType, false) newParameter.setType(
data.sourceToTargetClassSubstitutor.substitute(originalType, Variance.INVARIANT) ?: originalType,
false
)
newParameter.typeReference!!.addToShorteningWaitSet() newParameter.typeReference!!.addToShorteningWaitSet()
} }
} }
@@ -593,8 +610,7 @@ class KotlinPullUpHelper(
is KtSecondaryConstructor -> { is KtSecondaryConstructor -> {
if (it.hasImplicitDelegationCall()) { if (it.hasImplicitDelegationCall()) {
it.replaceImplicitDelegationCallWithExplicit(false) it.replaceImplicitDelegationCallWithExplicit(false)
} } else {
else {
it.getDelegationCall() it.getDelegationCall()
} }
} }
@@ -610,15 +626,15 @@ class KotlinPullUpHelper(
for ((constructorElement, propertyToInitializerInfo) in targetConstructorToPropertyInitializerInfoMap.entries) { for ((constructorElement, propertyToInitializerInfo) in targetConstructorToPropertyInitializerInfoMap.entries) {
val properties = propertyToInitializerInfo.keys.sortedWith( val properties = propertyToInitializerInfo.keys.sortedWith(
Comparator<KtProperty> { property1, property2 -> Comparator<KtProperty> { property1, property2 ->
val info1 = propertyToInitializerInfo[property1]!! val info1 = propertyToInitializerInfo[property1]!!
val info2 = propertyToInitializerInfo[property2]!! val info2 = propertyToInitializerInfo[property2]!!
when { when {
property2 in info1.usedProperties -> -1 property2 in info1.usedProperties -> -1
property1 in info2.usedProperties -> 1 property1 in info2.usedProperties -> 1
else -> 0 else -> 0
}
} }
}
) )
for (oldProperty in properties) { for (oldProperty in properties) {