handle setter calls used as expression bodies in "Use property access syntax" intention

#KT-10587 Fixed
This commit is contained in:
Dmitry Jemerov
2016-01-07 15:54:33 +01:00
parent 36488d21da
commit 76c9bbc06d
8 changed files with 62 additions and 6 deletions
@@ -69,7 +69,7 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
val arguments = element.valueArguments
return when (arguments.size) {
0 -> replaceWithPropertyGet(element, propertyName)
1 -> replaceWithPropertySet(element, propertyName, arguments.single())
1 -> replaceWithPropertySet(element, propertyName)
else -> error("More than one argument in call to accessor")
}
}
@@ -158,15 +158,27 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
}
//TODO: what if it was used as expression (of type Unit)?
private fun replaceWithPropertySet(callExpression: KtCallExpression, propertyName: Name, argument: KtValueArgument): KtExpression {
val qualifiedExpression = callExpression.getQualifiedExpressionForSelector()
private fun replaceWithPropertySet(callExpression: KtCallExpression, propertyName: Name): KtExpression {
val call = callExpression.getQualifiedExpressionForSelector() ?: callExpression
val callParent = call.parent
var callToConvert = callExpression
if (callParent is KtDeclarationWithBody && call == callParent.bodyExpression) {
ConvertToBlockBodyIntention.convert(callParent)
val firstStatement = (callParent.bodyExpression as? KtBlockExpression)?.statements?.first()
callToConvert = (firstStatement as? KtQualifiedExpression)?.selectorExpression as? KtCallExpression
?: firstStatement as? KtCallExpression
?: throw IllegalStateException("Unexpected contents of function after conversion: ${callParent.text}")
}
val qualifiedExpression = callToConvert.getQualifiedExpressionForSelector()
val argument = callToConvert.valueArguments.single()
if (qualifiedExpression != null) {
val pattern = when (qualifiedExpression) {
is KtDotQualifiedExpression -> "$0.$1=$2"
is KtSafeQualifiedExpression -> "$0?.$1=$2"
else -> error(qualifiedExpression) //TODO: make it sealed?
}
val newExpression = KtPsiFactory(callExpression).createExpressionByPattern(
val newExpression = KtPsiFactory(callToConvert).createExpressionByPattern(
pattern,
qualifiedExpression.receiverExpression,
propertyName,
@@ -175,8 +187,8 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
return qualifiedExpression.replaced(newExpression)
}
else {
val newExpression = KtPsiFactory(callExpression).createExpressionByPattern("$0=$1", propertyName, argument.getArgumentExpression()!!)
return callExpression.replaced(newExpression)
val newExpression = KtPsiFactory(callToConvert).createExpressionByPattern("$0=$1", propertyName, argument.getArgumentExpression()!!)
return callToConvert.replaced(newExpression)
}
}
}
@@ -0,0 +1,2 @@
// WITH_RUNTIME
fun foo(thread: Thread) = thread.setName("<name>")<caret>
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun foo(thread: Thread) {
thread.name = "<name>"
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
var Thread.otherName: String
get() = getName()
set(value) = setName(value)<caret>
@@ -0,0 +1,6 @@
// WITH_RUNTIME
var Thread.otherName: String
get() = getName()
set(value) {
name = value
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
class C: Thread() {
fun foo(n: String) = setName(n)<caret>
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
class C: Thread() {
fun foo(n: String) {
name = n
}
}
@@ -8740,6 +8740,24 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
doTest(fileName);
}
@TestMetadata("setAsExpressionBody.kt")
public void testSetAsExpressionBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/usePropertyAccessSyntax/setAsExpressionBody.kt");
doTest(fileName);
}
@TestMetadata("setAsExpressionBodyProperty.kt")
public void testSetAsExpressionBodyProperty() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/usePropertyAccessSyntax/setAsExpressionBodyProperty.kt");
doTest(fileName);
}
@TestMetadata("setAsExpressionBodyUnqualified.kt")
public void testSetAsExpressionBodyUnqualified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/usePropertyAccessSyntax/setAsExpressionBodyUnqualified.kt");
doTest(fileName);
}
@TestMetadata("setImplicitReceiver.kt")
public void testSetImplicitReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/usePropertyAccessSyntax/setImplicitReceiver.kt");