diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/SelfTargetingIntention.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/SelfTargetingIntention.kt index 229cca7352e..6cc257edcdd 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/SelfTargetingIntention.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/SelfTargetingIntention.kt @@ -58,10 +58,6 @@ abstract class SelfTargetingIntention( abstract fun applyTo(element: TElement, editor: Editor?) - protected fun runInWriteActionOrHere(inWriteAction: Boolean = true, action: () -> R): R = - if (inWriteAction) runWriteAction(action) - else run(action) - private fun getTarget(editor: Editor, file: PsiFile): TElement? { val offset = editor.caretModel.offset val leaf1 = file.findElementAt(offset) diff --git a/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt index 84c566b3f88..39273779a0b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt @@ -21,12 +21,15 @@ import com.intellij.codeInsight.editorActions.TextBlockTransferableData import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.RangeMarker +import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.openapi.util.Ref import com.intellij.openapi.util.TextRange +import com.intellij.openapi.util.ThrowableComputable import com.intellij.psi.* import org.jetbrains.annotations.TestOnly +import org.jetbrains.kotlin.idea.actions.JavaToKotlinAction import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference import org.jetbrains.kotlin.idea.codeInsight.KotlinCopyPasteReferenceProcessor import org.jetbrains.kotlin.idea.codeInsight.KotlinReferenceData @@ -34,6 +37,7 @@ import org.jetbrains.kotlin.idea.editor.KotlinEditorOptions import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor import org.jetbrains.kotlin.idea.util.ImportInsertHelper +import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.j2k.AfterConversionPass import org.jetbrains.kotlin.j2k.ConverterSettings @@ -212,7 +216,17 @@ internal fun ElementAndTextList.convertCodeToKotlin(project: Project): Conversio ) val inputElements = this.toList().filterIsInstance() - val results = converter.elementsToKotlin(inputElements).results + val results = + ProgressManager.getInstance().runProcessWithProgressSynchronously( + ThrowableComputable { + runReadAction { converter.elementsToKotlin(inputElements) } + }, + JavaToKotlinAction.title, + false, + project + ).results + + val importsToAdd = LinkedHashSet() var resultIndex = 0 diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToElvisIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToElvisIntention.kt index 925c07a428e..ac43b480249 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToElvisIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToElvisIntention.kt @@ -41,12 +41,10 @@ class IfThenToElvisInspection : IntentionBasedInspection( { it -> it.isUsedAsExpression(it.analyze(BodyResolveMode.PARTIAL)) } ) -class IfThenToElvisIntention(private val fromJ2K: Boolean) : SelfTargetingOffsetIndependentIntention( +class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention( KtIfExpression::class.java, "Replace 'if' expression with elvis expression" ) { - @Suppress("unused") - constructor(): this(fromJ2K = false) private fun KtExpression.clausesReplaceableByElvis(firstClause: KtExpression, secondClause: KtExpression, context: BindingContext) = !firstClause.isNullOrBlockExpression() && @@ -147,7 +145,7 @@ class IfThenToElvisIntention(private val fromJ2K: Boolean) : SelfTargetingOffset it.typeReference!!) } val checkedExpression = condition.checkedExpression()!! - val elvis = runInWriteActionOrHere(inWriteAction = !fromJ2K) { + val elvis = runWriteAction { val replacedLeft = if (left.evaluatesTo(checkedExpression)) { if (condition is KtIsExpression) newReceiver!! else left } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToSafeAccessIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToSafeAccessIntention.kt index 651bbbfe701..fe360dd4da0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToSafeAccessIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToSafeAccessIntention.kt @@ -21,16 +21,15 @@ import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.intentions.SelfTargetingOffsetIndependentIntention import org.jetbrains.kotlin.idea.intentions.branchedTransformations.* +import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* class IfThenToSafeAccessInspection : IntentionBasedInspection(IfThenToSafeAccessIntention::class) -class IfThenToSafeAccessIntention(private val fromJ2K: Boolean) : SelfTargetingOffsetIndependentIntention( +class IfThenToSafeAccessIntention : SelfTargetingOffsetIndependentIntention( KtIfExpression::class.java, "Replace 'if' expression with safe access expression" ) { - @Suppress("unused") - constructor(): this(fromJ2K = false) override fun isApplicableTo(element: KtIfExpression): Boolean { val condition = element.condition as? KtBinaryExpression ?: return false @@ -70,9 +69,7 @@ class IfThenToSafeAccessIntention(private val fromJ2K: Boolean) : SelfTargetingO } val newExpr = KtPsiFactory(element).createExpressionByPattern("$0?.$1", receiverExpression, selectorExpression) as KtSafeQualifiedExpression - val safeAccessExpr = runInWriteActionOrHere(inWriteAction = !fromJ2K) { - element.replaced(newExpr) - } + val safeAccessExpr = runWriteAction { element.replaced(newExpr) } if (editor != null) { safeAccessExpr.inlineReceiverIfApplicableWithPrompt(editor) diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt index 44d8fafcf6b..52344b5f529 100644 --- a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.idea.intentions.conventionNameCalls.ReplaceGetOrSetI import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix import org.jetbrains.kotlin.idea.quickfix.RemoveUselessCastFix import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType @@ -69,8 +70,8 @@ object J2KPostProcessingRegistrar { _processings.add(RemoveRedundantCastToNullableProcessing()) registerIntentionBasedProcessing(ConvertToExpressionBodyIntention(convertEmptyToUnit = false)) { it is KtPropertyAccessor } - registerIntentionBasedProcessing(IfThenToSafeAccessIntention(fromJ2K = true)) - registerIntentionBasedProcessing(IfThenToElvisIntention(fromJ2K = true)) + registerIntentionBasedProcessing(IfThenToSafeAccessIntention()) + registerIntentionBasedProcessing(IfThenToElvisIntention()) registerIntentionBasedProcessing(FoldInitializerAndIfToElvisIntention()) registerIntentionBasedProcessing(SimplifyNegatedBinaryExpressionIntention()) registerIntentionBasedProcessing(ReplaceGetOrSetIntention(), additionalChecker = ReplaceGetOrSetInspection.additionalChecker) @@ -136,7 +137,12 @@ object J2KPostProcessingRegistrar { if (!additionalChecker(tElement)) return null return { if (intention.applicabilityRange(tElement) != null) { // check availability of the intention again because something could change - intention.applyTo(element, null) + val apply = { intention.applyTo(element, null) } + + if (intention.startInWriteAction()) + runWriteAction(apply) + else + apply() } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessor.kt index 8979174b550..4edd1435173 100644 --- a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessor.kt @@ -16,15 +16,21 @@ package org.jetbrains.kotlin.idea.j2k +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.RangeMarker import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import com.intellij.psi.PsiRecursiveElementVisitor import com.intellij.psi.codeStyle.CodeStyleManager +import kotlinx.coroutines.experimental.run +import kotlinx.coroutines.experimental.runBlocking import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference import org.jetbrains.kotlin.idea.conversion.copy.range +import org.jetbrains.kotlin.idea.core.util.EDT import org.jetbrains.kotlin.idea.util.ImportInsertHelper +import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.j2k.PostProcessor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtElement @@ -35,8 +41,12 @@ import java.util.* class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor { override fun insertImport(file: KtFile, fqName: FqName) { - val descriptors = file.resolveImportReference(fqName) - descriptors.firstOrNull()?.let { ImportInsertHelper.getInstance(file.project).importDescriptor(file, it) } + ApplicationManager.getApplication().invokeAndWait { + runWriteAction { + val descriptors = file.resolveImportReference(fqName) + descriptors.firstOrNull()?.let { ImportInsertHelper.getInstance(file.project).importDescriptor(file, it) } + } + } } private enum class RangeFilterResult { @@ -45,39 +55,48 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor { PROCESS } - override fun doAdditionalProcessing(file: KtFile, rangeMarker: RangeMarker?) { - var elementToActions = collectAvailableActions(file, rangeMarker) - - while (elementToActions.isNotEmpty()) { + override fun doAdditionalProcessing(file: KtFile, rangeMarker: RangeMarker?) = runBlocking { + do { var modificationStamp: Long? = file.modificationStamp + val elementToActions = runReadAction { + collectAvailableActions(file, rangeMarker) + } - for ((element, action, _) in elementToActions) { - if (element.isValid) { - action() - } - else { - modificationStamp = null + run(EDT) { + for ((element, action, _) in elementToActions) { + if (element.isValid) { + action() + } + else { + modificationStamp = null + } } } if (modificationStamp == file.modificationStamp) break - - elementToActions = collectAvailableActions(file, rangeMarker) } + while (elementToActions.isNotEmpty()) + if (formatCode) { - val codeStyleManager = CodeStyleManager.getInstance(file.project) - if (rangeMarker != null) { - if (rangeMarker.isValid) { - codeStyleManager.reformatRange(file, rangeMarker.startOffset, rangeMarker.endOffset) + run(EDT) { + runWriteAction { + val codeStyleManager = CodeStyleManager.getInstance(file.project) + if (rangeMarker != null) { + if (rangeMarker.isValid) { + codeStyleManager.reformatRange(file, rangeMarker.startOffset, rangeMarker.endOffset) + } + } + else { + codeStyleManager.reformat(file) + } + Unit } } - else { - codeStyleManager.reformat(file) - } } } + private data class ActionData(val element: KtElement, val action: () -> Unit, val priority: Int) private fun collectAvailableActions(file: KtFile, rangeMarker: RangeMarker?): List {