Extract Function: Add support of initializer expressions

This commit is contained in:
Alexey Sedunov
2014-06-26 18:50:22 +04:00
parent 026bc05a86
commit 0c49d48a48
30 changed files with 302 additions and 12 deletions
@@ -53,6 +53,11 @@ import com.intellij.openapi.ui.popup.Balloon.Position
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
import org.jetbrains.jet.lang.psi.JetDeclaration
import java.util.Collections
import org.jetbrains.jet.lang.psi.JetProperty
import org.jetbrains.jet.lang.psi.JetParameterList
import org.jetbrains.jet.lang.psi.JetClassInitializer
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression
import org.jetbrains.jet.lang.psi.JetFunctionLiteral
public class ExtractKotlinFunctionHandler(public val allContainersEnabled: Boolean = false) : RefactoringActionHandler {
fun doInvoke(
@@ -178,7 +183,13 @@ fun selectElements(
val declaration = element.getParentByType(javaClass<JetDeclaration>(), strict)
if (declaration == null) return Collections.emptyList()
val parent = declaration.getParent()
val parent = declaration.getParent()?.let {
when (it) {
is JetProperty -> it.getParent()
is JetParameterList -> it.getParent()?.getParent()
else -> it
}
}
return when (parent) {
is JetFile -> Collections.singletonList(parent)
is JetClassBody -> {
@@ -189,7 +200,13 @@ fun selectElements(
.dropWhile { it !is JetClassBody }
}
else -> {
val targetContainer = parent?.getParentByType(javaClass<JetDeclarationWithBody>())?.getBodyExpression()
val enclosingDeclaration =
PsiTreeUtil.getNonStrictParentOfType(parent, javaClass<JetDeclarationWithBody>(), javaClass<JetClassInitializer>())
val targetContainer = when (enclosingDeclaration) {
is JetDeclarationWithBody -> enclosingDeclaration.getBodyExpression()
is JetClassInitializer -> enclosingDeclaration.getBody()
else -> null
}
if (targetContainer is JetBlockExpression) Collections.singletonList(targetContainer) else Collections.emptyList()
}
}
@@ -49,6 +49,7 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
import org.jetbrains.jet.lang.psi.JetPsiFactory
import org.jetbrains.jet.lang.resolve.BindingContextUtils
import org.jetbrains.jet.lang.psi.JetFunctionLiteral
import org.jetbrains.jet.lang.psi.JetClassInitializer
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getResolvedCall
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
@@ -79,7 +80,9 @@ class ExtractionData(
) {
val project: Project = originalFile.getProject()
val insertBefore: Boolean = targetSibling.getParentByType(javaClass<JetDeclaration>(), true) is JetDeclarationWithBody
val insertBefore: Boolean = targetSibling.getParentByType(javaClass<JetDeclaration>(), true)?.let {
it is JetDeclarationWithBody || it is JetClassInitializer
} ?: false
fun getExpressions(): List<JetExpression> = originalElements.filterIsInstance(javaClass<JetExpression>())
@@ -541,17 +541,28 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(ErrorMessage.NO_EXPRESSION))
}
val noContainerError = AnalysisResult(null, Status.CRITICAL_ERROR, listOf(ErrorMessage.NO_CONTAINER))
val commonParent = PsiTreeUtil.findCommonParent(originalElements)!!
val enclosingDeclaration = commonParent.getParentByType(javaClass<JetDeclarationWithBody>())
if (enclosingDeclaration == null) {
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(ErrorMessage.NO_CONTAINER))
val enclosingDeclaration = commonParent.getParentByType(javaClass<JetDeclaration>(), true)
val bodyElement = when (enclosingDeclaration) {
is JetDeclarationWithBody -> enclosingDeclaration.getBodyExpression()
is JetWithExpressionInitializer -> enclosingDeclaration.getInitializer()
is JetParameter -> enclosingDeclaration.getDefaultValue()
is JetClassInitializer -> enclosingDeclaration.getBody()
is JetClass -> {
if (commonParent.isInsideOf(enclosingDeclaration.getDelegationSpecifiers())) enclosingDeclaration else return noContainerError
}
else -> return noContainerError
}
val bindingContext = originalFile.getLazyResolveSession().resolveToElement(bodyElement)
val resolveSession = originalFile.getLazyResolveSession()
val bindingContext = resolveSession.resolveToElement(enclosingDeclaration.getBodyExpression())
val pseudocode = PseudocodeUtil.generatePseudocode(enclosingDeclaration, bindingContext)
val pseudocodeDeclaration = PsiTreeUtil.getParentOfType(
commonParent, javaClass<JetDeclarationWithBody>(), javaClass<JetClassOrObject>()
) ?: commonParent.getParentByType(javaClass<JetProperty>())
?: return noContainerError
val pseudocode = PseudocodeUtil.generatePseudocode(pseudocodeDeclaration, bindingContext)
val localInstructions = getLocalInstructions(pseudocode)
val replacementMap = HashMap<Int, Replacement>()
@@ -587,7 +598,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
val functionNameValidator =
JetNameValidatorImpl(
targetSibling.getParent(),
targetSibling,
if (targetSibling is JetClassInitializer) targetSibling.getParent() else targetSibling,
JetNameValidatorImpl.Target.FUNCTIONS_AND_CLASSES
)
val functionName = JetNameSuggester.suggestNames(controlFlow.returnType, functionNameValidator, DEFAULT_FUNCTION_NAME).first()