Extract Function: Generate function in property's enclosing declaration if original expression belongs to initializer of that property
#KT-6290 Fixed
This commit is contained in:
@@ -73,6 +73,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import com.intellij.psi.PsiPackage
|
import com.intellij.psi.PsiPackage
|
||||||
import org.jetbrains.jet.plugin.util.ProjectRootsUtil
|
import org.jetbrains.jet.plugin.util.ProjectRootsUtil
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||||
|
|
||||||
fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? {
|
fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? {
|
||||||
val data = getCopyableUserData(key)
|
val data = getCopyableUserData(key)
|
||||||
@@ -137,27 +138,27 @@ public fun PsiElement.getAllExtractionContainers(strict: Boolean = true): List<J
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun PsiElement.getExtractionContainers(strict: Boolean = true, includeAll: Boolean = false): List<JetElement> {
|
public fun PsiElement.getExtractionContainers(strict: Boolean = true, includeAll: Boolean = false): List<JetElement> {
|
||||||
|
fun getEnclosingDeclaration(element: PsiElement, strict: Boolean): PsiElement? {
|
||||||
|
return element.parents(!strict)
|
||||||
|
.filter {
|
||||||
|
(it is JetDeclarationWithBody && it !is JetFunctionLiteral)
|
||||||
|
|| it is JetClassInitializer
|
||||||
|
|| it is JetClassBody
|
||||||
|
|| it is JetFile
|
||||||
|
}
|
||||||
|
.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
if (includeAll) return getAllExtractionContainers(strict)
|
if (includeAll) return getAllExtractionContainers(strict)
|
||||||
|
|
||||||
val declaration = getParentOfType<JetDeclaration>(strict)?.let { declaration ->
|
val enclosingDeclaration = getEnclosingDeclaration(this, strict)?.let {
|
||||||
stream(declaration) { it.getStrictParentOfType<JetDeclaration>() }.firstOrNull { it !is JetFunctionLiteral }
|
if (it is JetDeclarationWithBody || it is JetClassInitializer) getEnclosingDeclaration(it, true) else it
|
||||||
} ?: return Collections.emptyList()
|
|
||||||
|
|
||||||
val parent = declaration.getParent()?.let {
|
|
||||||
when (it) {
|
|
||||||
is JetProperty, is JetMultiDeclaration -> it.getParent()
|
|
||||||
is JetParameterList -> it.getParent()?.getParent()
|
|
||||||
else -> it
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return when (parent) {
|
|
||||||
is JetFile -> Collections.singletonList(parent)
|
return when (enclosingDeclaration) {
|
||||||
is JetClassBody -> {
|
is JetFile -> Collections.singletonList(enclosingDeclaration)
|
||||||
getAllExtractionContainers(strict).filterIsInstance<JetClassBody>()
|
is JetClassBody -> getAllExtractionContainers(strict).filterIsInstance<JetClassBody>()
|
||||||
}
|
|
||||||
else -> {
|
else -> {
|
||||||
val enclosingDeclaration =
|
|
||||||
PsiTreeUtil.getNonStrictParentOfType(parent, javaClass<JetDeclarationWithBody>(), javaClass<JetClassInitializer>())
|
|
||||||
val targetContainer = when (enclosingDeclaration) {
|
val targetContainer = when (enclosingDeclaration) {
|
||||||
is JetDeclarationWithBody -> enclosingDeclaration.getBodyExpression()
|
is JetDeclarationWithBody -> enclosingDeclaration.getBodyExpression()
|
||||||
is JetClassInitializer -> enclosingDeclaration.getBody()
|
is JetClassInitializer -> enclosingDeclaration.getBody()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// ACTION: Create class 'SomeTest'
|
// ACTION: Create class 'SomeTest'
|
||||||
// ACTION: Create enum 'SomeTest'
|
// ACTION: Create enum 'SomeTest'
|
||||||
// ACTION: Create object 'SomeTest'
|
// ACTION: Create object 'SomeTest'
|
||||||
|
// ACTION: Create property 'SomeTest'
|
||||||
// ACTION: Create trait 'SomeTest'
|
// ACTION: Create trait 'SomeTest'
|
||||||
// ERROR: Unresolved reference: SomeTest
|
// ERROR: Unresolved reference: SomeTest
|
||||||
|
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
// ACTION: Create class 'A'
|
// ACTION: Create class 'A'
|
||||||
// ACTION: Create trait 'A'
|
// ACTION: Create trait 'A'
|
||||||
// ACTION: Create object 'A'
|
// ACTION: Create object 'A'
|
||||||
|
// ACTION: Create property 'A'
|
||||||
// ACTION: Create enum 'A'
|
// ACTION: Create enum 'A'
|
||||||
// ACTION: Create annotation 'A'
|
// ACTION: Create annotation 'A'
|
||||||
// ERROR: Unresolved reference: A
|
// ERROR: Unresolved reference: A
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
// ACTION: Create class 'A'
|
// ACTION: Create class 'A'
|
||||||
// ACTION: Create trait 'A'
|
// ACTION: Create trait 'A'
|
||||||
// ACTION: Create object 'A'
|
// ACTION: Create object 'A'
|
||||||
|
// ACTION: Create property 'A'
|
||||||
// ACTION: Create enum 'A'
|
// ACTION: Create enum 'A'
|
||||||
// ACTION: Create annotation 'A'
|
// ACTION: Create annotation 'A'
|
||||||
// ERROR: Unresolved reference: A
|
// ERROR: Unresolved reference: A
|
||||||
|
|||||||
+1
@@ -1,5 +1,6 @@
|
|||||||
// "Create parameter 'foo'" "false"
|
// "Create parameter 'foo'" "false"
|
||||||
// ACTION: Create local variable 'foo'
|
// ACTION: Create local variable 'foo'
|
||||||
|
// ACTION: Create property 'foo'
|
||||||
// ACTION: Split property declaration
|
// ACTION: Split property declaration
|
||||||
// ERROR: Unresolved reference: foo
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,8 +1,8 @@
|
|||||||
fun foo() {
|
fun foo() {
|
||||||
fun i(): Int {
|
|
||||||
return 1 + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
val x = i()
|
val x = i()
|
||||||
val y = i()
|
val y = i()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun i(): Int {
|
||||||
|
return 1 + 1
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// PARAM_TYPES: kotlin.Int
|
||||||
|
// PARAM_TYPES: kotlin.Int
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter val a: kotlin.Int defined in bar
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter val b: kotlin.Int defined in bar
|
||||||
fun bar(a: Int, b: Int) {
|
fun bar(a: Int, b: Int) {
|
||||||
val foo = <selection>a + b</selection> - 1
|
val foo = <selection>a + b</selection> - 1
|
||||||
}
|
}
|
||||||
+8
-4
@@ -1,7 +1,11 @@
|
|||||||
|
// PARAM_TYPES: kotlin.Int
|
||||||
|
// PARAM_TYPES: kotlin.Int
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter val a: kotlin.Int defined in bar
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter val b: kotlin.Int defined in bar
|
||||||
fun bar(a: Int, b: Int) {
|
fun bar(a: Int, b: Int) {
|
||||||
fun i(): Int {
|
val foo = i(a, b) - 1
|
||||||
return a + b
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val foo = i() - 1
|
private fun i(a: Int, b: Int): Int {
|
||||||
|
return a + b
|
||||||
}
|
}
|
||||||
+4
@@ -1,3 +1,7 @@
|
|||||||
|
// PARAM_TYPES: kotlin.Int
|
||||||
|
// PARAM_TYPES: kotlin.Int
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter val a: kotlin.Int defined in bar
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter val b: kotlin.Int defined in bar
|
||||||
fun bar(a: Int, b: Int) {
|
fun bar(a: Int, b: Int) {
|
||||||
val foo = { <selection>a + b</selection> - 1 }.invoke()
|
val foo = { <selection>a + b</selection> - 1 }.invoke()
|
||||||
}
|
}
|
||||||
+8
-4
@@ -1,7 +1,11 @@
|
|||||||
|
// PARAM_TYPES: kotlin.Int
|
||||||
|
// PARAM_TYPES: kotlin.Int
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter val a: kotlin.Int defined in bar
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter val b: kotlin.Int defined in bar
|
||||||
fun bar(a: Int, b: Int) {
|
fun bar(a: Int, b: Int) {
|
||||||
fun i(): Int {
|
val foo = { i(a, b) - 1 }.invoke()
|
||||||
return a + b
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val foo = { i() - 1 }.invoke()
|
private fun i(a: Int, b: Int): Int {
|
||||||
|
return a + b
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user