From 41f33169813b3d7df6d2d410635a0f6c5a9dee30 Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Thu, 28 Feb 2019 12:29:01 +0300 Subject: [PATCH] Fix caret position in "Convert function to property" intention #KT-19944 Fixed --- .../ConvertFunctionToPropertyIntention.kt | 22 +++++++++++-------- .../addExplicitAnonymousType.kt.after | 2 +- .../addExplicitLocalType.kt.after | 2 +- .../addExplicitType.kt.after | 2 +- .../blockBody.kt.after | 2 +- .../convertFunctionToProperty/comments.kt | 2 +- .../expressionBody.kt.after | 2 +- .../javaUsages.kt.after | 2 +- .../javaUsagesGet.kt.after | 2 +- .../javaUsagesIs.kt.after | 2 +- .../otherRefs.kt.after | 2 +- .../otherRefsGet.kt.after | 2 +- .../otherRefsIs.kt.after | 2 +- .../overrides.kt.after | 2 +- .../recursiveFunction.kt.after | 2 +- .../unchangedElements.kt.after | 2 +- 16 files changed, 28 insertions(+), 24 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionToPropertyIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionToPropertyIntention.kt index fb2b1af7514..2059adf7627 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionToPropertyIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionToPropertyIntention.kt @@ -45,10 +45,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.KtPsiFactory.CallableBuilder.Target.READ_ONLY_PROPERTY -import org.jetbrains.kotlin.psi.psiUtil.endOffset -import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch -import org.jetbrains.kotlin.psi.psiUtil.getStartOffsetIn -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.scopes.utils.findVariable @@ -64,6 +61,7 @@ class ConvertFunctionToPropertyIntention : private inner class Converter( project: Project, + private val file: KtFile, private val editor: Editor?, descriptor: FunctionDescriptor ) : CallableRefactoring(project, descriptor, text) { @@ -74,7 +72,7 @@ class ConvertFunctionToPropertyIntention : (SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(name) ?: name).asString() } - private fun convertFunction(originalFunction: KtNamedFunction, psiFactory: KtPsiFactory) { + private fun convertFunction(originalFunction: KtNamedFunction, psiFactory: KtPsiFactory, moveCaret: Boolean) { val propertyString = KtPsiFactory.CallableBuilder(READ_ONLY_PROPERTY).apply { // make sure to capture all comments and line breaks modifier(originalFunction.text.substring(0, originalFunction.funKeyword!!.getStartOffsetIn(originalFunction))) @@ -97,14 +95,14 @@ class ConvertFunctionToPropertyIntention : }.asString() val replaced = originalFunction.replaced(psiFactory.createDeclaration(propertyString)) - - editor?.caretModel?.moveToOffset(replaced.nameIdentifier!!.endOffset) + if (editor != null && moveCaret) editor.caretModel.moveToOffset(replaced.nameIdentifier!!.endOffset) } override fun performRefactoring(descriptorsForChange: Collection) { val conflicts = MultiMap() val getterName = JvmAbi.getterName(callableDescriptor.name.asString()) val callables = getAffectedCallables(project, descriptorsForChange) + val mainElement = findMainElement(callables) val kotlinCalls = ArrayList() val kotlinRefsToRename = ArrayList() val foreignRefs = ArrayList() @@ -177,7 +175,7 @@ class ConvertFunctionToPropertyIntention : foreignRefs.forEach { it.handleElementRename(newGetterName) } callables.forEach { when (it) { - is KtNamedFunction -> convertFunction(it, psiFactory) + is KtNamedFunction -> convertFunction(it, psiFactory, moveCaret = it == mainElement) is PsiMethod -> it.name = newGetterName } } @@ -186,6 +184,12 @@ class ConvertFunctionToPropertyIntention : } } } + + private fun findMainElement(callables: List): PsiElement? { + if (editor == null) return null + val offset = editor.caretModel.offset + return callables.find { file == it.containingFile && offset in it.textRange } + } } override fun startInWriteAction(): Boolean = false @@ -208,6 +212,6 @@ class ConvertFunctionToPropertyIntention : override fun applyTo(element: KtNamedFunction, editor: Editor?) { val descriptor = element.unsafeResolveToDescriptor(BodyResolveMode.PARTIAL) as FunctionDescriptor - Converter(element.project, editor, descriptor).run() + Converter(element.project, element.containingKtFile, editor, descriptor).run() } } diff --git a/idea/testData/intentions/convertFunctionToProperty/addExplicitAnonymousType.kt.after b/idea/testData/intentions/convertFunctionToProperty/addExplicitAnonymousType.kt.after index 86ac448773b..81ce16a20cc 100644 --- a/idea/testData/intentions/convertFunctionToProperty/addExplicitAnonymousType.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/addExplicitAnonymousType.kt.after @@ -3,7 +3,7 @@ interface T { } class A(val n: Int) { - val foo + val foo get() = object : T { override fun bar() { diff --git a/idea/testData/intentions/convertFunctionToProperty/addExplicitLocalType.kt.after b/idea/testData/intentions/convertFunctionToProperty/addExplicitLocalType.kt.after index 42b016dd117..e77f14684ea 100644 --- a/idea/testData/intentions/convertFunctionToProperty/addExplicitLocalType.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/addExplicitLocalType.kt.after @@ -2,7 +2,7 @@ fun test() { class X class A(val n: Int) { - val foo get() = X() + val foo get() = X() } val t = A(1).foo diff --git a/idea/testData/intentions/convertFunctionToProperty/addExplicitType.kt.after b/idea/testData/intentions/convertFunctionToProperty/addExplicitType.kt.after index ef981d2a83d..945f291e65f 100644 --- a/idea/testData/intentions/convertFunctionToProperty/addExplicitType.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/addExplicitType.kt.after @@ -1,5 +1,5 @@ class A(val n: Int) { - val foo get() = n > 1 + val foo get() = n > 1 } fun test() { diff --git a/idea/testData/intentions/convertFunctionToProperty/blockBody.kt.after b/idea/testData/intentions/convertFunctionToProperty/blockBody.kt.after index af3dd19af67..48843ed32d1 100644 --- a/idea/testData/intentions/convertFunctionToProperty/blockBody.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/blockBody.kt.after @@ -1,5 +1,5 @@ class A(val n: Int) { - val foo: Boolean + val foo: Boolean get() { return n > 1 } diff --git a/idea/testData/intentions/convertFunctionToProperty/comments.kt b/idea/testData/intentions/convertFunctionToProperty/comments.kt index d740d950d99..1876565aeca 100644 --- a/idea/testData/intentions/convertFunctionToProperty/comments.kt +++ b/idea/testData/intentions/convertFunctionToProperty/comments.kt @@ -2,7 +2,7 @@ annotation class X(val s: String) // 1 @X("") // 2 -/* 3 */ fun foo(): String { +/* 3 */ fun foo(): String { // 4 return "" } \ No newline at end of file diff --git a/idea/testData/intentions/convertFunctionToProperty/expressionBody.kt.after b/idea/testData/intentions/convertFunctionToProperty/expressionBody.kt.after index 56d590eb608..3da992ccdfe 100644 --- a/idea/testData/intentions/convertFunctionToProperty/expressionBody.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/expressionBody.kt.after @@ -1,5 +1,5 @@ class A(val n: Int) { - val foo: Boolean + val foo: Boolean get() = n > 1 } diff --git a/idea/testData/intentions/convertFunctionToProperty/javaUsages.kt.after b/idea/testData/intentions/convertFunctionToProperty/javaUsages.kt.after index fd61f65ed76..5aba85842c8 100644 --- a/idea/testData/intentions/convertFunctionToProperty/javaUsages.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/javaUsages.kt.after @@ -1,4 +1,4 @@ package test -val foo: Boolean +val foo: Boolean get() = true \ No newline at end of file diff --git a/idea/testData/intentions/convertFunctionToProperty/javaUsagesGet.kt.after b/idea/testData/intentions/convertFunctionToProperty/javaUsagesGet.kt.after index fd61f65ed76..5aba85842c8 100644 --- a/idea/testData/intentions/convertFunctionToProperty/javaUsagesGet.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/javaUsagesGet.kt.after @@ -1,4 +1,4 @@ package test -val foo: Boolean +val foo: Boolean get() = true \ No newline at end of file diff --git a/idea/testData/intentions/convertFunctionToProperty/javaUsagesIs.kt.after b/idea/testData/intentions/convertFunctionToProperty/javaUsagesIs.kt.after index 6149e40a9aa..6c71a3bad66 100644 --- a/idea/testData/intentions/convertFunctionToProperty/javaUsagesIs.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/javaUsagesIs.kt.after @@ -1,4 +1,4 @@ package test -val isFoo: Boolean +val isFoo: Boolean get() = true \ No newline at end of file diff --git a/idea/testData/intentions/convertFunctionToProperty/otherRefs.kt.after b/idea/testData/intentions/convertFunctionToProperty/otherRefs.kt.after index 2808393aa6f..e628720d204 100644 --- a/idea/testData/intentions/convertFunctionToProperty/otherRefs.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/otherRefs.kt.after @@ -5,7 +5,7 @@ import p.foo class A(val n: Int) -val A.foo: Boolean +val A.foo: Boolean get() = n > 1 fun test() { diff --git a/idea/testData/intentions/convertFunctionToProperty/otherRefsGet.kt.after b/idea/testData/intentions/convertFunctionToProperty/otherRefsGet.kt.after index 2808393aa6f..e628720d204 100644 --- a/idea/testData/intentions/convertFunctionToProperty/otherRefsGet.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/otherRefsGet.kt.after @@ -5,7 +5,7 @@ import p.foo class A(val n: Int) -val A.foo: Boolean +val A.foo: Boolean get() = n > 1 fun test() { diff --git a/idea/testData/intentions/convertFunctionToProperty/otherRefsIs.kt.after b/idea/testData/intentions/convertFunctionToProperty/otherRefsIs.kt.after index 509088f3daf..79d085c83f0 100644 --- a/idea/testData/intentions/convertFunctionToProperty/otherRefsIs.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/otherRefsIs.kt.after @@ -5,7 +5,7 @@ import p.isFoo class A(val n: Int) -val A.isFoo: Boolean +val A.isFoo: Boolean get() = n > 1 fun test() { diff --git a/idea/testData/intentions/convertFunctionToProperty/overrides.kt.after b/idea/testData/intentions/convertFunctionToProperty/overrides.kt.after index 8097e6f7fe7..4c5e0ced7e3 100644 --- a/idea/testData/intentions/convertFunctionToProperty/overrides.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/overrides.kt.after @@ -10,7 +10,7 @@ open class A(val n: Int): T { } class B: A(1) { - override val foo: Boolean + override val foo: Boolean get() = true } diff --git a/idea/testData/intentions/convertFunctionToProperty/recursiveFunction.kt.after b/idea/testData/intentions/convertFunctionToProperty/recursiveFunction.kt.after index 3472172745b..87010d5d2a2 100644 --- a/idea/testData/intentions/convertFunctionToProperty/recursiveFunction.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/recursiveFunction.kt.after @@ -1,3 +1,3 @@ // WITH_RUNTIME -val String.foo: String +val String.foo: String get() = if (isEmpty()) "" else substring(1).foo \ No newline at end of file diff --git a/idea/testData/intentions/convertFunctionToProperty/unchangedElements.kt.after b/idea/testData/intentions/convertFunctionToProperty/unchangedElements.kt.after index 39289e9d6c2..70e6ad64550 100644 --- a/idea/testData/intentions/convertFunctionToProperty/unchangedElements.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/unchangedElements.kt.after @@ -5,7 +5,7 @@ annotation class X(val s: String) class A(val n: Int) { val t = 1 internal @X("1") - val T.foo: Boolean + val T.foo: Boolean get() = toInt() - n > 1 val u = 2 }