Fix J2K to apply post convert intentions on EDT only
#KT-16754 fixed
This commit is contained in:
@@ -58,10 +58,6 @@ abstract class SelfTargetingIntention<TElement : PsiElement>(
|
||||
|
||||
abstract fun applyTo(element: TElement, editor: Editor?)
|
||||
|
||||
protected fun <R> 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)
|
||||
|
||||
+15
-1
@@ -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<PsiElement>()
|
||||
val results = converter.elementsToKotlin(inputElements).results
|
||||
val results =
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
ThrowableComputable<JavaToKotlinConverter.Result, Exception> {
|
||||
runReadAction { converter.elementsToKotlin(inputElements) }
|
||||
},
|
||||
JavaToKotlinAction.title,
|
||||
false,
|
||||
project
|
||||
).results
|
||||
|
||||
|
||||
val importsToAdd = LinkedHashSet<FqName>()
|
||||
|
||||
var resultIndex = 0
|
||||
|
||||
+2
-4
@@ -41,12 +41,10 @@ class IfThenToElvisInspection : IntentionBasedInspection<KtIfExpression>(
|
||||
{ it -> it.isUsedAsExpression(it.analyze(BodyResolveMode.PARTIAL)) }
|
||||
)
|
||||
|
||||
class IfThenToElvisIntention(private val fromJ2K: Boolean) : SelfTargetingOffsetIndependentIntention<KtIfExpression>(
|
||||
class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention<KtIfExpression>(
|
||||
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
|
||||
}
|
||||
|
||||
+3
-6
@@ -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<KtIfExpression>(IfThenToSafeAccessIntention::class)
|
||||
|
||||
class IfThenToSafeAccessIntention(private val fromJ2K: Boolean) : SelfTargetingOffsetIndependentIntention<KtIfExpression>(
|
||||
class IfThenToSafeAccessIntention : SelfTargetingOffsetIndependentIntention<KtIfExpression>(
|
||||
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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ActionData> {
|
||||
|
||||
Reference in New Issue
Block a user