KotlinIntroduceVariableHandler: fix for declarations with expression body
#KT-38449 Fixed
This commit is contained in:
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
+7
-1
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user