From 0a6010ff9d41780706322b248398ea98cd16d7da Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Wed, 25 Feb 2015 11:23:30 +0300 Subject: [PATCH] Refactoring: Move selectElements() function to introduceUtil.kt --- .../ExtractKotlinFunctionHandler.kt | 116 +++--------------- .../refactoring/introduce/introduceUtil.kt | 106 ++++++++++++++++ .../AbstractJetExtractionTest.kt | 24 ++-- 3 files changed, 132 insertions(+), 114 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ExtractKotlinFunctionHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ExtractKotlinFunctionHandler.kt index 54e490fc0d3..e0ab956c2ff 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ExtractKotlinFunctionHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ExtractKotlinFunctionHandler.kt @@ -22,17 +22,10 @@ import com.intellij.psi.PsiFile import com.intellij.openapi.editor.Editor import com.intellij.psi.PsiElement import com.intellij.openapi.project.Project -import com.intellij.openapi.editor.ScrollType -import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils -import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtil -import com.intellij.refactoring.HelpID import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.KotlinExtractFunctionDialog import org.jetbrains.kotlin.psi.JetFile -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.psi.JetElement import com.intellij.openapi.application.ApplicationManager -import org.jetbrains.kotlin.psi.psiUtil.getOutermostParentContainedIn import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.psi.JetBlockExpression @@ -46,9 +39,9 @@ import com.intellij.ui.awt.RelativePoint import com.intellij.openapi.ui.popup.Balloon.Position import org.jetbrains.kotlin.psi.JetFunctionLiteral import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange -import org.jetbrains.kotlin.idea.refactoring.chooseContainerElementIfNecessary import org.jetbrains.kotlin.idea.refactoring.getExtractionContainers import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.* +import org.jetbrains.kotlin.idea.refactoring.introduce.* public open class ExtractKotlinFunctionHandlerHelper { open fun adjustExtractionData(data: ExtractionData): ExtractionData = data @@ -112,7 +105,7 @@ public class ExtractKotlinFunctionHandler( val message = analysisResult.messages.map { it.renderMessage() }.joinToString("\n") when (analysisResult.status) { Status.CRITICAL_ERROR -> { - showErrorHint(project, editor, message) + showErrorHint(project, editor, message, EXTRACT_FUNCTION) } Status.NON_CRITICAL_ERROR -> { @@ -141,12 +134,19 @@ public class ExtractKotlinFunctionHandler( } } + fun selectElements(editor: Editor, file: PsiFile, continuation: (elements: List, targetSibling: PsiElement) -> Unit) { + selectElements( + EXTRACT_FUNCTION, + editor, + file, + {(elements, parent) -> parent.getExtractionContainers(elements.size() == 1, allContainersEnabled) }, + continuation + ) + } + override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) { if (file !is JetFile) return - - selectElements(editor, file, allContainersEnabled) { (elements, targetSibling) -> - doInvoke(editor, file, elements, targetSibling) - } + selectElements(editor, file) { (elements, targetSibling) -> doInvoke(editor, file, elements, targetSibling) } } override fun invoke(project: Project, elements: Array, dataContext: DataContext?) { @@ -154,92 +154,4 @@ public class ExtractKotlinFunctionHandler( } } -private val EXTRACT_FUNCTION: String = JetRefactoringBundle.message("extract.function")!! - -private fun showErrorHint(project: Project, editor: Editor, message: String) { - CodeInsightUtils.showErrorHint(project, editor, message, EXTRACT_FUNCTION, HelpID.EXTRACT_METHOD) -} - -private fun showErrorHintByKey(project: Project, editor: Editor, key: String) { - showErrorHint(project, editor, JetRefactoringBundle.message(key)!!) -} - -fun selectElements( - editor: Editor, - file: PsiFile, - allContainersEnabled: Boolean = false, - continuation: (elements: List, targetSibling: PsiElement) -> Unit -) { - fun noExpressionError() { - showErrorHintByKey(file.getProject(), editor, "cannot.refactor.no.expression") - } - - fun noContainerError() { - showErrorHintByKey(file.getProject(), editor, "cannot.refactor.no.container") - } - - fun onSelectionComplete(parent: PsiElement, elements: List, targetContainer: JetElement) { - if (parent == targetContainer) { - continuation(elements, elements.first()) - return - } - - val outermostParent = parent.getOutermostParentContainedIn(targetContainer) - if (outermostParent == null) { - noContainerError() - return - } - - continuation(elements, outermostParent) - } - - fun selectTargetContainer(elements: List) { - val parent = PsiTreeUtil.findCommonParent(elements) - ?: throw AssertionError("Should have at least one parent: ${elements.joinToString("\n")}") - - val containers = parent.getExtractionContainers(elements.size() == 1, allContainersEnabled) - if (containers.isEmpty()) { - noContainerError() - return - } - - chooseContainerElementIfNecessary( - containers, - editor, - "Select target code block", - true, - { it }, - { onSelectionComplete(parent, elements, it) } - ) - } - - fun selectMultipleExpressions() { - val startOffset = editor.getSelectionModel().getSelectionStart() - val endOffset = editor.getSelectionModel().getSelectionEnd() - - val elements = CodeInsightUtils.findStatements(file, startOffset, endOffset) - if (elements.isEmpty()) { - noExpressionError() - return - } - - selectTargetContainer(elements.toList()) - } - - fun selectSingleExpression() { - JetRefactoringUtil.selectExpression(editor, file, false) { expr -> - if (expr != null) { - selectTargetContainer(listOf(expr)) - } - else { - if (!editor.getSelectionModel().hasSelection()) { - editor.getSelectionModel().selectLineAtCaret() - } - selectMultipleExpressions() - } - } - } - - editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE) - selectSingleExpression() -} +private val EXTRACT_FUNCTION: String = JetRefactoringBundle.message("extract.function") diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt new file mode 100644 index 00000000000..0b4dbbc45a8 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.refactoring.introduce + +import org.jetbrains.kotlin.psi.psiUtil.* +import org.jetbrains.kotlin.idea.refactoring.* +import com.intellij.openapi.editor.* +import com.intellij.psi.* +import com.intellij.psi.util.* +import org.jetbrains.kotlin.idea.codeInsight.* +import com.intellij.openapi.project.* + +fun showErrorHint(project: Project, editor: Editor, message: String, title: String) { + CodeInsightUtils.showErrorHint(project, editor, message, title, null) +} + +fun selectElements( + operationName: String, + editor: Editor, + file: PsiFile, + getContainers: (elements: List, commonParent: PsiElement) -> List, + continuation: (elements: List, targetSibling: PsiElement) -> Unit +) { + fun showErrorHintByKey(key: String) { + showErrorHint(file.getProject(), editor, JetRefactoringBundle.message(key), operationName) + } + + fun onSelectionComplete(parent: PsiElement, elements: List, targetContainer: PsiElement) { + if (parent == targetContainer) { + continuation(elements, elements.first()) + return + } + + val outermostParent = parent.getOutermostParentContainedIn(targetContainer) + if (outermostParent == null) { + showErrorHintByKey("cannot.refactor.no.container") + return + } + + continuation(elements, outermostParent) + } + + fun selectTargetContainer(elements: List) { + val parent = PsiTreeUtil.findCommonParent(elements) + ?: throw AssertionError("Should have at least one parent: ${elements.joinToString("\n")}") + + val containers = getContainers(elements, parent) + if (containers.isEmpty()) { + showErrorHintByKey("cannot.refactor.no.container") + return + } + + chooseContainerElementIfNecessary( + containers, + editor, + "Select target code block", + true, + { it }, + { onSelectionComplete(parent, elements, it) } + ) + } + + fun selectMultipleExpressions() { + val startOffset = editor.getSelectionModel().getSelectionStart() + val endOffset = editor.getSelectionModel().getSelectionEnd() + + val elements = CodeInsightUtils.findStatements(file, startOffset, endOffset) + if (elements.isEmpty()) { + showErrorHintByKey("cannot.refactor.no.expression") + return + } + + selectTargetContainer(elements.toList()) + } + + fun selectSingleExpression() { + JetRefactoringUtil.selectExpression(editor, file, false) { expr -> + if (expr != null) { + selectTargetContainer(listOf(expr)) + } + else { + if (!editor.getSelectionModel().hasSelection()) { + editor.getSelectionModel().selectLineAtCaret() + } + selectMultipleExpressions() + } + } + } + + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE) + selectSingleExpression() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt index 82558da76cd..2e0b6014076 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt @@ -21,7 +21,6 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ExtractKotlinFunctionHandler import java.io.File -import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.selectElements import org.jetbrains.kotlin.psi.JetTreeVisitorVoid import com.intellij.psi.PsiComment import com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException @@ -106,12 +105,11 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe val renderer = DescriptorRenderer.DEBUG_TEXT val editor = fixture.getEditor() - selectElements(editor, file) {(elements, previousSibling) -> - ExtractKotlinFunctionHandler( - helper = object : ExtractKotlinFunctionHandlerHelper() { - override fun adjustExtractionData(data: ExtractionData): ExtractionData { - return data.copy(options = extractionOptions) - } + val handler = ExtractKotlinFunctionHandler( + helper = object : ExtractKotlinFunctionHandlerHelper() { + override fun adjustExtractionData(data: ExtractionData): ExtractionData { + return data.copy(options = extractionOptions) + } override fun adjustGeneratorOptions(options: ExtractionGeneratorOptions): ExtractionGeneratorOptions { return options.copy(extractAsProperty = extractAsProperty) @@ -124,13 +122,15 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe it.getParameterTypeCandidates(extractionOptions.allowSpecialClassNames).map { renderer.renderType(it) }.joinToString(", ", "[", "]") }.joinToString() - assertEquals(expectedDescriptors, actualDescriptors, "Expected descriptors mismatch.") - assertEquals(expectedTypes, actualTypes, "Expected types mismatch.") + assertEquals(expectedDescriptors, actualDescriptors, "Expected descriptors mismatch.") + assertEquals(expectedTypes, actualTypes, "Expected types mismatch.") - return if (descriptor.name == "") descriptor.copy(name = "__dummyTestFun__") else descriptor - } + return if (descriptor.name == "") descriptor.copy(name = "__dummyTestFun__") else descriptor } - ).doInvoke(editor, file, elements, explicitPreviousSibling ?: previousSibling) + } + ) + handler.selectElements(editor, file) {(elements, previousSibling) -> + handler.doInvoke(editor, file, elements, explicitPreviousSibling ?: previousSibling) } } }