KT-2836 Rename kotlin base function with overrides

#KT-2836 Fixed
This commit is contained in:
Nikolay Krasko
2013-09-18 19:55:00 +04:00
committed by Nikolay Krasko
parent 5350dc265a
commit 97c8e05984
10 changed files with 190 additions and 25 deletions
@@ -0,0 +1,17 @@
<root>
<item
name='com.intellij.refactoring.rename.RenamePsiElementProcessor void prepareRenaming(com.intellij.psi.PsiElement, java.lang.String, java.util.Map&lt;com.intellij.psi.PsiElement,java.lang.String&gt;, com.intellij.psi.search.SearchScope)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun prepareRenaming(element: PsiElement?, newName: String?, allRenames: MutableMap&lt;PsiElement, String&gt;, scope: SearchScope): Unit&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.rename.RenamePsiElementProcessor void prepareRenaming(com.intellij.psi.PsiElement, java.lang.String, java.util.Map&lt;com.intellij.psi.PsiElement,java.lang.String&gt;, com.intellij.psi.search.SearchScope) 2'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.refactoring.rename.RenamePsiElementProcessor void prepareRenaming(com.intellij.psi.PsiElement, java.lang.String, java.util.Map&lt;com.intellij.psi.PsiElement,java.lang.String&gt;, com.intellij.psi.search.SearchScope) 3'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
+3 -1
View File
@@ -216,7 +216,9 @@
<renamePsiElementProcessor id="KotlinClass"
implementation="org.jetbrains.jet.plugin.refactoring.rename.RenameJetClassProcessor"
order="first"/>
<renamePsiElementProcessor implementation="org.jetbrains.jet.plugin.refactoring.rename.RenameKotlinFunctionProcessor"/>
<renamePsiElementProcessor implementation="org.jetbrains.jet.plugin.refactoring.rename.RenameKotlinFunctionProcessor"
id="KotlinFunction"
order="first"/>
<liveTemplateContext implementation="org.jetbrains.jet.plugin.liveTemplates.JetTemplateContextType$Generic"/>
<liveTemplateContext implementation="org.jetbrains.jet.plugin.liveTemplates.JetTemplateContextType$Namespace"/>
@@ -16,34 +16,60 @@
package org.jetbrains.jet.plugin.refactoring.rename;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiCompiledElement;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.SearchScope;
import com.intellij.refactoring.rename.RenamePsiElementProcessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.asJava.KotlinLightClass;
import org.jetbrains.jet.lang.psi.JetFunction;
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiCompiledElement
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.refactoring.rename.RenamePsiElementProcessor
import com.intellij.psi.search.SearchScope
import com.intellij.psi.search.searches.OverridingMethodsSearch
import com.intellij.openapi.application.ApplicationManager
import org.jetbrains.jet.asJava.LightClassUtil
import org.jetbrains.jet.lang.psi.JetNamedFunction
import com.intellij.openapi.util.Computable
import com.intellij.psi.PsiMirrorElement
import com.intellij.psi.SyntheticElement
import com.intellij.refactoring.util.RefactoringUtil
import com.intellij.refactoring.rename.RenameProcessor
import com.intellij.refactoring.rename.RenameJavaMethodProcessor
import com.intellij.psi.PsiNamedElement
import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod
import kotlin.properties.Delegates
import java.util.Map;
public class RenameKotlinFunctionProcessor : RenamePsiElementProcessor() {
private val javaMethodProcessorInstance by Delegates.lazy {
// KT-4250
// RenamePsiElementProcessor.EP_NAME.findExtension(javaClass<RenameJavaMethodProcessor>())!!
public class RenameKotlinFunctionProcessor extends RenamePsiElementProcessor {
@Override
public boolean canProcessElement(@NotNull PsiElement element) {
if (element instanceof PsiMethod && ((PsiMethod) element).getContainingClass() instanceof KotlinLightClass) {
return true;
}
return element instanceof JetFunction;
RenameJavaMethodProcessor()
}
@Override
public PsiElement substituteElementToRename(PsiElement element, @Nullable Editor editor) {
if (element instanceof PsiMethod && element instanceof PsiCompiledElement &&
((PsiMethod) element).getContainingClass() instanceof KotlinLightClass) {
return ((PsiCompiledElement) element).getMirror();
override fun canProcessElement(element: PsiElement): Boolean {
return element is JetNamedFunction || element is KotlinLightMethod
}
override fun substituteElementToRename(element: PsiElement?, editor: Editor?): PsiElement? {
val wrappedMethod = wrapPsiMethod(element)
if (wrappedMethod == null) {
// Cancel rename
return null
}
return super.substituteElementToRename(element, editor);
// Use java dialog to ask we should rename function with the base element
return unwrapPsiMethod(javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor))
}
override fun prepareRenaming(element: PsiElement?, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
javaMethodProcessorInstance.prepareRenaming(wrapPsiMethod(element), newName, allRenames, scope)
}
private fun wrapPsiMethod(element: PsiElement?): PsiMethod? = when (element) {
is KotlinLightMethod -> element
is JetNamedFunction -> ApplicationManager.getApplication()!!.runReadAction(Computable { LightClassUtil.getLightClassMethod(element) })
else -> throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
}
private fun unwrapPsiMethod(element: PsiElement?): JetNamedFunction? {
return (element as? KotlinLightMethod)?.getOrigin() as? JetNamedFunction
}
}
@@ -0,0 +1,27 @@
package testing.rename
trait A {
fun second() : Int
}
public open class B: A {
override fun second() = 1
fun first(a: Int) = 12
}
class C: B() {
override fun second() = 2
}
fun usages() {
val b = B()
val a: A = b
val c = C()
a.second()
b.second()
c.second()
}
@@ -0,0 +1,26 @@
package testing;
import testing.rename.*;
class JavaClient {
public void foo(A a) {
a.second();
new B().second();
new C().second();
new D().second();
}
public static class D implements A {
@Override
public int second() {
return 3;
}
}
public static class E extends D {
@Override
public int second() {
return 4;
}
}
}
@@ -0,0 +1,27 @@
package testing.rename
trait A {
fun first() : Int
}
public open class B: A {
override fun first() = 1
fun first(a: Int) = 12
}
class C: B() {
override fun first() = 2
}
fun usages() {
val b = B()
val a: A = b
val c = C()
a.first()
b.first()
c.first()
}
@@ -0,0 +1,26 @@
package testing;
import testing.rename.*;
class JavaClient {
public void foo(A a) {
a.first();
new B().first();
new C().first();
new D().first();
}
public static class D implements A {
@Override
public int first() {
return 3;
}
}
public static class E extends D {
@Override
public int first() {
return 4;
}
}
}
@@ -0,0 +1 @@
// RENAME: JAVA_METHOD->testing.rename.A->void first()->second
@@ -0,0 +1,3 @@
// RENAME: KOTLIN_FUNCTION->testing.rename.A.first->second
// KT-2836 Rename method with all its implementations
@@ -41,6 +41,16 @@ public class RenameTestGenerated extends AbstractRenameTest {
doTest("idea/testData/refactoring/rename/renameJavaClass/renameJavaClass.test");
}
@TestMetadata("renameKotlinBaseMethod/javaWrapperForBaseFunction.test")
public void testRenameKotlinBaseMethod_JavaWrapperForBaseFunction() throws Exception {
doTest("idea/testData/refactoring/rename/renameKotlinBaseMethod/javaWrapperForBaseFunction.test");
}
@TestMetadata("renameKotlinBaseMethod/kotlinBaseFunction.test")
public void testRenameKotlinBaseMethod_KotlinBaseFunction() throws Exception {
doTest("idea/testData/refactoring/rename/renameKotlinBaseMethod/kotlinBaseFunction.test");
}
@TestMetadata("renameKotlinClass/javaWrapperForKotlinClass.test")
public void testRenameKotlinClass_JavaWrapperForKotlinClass() throws Exception {
doTest("idea/testData/refactoring/rename/renameKotlinClass/javaWrapperForKotlinClass.test");