Introduce Variable: Do not replace assignment left-hand sides

#KT-14240 Fixed
This commit is contained in:
Alexey Sedunov
2016-10-12 11:42:45 +03:00
parent ec00b9f3ea
commit 5c2ad48375
11 changed files with 98 additions and 0 deletions
+1
View File
@@ -252,6 +252,7 @@ These artifacts include extensions for the types available in the latter JDKs, s
- [`KT-14182`](https://youtrack.jetbrains.com/issue/KT-14182) Move: Show error message on applying to enum entries
- Extract Function: Support implicit abnormal exits via Nothing-typed expressions
- [`KT-14285`](https://youtrack.jetbrains.com/issue/KT-14285) Rename: Forbid on backing field reference
- [`KT-14240`](https://youtrack.jetbrains.com/issue/KT-14240) Introduce Variable: Do not replace assignment left-hand sides
##### New features
@@ -320,11 +320,18 @@ object KotlinIntroduceVariableHandler : RefactoringActionHandler {
return commonContainer.allChildren.lastOrNull { it.textRange.contains(startOffset) } ?: return null
}
private fun PsiElement.isAssignmentLHS(): Boolean {
return parents.any { KtPsiUtil.isAssignment(it) && (it as KtBinaryExpression).left == this }
}
private fun KtExpression.findOccurrences(occurrenceContainer: PsiElement): List<KtExpression> {
return toRange()
.match(occurrenceContainer, KotlinPsiUnifier.DEFAULT)
.mapNotNull {
val candidate = it.range.elements.first()
if (candidate.isAssignmentLHS()) return@mapNotNull null
when (candidate) {
is KtExpression -> candidate
is KtStringTemplateEntryWithExpression -> candidate.expression
@@ -694,6 +701,10 @@ object KotlinIntroduceVariableHandler : RefactoringActionHandler {
val expression = expressionToExtract?.let { KtPsiUtil.safeDeparenthesize(it) }
?: return showErrorHint(project, editor, KotlinRefactoringBundle.message("cannot.refactor.no.expression"))
if (expression.isAssignmentLHS()) {
return showErrorHint(project, editor, KotlinRefactoringBundle.message("cannot.refactor.no.expression"))
}
val physicalExpression = expression.substringContextOrThis
val resolutionFacade = physicalExpression.getResolutionFacade()
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class Foo(var bar: IntArray)
fun test() {
val foo = Foo(IntArray(1) { 1 })
println(<selection>foo.bar</selection>)
foo.bar[0] = foo.bar[0] + 1
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
class Foo(var bar: IntArray)
fun test() {
val foo = Foo(IntArray(1) { 1 })
val message = foo.bar
println(message)
message[0] = message[0] + 1
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class Foo(var bar: Int)
fun test() {
val foo = Foo(1)
println(foo.bar)
<selection>foo.bar</selection> = foo.bar + 1
}
@@ -0,0 +1 @@
Cannot perform refactoring without an expression
@@ -0,0 +1,9 @@
// WITH_RUNTIME
class Foo(var bar: Bar)
class Bar(var baz: Int)
fun test() {
val foo = Foo(Bar(1))
println(<selection>foo.bar</selection>)
foo.bar.baz = foo.bar.baz + 1
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
class Foo(var bar: Bar)
class Bar(var baz: Int)
fun test() {
val foo = Foo(Bar(1))
val message = foo.bar
println(message)
message.baz = message.baz + 1
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class Foo(var bar: Int)
fun test() {
val foo = Foo(1)
println(<selection>foo.bar</selection>)
foo.bar = foo.bar + 1
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
class Foo(var bar: Int)
fun test() {
val foo = Foo(1)
val message = foo.bar
println(message)
foo.bar = message + 1
}
@@ -43,6 +43,12 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
doIntroduceVariableTest(fileName);
}
@TestMetadata("arrayAssignment.kt")
public void testArrayAssignment() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceVariable/arrayAssignment.kt");
doIntroduceVariableTest(fileName);
}
@TestMetadata("callUnderSmartCast.kt")
public void testCallUnderSmartCast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceVariable/callUnderSmartCast.kt");
@@ -337,6 +343,12 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
doIntroduceVariableTest(fileName);
}
@TestMetadata("onAssignmentLHS.kt")
public void testOnAssignmentLHS() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceVariable/onAssignmentLHS.kt");
doIntroduceVariableTest(fileName);
}
@TestMetadata("OneExplicitReceiver.kt")
public void testOneExplicitReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceVariable/OneExplicitReceiver.kt");
@@ -367,6 +379,12 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
doIntroduceVariableTest(fileName);
}
@TestMetadata("selectorAssignment.kt")
public void testSelectorAssignment() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceVariable/selectorAssignment.kt");
doIntroduceVariableTest(fileName);
}
@TestMetadata("Simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceVariable/Simple.kt");
@@ -385,6 +403,12 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
doIntroduceVariableTest(fileName);
}
@TestMetadata("skipUsageInAssignmentLHS.kt")
public void testSkipUsageInAssignmentLHS() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceVariable/skipUsageInAssignmentLHS.kt");
doIntroduceVariableTest(fileName);
}
@TestMetadata("StringInjection.kt")
public void testStringInjection() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceVariable/StringInjection.kt");