Pull Up/Push Down/Extract Super: Support references to Java-declared superinterfaces
This commit is contained in:
+1
-1
@@ -150,4 +150,4 @@ private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElemen
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,6 +80,7 @@ import org.jetbrains.kotlin.idea.intentions.RemoveCurlyBracesFromTemplateIntenti
|
|||||||
import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices
|
import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.toValVar
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.toValVar
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KtPsiClassWrapper
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||||
import org.jetbrains.kotlin.idea.util.string.collapseSpaces
|
import org.jetbrains.kotlin.idea.util.string.collapseSpaces
|
||||||
@@ -714,7 +715,12 @@ fun FqNameUnsafe.hasIdentifiersOnly(): Boolean = pathSegments().all { KotlinName
|
|||||||
|
|
||||||
fun FqName.hasIdentifiersOnly(): Boolean = pathSegments().all { KotlinNameSuggester.isIdentifier(it.asString().quoteIfNeeded()) }
|
fun FqName.hasIdentifiersOnly(): Boolean = pathSegments().all { KotlinNameSuggester.isIdentifier(it.asString().quoteIfNeeded()) }
|
||||||
|
|
||||||
fun PsiNamedElement.isInterfaceClass(): Boolean = this is KtClass && isInterface() || this is PsiClass && isInterface
|
fun PsiNamedElement.isInterfaceClass(): Boolean = when (this) {
|
||||||
|
is KtClass -> isInterface()
|
||||||
|
is PsiClass -> isInterface
|
||||||
|
is KtPsiClassWrapper -> psiClass.isInterface
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
fun <ListType : KtElement> replaceListPsiAndKeepDelimiters(
|
fun <ListType : KtElement> replaceListPsiAndKeepDelimiters(
|
||||||
originalList: ListType,
|
originalList: ListType,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.asJava.unwrapped
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.refactoring.isInterfaceClass
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
|
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
|
||||||
@@ -49,11 +49,11 @@ class KotlinMemberInfo @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val memberDescriptor = member.resolveToDescriptor()
|
val memberDescriptor = member.resolveToDescriptorWrapperAware()
|
||||||
isStatic = member.parent is KtFile
|
isStatic = member.parent is KtFile
|
||||||
|
|
||||||
if (member is KtClass && isSuperClass) {
|
if ((member is KtClass || member is KtPsiClassWrapper) && isSuperClass) {
|
||||||
if (member.isInterface()) {
|
if (member.isInterfaceClass()) {
|
||||||
displayName = RefactoringBundle.message("member.info.implements.0", member.name)
|
displayName = RefactoringBundle.message("member.info.implements.0", member.name)
|
||||||
overrides = false
|
overrides = false
|
||||||
}
|
}
|
||||||
@@ -86,6 +86,7 @@ fun lightElementForMemberInfo(declaration: KtNamedDeclaration?): PsiMember? {
|
|||||||
it.firstIsInstanceOrNull<PsiMethod>() ?: it.firstIsInstanceOrNull<PsiField>()
|
it.firstIsInstanceOrNull<PsiMethod>() ?: it.firstIsInstanceOrNull<PsiField>()
|
||||||
} as PsiMember?
|
} as PsiMember?
|
||||||
is KtClassOrObject -> declaration.toLightClass()
|
is KtClassOrObject -> declaration.toLightClass()
|
||||||
|
is KtPsiClassWrapper -> declaration.psiClass
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-5
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.refactoring.isInterfaceClass
|
||||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -40,8 +40,8 @@ class KotlinMemberInfoStorage(
|
|||||||
filter: (KtNamedDeclaration) -> Boolean = { true }
|
filter: (KtNamedDeclaration) -> Boolean = { true }
|
||||||
): AbstractMemberInfoStorage<KtNamedDeclaration, PsiNamedElement, KotlinMemberInfo>(classOrObject, filter) {
|
): AbstractMemberInfoStorage<KtNamedDeclaration, PsiNamedElement, KotlinMemberInfo>(classOrObject, filter) {
|
||||||
override fun memberConflict(member1: KtNamedDeclaration, member: KtNamedDeclaration): Boolean {
|
override fun memberConflict(member1: KtNamedDeclaration, member: KtNamedDeclaration): Boolean {
|
||||||
val descriptor1 = member1.resolveToDescriptor()
|
val descriptor1 = member1.resolveToDescriptorWrapperAware()
|
||||||
val descriptor = member.resolveToDescriptor()
|
val descriptor = member.resolveToDescriptorWrapperAware()
|
||||||
if (descriptor1.name != descriptor.name) return false
|
if (descriptor1.name != descriptor.name) return false
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
@@ -111,9 +111,14 @@ fun extractClassMembers(
|
|||||||
val typeReference = it.typeReference ?: return@mapNotNull null
|
val typeReference = it.typeReference ?: return@mapNotNull null
|
||||||
val type = typeReference.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, typeReference]
|
val type = typeReference.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, typeReference]
|
||||||
val classDescriptor = type?.constructor?.declarationDescriptor as? ClassDescriptor
|
val classDescriptor = type?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||||
classDescriptor?.source?.getPsi() as? KtClass
|
val classPsi = classDescriptor?.source?.getPsi()
|
||||||
|
when (classPsi) {
|
||||||
|
is KtClass -> classPsi
|
||||||
|
is PsiClass -> KtPsiClassWrapper(classPsi)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.filter { it.isInterface() }
|
.filter { it.isInterfaceClass() }
|
||||||
.mapTo(result) { KotlinMemberInfo(it, true) }
|
.mapTo(result) { KotlinMemberInfo(it, true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.refactoring.memberInfo
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
|
|
||||||
|
interface KtPsiClassWrapper : KtNamedDeclaration {
|
||||||
|
val psiClass: PsiClass
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KtPsiClassWrapper(psiClass: PsiClass): KtPsiClassWrapper {
|
||||||
|
val dummyKtClass = KtPsiFactory(psiClass.project).createClass("class ${psiClass.name}")
|
||||||
|
return object : KtPsiClassWrapper, KtNamedDeclaration by dummyKtClass {
|
||||||
|
override fun equals(other: Any?) = psiClass == (other as? KtPsiClassWrapper)?.psiClass
|
||||||
|
|
||||||
|
override fun hashCode() = psiClass.hashCode()
|
||||||
|
|
||||||
|
override val psiClass: PsiClass
|
||||||
|
get() = psiClass
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,8 +18,12 @@ package org.jetbrains.kotlin.idea.refactoring.memberInfo
|
|||||||
|
|
||||||
import com.intellij.psi.PsiClass
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiMember
|
||||||
import com.intellij.psi.PsiNamedElement
|
import com.intellij.psi.PsiNamedElement
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
|
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getJavaClassDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.getJavaClassDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
@@ -59,4 +63,14 @@ fun KotlinMemberInfo.getChildrenToAnalyze(): List<PsiElement> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return childrenToCheck
|
return childrenToCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KtNamedDeclaration.resolveToDescriptorWrapperAware(resolutionFacade: ResolutionFacade? = null): DeclarationDescriptor {
|
||||||
|
if (this is KtPsiClassWrapper) return psiClass.getJavaClassDescriptor(resolutionFacade)!!
|
||||||
|
return (resolutionFacade ?: getResolutionFacade()).resolveToDescriptor(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun PsiMember.toKtDeclarationWrapperAware(): KtNamedDeclaration? {
|
||||||
|
if (this is PsiClass && this !is KtLightClass) return KtPsiClassWrapper(this)
|
||||||
|
return namedUnwrappedElement as? KtNamedDeclaration
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,9 @@ import com.intellij.psi.PsiNamedElement
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.getJavaClassDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KtPsiClassWrapper
|
||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.getClassDescriptorIfAny
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.getClassDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
@@ -45,11 +47,10 @@ class KotlinPullUpData(val sourceClass: KtClassOrObject,
|
|||||||
val sourceClassDescriptor = sourceClassContext[BindingContext.DECLARATION_TO_DESCRIPTOR, sourceClass] as ClassDescriptor
|
val sourceClassDescriptor = sourceClassContext[BindingContext.DECLARATION_TO_DESCRIPTOR, sourceClass] as ClassDescriptor
|
||||||
|
|
||||||
val memberDescriptors = membersToMove.keysToMap {
|
val memberDescriptors = membersToMove.keysToMap {
|
||||||
if (it is KtParameter) {
|
when (it) {
|
||||||
sourceClassContext[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it]!!
|
is KtPsiClassWrapper -> it.psiClass.getJavaClassDescriptor(resolutionFacade)!!
|
||||||
}
|
is KtParameter -> sourceClassContext[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it]!!
|
||||||
else {
|
else -> sourceClassContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it]!!
|
||||||
sourceClassContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it]!!
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,7 @@ import com.intellij.refactoring.util.DocCommentPolicy
|
|||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
import org.jetbrains.kotlin.idea.refactoring.isCompanionMemberOf
|
import org.jetbrains.kotlin.idea.refactoring.isCompanionMemberOf
|
||||||
import org.jetbrains.kotlin.idea.refactoring.isInterfaceClass
|
import org.jetbrains.kotlin.idea.refactoring.isInterfaceClass
|
||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfoStorage
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionTable
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.toJavaMemberInfo
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
class KotlinPullUpDialog(
|
class KotlinPullUpDialog(
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ import org.jetbrains.kotlin.idea.intentions.setType
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.createJavaField
|
import org.jetbrains.kotlin.idea.refactoring.createJavaField
|
||||||
import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary
|
import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary
|
||||||
import org.jetbrains.kotlin.idea.refactoring.isCompanionMemberOf
|
import org.jetbrains.kotlin.idea.refactoring.isCompanionMemberOf
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KtPsiClassWrapper
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.toKtDeclarationWrapperAware
|
||||||
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.anonymousObjectSuperTypeOrNull
|
||||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiUnifier
|
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiUnifier
|
||||||
@@ -325,7 +327,8 @@ class KotlinPullUpHelper(
|
|||||||
return clashingSuperDescriptor.source.getPsi() as? KtCallableDeclaration
|
return clashingSuperDescriptor.source.getPsi() as? KtCallableDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun moveSuperInterface(member: KtClass, substitutor: PsiSubstitutor) {
|
private fun moveSuperInterface(member: PsiNamedElement, substitutor: PsiSubstitutor) {
|
||||||
|
val realMemberPsi = if (member is KtPsiClassWrapper) member.psiClass else member
|
||||||
val classDescriptor = data.memberDescriptors[member] as? ClassDescriptor ?: return
|
val classDescriptor = data.memberDescriptors[member] as? ClassDescriptor ?: return
|
||||||
val currentSpecifier = data.sourceClass.getSuperTypeEntryByDescriptor(classDescriptor, data.sourceClassContext) ?: return
|
val currentSpecifier = data.sourceClass.getSuperTypeEntryByDescriptor(classDescriptor, data.sourceClassContext) ?: return
|
||||||
when (data.targetClass) {
|
when (data.targetClass) {
|
||||||
@@ -340,7 +343,7 @@ 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 == member }
|
?.firstOrNull { it.resolve()?.unwrapped == realMemberPsi }
|
||||||
?: return
|
?: return
|
||||||
val superTypeForTarget = substitutor.substitute(elementFactory.createType(superRef))
|
val superTypeForTarget = substitutor.substitute(elementFactory.createType(superRef))
|
||||||
|
|
||||||
@@ -426,9 +429,9 @@ class KotlinPullUpHelper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun move(info: MemberInfoBase<PsiMember>, substitutor: PsiSubstitutor) {
|
override fun move(info: MemberInfoBase<PsiMember>, substitutor: PsiSubstitutor) {
|
||||||
val member = info.member.namedUnwrappedElement as? KtNamedDeclaration ?: return
|
val member = info.member.toKtDeclarationWrapperAware() ?: return
|
||||||
|
|
||||||
if (member is KtClass && info.overrides != null) {
|
if ((member is KtClass || member is KtPsiClassWrapper) && info.overrides != null) {
|
||||||
moveSuperInterface(member, substitutor)
|
moveSuperInterface(member, substitutor)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ import com.intellij.refactoring.memberPullUp.JavaPullUpHelper
|
|||||||
import com.intellij.refactoring.memberPullUp.PullUpData
|
import com.intellij.refactoring.memberPullUp.PullUpData
|
||||||
import com.intellij.refactoring.memberPullUp.PullUpHelper
|
import com.intellij.refactoring.memberPullUp.PullUpHelper
|
||||||
import com.intellij.refactoring.memberPullUp.PullUpHelperFactory
|
import com.intellij.refactoring.memberPullUp.PullUpHelperFactory
|
||||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
import org.jetbrains.kotlin.asJava.unwrapped
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.idea.refactoring.createJavaClass
|
import org.jetbrains.kotlin.idea.refactoring.createJavaClass
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.toKtDeclarationWrapperAware
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ class KotlinPullUpHelperFactory : PullUpHelperFactory {
|
|||||||
val sourceClass = sourceClass.unwrapped as? KtClassOrObject ?: return null
|
val sourceClass = sourceClass.unwrapped as? KtClassOrObject ?: return null
|
||||||
val targetClass = targetClass.unwrapped as? PsiNamedElement ?: return null
|
val targetClass = targetClass.unwrapped as? PsiNamedElement ?: return null
|
||||||
val membersToMove = membersToMove
|
val membersToMove = membersToMove
|
||||||
.mapNotNull { it.namedUnwrappedElement as? KtNamedDeclaration }
|
.mapNotNull { it.toKtDeclarationWrapperAware() }
|
||||||
.sortedBy { it.startOffset }
|
.sortedBy { it.startOffset }
|
||||||
return KotlinPullUpData(sourceClass, targetClass, membersToMove)
|
return KotlinPullUpData(sourceClass, targetClass, membersToMove)
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ class KotlinPullUpHelperFactory : PullUpHelperFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class JavaToKotlinPullUpHelperFactory : PullUpHelperFactory {
|
class JavaToKotlinPullUpHelperFactory : PullUpHelperFactory {
|
||||||
private fun createJavaToKotlinPullUpHelper(data: PullUpData): JavaToKotlinPreconversionPullUpHelper? {
|
private fun createJavaToKotlinPullUpHelper(data: PullUpData): PullUpHelper<*>? {
|
||||||
if (!data.sourceClass.isInheritor(data.targetClass, true)) return null
|
if (!data.sourceClass.isInheritor(data.targetClass, true)) return null
|
||||||
val dummyTargetClass = createDummyTargetClass(data) ?: return null
|
val dummyTargetClass = createDummyTargetClass(data) ?: return null
|
||||||
val dataForDelegate = object : PullUpData by data {
|
val dataForDelegate = object : PullUpData by data {
|
||||||
@@ -96,6 +96,8 @@ class JavaToKotlinPullUpHelperFactory : PullUpHelperFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun createPullUpHelper(data: PullUpData): PullUpHelper<*> {
|
override fun createPullUpHelper(data: PullUpData): PullUpHelper<*> {
|
||||||
|
if (data.sourceClass is KtLightClass) return KotlinPullUpHelperFactory().createPullUpHelper(data)
|
||||||
|
|
||||||
createJavaToKotlinPullUpHelper(data)?.let { return it }
|
createJavaToKotlinPullUpHelper(data)?.let { return it }
|
||||||
|
|
||||||
return PullUpHelper.INSTANCE
|
return PullUpHelper.INSTANCE
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
|
import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
|
||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo
|
||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.getChildrenToAnalyze
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.getChildrenToAnalyze
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.resolveToDescriptorWrapperAware
|
||||||
import org.jetbrains.kotlin.idea.references.KtReference
|
import org.jetbrains.kotlin.idea.references.KtReference
|
||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
|
||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
|
||||||
@@ -57,7 +58,7 @@ fun checkConflicts(project: Project,
|
|||||||
with(pullUpData) {
|
with(pullUpData) {
|
||||||
for (memberInfo in memberInfos) {
|
for (memberInfo in memberInfos) {
|
||||||
val member = memberInfo.member
|
val member = memberInfo.member
|
||||||
val memberDescriptor = resolutionFacade.resolveToDescriptor(member)
|
val memberDescriptor = member.resolveToDescriptorWrapperAware(resolutionFacade)
|
||||||
|
|
||||||
checkClashWithSuperDeclaration(member, memberDescriptor, conflicts)
|
checkClashWithSuperDeclaration(member, memberDescriptor, conflicts)
|
||||||
checkAccidentalOverrides(member, memberDescriptor, conflicts)
|
checkAccidentalOverrides(member, memberDescriptor, conflicts)
|
||||||
@@ -131,7 +132,7 @@ private fun KotlinPullUpData.checkAccidentalOverrides(
|
|||||||
.filterNot { it.isSourceOrTarget(this) }
|
.filterNot { it.isSourceOrTarget(this) }
|
||||||
.mapNotNull { it.unwrapped as? KtClassOrObject }
|
.mapNotNull { it.unwrapped as? KtClassOrObject }
|
||||||
.forEach {
|
.forEach {
|
||||||
val subClassDescriptor = resolutionFacade.resolveToDescriptor(it) as ClassDescriptor
|
val subClassDescriptor = it.resolveToDescriptorWrapperAware(resolutionFacade) as ClassDescriptor
|
||||||
val substitutor = getTypeSubstitutor(targetClassDescriptor.defaultType,
|
val substitutor = getTypeSubstitutor(targetClassDescriptor.defaultType,
|
||||||
subClassDescriptor.defaultType) ?: TypeSubstitutor.EMPTY
|
subClassDescriptor.defaultType) ?: TypeSubstitutor.EMPTY
|
||||||
val memberDescriptorInSubClass =
|
val memberDescriptorInSubClass =
|
||||||
@@ -142,7 +143,7 @@ private fun KotlinPullUpData.checkAccidentalOverrides(
|
|||||||
|
|
||||||
val message = memberDescriptor.renderForConflicts() +
|
val message = memberDescriptor.renderForConflicts() +
|
||||||
" in super class would clash with existing member of " +
|
" in super class would clash with existing member of " +
|
||||||
resolutionFacade.resolveToDescriptor(it).renderForConflicts()
|
it.resolveToDescriptorWrapperAware(resolutionFacade).renderForConflicts()
|
||||||
conflicts.putValue(clashingMember, message.capitalize())
|
conflicts.putValue(clashingMember, message.capitalize())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,12 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.getJavaClassDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||||
import org.jetbrains.kotlin.idea.refactoring.runSynchronouslyWithProgress
|
import org.jetbrains.kotlin.idea.refactoring.runSynchronouslyWithProgress
|
||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KtPsiClassWrapper
|
||||||
import org.jetbrains.kotlin.idea.refactoring.pullUp.*
|
import org.jetbrains.kotlin.idea.refactoring.pullUp.*
|
||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
|
||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
|
||||||
@@ -62,7 +64,12 @@ class KotlinPushDownContext(
|
|||||||
|
|
||||||
val memberDescriptors = membersToMove
|
val memberDescriptors = membersToMove
|
||||||
.map { it.member }
|
.map { it.member }
|
||||||
.keysToMap { sourceClassContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it]!! }
|
.keysToMap {
|
||||||
|
when (it) {
|
||||||
|
is KtPsiClassWrapper -> it.psiClass.getJavaClassDescriptor(resolutionFacade)!!
|
||||||
|
else -> sourceClassContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it]!!
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KotlinPushDownProcessor(
|
class KotlinPushDownProcessor(
|
||||||
@@ -161,7 +168,7 @@ class KotlinPushDownProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtClassOrObject -> {
|
is KtClassOrObject, is KtPsiClassWrapper -> {
|
||||||
if (memberInfo.overrides != null) {
|
if (memberInfo.overrides != null) {
|
||||||
context.sourceClass.getSuperTypeEntryByDescriptor(
|
context.sourceClass.getSuperTypeEntryByDescriptor(
|
||||||
memberDescriptor as ClassDescriptor,
|
memberDescriptor as ClassDescriptor,
|
||||||
@@ -202,7 +209,7 @@ class KotlinPushDownProcessor(
|
|||||||
member.delete()
|
member.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is KtClassOrObject -> {
|
is KtClassOrObject, is KtPsiClassWrapper -> {
|
||||||
if (memberInfo.overrides != null) {
|
if (memberInfo.overrides != null) {
|
||||||
context.sourceClass.getSuperTypeEntryByDescriptor(
|
context.sourceClass.getSuperTypeEntryByDescriptor(
|
||||||
memberDescriptor as ClassDescriptor,
|
memberDescriptor as ClassDescriptor,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.intellij.usageView.UsageInfo
|
|||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import org.jetbrains.kotlin.asJava.unwrapped
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KtPsiClassWrapper
|
||||||
import org.jetbrains.kotlin.idea.refactoring.pullUp.renderForConflicts
|
import org.jetbrains.kotlin.idea.refactoring.pullUp.renderForConflicts
|
||||||
import org.jetbrains.kotlin.idea.references.KtReference
|
import org.jetbrains.kotlin.idea.references.KtReference
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
@@ -50,7 +51,7 @@ fun analyzePushDownConflicts(context: KotlinPushDownContext,
|
|||||||
val membersToKeepAbstract = ArrayList<KtNamedDeclaration>()
|
val membersToKeepAbstract = ArrayList<KtNamedDeclaration>()
|
||||||
for (info in context.membersToMove) {
|
for (info in context.membersToMove) {
|
||||||
val member = info.member
|
val member = info.member
|
||||||
if (!info.isChecked || (member is KtClassOrObject && info.overrides != null)) continue
|
if (!info.isChecked || ((member is KtClassOrObject || member is KtPsiClassWrapper) && info.overrides != null)) continue
|
||||||
|
|
||||||
membersToPush += member
|
membersToPush += member
|
||||||
if ((member is KtNamedFunction || member is KtProperty)
|
if ((member is KtNamedFunction || member is KtProperty)
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
class A implements Z {
|
class A implements Z {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// INFO: {"checked": "true"}
|
||||||
|
interface J {
|
||||||
|
|
||||||
}
|
}
|
||||||
+6
-1
@@ -1,3 +1,8 @@
|
|||||||
class A implements Z, X {
|
class A implements Z, X, J {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// INFO: {"checked": "true"}
|
||||||
|
interface J {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,4 +7,4 @@ interface Y
|
|||||||
// INFO: {"checked": "true"}
|
// INFO: {"checked": "true"}
|
||||||
interface Z
|
interface Z
|
||||||
|
|
||||||
class <caret>B: A(), X, Y, Z
|
class <caret>B: A(), X, Y, Z, J
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
interface I extends Z {
|
interface I extends Z {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// INFO: {"checked": "true"}
|
||||||
|
interface J {
|
||||||
|
|
||||||
}
|
}
|
||||||
+6
-1
@@ -1,3 +1,8 @@
|
|||||||
interface I extends Z, X {
|
interface I extends Z, X, J {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// INFO: {"checked": "true"}
|
||||||
|
interface J {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,4 +7,4 @@ interface Y
|
|||||||
// INFO: {"checked": "true"}
|
// INFO: {"checked": "true"}
|
||||||
interface Z
|
interface Z
|
||||||
|
|
||||||
class <caret>B: I, X, Y, Z
|
class <caret>B: I, X, Y, Z, J
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// INFO: {"checked": "true"}
|
||||||
|
interface J {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// INFO: {"checked": "true"}
|
||||||
|
interface J {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -11,4 +11,4 @@ interface Y
|
|||||||
// INFO: {"checked": "true"}
|
// INFO: {"checked": "true"}
|
||||||
interface Z
|
interface Z
|
||||||
|
|
||||||
class <caret>B: A(), X, Y, Z
|
class <caret>B: A(), X, Y, Z, J
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
open class A: Z, X, Y {
|
open class A: Z, X, Y, J {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import com.intellij.refactoring.BaseRefactoringProcessor
|
|||||||
import com.intellij.refactoring.classMembers.MemberInfoBase
|
import com.intellij.refactoring.classMembers.MemberInfoBase
|
||||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KtPsiClassWrapper
|
||||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
@@ -64,6 +65,7 @@ abstract class AbstractMemberPullPushTest : KotlinLightCodeInsightFixtureTestCas
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
markMembersInfo(file)
|
markMembersInfo(file)
|
||||||
|
extraFilesToPsi.keys.forEach(::markMembersInfo)
|
||||||
|
|
||||||
action(file)
|
action(file)
|
||||||
|
|
||||||
@@ -105,7 +107,8 @@ internal var PsiElement.elementInfo: ElementInfo by NotNullableUserDataProperty(
|
|||||||
|
|
||||||
internal fun <T : MemberInfoBase<*>> chooseMembers(members: List<T>): List<T> {
|
internal fun <T : MemberInfoBase<*>> chooseMembers(members: List<T>): List<T> {
|
||||||
members.forEach {
|
members.forEach {
|
||||||
val info = it.member.elementInfo
|
val memberPsi = it.member.let { if (it is KtPsiClassWrapper) it.psiClass else it }
|
||||||
|
val info = memberPsi.elementInfo
|
||||||
it.isChecked = info.checked
|
it.isChecked = info.checked
|
||||||
it.isToAbstract = info.toAbstract
|
it.isToAbstract = info.toAbstract
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user