J2K: use refactorings and runWriteAction more accurately #KT-19371 Fixed

Do not invoke runWriteAction for post-processings
in Convert(Text)JavaCopyPasteProcessor.
Instead each processing can need write action or not,
and J2kPostProcessor takes this into account.
This commit is contained in:
Mikhail Glukhikh
2017-08-01 16:41:09 +03:00
parent 8d5e69b06c
commit 4ca8d3d6cf
4 changed files with 58 additions and 26 deletions
@@ -153,12 +153,10 @@ class ConvertJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransferab
val newBounds = insertImports(boundsAfterReplace, referenceData, explicitImports) val newBounds = insertImports(boundsAfterReplace, referenceData, explicitImports)
runWriteAction { PsiDocumentManager.getInstance(project).commitAllDocuments()
PsiDocumentManager.getInstance(project).commitAllDocuments() AfterConversionPass(project, J2kPostProcessor(formatCode = true)).run(targetFile, newBounds)
AfterConversionPass(project, J2kPostProcessor(formatCode = true)).run(targetFile, newBounds)
conversionPerformed = true conversionPerformed = true
}
} }
} }
@@ -111,7 +111,7 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
val convertedText = dataForConversion.convertCodeToKotlin(project).text val convertedText = dataForConversion.convertCodeToKotlin(project).text
runWriteAction { val newBounds = runWriteAction {
val importsInsertOffset = targetFile.importList?.endOffset ?: 0 val importsInsertOffset = targetFile.importList?.endOffset ?: 0
if (targetFile.importDirectives.isEmpty() && importsInsertOffset > 0) if (targetFile.importDirectives.isEmpty() && importsInsertOffset > 0)
@@ -125,14 +125,13 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
val endOffsetAfterCopy = startOffset + convertedText.length val endOffsetAfterCopy = startOffset + convertedText.length
editor.caretModel.moveToOffset(endOffsetAfterCopy) editor.caretModel.moveToOffset(endOffsetAfterCopy)
val newBounds = TextRange(startOffset, startOffset + convertedText.length) TextRange(startOffset, startOffset + convertedText.length)
psiDocumentManager.commitAllDocuments()
AfterConversionPass(project, J2kPostProcessor(formatCode = true)).run(targetFile, newBounds)
conversionPerformed = true
} }
psiDocumentManager.commitAllDocuments()
AfterConversionPass(project, J2kPostProcessor(formatCode = true)).run(targetFile, newBounds)
conversionPerformed = true
} }
private fun DataForConversion.convertCodeToKotlin(project: Project): ConversionResult { private fun DataForConversion.convertCodeToKotlin(project: Project): ConversionResult {
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
import org.jetbrains.kotlin.idea.quickfix.RemoveUselessCastFix import org.jetbrains.kotlin.idea.quickfix.RemoveUselessCastFix
import org.jetbrains.kotlin.idea.refactoring.inline.KotlinInlineValHandler import org.jetbrains.kotlin.idea.refactoring.inline.KotlinInlineValHandler
import org.jetbrains.kotlin.idea.references.mainReference 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.lexer.KtTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
@@ -57,6 +56,8 @@ import java.util.*
interface J2kPostProcessing { interface J2kPostProcessing {
fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)?
val writeActionNeeded: Boolean
} }
object J2KPostProcessingRegistrar { object J2KPostProcessingRegistrar {
@@ -67,9 +68,7 @@ object J2KPostProcessingRegistrar {
private val processingsToPriorityMap = HashMap<J2kPostProcessing, Int>() private val processingsToPriorityMap = HashMap<J2kPostProcessing, Int>()
fun priority(processing: J2kPostProcessing): Int { fun priority(processing: J2kPostProcessing): Int = processingsToPriorityMap[processing]!!
return processingsToPriorityMap[processing]!!
}
init { init {
_processings.add(RemoveExplicitTypeArgumentsProcessing()) _processings.add(RemoveExplicitTypeArgumentsProcessing())
@@ -153,6 +152,9 @@ object J2KPostProcessingRegistrar {
noinline additionalChecker: (TElement) -> Boolean = { true } noinline additionalChecker: (TElement) -> Boolean = { true }
) { ) {
_processings.add(object : J2kPostProcessing { _processings.add(object : J2kPostProcessing {
// Intention can either need or not need write action
override val writeActionNeeded = intention.startInWriteAction()
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (!TElement::class.java.isInstance(element)) return null if (!TElement::class.java.isInstance(element)) return null
val tElement = element as TElement val tElement = element as TElement
@@ -161,11 +163,7 @@ object J2KPostProcessingRegistrar {
return { return {
if (intention.applicabilityRange(tElement) != null) { // check availability of the intention again because something could change if (intention.applicabilityRange(tElement) != null) { // check availability of the intention again because something could change
val apply = { intention.applyTo(element, null) } val apply = { intention.applyTo(element, null) }
apply()
if (intention.startInWriteAction())
runWriteAction(apply)
else
apply()
} }
} }
} }
@@ -184,6 +182,9 @@ object J2KPostProcessingRegistrar {
crossinline fixFactory: (TElement, Diagnostic) -> (() -> Unit)? crossinline fixFactory: (TElement, Diagnostic) -> (() -> Unit)?
) { ) {
_processings.add(object : J2kPostProcessing { _processings.add(object : J2kPostProcessing {
// ???
override val writeActionNeeded = true
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (!TElement::class.java.isInstance(element)) return null if (!TElement::class.java.isInstance(element)) return null
val diagnostic = diagnostics.forElement(element).firstOrNull { it.factory in diagnosticFactory } ?: return null val diagnostic = diagnostics.forElement(element).firstOrNull { it.factory in diagnosticFactory } ?: return null
@@ -193,6 +194,8 @@ object J2KPostProcessingRegistrar {
} }
private class RemoveExplicitTypeArgumentsProcessing : J2kPostProcessing { private class RemoveExplicitTypeArgumentsProcessing : J2kPostProcessing {
override val writeActionNeeded = true
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (element !is KtTypeArgumentList || !RemoveExplicitTypeArgumentsIntention.isApplicableTo(element, approximateFlexible = true)) return null if (element !is KtTypeArgumentList || !RemoveExplicitTypeArgumentsIntention.isApplicableTo(element, approximateFlexible = true)) return null
@@ -205,6 +208,8 @@ object J2KPostProcessingRegistrar {
} }
private class RemoveRedundantOverrideVisibilityProcessing : J2kPostProcessing { private class RemoveRedundantOverrideVisibilityProcessing : J2kPostProcessing {
override val writeActionNeeded = true
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (element !is KtCallableDeclaration || !element.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return null if (element !is KtCallableDeclaration || !element.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return null
val modifier = element.visibilityModifierType() ?: return null val modifier = element.visibilityModifierType() ?: return null
@@ -213,6 +218,8 @@ object J2KPostProcessingRegistrar {
} }
private class MoveLambdaOutsideParenthesesProcessing : J2kPostProcessing { private class MoveLambdaOutsideParenthesesProcessing : J2kPostProcessing {
override val writeActionNeeded = true
private val intention = MoveLambdaOutsideParenthesesIntention() private val intention = MoveLambdaOutsideParenthesesIntention()
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
@@ -224,6 +231,8 @@ object J2KPostProcessingRegistrar {
} }
private class ConvertToStringTemplateProcessing : J2kPostProcessing { private class ConvertToStringTemplateProcessing : J2kPostProcessing {
override val writeActionNeeded = true
private val intention = ConvertToStringTemplateIntention() private val intention = ConvertToStringTemplateIntention()
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
@@ -237,6 +246,8 @@ object J2KPostProcessingRegistrar {
} }
private class UsePropertyAccessSyntaxProcessing : J2kPostProcessing { private class UsePropertyAccessSyntaxProcessing : J2kPostProcessing {
override val writeActionNeeded = true
private val intention = UsePropertyAccessSyntaxIntention() private val intention = UsePropertyAccessSyntaxIntention()
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
@@ -247,6 +258,8 @@ object J2KPostProcessingRegistrar {
} }
private class RemoveRedundantSamAdaptersProcessing : J2kPostProcessing { private class RemoveRedundantSamAdaptersProcessing : J2kPostProcessing {
override val writeActionNeeded = true
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (element !is KtCallExpression) return null if (element !is KtCallExpression) return null
@@ -261,6 +274,8 @@ object J2KPostProcessingRegistrar {
} }
private class UseExpressionBodyProcessing : J2kPostProcessing { private class UseExpressionBodyProcessing : J2kPostProcessing {
override val writeActionNeeded = true
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (element !is KtPropertyAccessor) return null if (element !is KtPropertyAccessor) return null
@@ -274,6 +289,9 @@ object J2KPostProcessingRegistrar {
} }
private class UnnecessaryVariableProcessing : J2kPostProcessing { private class UnnecessaryVariableProcessing : J2kPostProcessing {
// Refactoring
override val writeActionNeeded = false
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (element !is KtProperty) return null if (element !is KtProperty) return null
@@ -286,6 +304,8 @@ object J2KPostProcessingRegistrar {
} }
private class RemoveRedundantCastToNullableProcessing : J2kPostProcessing { private class RemoveRedundantCastToNullableProcessing : J2kPostProcessing {
override val writeActionNeeded = true
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (element !is KtBinaryExpressionWithTypeRHS) return null if (element !is KtBinaryExpressionWithTypeRHS) return null
@@ -305,6 +325,8 @@ object J2KPostProcessingRegistrar {
} }
private class FixObjectStringConcatenationProcessing : J2kPostProcessing { private class FixObjectStringConcatenationProcessing : J2kPostProcessing {
override val writeActionNeeded = true
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (element !is KtBinaryExpression || if (element !is KtBinaryExpression ||
element.operationToken != KtTokens.PLUS || element.operationToken != KtTokens.PLUS ||
@@ -332,6 +354,8 @@ object J2KPostProcessingRegistrar {
} }
private class UninitializedVariableReferenceFromInitializerToThisReferenceProcessing : J2kPostProcessing { private class UninitializedVariableReferenceFromInitializerToThisReferenceProcessing : J2kPostProcessing {
override val writeActionNeeded = true
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (element !is KtSimpleNameExpression || diagnostics.forElement(element).none { it.factory == Errors.UNINITIALIZED_VARIABLE }) return null if (element !is KtSimpleNameExpression || diagnostics.forElement(element).none { it.factory == Errors.UNINITIALIZED_VARIABLE }) return null
@@ -350,6 +374,8 @@ object J2KPostProcessingRegistrar {
} }
private class UnresolvedVariableReferenceFromInitializerToThisReferenceProcessing : J2kPostProcessing { private class UnresolvedVariableReferenceFromInitializerToThisReferenceProcessing : J2kPostProcessing {
override val writeActionNeeded = true
override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? {
if (element !is KtSimpleNameExpression || diagnostics.forElement(element).none { it.factory == Errors.UNRESOLVED_REFERENCE }) return null if (element !is KtSimpleNameExpression || diagnostics.forElement(element).none { it.factory == Errors.UNRESOLVED_REFERENCE }) return null
@@ -65,9 +65,16 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
} }
run(EDT) { run(EDT) {
for ((element, action, _) in elementToActions) { for ((element, action, _, writeActionNeeded) in elementToActions) {
if (element.isValid) { if (element.isValid) {
action() if (writeActionNeeded) {
runWriteAction {
action()
}
}
else {
action()
}
} }
else { else {
modificationStamp = null modificationStamp = null
@@ -99,7 +106,7 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
} }
private data class ActionData(val element: KtElement, val action: () -> Unit, val priority: Int) private data class ActionData(val element: KtElement, val action: () -> Unit, val priority: Int, val writeActionNeeded: Boolean)
private fun collectAvailableActions(file: KtFile, rangeMarker: RangeMarker?): List<ActionData> { private fun collectAvailableActions(file: KtFile, rangeMarker: RangeMarker?): List<ActionData> {
val diagnostics = analyzeFileRange(file, rangeMarker) val diagnostics = analyzeFileRange(file, rangeMarker)
@@ -118,7 +125,9 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
J2KPostProcessingRegistrar.processings.forEach { processing -> J2KPostProcessingRegistrar.processings.forEach { processing ->
val action = processing.createAction(element, diagnostics) val action = processing.createAction(element, diagnostics)
if (action != null) { if (action != null) {
availableActions.add(ActionData(element, action, J2KPostProcessingRegistrar.priority(processing))) availableActions.add(ActionData(element, action,
J2KPostProcessingRegistrar.priority(processing),
processing.writeActionNeeded))
} }
} }
} }