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) forEachKotlinOverride(ktClass, members, scope, processor)
} }
fun findDeepestSuperMethodsKotlinAware(method: PsiElement): List<PsiMethod> { fun findDeepestSuperMethodsNoWrapping(method: PsiElement): List<PsiElement> {
val element = method.unwrapped val element = method.unwrapped
return when (element) { return when (element) {
is PsiMethod -> element.findDeepestSuperMethods().toList() is PsiMethod -> element.findDeepestSuperMethods().toList()
is KtCallableDeclaration -> { is KtCallableDeclaration -> {
val descriptor = element.resolveToDescriptorIfAny() as? CallableMemberDescriptor ?: return emptyList() 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() else -> emptyList()
} }
} }
fun findDeepestSuperMethodsKotlinAware(method: PsiElement) =
findDeepestSuperMethodsNoWrapping(method).mapNotNull { it.getRepresentativeLightMethod() }
@@ -914,7 +914,7 @@ fun checkSuperMethods(
fun checkSuperMethodsWithPopup( fun checkSuperMethodsWithPopup(
declaration: KtNamedDeclaration, declaration: KtNamedDeclaration,
deepestSuperMethods: List<PsiMethod>, deepestSuperMethods: List<PsiElement>,
actionString: String, actionString: String,
editor: Editor, editor: Editor,
action: (List<PsiElement>) -> Unit action: (List<PsiElement>) -> Unit
@@ -923,7 +923,12 @@ fun checkSuperMethodsWithPopup(
val superMethod = deepestSuperMethods.first() 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) if (ApplicationManager.getApplication().isUnitTestMode) return action(deepestSuperMethods)
@@ -946,7 +951,7 @@ fun checkSuperMethodsWithPopup(
val renameCurrent = actionString + " only current $kind" val renameCurrent = actionString + " only current $kind"
val title = buildString { val title = buildString {
append(declaration.name) 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(ElementDescriptionUtil.getElementDescription(superMethod, UsageViewTypeLocation.INSTANCE))
append(" of ") append(" of ")
append(SymbolPresentationUtil.getSymbolPresentableText(superClass)) 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.refactoring.dropOverrideKeywordIfNecessary
import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsKotlinAware 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.search.declarationsSearch.forEachOverridingMethod
import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -147,18 +148,21 @@ class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() {
substituteForExpectOrActual(element)?.let { return preprocessAndPass(it) } substituteForExpectOrActual(element)?.let { return preprocessAndPass(it) }
val wrappedMethod = wrapPsiMethod(element) ?: return val wrappedMethod = wrapPsiMethod(element)
val deepestSuperMethods = if (wrappedMethod != null) {
val deepestSuperMethods = findDeepestSuperMethodsKotlinAware(wrappedMethod) findDeepestSuperMethodsKotlinAware(wrappedMethod)
} else {
findDeepestSuperMethodsNoWrapping(element)
}
when { when {
deepestSuperMethods.isEmpty() -> preprocessAndPass(element) deepestSuperMethods.isEmpty() -> preprocessAndPass(element)
wrappedMethod.isConstructor || element !is KtNamedFunction -> { wrappedMethod != null && (wrappedMethod.isConstructor || element !is KtNamedFunction) -> {
javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor, Pass(::preprocessAndPass)) javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor, Pass(::preprocessAndPass))
} }
else -> { else -> {
val declaration = element.unwrapped as? KtNamedDeclaration ?: return val declaration = element.unwrapped as? KtNamedFunction ?: return
checkSuperMethodsWithPopup(declaration, deepestSuperMethods.toList(), "Rename", editor) { 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); 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") @TestMetadata("privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test")
public void testPrivateTopLevelDeclarationsNoConflict_PrivateTopLevelDeclarationsNoConflict() throws Exception { public void testPrivateTopLevelDeclarationsNoConflict_PrivateTopLevelDeclarationsNoConflict() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/privateTopLevelDeclarationsNoConflict/privateTopLevelDeclarationsNoConflict.test");