Skip to content

Commit 9b7bccc

Browse files
committed
Move: Move refactoring should correct constructor call when moving inner class
#KT-4676 Fixed
1 parent feb393e commit 9b7bccc

File tree

15 files changed

+162
-0
lines changed

15 files changed

+162
-0
lines changed

idea/src/META-INF/plugin.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@
207207
implementation="org.jetbrains.jet.plugin.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsHandler"
208208
order="before kotlin.moveFilesOrDirectories"/>
209209
<moveFileHandler implementation="org.jetbrains.jet.plugin.refactoring.move.moveFilesOrDirectories.MoveKotlinFileHandler" />
210+
<refactoring.moveInnerClassUsagesHandler
211+
implementationClass="org.jetbrains.jet.plugin.refactoring.move.MoveJavaInnerClassKotlinUsagesHandler"
212+
language="jet" />
210213
<refactoring.copyHandler implementation="org.jetbrains.jet.plugin.refactoring.copy.JetCopyClassHandler"/>
211214
<refactoring.changeSignatureUsageProcessor implementation="org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeSignatureUsageProcessor"/>
212215
<inlineActionHandler implementation="org.jetbrains.jet.plugin.refactoring.inline.KotlinInlineValHandler"/>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2010-2014 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.jetbrains.jet.plugin.refactoring.move
18+
19+
import com.intellij.refactoring.move.moveInner.MoveInnerClassUsagesHandler
20+
import com.intellij.usageView.UsageInfo
21+
import com.intellij.psi.PsiClass
22+
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
23+
import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector
24+
import org.jetbrains.jet.lang.psi.JetReferenceExpression
25+
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
26+
import org.jetbrains.jet.lang.resolve.BindingContext
27+
import org.jetbrains.jet.lang.psi.JetCallExpression
28+
import org.jetbrains.jet.lang.psi.JetPsiFactory
29+
import java.util.Collections
30+
import java.util.ArrayList
31+
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
32+
import com.intellij.psi.util.PsiTreeUtil
33+
import com.intellij.psi.PsiWhiteSpace
34+
35+
public class MoveJavaInnerClassKotlinUsagesHandler: MoveInnerClassUsagesHandler {
36+
override fun correctInnerClassUsage(usage: UsageInfo, outerClass: PsiClass) {
37+
val innerCall = usage.getElement()?.getParent() as? JetCallExpression
38+
if (innerCall == null) return
39+
40+
val receiver = (innerCall.getParent() as? JetQualifiedExpression)?.getReceiverExpression()
41+
val outerClassRef = when (receiver) {
42+
is JetCallExpression -> receiver.getCalleeExpression()
43+
is JetQualifiedExpression -> receiver.getQualifiedElementSelector()
44+
else -> null
45+
} as? JetSimpleNameExpression
46+
if (outerClassRef?.getReference()?.resolve() != outerClass) return
47+
48+
val outerCall = outerClassRef!!.getParent() as? JetCallExpression
49+
if (outerCall == null) return
50+
51+
val psiFactory = JetPsiFactory(usage.getProject())
52+
53+
val argumentList = innerCall.getValueArgumentList()
54+
if (argumentList != null) {
55+
val newArguments = ArrayList<String>()
56+
newArguments.add(outerCall.getText()!!)
57+
argumentList.getArguments().mapTo(newArguments) { it.getText()!! }
58+
argumentList.replace(psiFactory.createCallArguments(newArguments.joinToString(prefix = "(", postfix = ")")))
59+
}
60+
else {
61+
innerCall.getFunctionLiteralArguments().firstOrNull()?.let { lambdaArg ->
62+
val anchor = PsiTreeUtil.skipSiblingsBackward(lambdaArg, javaClass<PsiWhiteSpace>())
63+
innerCall.addAfter(psiFactory.createCallArguments("(${outerCall.getText()})"), anchor)
64+
}
65+
}
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package a;
2+
3+
import kotlin.Function0;
4+
5+
public class X {
6+
private A outer;
7+
8+
public X(A outer, Function0<String> f) {
9+
this.outer = outer;
10+
System.out.println(f.invoke());
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package a;
2+
3+
import kotlin.Function0;
4+
5+
public class A {
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package a
2+
3+
fun bar(s: String) {
4+
val t: X = X(A()) { s }
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package a
2+
3+
import a.A.*
4+
5+
fun bar(s: String) {
6+
val t: X = X(A()) { s }
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package a
2+
3+
import a.X
4+
5+
fun bar(s: String) {
6+
val t: X = X(A()) { s }
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package a;
2+
3+
import kotlin.Function0;
4+
5+
public class A {
6+
public class <caret>X {
7+
public X(Function0<String> f) {
8+
System.out.println(f.invoke());
9+
}
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package a
2+
3+
fun bar(s: String) {
4+
val t: A.X = A().X { s }
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package a
2+
3+
import a.A.*
4+
5+
fun bar(s: String) {
6+
val t: X = A().X { s }
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package a
2+
3+
import a.A.X
4+
5+
fun bar(s: String) {
6+
val t: X = A().X { s }
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"mainFile": "a/main.java",
3+
"type": "MOVE_INNER_CLASS",
4+
"targetPackage": "a",
5+
"outerInstanceParameterName": "outer",
6+
"withRuntime": "true"
7+
}

idea/tests/org/jetbrains/jet/plugin/refactoring/move/AbstractJetMoveTest.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ import org.jetbrains.jet.plugin.refactoring.move.moveTopLevelDeclarations.JetFil
5959
import org.jetbrains.jet.lang.psi.JetFile
6060
import org.jetbrains.jet.plugin.search.allScope
6161
import org.jetbrains.jet.plugin.refactoring.runWriteAction
62+
import org.jetbrains.jet.InTextDirectivesUtils
63+
import org.jetbrains.jet.testing.ConfigLibraryUtil
6264

6365
public abstract class AbstractJetMoveTest : MultiFileTestCase() {
6466
protected fun doTest(path: String) {
@@ -78,6 +80,10 @@ public abstract class AbstractJetMoveTest : MultiFileTestCase() {
7880

7981
val config = JsonParser().parse(FileUtil.loadFile(File(path), true)) as JsonObject
8082

83+
if (config["withRuntime"]?.getAsBoolean() ?: false) {
84+
ConfigLibraryUtil.configureKotlinRuntime(myModule, PluginTestCaseBase.fullJdk())
85+
}
86+
8187
val action = MoveAction.valueOf(config.getString("type"))
8288

8389
val testDir = path.substring(0, path.lastIndexOf("/"))

idea/tests/org/jetbrains/jet/plugin/refactoring/move/JetMoveTestGenerated.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ public void testJava_moveClass_moveInnerToTop_moveNestedClassToTopLevelInTheSame
8686
doTest(fileName);
8787
}
8888

89+
@TestMetadata("java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance.test")
90+
public void testJava_moveClass_moveInnerToTop_moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance_MoveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance() throws Exception {
91+
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance.test");
92+
doTest(fileName);
93+
}
94+
95+
@TestMetadata("java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda.test")
96+
public void testJava_moveClass_moveInnerToTop_moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda_MoveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda() throws Exception {
97+
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda.test");
98+
doTest(fileName);
99+
}
100+
89101
@TestMetadata("java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndRename/moveNestedClassToTopLevelInTheSamePackageAndRename.test")
90102
public void testJava_moveClass_moveInnerToTop_moveNestedClassToTopLevelInTheSamePackageAndRename_MoveNestedClassToTopLevelInTheSamePackageAndRename() throws Exception {
91103
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndRename/moveNestedClassToTopLevelInTheSamePackageAndRename.test");

0 commit comments

Comments
 (0)