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 {
|
private fun <TElement : KtElement> withElementToBeReplacedPreserved(action: () -> TElement): TElement {
|
||||||
elementToBeReplaced.putCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY, Unit)
|
elementToBeReplaced.putCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY, Unit)
|
||||||
val result = action()
|
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)
|
elementToBeReplaced.putCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY, null)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ class ConvertToBlockBodyIntention : SelfTargetingIntention<KtDeclarationWithBody
|
|||||||
override fun allowCaretInsideElement(element: PsiElement) = element !is KtDeclaration && super.allowCaretInsideElement(element)
|
override fun allowCaretInsideElement(element: PsiElement) = element !is KtDeclaration && super.allowCaretInsideElement(element)
|
||||||
|
|
||||||
override fun applyTo(element: KtDeclarationWithBody, editor: Editor?) {
|
override fun applyTo(element: KtDeclarationWithBody, editor: Editor?) {
|
||||||
convert(element)
|
convert(element, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun convert(declaration: KtDeclarationWithBody): KtDeclarationWithBody {
|
fun convert(declaration: KtDeclarationWithBody, withReformat: Boolean = false): KtDeclarationWithBody {
|
||||||
val body = declaration.bodyExpression!!
|
val body = declaration.bodyExpression!!
|
||||||
|
|
||||||
fun generateBody(returnsValue: Boolean): KtExpression {
|
fun generateBody(returnsValue: Boolean): KtExpression {
|
||||||
@@ -86,13 +86,10 @@ class ConvertToBlockBodyIntention : SelfTargetingIntention<KtDeclarationWithBody
|
|||||||
|
|
||||||
declaration.equalsToken!!.delete()
|
declaration.equalsToken!!.delete()
|
||||||
val replaced = body.replace(newBody)
|
val replaced = body.replace(newBody)
|
||||||
declaration.containingKtFile.adjustLineIndent(replaced.startOffset, replaced.endOffset)
|
if (withReformat) declaration.containingKtFile.adjustLineIndent(replaced.startOffset, replaced.endOffset)
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtNamedFunction.returnType(): KotlinType? {
|
private fun KtNamedFunction.returnType(): KotlinType? = resolveToDescriptorIfAny()?.returnType
|
||||||
val descriptor = resolveToDescriptorIfAny() ?: return null
|
|
||||||
return descriptor.returnType
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
|
|||||||
val callParent = call.parent
|
val callParent = call.parent
|
||||||
var callToConvert = callExpression
|
var callToConvert = callExpression
|
||||||
if (callParent is KtDeclarationWithBody && call == callParent.bodyExpression) {
|
if (callParent is KtDeclarationWithBody && call == callParent.bodyExpression) {
|
||||||
ConvertToBlockBodyIntention.convert(callParent)
|
ConvertToBlockBodyIntention.convert(callParent, true)
|
||||||
val firstStatement = callParent.bodyBlockExpression?.statements?.first()
|
val firstStatement = callParent.bodyBlockExpression?.statements?.first()
|
||||||
callToConvert = (firstStatement as? KtQualifiedExpression)?.selectorExpression as? KtCallExpression
|
callToConvert = (firstStatement as? KtQualifiedExpression)?.selectorExpression as? KtCallExpression
|
||||||
?: firstStatement as? KtCallExpression
|
?: firstStatement as? KtCallExpression
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ object CreateLocalVariableActionFactory : KotlinSingleIntentionActionFactory() {
|
|||||||
|
|
||||||
val actualContainer = when (container) {
|
val actualContainer = when (container) {
|
||||||
is KtBlockExpression -> container
|
is KtBlockExpression -> container
|
||||||
else -> ConvertToBlockBodyIntention.convert(container as KtDeclarationWithBody).bodyExpression!!
|
else -> ConvertToBlockBodyIntention.convert(container as KtDeclarationWithBody, true).bodyExpression!!
|
||||||
} as KtBlockExpression
|
} as KtBlockExpression
|
||||||
|
|
||||||
if (actualContainer != container) {
|
if (actualContainer != container) {
|
||||||
|
|||||||
@@ -164,8 +164,8 @@ fun PsiElement.findExpressionByCopyableDataAndClearIt(key: Key<Boolean>): KtExpr
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun PsiElement.findElementByCopyableDataAndClearIt(key: Key<Boolean>): PsiElement {
|
fun PsiElement.findElementByCopyableDataAndClearIt(key: Key<Boolean>): PsiElement? {
|
||||||
val result = findDescendantOfType<PsiElement> { it.getCopyableUserData(key) != null }!!
|
val result = findDescendantOfType<PsiElement> { it.getCopyableUserData(key) != null } ?: return null
|
||||||
result.putCopyableUserData(key, null)
|
result.putCopyableUserData(key, null)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -311,7 +311,13 @@ object KotlinIntroduceVariableHandler : RefactoringActionHandler {
|
|||||||
} ?: newReplace
|
} ?: 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");
|
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")
|
@TestMetadata("LoopRange.kt")
|
||||||
public void testLoopRange() throws Exception {
|
public void testLoopRange() throws Exception {
|
||||||
runTest("idea/testData/refactoring/introduceVariable/LoopRange.kt");
|
runTest("idea/testData/refactoring/introduceVariable/LoopRange.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user