Extract Function: Forbid inappropriate declarations inside extractable fragment
#KT-20467 Fixed #KT-20469 Fixed
This commit is contained in:
+3
-2
@@ -28,9 +28,9 @@ import org.jetbrains.kotlin.idea.refactoring.getExtractionContainers
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.KotlinExtractFunctionDialog
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.selectElementsWithTargetSibling
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.validateExpressionElements
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class ExtractKotlinFunctionHandler(
|
||||
private val allContainersEnabled: Boolean = false,
|
||||
@@ -69,6 +69,7 @@ class ExtractKotlinFunctionHandler(
|
||||
file,
|
||||
"Select target code block",
|
||||
listOf(CodeInsightUtils.ElementKind.EXPRESSION),
|
||||
::validateExpressionElements,
|
||||
{ elements, parent -> parent.getExtractionContainers(elements.size == 1, allContainersEnabled) },
|
||||
continuation
|
||||
)
|
||||
|
||||
+1
@@ -187,6 +187,7 @@ fun selectNewParameterContext(
|
||||
file = file,
|
||||
title = "Introduce parameter to declaration",
|
||||
elementKinds = listOf(CodeInsightUtils.ElementKind.EXPRESSION),
|
||||
elementValidator = ::validateExpressionElements,
|
||||
getContainers = { _, parent ->
|
||||
val parents = parent.parents
|
||||
val stopAt = (parent.parents.zip(parent.parents.drop(1)))
|
||||
|
||||
+2
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.selectElementsWithTargetSibling
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.showErrorHint
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.showErrorHintByKey
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.validateExpressionElements
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtClassBody
|
||||
@@ -73,6 +74,7 @@ class KotlinIntroducePropertyHandler(
|
||||
file,
|
||||
"Select target code block",
|
||||
listOf(CodeInsightUtils.ElementKind.EXPRESSION),
|
||||
::validateExpressionElements,
|
||||
{ _, parent ->
|
||||
parent.getExtractionContainers(strict = true, includeAll = true).filter { it is KtClassBody || (it is KtFile && !it.isScript()) }
|
||||
},
|
||||
|
||||
+1
@@ -55,6 +55,7 @@ open class KotlinIntroduceTypeAliasHandler : RefactoringActionHandler {
|
||||
file,
|
||||
"Select target code block",
|
||||
listOf(TYPE_ELEMENT, TYPE_CONSTRUCTOR),
|
||||
{ null },
|
||||
{ _, parent -> listOf(parent.containingFile) },
|
||||
continuation
|
||||
)
|
||||
|
||||
+1
@@ -74,6 +74,7 @@ object KotlinIntroduceTypeParameterHandler : RefactoringActionHandler {
|
||||
file,
|
||||
"Introduce type parameter to declaration",
|
||||
listOf(CodeInsightUtils.ElementKind.TYPE_ELEMENT),
|
||||
{ null },
|
||||
{ _, parent -> getPossibleTypeParameterContainers(parent) },
|
||||
continuation
|
||||
)
|
||||
|
||||
@@ -47,6 +47,7 @@ fun selectElementsWithTargetSibling(
|
||||
file: KtFile,
|
||||
title: String,
|
||||
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
||||
elementValidator: (List<PsiElement>) -> String?,
|
||||
getContainers: (elements: List<PsiElement>, commonParent: PsiElement) -> List<PsiElement>,
|
||||
continuation: (elements: List<PsiElement>, targetSibling: PsiElement) -> Unit
|
||||
) {
|
||||
@@ -69,7 +70,7 @@ fun selectElementsWithTargetSibling(
|
||||
continuation(elements, outermostParent)
|
||||
}
|
||||
|
||||
selectElementsWithTargetParent(operationName, editor, file, title, elementKinds, getContainers, ::onSelectionComplete)
|
||||
selectElementsWithTargetParent(operationName, editor, file, title, elementKinds, elementValidator, getContainers, ::onSelectionComplete)
|
||||
}
|
||||
|
||||
fun selectElementsWithTargetParent(
|
||||
@@ -78,6 +79,7 @@ fun selectElementsWithTargetParent(
|
||||
file: KtFile,
|
||||
title: String,
|
||||
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
||||
elementValidator: (List<PsiElement>) -> String?,
|
||||
getContainers: (elements: List<PsiElement>, commonParent: PsiElement) -> List<PsiElement>,
|
||||
continuation: (elements: List<PsiElement>, targetParent: PsiElement) -> Unit
|
||||
) {
|
||||
@@ -86,6 +88,11 @@ fun selectElementsWithTargetParent(
|
||||
}
|
||||
|
||||
fun selectTargetContainer(elements: List<PsiElement>) {
|
||||
elementValidator(elements)?.let {
|
||||
showErrorHint(file.project, editor, it, operationName)
|
||||
return
|
||||
}
|
||||
|
||||
val physicalElements = elements.map { it.substringContextOrThis }
|
||||
val parent = PsiTreeUtil.findCommonParent(physicalElements)
|
||||
?: throw AssertionError("Should have at least one parent: ${physicalElements.joinToString("\n")}")
|
||||
@@ -236,4 +243,11 @@ fun <T : KtDeclaration> insertDeclaration(declaration: T, targetSibling: PsiElem
|
||||
return (targetContainer.addBefore(declaration, anchor) as T).apply {
|
||||
targetContainer.addBefore(KtPsiFactory(declaration).createWhiteSpace("\n\n"), anchor)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun validateExpressionElements(elements: List<PsiElement>): String? {
|
||||
if (elements.any { it is KtConstructor<*> || it is KtParameter || it is KtTypeAlias || it is KtPropertyAccessor }) {
|
||||
return "Refactoring is not applicable to this code fragment"
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// SIBLING:
|
||||
class Foo {
|
||||
<selection>constructor(bar: Int)</selection>
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
Refactoring is not applicable to this code fragment
|
||||
@@ -0,0 +1,2 @@
|
||||
// SIBLING:
|
||||
class Foo(<selection>bar: String = "baz"</selection>)
|
||||
+1
@@ -0,0 +1 @@
|
||||
Refactoring is not applicable to this code fragment
|
||||
+1
-1
@@ -1 +1 @@
|
||||
Cannot refactor in this place
|
||||
Cannot refactor in this place
|
||||
+1
-1
@@ -1 +1 @@
|
||||
Cannot refactor in this place
|
||||
Cannot refactor in this place
|
||||
+10
@@ -986,6 +986,16 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
|
||||
runTest("idea/testData/refactoring/extractFunction/basic/refInReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("selectedConstructor.kt")
|
||||
public void testSelectedConstructor() throws Exception {
|
||||
runTest("idea/testData/refactoring/extractFunction/basic/selectedConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("selectedParameter.kt")
|
||||
public void testSelectedParameter() throws Exception {
|
||||
runTest("idea/testData/refactoring/extractFunction/basic/selectedParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendCall.kt")
|
||||
public void testSuspendCall() throws Exception {
|
||||
runTest("idea/testData/refactoring/extractFunction/basic/suspendCall.kt");
|
||||
|
||||
Reference in New Issue
Block a user