Move: Move refactoring should correct constructor call when moving inner class

#KT-4676 Fixed
This commit is contained in:
Alexey Sedunov
2014-09-09 13:51:23 +04:00
parent feb393e4c8
commit 9b7bccce22
15 changed files with 162 additions and 0 deletions
+3
View File
@@ -207,6 +207,9 @@
implementation="org.jetbrains.jet.plugin.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsHandler"
order="before kotlin.moveFilesOrDirectories"/>
<moveFileHandler implementation="org.jetbrains.jet.plugin.refactoring.move.moveFilesOrDirectories.MoveKotlinFileHandler" />
<refactoring.moveInnerClassUsagesHandler
implementationClass="org.jetbrains.jet.plugin.refactoring.move.MoveJavaInnerClassKotlinUsagesHandler"
language="jet" />
<refactoring.copyHandler implementation="org.jetbrains.jet.plugin.refactoring.copy.JetCopyClassHandler"/>
<refactoring.changeSignatureUsageProcessor implementation="org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeSignatureUsageProcessor"/>
<inlineActionHandler implementation="org.jetbrains.jet.plugin.refactoring.inline.KotlinInlineValHandler"/>
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2014 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.jet.plugin.refactoring.move
import com.intellij.refactoring.move.moveInner.MoveInnerClassUsagesHandler
import com.intellij.usageView.UsageInfo
import com.intellij.psi.PsiClass
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector
import org.jetbrains.jet.lang.psi.JetReferenceExpression
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.lang.psi.JetPsiFactory
import java.util.Collections
import java.util.ArrayList
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.PsiWhiteSpace
public class MoveJavaInnerClassKotlinUsagesHandler: MoveInnerClassUsagesHandler {
override fun correctInnerClassUsage(usage: UsageInfo, outerClass: PsiClass) {
val innerCall = usage.getElement()?.getParent() as? JetCallExpression
if (innerCall == null) return
val receiver = (innerCall.getParent() as? JetQualifiedExpression)?.getReceiverExpression()
val outerClassRef = when (receiver) {
is JetCallExpression -> receiver.getCalleeExpression()
is JetQualifiedExpression -> receiver.getQualifiedElementSelector()
else -> null
} as? JetSimpleNameExpression
if (outerClassRef?.getReference()?.resolve() != outerClass) return
val outerCall = outerClassRef!!.getParent() as? JetCallExpression
if (outerCall == null) return
val psiFactory = JetPsiFactory(usage.getProject())
val argumentList = innerCall.getValueArgumentList()
if (argumentList != null) {
val newArguments = ArrayList<String>()
newArguments.add(outerCall.getText()!!)
argumentList.getArguments().mapTo(newArguments) { it.getText()!! }
argumentList.replace(psiFactory.createCallArguments(newArguments.joinToString(prefix = "(", postfix = ")")))
}
else {
innerCall.getFunctionLiteralArguments().firstOrNull()?.let { lambdaArg ->
val anchor = PsiTreeUtil.skipSiblingsBackward(lambdaArg, javaClass<PsiWhiteSpace>())
innerCall.addAfter(psiFactory.createCallArguments("(${outerCall.getText()})"), anchor)
}
}
}
}
@@ -0,0 +1,12 @@
package a;
import kotlin.Function0;
public class X {
private A outer;
public X(A outer, Function0<String> f) {
this.outer = outer;
System.out.println(f.invoke());
}
}
@@ -0,0 +1,7 @@
package a
import a.A.*
fun bar(s: String) {
val t: X = X(A()) { s }
}
@@ -0,0 +1,7 @@
package a
import a.X
fun bar(s: String) {
val t: X = X(A()) { s }
}
@@ -0,0 +1,11 @@
package a;
import kotlin.Function0;
public class A {
public class <caret>X {
public X(Function0<String> f) {
System.out.println(f.invoke());
}
}
}
@@ -0,0 +1,7 @@
package a
import a.A.*
fun bar(s: String) {
val t: X = A().X { s }
}
@@ -0,0 +1,7 @@
package a
import a.A.X
fun bar(s: String) {
val t: X = A().X { s }
}
@@ -0,0 +1,7 @@
{
"mainFile": "a/main.java",
"type": "MOVE_INNER_CLASS",
"targetPackage": "a",
"outerInstanceParameterName": "outer",
"withRuntime": "true"
}
@@ -59,6 +59,8 @@ import org.jetbrains.jet.plugin.refactoring.move.moveTopLevelDeclarations.JetFil
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.plugin.search.allScope
import org.jetbrains.jet.plugin.refactoring.runWriteAction
import org.jetbrains.jet.InTextDirectivesUtils
import org.jetbrains.jet.testing.ConfigLibraryUtil
public abstract class AbstractJetMoveTest : MultiFileTestCase() {
protected fun doTest(path: String) {
@@ -78,6 +80,10 @@ public abstract class AbstractJetMoveTest : MultiFileTestCase() {
val config = JsonParser().parse(FileUtil.loadFile(File(path), true)) as JsonObject
if (config["withRuntime"]?.getAsBoolean() ?: false) {
ConfigLibraryUtil.configureKotlinRuntime(myModule, PluginTestCaseBase.fullJdk())
}
val action = MoveAction.valueOf(config.getString("type"))
val testDir = path.substring(0, path.lastIndexOf("/"))
@@ -86,6 +86,18 @@ public class JetMoveTestGenerated extends AbstractJetMoveTest {
doTest(fileName);
}
@TestMetadata("java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance.test")
public void testJava_moveClass_moveInnerToTop_moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance_MoveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance.test");
doTest(fileName);
}
@TestMetadata("java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda.test")
public void testJava_moveClass_moveInnerToTop_moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda_MoveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda.test");
doTest(fileName);
}
@TestMetadata("java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndRename/moveNestedClassToTopLevelInTheSamePackageAndRename.test")
public void testJava_moveClass_moveInnerToTop_moveNestedClassToTopLevelInTheSamePackageAndRename_MoveNestedClassToTopLevelInTheSamePackageAndRename() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndRename/moveNestedClassToTopLevelInTheSamePackageAndRename.test");