diff --git a/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/MutableReplacementCode.kt b/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/MutableReplacementCode.kt index f8f57649746..8f90dfd4318 100644 --- a/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/MutableReplacementCode.kt +++ b/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/MutableReplacementCode.kt @@ -16,31 +16,40 @@ package org.jetbrains.kotlin.idea.replacement +import com.intellij.openapi.util.Key import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.core.copied import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.isAncestor -import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList -import java.util.* + +private val POST_INSERTION_ACTION: Key<(KtElement) -> Unit> = Key("POST_INSERTION_ACTION") internal class MutableReplacementCode( var mainExpression: KtExpression?, val statementsBefore: MutableList, val fqNamesToImport: MutableCollection ) { - private val _postInsertionActions = HashMap KtExpression>>() - - val postInsertionActions: Map KtExpression>> - get() = _postInsertionActions - - fun addPostInsertionAction(statementBefore: TStatement, action: (TStatement) -> TStatement) { - assert(statementBefore in statementsBefore) + fun addPostInsertionAction(element: TElement, action: (TElement) -> Unit) { + assert(element in this) @Suppress("UNCHECKED_CAST") - _postInsertionActions.getOrPut(statementBefore) { SmartList() }.add(action as (KtExpression) -> KtExpression) + element.putCopyableUserData(POST_INSERTION_ACTION, action as (KtElement) -> Unit) + } + + fun performPostInsertionActions(elements: Collection) { + for (element in elements) { + element.forEachDescendantOfType { + val action = it.getCopyableUserData(POST_INSERTION_ACTION) + if (action != null) { + it.putCopyableUserData(POST_INSERTION_ACTION, null) + action.invoke(it) + } + } + } } fun replaceExpression(oldExpression: KtExpression, newExpression: KtExpression): KtExpression { diff --git a/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/ReplacementPerformer.kt b/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/ReplacementPerformer.kt index 615e976320c..7bd8d7c2989 100644 --- a/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/ReplacementPerformer.kt +++ b/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/ReplacementPerformer.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf +import org.jetbrains.kotlin.utils.addToStdlib.singletonList import java.util.* internal abstract class ReplacementPerformer( @@ -45,6 +46,9 @@ internal class AnnotationEntryReplacementPerformer( val dummyAnnotationEntry = createByPattern("@Dummy($0)", replacement.mainExpression!!) { psiFactory.createAnnotationEntry(it) } val replaced = elementToBeReplaced.replace(dummyAnnotationEntry) + + replacement.performPostInsertionActions(replaced.singletonList()) + var range = PsiChildRange.singleElement(replaced) range = postProcessing(range) @@ -63,7 +67,6 @@ internal class ExpressionReplacementPerformer( override fun doIt(postProcessing: (PsiChildRange) -> PsiChildRange): KtExpression { val insertedStatements = ArrayList() - val toInsertedStatementMap = HashMap() for (statement in replacement.statementsBefore) { // copy the statement if it can get invalidated by findOrCreateBlockToInsertStatement() val statementToUse = if (statement.isPhysical) statement.copy() else statement @@ -73,16 +76,12 @@ internal class ExpressionReplacementPerformer( val inserted = block.addBefore(statementToUse, anchor) as KtExpression block.addBefore(psiFactory.createNewLine(), anchor) block.addBefore(psiFactory.createNewLine(), inserted) - toInsertedStatementMap.put(statement, inserted) insertedStatements.add(inserted) } val replaced = elementToBeReplaced.replace(replacement.mainExpression!!) //TODO: support null here - for ((statement, actions) in replacement.postInsertionActions) { - val inserted = toInsertedStatementMap[statement]!! - actions.forEach { it(inserted) } - } + replacement.performPostInsertionActions(insertedStatements + replaced.singletonList()) var range = if (insertedStatements.isEmpty()) { PsiChildRange.singleElement(replaced) diff --git a/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/introduceValue.kt b/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/introduceValue.kt index 2000f48671a..18136c3fb9a 100644 --- a/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/introduceValue.kt +++ b/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/introduceValue.kt @@ -91,7 +91,7 @@ internal fun MutableReplacementCode.introduceValue( val declaration = psiFactory.createDeclarationByPattern("val $0 = $1", name, value) statementsBefore.add(0, declaration) if (explicitType != null) { - addPostInsertionAction(declaration) { it.setType(explicitType!!); it } + addPostInsertionAction(declaration) { it.setType(explicitType!!) } } replaceUsages(name) @@ -123,7 +123,7 @@ internal fun MutableReplacementCode.introduceValue( appendFixedText("}") } - statementsBefore.clear() //TODO: postInsertActions! + statementsBefore.clear() } }