New J2K: do not use global write action for some post-processings which may use resolving while applying

Also, modify that post-processings & inspections to explicitly use write action
when modifying PSI elements

#KT-33875 fixed
This commit is contained in:
Ilya Kirillov
2019-09-18 20:28:16 +03:00
parent 74ba5b210a
commit 4e27d2e658
12 changed files with 148 additions and 65 deletions
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.nj2k.postProcessing
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.editor.RangeMarker
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
@@ -13,7 +12,6 @@ import com.intellij.psi.PsiRecursiveElementVisitor
import org.jetbrains.kotlin.idea.inspections.AbstractApplicabilityBasedInspection
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.j2k.ConverterSettings
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.psi.KtElement
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.idea.quickfix.AddConstModifierFix
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.references.readWriteAccess
import org.jetbrains.kotlin.idea.util.CommentSaver
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.j2k.ConverterSettings
import org.jetbrains.kotlin.lexer.KtTokens
@@ -127,13 +129,29 @@ class RemoveRedundantOverrideVisibilityProcessing :
}
}
class UseExpressionBodyProcessing : InspectionLikeProcessingForElement<KtPropertyAccessor>(KtPropertyAccessor::class) {
private val inspection = UseExpressionBodyInspection(convertEmptyToUnit = false)
override fun isApplicableTo(element: KtPropertyAccessor, settings: ConverterSettings?): Boolean =
inspection.isActiveFor(element)
class ReplaceGetterBodyWithSingleReturnStatementWithExpressionBody :
InspectionLikeProcessingForElement<KtPropertyAccessor>(KtPropertyAccessor::class) {
private fun KtPropertyAccessor.singleBodyStatementExpression() =
bodyBlockExpression?.statements
?.singleOrNull()
?.safeAs<KtReturnExpression>()
?.takeIf { it.labeledExpression == null }
?.returnedExpression
override fun isApplicableTo(element: KtPropertyAccessor, settings: ConverterSettings?): Boolean {
if (!element.isGetter) return false
return element.singleBodyStatementExpression() != null
}
override fun apply(element: KtPropertyAccessor) {
inspection.simplify(element, false)
val body = element.bodyExpression ?: return
val returnedExpression = element.singleBodyStatementExpression() ?: return
val commentSaver = CommentSaver(body)
element.addBefore(KtPsiFactory(element).createEQ(), body)
val newBody = body.replaced(returnedExpression)
commentSaver.restore(newBody)
}
}
@@ -156,13 +174,17 @@ class RemoveRedundantCastToNullableProcessing :
class RemoveRedundantSamAdaptersProcessing :
InspectionLikeProcessingForElement<KtCallExpression>(KtCallExpression::class) {
override val writeActionNeeded = false
override fun isApplicableTo(element: KtCallExpression, settings: ConverterSettings?): Boolean =
RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element).isNotEmpty()
override fun apply(element: KtCallExpression) {
RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element).forEach { call ->
RedundantSamConstructorInspection.replaceSamConstructorCall(call)
val callsToBeConverted = RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element)
runWriteAction {
for (call in callsToBeConverted) {
RedundantSamConstructorInspection.replaceSamConstructorCall(call)
}
}
}
}
@@ -6,8 +6,12 @@
package org.jetbrains.kotlin.nj2k
import com.intellij.psi.CommonClassNames
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.load.java.NULLABILITY_ANNOTATIONS
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtQualifiedExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
class ImportStorage {
private val imports = mutableSetOf<FqName>()
@@ -27,6 +31,16 @@ class ImportStorage {
return true
}
fun isImportNeededForCall(qualifiedExpression: KtQualifiedExpression): Boolean {
val shortName = qualifiedExpression.getCalleeExpressionIfAny()?.text ?: return true
if (shortName !in SHORT_NAMES) return true
val fqName = qualifiedExpression.selectorExpression?.mainReference?.resolve()?.getKotlinFqName() ?: return true
return isImportNeeded(fqName)
}
fun isImportNeeded(fqName: String): Boolean = isImportNeeded(FqName(fqName))
private val JAVA_TYPE_WRAPPERS_WHICH_HAVE_CONFLICTS_WITH_KOTLIN_ONES = setOf(
FqName(CommonClassNames.JAVA_LANG_BYTE),
FqName(CommonClassNames.JAVA_LANG_SHORT),
@@ -35,6 +49,9 @@ class ImportStorage {
FqName(CommonClassNames.JAVA_LANG_DOUBLE)
)
fun isImportNeeded(fqName: String): Boolean = isImportNeeded(FqName(fqName))
private val SHORT_NAMES =
(NULLABILITY_ANNOTATIONS + JAVA_TYPE_WRAPPERS_WHICH_HAVE_CONFLICTS_WITH_KOTLIN_ONES)
.map { it.shortName().asString() }
.toSet()
}
}