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
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
import org.jetbrains.kotlin.idea.imports.getImportableTargets import org.jetbrains.kotlin.idea.imports.getImportableTargets
import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.idea.util.*
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.psi.psiUtil.*
@@ -207,20 +208,24 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
processors.forEach { it.analyzeCollectedElements(bindingContext) } processors.forEach { it.analyzeCollectedElements(bindingContext) }
// step 3: shorten elements that can be shortened right now // step 3: shorten elements that can be shortened right now
processors.forEach { it.shortenElements(elementSetToUpdate = elementsToUse, options = options) } runWriteAction {
processors.forEach { it.shortenElements(elementSetToUpdate = elementsToUse, options = options) }
}
// step 4: try to import descriptors needed to shorten other elements // step 4: try to import descriptors needed to shorten other elements
val descriptorsToImport = processors.flatMap { it.getDescriptorsToImport() }.toSet() val descriptorsToImport = processors.flatMap { it.getDescriptorsToImport() }.toSet()
var anyChange = false var anyChange = false
for (descriptor in descriptorsToImport) { runWriteAction {
assert(descriptor !in failedToImportDescriptors) for (descriptor in descriptorsToImport) {
assert(descriptor !in failedToImportDescriptors)
val result = helper.importDescriptor(file, descriptor) val result = helper.importDescriptor(file, descriptor)
if (result != ImportDescriptorResult.ALREADY_IMPORTED) { if (result != ImportDescriptorResult.ALREADY_IMPORTED) {
anyChange = true anyChange = true
} }
if (result == ImportDescriptorResult.FAIL) { if (result == ImportDescriptorResult.FAIL) {
failedToImportDescriptors.add(descriptor) failedToImportDescriptors.add(descriptor)
}
} }
} }
if (!anyChange) break if (!anyChange) break
@@ -9,6 +9,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.nameIdentifierTextRangeInThis import org.jetbrains.kotlin.idea.util.nameIdentifierTextRangeInThis
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
@@ -28,8 +29,11 @@ class AddOperatorModifierInspection : AbstractApplicabilityBasedInspection<KtNam
} }
override fun applyTo(element: KtNamedFunction, project: Project, editor: Editor?) { override fun applyTo(element: KtNamedFunction, project: Project, editor: Editor?) {
for (declaration in element.withExpectedActuals()) { val declarations = element.withExpectedActuals()
declaration.addModifier(KtTokens.OPERATOR_KEYWORD) runWriteAction {
for (declaration in declarations) {
declaration.addModifier(KtTokens.OPERATOR_KEYWORD)
}
} }
} }
} }
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.expressionCo
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.fromIfKeywordToRightParenthesisTextRangeInThis import org.jetbrains.kotlin.idea.intentions.branchedTransformations.fromIfKeywordToRightParenthesisTextRangeInThis
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.shouldBeTransformed import org.jetbrains.kotlin.idea.intentions.branchedTransformations.shouldBeTransformed
import org.jetbrains.kotlin.idea.util.CommentSaver import org.jetbrains.kotlin.idea.util.CommentSaver
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.hasComments import org.jetbrains.kotlin.idea.util.hasComments
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -86,19 +87,21 @@ class FoldInitializerAndIfToElvisInspection : AbstractApplicabilityBasedInspecti
val pattern = elvisPattern(declaration.textLength + ifNullExpr.textLength + 5 >= margin || element.then?.hasComments() == true) val pattern = elvisPattern(declaration.textLength + ifNullExpr.textLength + 5 >= margin || element.then?.hasComments() == true)
val elvis = factory.createExpressionByPattern(pattern, initializer, ifNullExpr) as KtBinaryExpression val elvis = factory.createExpressionByPattern(pattern, initializer, ifNullExpr) as KtBinaryExpression
if (typeReference != null) {
elvis.left!!.replace(factory.createExpressionByPattern("$0 as? $1", initializer, typeReference)) return runWriteAction {
if (typeReference != null) {
elvis.left!!.replace(factory.createExpressionByPattern("$0 as? $1", initializer, typeReference))
}
val newElvis = initializer.replaced(elvis)
element.delete()
if (explicitTypeToSet != null && !explicitTypeToSet.isError) {
declaration.setType(explicitTypeToSet)
}
commentSaver.restore(childRangeAfter)
newElvis
} }
val newElvis = initializer.replaced(elvis)
element.delete()
if (explicitTypeToSet != null && !explicitTypeToSet.isError) {
declaration.setType(explicitTypeToSet)
}
commentSaver.restore(childRangeAfter)
return newElvis
} }
private fun calcData(ifExpression: KtIfExpression): Data? { private fun calcData(ifExpression: KtIfExpression): Data? {
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
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.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
@@ -47,7 +48,10 @@ open class ConvertToStringTemplateIntention : SelfTargetingOffsetIndependentInte
} }
override fun applyTo(element: KtBinaryExpression, editor: Editor?) { override fun applyTo(element: KtBinaryExpression, editor: Editor?) {
element.replaced(buildReplacement(element)) val replacement = buildReplacement(element)
runWriteAction {
element.replaced(replacement)
}
} }
companion object { companion object {
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.core.isVisible
import org.jetbrains.kotlin.idea.findUsages.ReferencesSearchScopeHelper import org.jetbrains.kotlin.idea.findUsages.ReferencesSearchScopeHelper
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -89,9 +90,12 @@ class DestructureIntention : SelfTargetingRangeIntention<KtDeclaration>(
else { else {
name ?: KotlinNameSuggester.suggestNameByName(descriptor.name.asString(), validator) name ?: KotlinNameSuggester.suggestNameByName(descriptor.name.asString(), validator)
} }
variableToDrop?.delete()
usagesToReplace.forEach { runWriteAction {
it.replace(factory.createExpression(suggestedName)) variableToDrop?.delete()
usagesToReplace.forEach {
it.replace(factory.createExpression(suggestedName))
}
} }
names.add(suggestedName) names.add(suggestedName)
} }
@@ -100,31 +104,42 @@ class DestructureIntention : SelfTargetingRangeIntention<KtDeclaration>(
when (element) { when (element) {
is KtParameter -> { is KtParameter -> {
val loopRange = (element.parent as? KtForExpression)?.loopRange val loopRange = (element.parent as? KtForExpression)?.loopRange
element.replace(factory.createDestructuringParameter("($joinedNames)")) runWriteAction {
if (removeSelectorInLoopRange && loopRange is KtDotQualifiedExpression) { element.replace(factory.createDestructuringParameter("($joinedNames)"))
loopRange.replace(loopRange.receiverExpression) if (removeSelectorInLoopRange && loopRange is KtDotQualifiedExpression) {
loopRange.replace(loopRange.receiverExpression)
}
} }
} }
is KtFunctionLiteral -> { is KtFunctionLiteral -> {
val lambda = element.parent as KtLambdaExpression val lambda = element.parent as KtLambdaExpression
SpecifyExplicitLambdaSignatureIntention().applyTo(lambda, editor) SpecifyExplicitLambdaSignatureIntention().applyTo(lambda, editor)
lambda.functionLiteral.valueParameters.singleOrNull()?.replace( runWriteAction {
lambda.functionLiteral.valueParameters.singleOrNull()?.replace(
factory.createDestructuringParameter("($joinedNames)") factory.createDestructuringParameter("($joinedNames)")
) )
}
} }
is KtVariableDeclaration -> { is KtVariableDeclaration -> {
val rangeAfterEq = PsiChildRange(element.initializer, element.lastChild) val rangeAfterEq = PsiChildRange(element.initializer, element.lastChild)
val modifierList = element.modifierList val modifierList = element.modifierList
if (modifierList == null) { runWriteAction {
element.replace(factory.createDestructuringDeclarationByPattern( if (modifierList == null) {
"val ($joinedNames) = $0", rangeAfterEq)) element.replace(
} factory.createDestructuringDeclarationByPattern(
else { "val ($joinedNames) = $0", rangeAfterEq
val rangeBeforeVal = PsiChildRange(element.firstChild, modifierList) )
element.replace(factory.createDestructuringDeclarationByPattern( )
"$0:'@xyz' val ($joinedNames) = $1", rangeBeforeVal, rangeAfterEq)) } else {
val rangeBeforeVal = PsiChildRange(element.firstChild, modifierList)
element.replace(
factory.createDestructuringDeclarationByPattern(
"$0:'@xyz' val ($joinedNames) = $1", rangeBeforeVal, rangeAfterEq
)
)
}
} }
} }
} }
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.inspections.RedundantSamConstructorInspection import org.jetbrains.kotlin.idea.inspections.RedundantSamConstructorInspection
import org.jetbrains.kotlin.idea.util.CommentSaver import org.jetbrains.kotlin.idea.util.CommentSaver
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -157,21 +158,22 @@ class ObjectLiteralToLambdaIntention : SelfTargetingRangeIntention<KtObjectLiter
appendFixedText("}") appendFixedText("}")
} }
val replaced = element.replaced(newExpression) val replaced = runWriteAction { element.replaced(newExpression) }
val callee = replaced.getCalleeExpressionIfAny()!! as KtNameReferenceExpression val callee = replaced.getCalleeExpressionIfAny()!! as KtNameReferenceExpression
val callExpression = callee.parent as KtCallExpression val callExpression = callee.parent as KtCallExpression
val functionLiteral = callExpression.lambdaArguments.single().getLambdaExpression()!! val functionLiteral = callExpression.lambdaArguments.single().getLambdaExpression()!!
val returnLabel = callee.getReferencedNameAsName() val returnLabel = callee.getReferencedNameAsName()
returnSaver.restore(functionLiteral, returnLabel) runWriteAction {
commentSaver.restore(replaced, forceAdjustIndent = true/* by some reason lambda body is sometimes not properly indented */) returnSaver.restore(functionLiteral, returnLabel)
commentSaver.restore(replaced, forceAdjustIndent = true/* by some reason lambda body is sometimes not properly indented */)
}
val parentCall = ((replaced.parent as? KtValueArgument) val parentCall = ((replaced.parent as? KtValueArgument)
?.parent as? KtValueArgumentList) ?.parent as? KtValueArgumentList)
?.parent as? KtCallExpression ?.parent as? KtCallExpression
if (parentCall != null && RedundantSamConstructorInspection.samConstructorCallsToBeConverted(parentCall).singleOrNull() == callExpression) { if (parentCall != null && RedundantSamConstructorInspection.samConstructorCallsToBeConverted(parentCall).singleOrNull() == callExpression) {
RedundantSamConstructorInspection.replaceSamConstructorCall(callExpression) RedundantSamConstructorInspection.replaceSamConstructorCall(callExpression)
if (parentCall.canMoveLambdaOutsideParentheses()) { if (parentCall.canMoveLambdaOutsideParentheses()) runWriteAction {
parentCall.moveFunctionLiteralOutsideParentheses() parentCall.moveFunctionLiteralOutsideParentheses()
} }
} }
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.KtFunctionLiteral import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.psi.KtLambdaExpression import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtParameterList import org.jetbrains.kotlin.psi.KtParameterList
@@ -85,8 +86,10 @@ open class SpecifyExplicitLambdaSignatureIntention : SelfTargetingOffsetIndepend
val psiFactory = KtPsiFactory(element) val psiFactory = KtPsiFactory(element)
val functionLiteral = element.functionLiteral val functionLiteral = element.functionLiteral
val newParameterList = psiFactory.createLambdaParameterListIfAny(parameterString) val newParameterList = psiFactory.createLambdaParameterListIfAny(parameterString)
functionLiteral.setParameterListIfAny(psiFactory, newParameterList) runWriteAction {
ShortenReferences.DEFAULT.process(element.valueParameters) functionLiteral.setParameterListIfAny(psiFactory, newParameterList)
ShortenReferences.DEFAULT.process(element.valueParameters)
}
} }
} }
} }
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.resolve.frontendService import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.idea.util.shouldNotConvertToProperty import org.jetbrains.kotlin.idea.util.shouldNotConvertToProperty
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
@@ -131,7 +132,10 @@ class UsePropertyAccessSyntaxIntention :
} }
override fun applyTo(element: KtCallExpression, editor: Editor?) { override fun applyTo(element: KtCallExpression, editor: Editor?) {
applyTo(element, detectPropertyNameToUse(element)!!, reformat = true) val propertyName = detectPropertyNameToUse(element) ?: return
runWriteAction {
applyTo(element, propertyName, reformat = true)
}
} }
fun applyTo(element: KtCallExpression, propertyName: Name, reformat: Boolean): KtExpression { fun applyTo(element: KtCallExpression, propertyName: Name, reformat: Boolean): KtExpression {
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.intentions.SelfTargetingIntention import org.jetbrains.kotlin.idea.intentions.SelfTargetingIntention
import org.jetbrains.kotlin.idea.search.allScope import org.jetbrains.kotlin.idea.search.allScope
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.findAnnotation import org.jetbrains.kotlin.idea.util.findAnnotation
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -52,9 +53,12 @@ class AddConstModifierFix(val property: KtProperty) : AddModifierFix(property, K
private val removeAnnotations = listOf(FqName("kotlin.jvm.JvmStatic"), FqName("kotlin.jvm.JvmField")) private val removeAnnotations = listOf(FqName("kotlin.jvm.JvmStatic"), FqName("kotlin.jvm.JvmField"))
fun addConstModifier(property: KtProperty) { fun addConstModifier(property: KtProperty) {
val annotationsToRemove = removeAnnotations.mapNotNull { property.findAnnotation(it) }
replaceReferencesToGetterByReferenceToField(property) replaceReferencesToGetterByReferenceToField(property)
property.addModifier(KtTokens.CONST_KEYWORD) runWriteAction {
removeAnnotations.mapNotNull { property.findAnnotation(it) }.forEach(KtAnnotationEntry::delete) property.addModifier(KtTokens.CONST_KEYWORD)
annotationsToRemove.forEach(KtAnnotationEntry::delete)
}
} }
} }
} }
@@ -110,11 +114,13 @@ fun replaceReferencesToGetterByReferenceToField(property: KtProperty) {
val factory = PsiElementFactory.SERVICE.getInstance(project) val factory = PsiElementFactory.SERVICE.getInstance(project)
val fieldFQName = backingField.containingClass!!.qualifiedName + "." + backingField.name val fieldFQName = backingField.containingClass!!.qualifiedName + "." + backingField.name
getterUsages.forEach { runWriteAction {
val call = it.element.getNonStrictParentOfType<PsiMethodCallExpression>() getterUsages.forEach {
if (call != null && it.element == call.methodExpression) { val call = it.element.getNonStrictParentOfType<PsiMethodCallExpression>()
val fieldRef = factory.createExpressionFromText(fieldFQName, it.element) if (call != null && it.element == call.methodExpression) {
call.replace(fieldRef) val fieldRef = factory.createExpressionFromText(fieldFQName, it.element)
call.replace(fieldRef)
}
} }
} }
} }
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.nj2k.postProcessing package org.jetbrains.kotlin.nj2k.postProcessing
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.editor.RangeMarker import com.intellij.openapi.editor.RangeMarker
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement 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.inspections.AbstractApplicabilityBasedInspection
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
import org.jetbrains.kotlin.idea.util.application.runReadAction 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.j2k.ConverterSettings
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.psi.KtElement 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.KtSimpleNameReference
import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.references.readWriteAccess 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.idea.util.getResolutionScope
import org.jetbrains.kotlin.j2k.ConverterSettings import org.jetbrains.kotlin.j2k.ConverterSettings
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
@@ -127,13 +129,29 @@ class RemoveRedundantOverrideVisibilityProcessing :
} }
} }
class UseExpressionBodyProcessing : InspectionLikeProcessingForElement<KtPropertyAccessor>(KtPropertyAccessor::class) { class ReplaceGetterBodyWithSingleReturnStatementWithExpressionBody :
private val inspection = UseExpressionBodyInspection(convertEmptyToUnit = false) InspectionLikeProcessingForElement<KtPropertyAccessor>(KtPropertyAccessor::class) {
override fun isApplicableTo(element: KtPropertyAccessor, settings: ConverterSettings?): Boolean =
inspection.isActiveFor(element) 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) { 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 : class RemoveRedundantSamAdaptersProcessing :
InspectionLikeProcessingForElement<KtCallExpression>(KtCallExpression::class) { InspectionLikeProcessingForElement<KtCallExpression>(KtCallExpression::class) {
override val writeActionNeeded = false
override fun isApplicableTo(element: KtCallExpression, settings: ConverterSettings?): Boolean = override fun isApplicableTo(element: KtCallExpression, settings: ConverterSettings?): Boolean =
RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element).isNotEmpty() RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element).isNotEmpty()
override fun apply(element: KtCallExpression) { override fun apply(element: KtCallExpression) {
RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element).forEach { call -> val callsToBeConverted = RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element)
RedundantSamConstructorInspection.replaceSamConstructorCall(call) runWriteAction {
for (call in callsToBeConverted) {
RedundantSamConstructorInspection.replaceSamConstructorCall(call)
}
} }
} }
} }
@@ -6,8 +6,12 @@
package org.jetbrains.kotlin.nj2k package org.jetbrains.kotlin.nj2k
import com.intellij.psi.CommonClassNames 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.load.java.NULLABILITY_ANNOTATIONS
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtQualifiedExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
class ImportStorage { class ImportStorage {
private val imports = mutableSetOf<FqName>() private val imports = mutableSetOf<FqName>()
@@ -27,6 +31,16 @@ class ImportStorage {
return true 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( private val JAVA_TYPE_WRAPPERS_WHICH_HAVE_CONFLICTS_WITH_KOTLIN_ONES = setOf(
FqName(CommonClassNames.JAVA_LANG_BYTE), FqName(CommonClassNames.JAVA_LANG_BYTE),
FqName(CommonClassNames.JAVA_LANG_SHORT), FqName(CommonClassNames.JAVA_LANG_SHORT),
@@ -35,6 +49,9 @@ class ImportStorage {
FqName(CommonClassNames.JAVA_LANG_DOUBLE) 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()
} }
} }