mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[kotlin extract method] KTIJ-21622: replace template with dialog on second call
GitOrigin-RevId: 0f6bb8e089657a0b7f69cc801870e3b2a30baa66
This commit is contained in:
committed by
intellij-monorepo-bot
parent
096180cef6
commit
2b9d34dcb4
+1
-1
@@ -41,7 +41,7 @@ class KotlinRefactoringSupportProvider : RefactoringSupportProvider() {
|
||||
fun getExtractFunctionHandler(): RefactoringActionHandler = ExtractKotlinFunctionHandler()
|
||||
|
||||
fun getExtractFunctionToScopeHandler(): RefactoringActionHandler =
|
||||
ExtractKotlinFunctionHandler(true, ExtractKotlinFunctionHandler.InteractiveExtractionHelper)
|
||||
ExtractKotlinFunctionHandler(allContainersEnabled = true)
|
||||
|
||||
override fun getChangeSignatureHandler() = KotlinChangeSignatureHandler()
|
||||
|
||||
|
||||
+66
-44
@@ -4,6 +4,7 @@ package org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction
|
||||
|
||||
import com.intellij.codeInsight.template.Template
|
||||
import com.intellij.codeInsight.template.TemplateEditingAdapter
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
|
||||
@@ -36,7 +37,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class ExtractKotlinFunctionHandler(
|
||||
private val allContainersEnabled: Boolean = false,
|
||||
private val helper: ExtractionEngineHelper = InteractiveExtractionHelper
|
||||
private val helper: ExtractionEngineHelper = getDefaultHelper(allContainersEnabled)
|
||||
) : RefactoringActionHandler {
|
||||
|
||||
companion object {
|
||||
@@ -45,6 +46,10 @@ class ExtractKotlinFunctionHandler(
|
||||
return EditorSettingsExternalizable.getInstance().isVariableInplaceRenameEnabled
|
||||
&& Registry.`is`("kotlin.enable.inplace.extract.method")
|
||||
}
|
||||
|
||||
fun getDefaultHelper(allContainersEnabled: Boolean): ExtractionEngineHelper {
|
||||
return if (isInplaceRefactoringEnabled) InplaceExtractionHelper(allContainersEnabled) else InteractiveExtractionHelper
|
||||
}
|
||||
}
|
||||
|
||||
object InteractiveExtractionHelper : ExtractionEngineHelper(EXTRACT_FUNCTION) {
|
||||
@@ -54,15 +59,66 @@ class ExtractKotlinFunctionHandler(
|
||||
descriptorWithConflicts: ExtractableCodeDescriptorWithConflicts,
|
||||
onFinish: (ExtractionResult) -> Unit
|
||||
) {
|
||||
if (isInplaceRefactoringEnabled) {
|
||||
val descriptor = descriptorWithConflicts.descriptor.copy(suggestedNames = listOf("extracted"))
|
||||
val configuration = ExtractionGeneratorConfiguration(descriptor, ExtractionGeneratorOptions.DEFAULT)
|
||||
doRefactor(configuration, onFinish)
|
||||
} else {
|
||||
KotlinExtractFunctionDialog(descriptorWithConflicts.descriptor.extractionData.project, descriptorWithConflicts) {
|
||||
doRefactor(it.currentConfiguration, onFinish)
|
||||
}.show()
|
||||
fun afterFinish(extraction: ExtractionResult){
|
||||
processDuplicates(extraction.duplicateReplacers, project, editor)
|
||||
onFinish(extraction)
|
||||
}
|
||||
KotlinExtractFunctionDialog(descriptorWithConflicts.descriptor.extractionData.project, descriptorWithConflicts) {
|
||||
doRefactor(it.currentConfiguration, ::afterFinish)
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
class InplaceExtractionHelper(private val allContainersEnabled: Boolean) : ExtractionEngineHelper(EXTRACT_FUNCTION) {
|
||||
override fun configureAndRun(
|
||||
project: Project,
|
||||
editor: Editor,
|
||||
descriptorWithConflicts: ExtractableCodeDescriptorWithConflicts,
|
||||
onFinish: (ExtractionResult) -> Unit
|
||||
) {
|
||||
val activeTemplateState = TemplateManagerImpl.getTemplateState(editor)
|
||||
if (activeTemplateState != null) {
|
||||
activeTemplateState.gotoEnd(true)
|
||||
ExtractKotlinFunctionHandler(allContainersEnabled, InteractiveExtractionHelper)
|
||||
.invoke(project, editor, descriptorWithConflicts.descriptor.extractionData.originalFile, null)
|
||||
}
|
||||
|
||||
val descriptor = descriptorWithConflicts.descriptor.copy(suggestedNames = listOf("extracted"))
|
||||
val elements = descriptor.extractionData.originalElements
|
||||
val file = descriptor.extractionData.originalFile
|
||||
val callRange = editor.document.createRangeMarker(elements.first().textRange.startOffset, elements.last().textRange.endOffset)
|
||||
.apply { isGreedyToLeft = true; isGreedyToRight = true }
|
||||
val editorState = EditorState(editor)
|
||||
fun afterFinish(extraction: ExtractionResult){
|
||||
val callIdentifier = findSingleCallExpression(file, callRange.range)?.calleeExpression ?: throw IllegalStateException()
|
||||
val methodRange = extraction.declaration.textRange
|
||||
val methodOffset = extraction.declaration.navigationElement.textRange.endOffset
|
||||
val callOffset = callIdentifier.textRange.endOffset
|
||||
val preview = InplaceExtractUtils.createPreview(editor, methodRange, methodOffset, callRange.range!!, callOffset)
|
||||
val templateState = ExtractMethodTemplate(editor, extraction.declaration, callIdentifier).runTemplate(LinkedHashSet())
|
||||
callRange.dispose()
|
||||
Disposer.register(templateState, preview)
|
||||
templateState.addTemplateStateListener(object: TemplateEditingAdapter() {
|
||||
override fun templateFinished(template: Template, brokenOff: Boolean) {
|
||||
if (brokenOff) {
|
||||
editorState.revert()
|
||||
}
|
||||
}
|
||||
})
|
||||
InplaceExtractUtils.addTemplateFinishedListener(templateState) {
|
||||
processDuplicates(extraction.duplicateReplacers, file.project, editor)
|
||||
}
|
||||
onFinish(extraction)
|
||||
}
|
||||
val configuration = ExtractionGeneratorConfiguration(descriptor, ExtractionGeneratorOptions.DEFAULT)
|
||||
doRefactor(configuration, ::afterFinish)
|
||||
}
|
||||
|
||||
private fun findSingleCallExpression(file: KtFile, range: TextRange?): KtCallExpression? {
|
||||
if (range == null) return null
|
||||
val container = PsiTreeUtil.findCommonParent(file.findElementAt(range.startOffset), file.findElementAt(range.endOffset))
|
||||
val callExpressions = PsiTreeUtil.findChildrenOfType(container, KtCallExpression::class.java)
|
||||
return callExpressions.singleOrNull { it.textRange in range }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,44 +132,10 @@ class ExtractKotlinFunctionHandler(
|
||||
val adjustedElements = elements.singleOrNull().safeAs<KtBlockExpression>()?.statements ?: elements
|
||||
ExtractionData(file, adjustedElements.toRange(false), targetSibling)
|
||||
}) { extractionData ->
|
||||
val callRange = editor.document.createRangeMarker(elements.first().textRange.startOffset, elements.last().textRange.endOffset)
|
||||
.apply { isGreedyToLeft = true; isGreedyToRight = true }
|
||||
val editorState = EditorState(editor)
|
||||
ExtractionEngine(helper).run(editor, extractionData) { extraction ->
|
||||
if (isInplaceRefactoringEnabled) {
|
||||
val callIdentifier = findSingleCallExpression(file, callRange.range)?.calleeExpression ?: throw IllegalStateException()
|
||||
val methodRange = extraction.declaration.textRange
|
||||
val methodOffset = extraction.declaration.navigationElement.textRange.endOffset
|
||||
val callOffset = callIdentifier.textRange.endOffset
|
||||
val preview = InplaceExtractUtils.createPreview(editor, methodRange, methodOffset, callRange.range!!, callOffset)
|
||||
val templateState = ExtractMethodTemplate(editor, extraction.declaration, callIdentifier).runTemplate(LinkedHashSet())
|
||||
templateState.properties.put("ExtractMethod", true)
|
||||
callRange.dispose()
|
||||
Disposer.register(templateState, preview)
|
||||
templateState.addTemplateStateListener(object: TemplateEditingAdapter() {
|
||||
override fun templateFinished(template: Template, brokenOff: Boolean) {
|
||||
if (brokenOff) {
|
||||
editorState.revert()
|
||||
}
|
||||
}
|
||||
})
|
||||
InplaceExtractUtils.addTemplateFinishedListener(templateState) {
|
||||
processDuplicates(extraction.duplicateReplacers, file.project, editor)
|
||||
}
|
||||
} else {
|
||||
processDuplicates(extraction.duplicateReplacers, file.project, editor)
|
||||
}
|
||||
}
|
||||
ExtractionEngine(helper).run(editor, extractionData) { }
|
||||
}
|
||||
}
|
||||
|
||||
private fun findSingleCallExpression(file: KtFile, range: TextRange?): KtCallExpression? {
|
||||
if (range == null) return null
|
||||
val container = PsiTreeUtil.findCommonParent(file.findElementAt(range.startOffset), file.findElementAt(range.endOffset))
|
||||
val callExpressions = PsiTreeUtil.findChildrenOfType(container, KtCallExpression::class.java)
|
||||
return callExpressions.filter { it.textRange in range }.singleOrNull()
|
||||
}
|
||||
|
||||
fun selectElements(editor: Editor, file: KtFile, continuation: (elements: List<PsiElement>, targetSibling: PsiElement) -> Unit) {
|
||||
selectElementsWithTargetSibling(
|
||||
EXTRACT_FUNCTION,
|
||||
|
||||
+5
-1
@@ -496,7 +496,11 @@ fun doExtractFunction(fixture: CodeInsightTestFixture, file: KtFile) {
|
||||
descriptor
|
||||
}
|
||||
|
||||
doRefactor(ExtractionGeneratorConfiguration(newDescriptor, ExtractionGeneratorOptions.DEFAULT), onFinish)
|
||||
fun afterFinish(extraction: ExtractionResult){
|
||||
processDuplicates(extraction.duplicateReplacers, project, editor)
|
||||
onFinish(extraction)
|
||||
}
|
||||
doRefactor(ExtractionGeneratorConfiguration(newDescriptor, ExtractionGeneratorOptions.DEFAULT), ::afterFinish)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user