KotlinIntroduceVariableHandler: fix for declarations with expression body

#KT-38449 Fixed
This commit is contained in:
Dmitry Gridin
2020-04-22 21:15:03 +07:00
parent d21e383094
commit 8e35b7a29c
11 changed files with 62 additions and 13 deletions
@@ -265,7 +265,9 @@ internal class ExpressionReplacementPerformer(
private fun <TElement : KtElement> withElementToBeReplacedPreserved(action: () -> TElement): TElement {
elementToBeReplaced.putCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY, Unit)
val result = action()
elementToBeReplaced = result.findDescendantOfType { it.getCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY) != null }!!
elementToBeReplaced = result.findDescendantOfType { it.getCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY) != null }
?: error("Element `elementToBeReplaced` not found")
elementToBeReplaced.putCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY, null)
return result
}
@@ -44,11 +44,11 @@ class ConvertToBlockBodyIntention : SelfTargetingIntention<KtDeclarationWithBody
override fun allowCaretInsideElement(element: PsiElement) = element !is KtDeclaration && super.allowCaretInsideElement(element)
override fun applyTo(element: KtDeclarationWithBody, editor: Editor?) {
convert(element)
convert(element, true)
}
companion object {
fun convert(declaration: KtDeclarationWithBody): KtDeclarationWithBody {
fun convert(declaration: KtDeclarationWithBody, withReformat: Boolean = false): KtDeclarationWithBody {
val body = declaration.bodyExpression!!
fun generateBody(returnsValue: Boolean): KtExpression {
@@ -86,13 +86,10 @@ class ConvertToBlockBodyIntention : SelfTargetingIntention<KtDeclarationWithBody
declaration.equalsToken!!.delete()
val replaced = body.replace(newBody)
declaration.containingKtFile.adjustLineIndent(replaced.startOffset, replaced.endOffset)
if (withReformat) declaration.containingKtFile.adjustLineIndent(replaced.startOffset, replaced.endOffset)
return declaration
}
private fun KtNamedFunction.returnType(): KotlinType? {
val descriptor = resolveToDescriptorIfAny() ?: return null
return descriptor.returnType
}
private fun KtNamedFunction.returnType(): KotlinType? = resolveToDescriptorIfAny()?.returnType
}
}
@@ -273,7 +273,7 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
val callParent = call.parent
var callToConvert = callExpression
if (callParent is KtDeclarationWithBody && call == callParent.bodyExpression) {
ConvertToBlockBodyIntention.convert(callParent)
ConvertToBlockBodyIntention.convert(callParent, true)
val firstStatement = callParent.bodyBlockExpression?.statements?.first()
callToConvert = (firstStatement as? KtQualifiedExpression)?.selectorExpression as? KtCallExpression
?: firstStatement as? KtCallExpression
@@ -46,7 +46,7 @@ object CreateLocalVariableActionFactory : KotlinSingleIntentionActionFactory() {
val actualContainer = when (container) {
is KtBlockExpression -> container
else -> ConvertToBlockBodyIntention.convert(container as KtDeclarationWithBody).bodyExpression!!
else -> ConvertToBlockBodyIntention.convert(container as KtDeclarationWithBody, true).bodyExpression!!
} as KtBlockExpression
if (actualContainer != container) {
@@ -164,8 +164,8 @@ fun PsiElement.findExpressionByCopyableDataAndClearIt(key: Key<Boolean>): KtExpr
return result
}
fun PsiElement.findElementByCopyableDataAndClearIt(key: Key<Boolean>): PsiElement {
val result = findDescendantOfType<PsiElement> { it.getCopyableUserData(key) != null }!!
fun PsiElement.findElementByCopyableDataAndClearIt(key: Key<Boolean>): PsiElement? {
val result = findDescendantOfType<PsiElement> { it.getCopyableUserData(key) != null } ?: return null
result.putCopyableUserData(key, null)
return result
}
@@ -311,7 +311,13 @@ object KotlinIntroduceVariableHandler : RefactoringActionHandler {
} ?: newReplace
}
runRefactoring(isVar, newExpression ?: return, newCommonContainer, newCommonParent, newAllReplaces)
runRefactoring(
isVar,
newExpression ?: return,
newCommonContainer,
newCommonParent ?: return,
newAllReplaces
)
}
}
@@ -0,0 +1,7 @@
fun b(body: () -> Int) = body()
class A {
fun test() = b {
<selection>24</selection>
}
}
@@ -0,0 +1,10 @@
fun b(body: () -> Int) = body()
class A {
fun test(): Int {
val i = 24
return b {
i
}
}
}
@@ -0,0 +1,7 @@
fun b(body: () -> Unit): Unit = body()
class A {
fun test() = b {
<selection>24</selection>
}
}
@@ -0,0 +1,10 @@
fun b(body: () -> Unit): Unit = body()
class A {
fun test() {
val i = 24
b {
i
}
}
}
@@ -220,6 +220,16 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
runTest("idea/testData/refactoring/introduceVariable/kt21530_withParam.kt");
}
@TestMetadata("kt38449_int.kt")
public void testKt38449_int() throws Exception {
runTest("idea/testData/refactoring/introduceVariable/kt38449_int.kt");
}
@TestMetadata("kt38449_unit.kt")
public void testKt38449_unit() throws Exception {
runTest("idea/testData/refactoring/introduceVariable/kt38449_unit.kt");
}
@TestMetadata("LoopRange.kt")
public void testLoopRange() throws Exception {
runTest("idea/testData/refactoring/introduceVariable/LoopRange.kt");