Rename: Fix processing of functions without light methods

#KT-22461 Fixed
This commit is contained in:
Alexey Sedunov
2018-01-24 13:25:22 +03:00
parent 245d1de2a2
commit 80643c5603
7 changed files with 53 additions and 12 deletions
@@ -198,14 +198,17 @@ fun PsiClass.forEachDeclaredMemberOverride(processor: (superMember: PsiElement,
forEachKotlinOverride(ktClass, members, scope, processor)
}
fun findDeepestSuperMethodsKotlinAware(method: PsiElement): List<PsiMethod> {
fun findDeepestSuperMethodsNoWrapping(method: PsiElement): List<PsiElement> {
val element = method.unwrapped
return when (element) {
is PsiMethod -> element.findDeepestSuperMethods().toList()
is KtCallableDeclaration -> {
val descriptor = element.resolveToDescriptorIfAny() as? CallableMemberDescriptor ?: return emptyList()
descriptor.getDeepestSuperDeclarations(false).mapNotNull { it.source.getPsi()?.getRepresentativeLightMethod() }
descriptor.getDeepestSuperDeclarations(false).mapNotNull { it.source.getPsi() }
}
else -> emptyList()
}
}
}
fun findDeepestSuperMethodsKotlinAware(method: PsiElement) =
findDeepestSuperMethodsNoWrapping(method).mapNotNull { it.getRepresentativeLightMethod() }
@@ -914,7 +914,7 @@ fun checkSuperMethods(
fun checkSuperMethodsWithPopup(
declaration: KtNamedDeclaration,
deepestSuperMethods: List<PsiMethod>,
deepestSuperMethods: List<PsiElement>,
actionString: String,
editor: Editor,
action: (List<PsiElement>) -> Unit
@@ -923,7 +923,12 @@ fun checkSuperMethodsWithPopup(
val superMethod = deepestSuperMethods.first()
val superClass = superMethod.containingClass ?: return action(listOf(declaration))
val (superClass, isAbstract) = when (superMethod) {
is PsiMember -> superMethod.containingClass to superMethod.hasModifierProperty(PsiModifier.ABSTRACT)
is KtNamedDeclaration -> superMethod.containingClassOrObject to superMethod.isAbstract()
else -> null
} ?: return action(listOf(declaration))
if (superClass == null) return action(listOf(declaration))
if (ApplicationManager.getApplication().isUnitTestMode) return action(deepestSuperMethods)
@@ -946,7 +951,7 @@ fun checkSuperMethodsWithPopup(
val renameCurrent = actionString + " only current $kind"
val title = buildString {
append(declaration.name)
append(if (superMethod.hasModifierProperty(PsiModifier.ABSTRACT)) " implements " else " overrides ")
append(if (isAbstract) " implements " else " overrides ")
append(ElementDescriptionUtil.getElementDescription(superMethod, UsageViewTypeLocation.INSTANCE))
append(" of ")
append(SymbolPresentationUtil.getSymbolPresentableText(superClass))
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.idea.refactoring.checkSuperMethodsWithPopup
import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsKotlinAware
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsNoWrapping
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.*
@@ -147,18 +148,21 @@ class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() {
substituteForExpectOrActual(element)?.let { return preprocessAndPass(it) }
val wrappedMethod = wrapPsiMethod(element) ?: return
val deepestSuperMethods = findDeepestSuperMethodsKotlinAware(wrappedMethod)
val wrappedMethod = wrapPsiMethod(element)
val deepestSuperMethods = if (wrappedMethod != null) {
findDeepestSuperMethodsKotlinAware(wrappedMethod)
} else {
findDeepestSuperMethodsNoWrapping(element)
}
when {
deepestSuperMethods.isEmpty() -> preprocessAndPass(element)
wrappedMethod.isConstructor || element !is KtNamedFunction -> {
wrappedMethod != null && (wrappedMethod.isConstructor || element !is KtNamedFunction) -> {
javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor, Pass(::preprocessAndPass))
}
else -> {
val declaration = element.unwrapped as? KtNamedDeclaration ?: return
val declaration = element.unwrapped as? KtNamedFunction ?: return
checkSuperMethodsWithPopup(declaration, deepestSuperMethods.toList(), "Rename", editor) {
preprocessAndPass(if (it.size > 1) FunctionWithSupersWrapper(element, it) else wrappedMethod)
preprocessAndPass(if (it.size > 1) FunctionWithSupersWrapper(declaration, it) else wrappedMethod ?: element)
}
}
}
@@ -0,0 +1,9 @@
@file:JvmMultifileClass()
@file:JvmName("Bazz")
package test
private fun bar() { }
fun test() {
bar()
}
@@ -0,0 +1,9 @@
@file:JvmMultifileClass()
@file:JvmName("Bazz")
package test
private fun /*rename*/foo() { }
fun test() {
foo()
}
@@ -0,0 +1,5 @@
{
"type": "MARKED_ELEMENT",
"mainFile": "test.kt",
"newName": "bar"
}
@@ -469,6 +469,12 @@ public class RenameTestGenerated extends AbstractRenameTest {
doTest(fileName);
}
@TestMetadata("privateFunInMultifileFacade/privateFunInMultifileFacade.test")
public void testPrivateFunInMultifileFacade_privateFunInMultifileFacade() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/privateFunInMultifileFacade/privateFunInMultifileFacade.test");
doTest(fileName);
}
@TestMetadata("privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test")
public void testPrivateTopLevelDeclarationsNoConflict_PrivateTopLevelDeclarationsNoConflict() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test");