New J2K: do not analyze code for post-processings in edt thread
This commit is contained in:
+11
-6
@@ -5,7 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.inference.common
|
||||
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.runUndoTransparentActionInEdt
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
|
||||
@@ -19,15 +20,19 @@ class InferenceFacade(
|
||||
private val printDebugConstraints: Boolean = false
|
||||
) {
|
||||
fun runOn(elements: List<KtElement>) {
|
||||
val inferenceContext = typeVariablesCollector.collectTypeVariables(elements)
|
||||
val constraints = constraintsCollectorAggregator.collectConstraints(boundTypeCalculator, inferenceContext, elements)
|
||||
val inferenceContext = runReadAction { typeVariablesCollector.collectTypeVariables(elements) }
|
||||
val constraints = runReadAction {
|
||||
constraintsCollectorAggregator.collectConstraints(boundTypeCalculator, inferenceContext, elements)
|
||||
}
|
||||
|
||||
val initialConstraints = if (renderDebugTypes) constraints.map { it.copy() } else null
|
||||
Solver(inferenceContext, printDebugConstraints, defaultStateProvider).solveConstraints(constraints)
|
||||
runReadAction {
|
||||
Solver(inferenceContext, printDebugConstraints, defaultStateProvider).solveConstraints(constraints)
|
||||
}
|
||||
|
||||
if (renderDebugTypes) {
|
||||
with(DebugPrinter(inferenceContext)) {
|
||||
runWriteAction {
|
||||
runUndoTransparentActionInEdt(inWriteAction = true) {
|
||||
for ((expression, boundType) in boundTypeCalculator.expressionsWithBoundType()) {
|
||||
val comment = KtPsiFactory(expression.project).createComment("/*${boundType.asString()}*/")
|
||||
expression.parent.addAfter(comment, expression)
|
||||
@@ -46,7 +51,7 @@ class InferenceFacade(
|
||||
}
|
||||
}
|
||||
}
|
||||
runWriteAction {
|
||||
runUndoTransparentActionInEdt(inWriteAction = true) {
|
||||
stateUpdater.updateStates(inferenceContext)
|
||||
}
|
||||
}
|
||||
|
||||
+32
-48
@@ -5,17 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.postProcessing
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.RangeMarker
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.idea.formatter.commitAndUnblockDocument
|
||||
import org.jetbrains.kotlin.idea.inspections.*
|
||||
import org.jetbrains.kotlin.idea.inspections.branchedTransformations.IfThenToElvisInspection
|
||||
@@ -27,7 +21,6 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.F
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isTrivialStatementBody
|
||||
import org.jetbrains.kotlin.idea.quickfix.*
|
||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.j2k.ConverterContext
|
||||
import org.jetbrains.kotlin.j2k.PostProcessor
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -41,11 +34,9 @@ class NewJ2kPostProcessor : PostProcessor {
|
||||
private val LOG = Logger.getInstance("@org.jetbrains.kotlin.nj2k.postProcessing.NewJ2kPostProcessor")
|
||||
|
||||
override fun insertImport(file: KtFile, fqName: FqName) {
|
||||
ApplicationManager.getApplication().invokeAndWait {
|
||||
runWriteAction {
|
||||
val descriptors = file.resolveImportReference(fqName)
|
||||
descriptors.firstOrNull()?.let { ImportInsertHelper.getInstance(file.project).importDescriptor(file, it) }
|
||||
}
|
||||
runUndoTransparentActionInEdt(inWriteAction = true) {
|
||||
val descriptors = file.resolveImportReference(fqName)
|
||||
descriptors.firstOrNull()?.let { ImportInsertHelper.getInstance(file.project).importDescriptor(file, it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,31 +48,25 @@ class NewJ2kPostProcessor : PostProcessor {
|
||||
rangeMarker: RangeMarker?,
|
||||
onPhaseChanged: ((Int, String) -> Unit)?
|
||||
) {
|
||||
runBlocking(EDT.ModalityStateElement(ModalityState.defaultModalityState())) {
|
||||
for ((i, group) in processings.withIndex()) {
|
||||
onPhaseChanged?.invoke(i + 1, group.description)
|
||||
for (processing in group.processings) {
|
||||
try {
|
||||
processing.runProcessing(file, rangeMarker, converterContext as NewJ2kConverterContext)
|
||||
} catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
} catch (t: Throwable) {
|
||||
LOG.error(t)
|
||||
} finally {
|
||||
commitFile(file)
|
||||
}
|
||||
for ((i, group) in processings.withIndex()) {
|
||||
onPhaseChanged?.invoke(i + 1, group.description)
|
||||
for (processing in group.processings) {
|
||||
try {
|
||||
processing.runProcessing(file, rangeMarker, converterContext as NewJ2kConverterContext)
|
||||
} catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
} catch (t: Throwable) {
|
||||
LOG.error(t)
|
||||
} finally {
|
||||
commitFile(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun commitFile(file: KtFile) {
|
||||
withContext(EDT) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||
runWriteAction {
|
||||
file.commitAndUnblockDocument()
|
||||
}
|
||||
}
|
||||
private fun commitFile(file: KtFile) {
|
||||
runUndoTransparentActionInEdt(inWriteAction = true) {
|
||||
file.commitAndUnblockDocument()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +136,7 @@ private val addOrRemoveModifiersProcessingGroup =
|
||||
processings = listOf(
|
||||
RemoveRedundantVisibilityModifierProcessing(),
|
||||
RemoveRedundantModalityModifierProcessing(),
|
||||
inspectionBasedProcessing(AddOperatorModifierInspection()),
|
||||
inspectionBasedProcessing(AddOperatorModifierInspection(), writeActionNeeded = false),
|
||||
RemoveExplicitUnitTypeProcessing()
|
||||
)
|
||||
)
|
||||
@@ -183,24 +168,24 @@ private val inspectionLikePostProcessingGroup =
|
||||
RemoveRedundantConstructorKeywordProcessing(),
|
||||
RemoveExplicitOpenInInterfaceProcessing(),
|
||||
RemoveRedundantOverrideVisibilityProcessing(),
|
||||
inspectionBasedProcessing(MoveLambdaOutsideParenthesesInspection()),
|
||||
intentionBasedProcessing(ConvertToStringTemplateIntention()) {
|
||||
MoveLambdaOutsideParenthesesProcessing(),
|
||||
intentionBasedProcessing(ConvertToStringTemplateIntention(), writeActionNeeded = false) {
|
||||
ConvertToStringTemplateIntention.shouldSuggestToConvert(it)
|
||||
},
|
||||
intentionBasedProcessing(UsePropertyAccessSyntaxIntention()),
|
||||
intentionBasedProcessing(UsePropertyAccessSyntaxIntention(), writeActionNeeded = false),
|
||||
UninitializedVariableReferenceFromInitializerToThisReferenceProcessing(),
|
||||
UnresolvedVariableReferenceFromInitializerToThisReferenceProcessing(),
|
||||
RemoveRedundantSamAdaptersProcessing(),
|
||||
RemoveRedundantCastToNullableProcessing(),
|
||||
inspectionBasedProcessing(ReplacePutWithAssignmentInspection()),
|
||||
UseExpressionBodyProcessing(),
|
||||
inspectionBasedProcessing(UnnecessaryVariableInspection()),
|
||||
ReplaceGetterBodyWithSingleReturnStatementWithExpressionBody(),
|
||||
inspectionBasedProcessing(UnnecessaryVariableInspection(), writeActionNeeded = false),
|
||||
RedundantExplicitTypeInspectionBasedProcessing(),
|
||||
JavaObjectEqualsToEqOperatorProcessing(),
|
||||
RemoveExplicitPropertyTypeProcessing(),
|
||||
RemoveRedundantNullabilityProcessing(),
|
||||
CanBeValInspectionBasedProcessing(),
|
||||
inspectionBasedProcessing(FoldInitializerAndIfToElvisInspection()),
|
||||
inspectionBasedProcessing(FoldInitializerAndIfToElvisInspection(), writeActionNeeded = false),
|
||||
intentionBasedProcessing(RemoveRedundantCallsOfConversionMethodsIntention()),
|
||||
inspectionBasedProcessing(JavaMapForEachInspection()),
|
||||
intentionBasedProcessing(FoldIfToReturnIntention()) { it.then.isTrivialStatementBody() && it.`else`.isTrivialStatementBody() },
|
||||
@@ -209,14 +194,13 @@ private val inspectionLikePostProcessingGroup =
|
||||
it
|
||||
) as KtReturnExpression).returnedExpression.isTrivialStatementBody()
|
||||
},
|
||||
inspectionBasedProcessing(IfThenToSafeAccessInspection()),
|
||||
inspectionBasedProcessing(IfThenToElvisInspection(highlightStatement = true)),
|
||||
inspectionBasedProcessing(IfThenToSafeAccessInspection(), writeActionNeeded = false),
|
||||
inspectionBasedProcessing(IfThenToElvisInspection(highlightStatement = true), writeActionNeeded = false),
|
||||
inspectionBasedProcessing(SimplifyNegatedBinaryExpressionInspection()),
|
||||
inspectionBasedProcessing(ReplaceGetOrSetInspection()),
|
||||
intentionBasedProcessing(ObjectLiteralToLambdaIntention()),
|
||||
intentionBasedProcessing(AnonymousFunctionToLambdaIntention()),
|
||||
intentionBasedProcessing(ObjectLiteralToLambdaIntention(), writeActionNeeded = true),
|
||||
intentionBasedProcessing(RemoveUnnecessaryParenthesesIntention()),
|
||||
intentionBasedProcessing(DestructureIntention()),
|
||||
intentionBasedProcessing(DestructureIntention(), writeActionNeeded = false),
|
||||
inspectionBasedProcessing(SimplifyAssertNotNullInspection()),
|
||||
intentionBasedProcessing(RemoveRedundantCallsOfConversionMethodsIntention()),
|
||||
LiftReturnInspectionBasedProcessing(),
|
||||
@@ -250,12 +234,12 @@ private val processings: List<NamedPostProcessingGroup> = listOf(
|
||||
),
|
||||
NullabilityInferenceProcessing(),
|
||||
MutabilityInferenceProcessing(),
|
||||
clearUnknownLabelsProcessing
|
||||
ClearUnknownLabelsProcessing()
|
||||
)
|
||||
),
|
||||
NamedPostProcessingGroup(
|
||||
"Formatting code",
|
||||
listOf(formatCodeProcessing)
|
||||
listOf(FormatCodeProcessing())
|
||||
),
|
||||
NamedPostProcessingGroup(
|
||||
"Shortening fully-qualified references",
|
||||
@@ -288,12 +272,12 @@ private val processings: List<NamedPostProcessingGroup> = listOf(
|
||||
NamedPostProcessingGroup(
|
||||
"Optimizing imports",
|
||||
listOf(
|
||||
optimizeImportsProcessing,
|
||||
OptimizeImportsProcessing(),
|
||||
ShortenReferenceProcessing()
|
||||
)
|
||||
),
|
||||
NamedPostProcessingGroup(
|
||||
"Formatting code",
|
||||
listOf(formatCodeProcessing)
|
||||
listOf(FormatCodeProcessing())
|
||||
)
|
||||
)
|
||||
+10
-15
@@ -6,19 +6,16 @@
|
||||
package org.jetbrains.kotlin.nj2k.postProcessing
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.editor.RangeMarker
|
||||
import com.intellij.psi.PsiElement
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.idea.core.util.range
|
||||
import org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -36,17 +33,15 @@ class DiagnosticBasedPostProcessingGroup(diagnosticBasedProcessings: List<Diagno
|
||||
list.map { it.second }
|
||||
}
|
||||
|
||||
override suspend fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
withContext(EDT) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||
val diagnostics = runWriteAction { analyzeFileRange(file, rangeMarker) }
|
||||
for (diagnostic in diagnostics.all()) {
|
||||
val range = rangeMarker?.range ?: file.textRange
|
||||
if (diagnostic.psiElement.isInRange(range)) {
|
||||
diagnosticToFix[diagnostic.factory]?.forEach { fix ->
|
||||
if (diagnostic.psiElement.isValid) {
|
||||
runWriteAction { fix(diagnostic) }
|
||||
}
|
||||
override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
val diagnostics = runReadAction { analyzeFileRange(file, rangeMarker).all() }
|
||||
runUndoTransparentActionInEdt(inWriteAction = true) {
|
||||
for (diagnostic in diagnostics) {
|
||||
val range = rangeMarker?.range ?: file.textRange
|
||||
if (diagnostic.psiElement.isInRange(range)) {
|
||||
diagnosticToFix[diagnostic.factory]?.forEach { fix ->
|
||||
if (diagnostic.psiElement.isValid) {
|
||||
fix(diagnostic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+66
-94
@@ -5,29 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.postProcessing
|
||||
|
||||
import com.intellij.codeInspection.*
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.editor.RangeMarker
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiRecursiveElementVisitor
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractApplicabilityBasedInspection
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
|
||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
|
||||
import org.jetbrains.kotlin.idea.quickfix.QuickFixActionBase
|
||||
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
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.utils.mapToIndex
|
||||
import java.util.*
|
||||
import kotlin.reflect.KClass
|
||||
@@ -39,7 +29,6 @@ class InspectionLikeProcessingGroup(
|
||||
private val acceptNonKtElements: Boolean = false,
|
||||
private val processings: List<InspectionLikeProcessing>
|
||||
) : ProcessingGroup {
|
||||
|
||||
constructor(vararg processings: InspectionLikeProcessing) : this(
|
||||
runSingleTime = false,
|
||||
acceptNonKtElements = false,
|
||||
@@ -49,49 +38,45 @@ class InspectionLikeProcessingGroup(
|
||||
private val processingsToPriorityMap = processings.mapToIndex()
|
||||
fun priority(processing: InspectionLikeProcessing): Int = processingsToPriorityMap.getValue(processing)
|
||||
|
||||
override suspend fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
do {
|
||||
var modificationStamp: Long? = file.modificationStamp
|
||||
val elementToActions = runReadAction {
|
||||
collectAvailableActions(file, converterContext, rangeMarker)
|
||||
}
|
||||
withContext(EDT) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||
for ((element, action, _, writeActionNeeded) in elementToActions) {
|
||||
if (element.isValid) {
|
||||
if (writeActionNeeded) {
|
||||
runWriteAction {
|
||||
action()
|
||||
}
|
||||
} else {
|
||||
action()
|
||||
}
|
||||
} else {
|
||||
modificationStamp = null
|
||||
}
|
||||
}
|
||||
|
||||
for ((processing, element, _) in elementToActions) {
|
||||
val needRun = runReadAction {
|
||||
element.isValid && processing.isApplicableToElement(element, converterContext.converter.settings)
|
||||
}
|
||||
if (needRun) runUndoTransparentActionInEdt(inWriteAction = processing.writeActionNeeded) {
|
||||
processing.applyToElement(element)
|
||||
} else {
|
||||
modificationStamp = null
|
||||
}
|
||||
}
|
||||
if (runSingleTime) break
|
||||
} while (modificationStamp != file.modificationStamp && elementToActions.isNotEmpty())
|
||||
}
|
||||
|
||||
|
||||
private enum class RangeFilterResult {
|
||||
SKIP,
|
||||
GO_INSIDE,
|
||||
PROCESS
|
||||
}
|
||||
|
||||
|
||||
private data class ActionData(val element: PsiElement, val action: () -> Unit, val priority: Int, val writeActionNeeded: Boolean)
|
||||
private data class ProcessingData(
|
||||
val processing: InspectionLikeProcessing,
|
||||
val element: PsiElement,
|
||||
val priority: Int
|
||||
)
|
||||
|
||||
private fun collectAvailableActions(
|
||||
file: KtFile,
|
||||
context: NewJ2kConverterContext,
|
||||
rangeMarker: RangeMarker?
|
||||
): List<ActionData> {
|
||||
val availableActions = ArrayList<ActionData>()
|
||||
): List<ProcessingData> {
|
||||
val availableActions = ArrayList<ProcessingData>()
|
||||
|
||||
file.accept(object : PsiRecursiveElementVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
@@ -102,15 +87,10 @@ class InspectionLikeProcessingGroup(
|
||||
super.visitElement(element)
|
||||
|
||||
if (rangeResult == RangeFilterResult.PROCESS) {
|
||||
processings.forEach { processing ->
|
||||
val action = processing.createAction(element, context.converter.settings)
|
||||
if (action != null) {
|
||||
for (processing in processings) {
|
||||
if (processing.isApplicableToElement(element, context.converter.settings)) {
|
||||
availableActions.add(
|
||||
ActionData(
|
||||
element, action,
|
||||
priority(processing),
|
||||
processing.writeActionNeeded
|
||||
)
|
||||
ProcessingData(processing, element, priority(processing))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -136,71 +116,63 @@ class InspectionLikeProcessingGroup(
|
||||
}
|
||||
}
|
||||
|
||||
interface InspectionLikeProcessing {
|
||||
fun createAction(element: PsiElement, settings: ConverterSettings?): (() -> Unit)?
|
||||
abstract class InspectionLikeProcessing {
|
||||
abstract fun isApplicableToElement(element: PsiElement, settings: ConverterSettings?): Boolean
|
||||
abstract fun applyToElement(element: PsiElement)
|
||||
|
||||
val writeActionNeeded: Boolean
|
||||
// Some post-processings may need to do some resolving operations when applying
|
||||
// Running it in outer write action may lead to UI freezes
|
||||
// So we let that post-processings to handle write actions by themselves
|
||||
open val writeActionNeeded = true
|
||||
}
|
||||
|
||||
abstract class ApplicabilityBasedInspectionLikeProcessing<E : PsiElement>(private val classTag: KClass<E>) : InspectionLikeProcessing {
|
||||
abstract class InspectionLikeProcessingForElement<E : PsiElement>(private val classTag: KClass<E>) : InspectionLikeProcessing() {
|
||||
protected abstract fun isApplicableTo(element: E, settings: ConverterSettings?): Boolean
|
||||
protected abstract fun apply(element: E)
|
||||
|
||||
final override fun createAction(element: PsiElement, settings: ConverterSettings?): (() -> Unit)? {
|
||||
if (!element::class.isSubclassOf(classTag)) return null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
if (!isApplicableTo(element as E, settings)) return null
|
||||
return {
|
||||
if (element.isValid && isApplicableTo(element, settings)) {
|
||||
apply(element)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
final override fun isApplicableToElement(element: PsiElement, settings: ConverterSettings?): Boolean {
|
||||
if (!element::class.isSubclassOf(classTag)) return false
|
||||
if (!element.isValid) return false
|
||||
@Suppress("UNCHECKED_CAST") return isApplicableTo(element as E, settings)
|
||||
}
|
||||
|
||||
final override val writeActionNeeded: Boolean = true
|
||||
}
|
||||
|
||||
|
||||
inline fun <reified TElement : PsiElement, TIntention : SelfTargetingRangeIntention<TElement>> intentionBasedProcessing(
|
||||
intention: TIntention,
|
||||
noinline additionalChecker: (TElement) -> Boolean = { true }
|
||||
) = object : InspectionLikeProcessing {
|
||||
// Intention can either need or not need write apply
|
||||
override val writeActionNeeded = intention.startInWriteAction()
|
||||
|
||||
override fun createAction(element: PsiElement, settings: ConverterSettings?): (() -> Unit)? {
|
||||
if (!TElement::class.java.isInstance(element)) return null
|
||||
val tElement = element as TElement
|
||||
if (intention.applicabilityRange(tElement) == null) return null
|
||||
if (!additionalChecker(tElement)) return null
|
||||
return {
|
||||
if (intention.applicabilityRange(tElement) != null) { // isApplicableTo availability of the intention again because something could change
|
||||
intention.applyTo(element, null)
|
||||
}
|
||||
}
|
||||
final override fun applyToElement(element: PsiElement) {
|
||||
if (!element::class.isSubclassOf(classTag)) return
|
||||
if (!element.isValid) return
|
||||
@Suppress("UNCHECKED_CAST") apply(element as E)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline fun <reified TElement : PsiElement, TInspection : AbstractApplicabilityBasedInspection<TElement>>
|
||||
inspectionBasedProcessing(inspection: TInspection, acceptInformationLevel: Boolean = false) =
|
||||
object : InspectionLikeProcessing {
|
||||
// Inspection can either need or not need write apply
|
||||
override val writeActionNeeded = inspection.startFixInWriteAction
|
||||
inline fun <reified E : PsiElement, I : SelfTargetingRangeIntention<E>> intentionBasedProcessing(
|
||||
intention: I,
|
||||
writeActionNeeded: Boolean = true,
|
||||
noinline additionalChecker: (E) -> Boolean = { true }
|
||||
) = object : InspectionLikeProcessingForElement<E>(E::class) {
|
||||
override fun isApplicableTo(element: E, settings: ConverterSettings?): Boolean =
|
||||
intention.applicabilityRange(element) != null
|
||||
&& additionalChecker(element)
|
||||
|
||||
fun isApplicable(element: TElement): Boolean {
|
||||
if (!inspection.isApplicable(element)) return false
|
||||
return acceptInformationLevel || inspection.inspectionHighlightType(element) != ProblemHighlightType.INFORMATION
|
||||
}
|
||||
|
||||
override fun createAction(element: PsiElement, settings: ConverterSettings?): (() -> Unit)? {
|
||||
if (!TElement::class.java.isInstance(element)) return null
|
||||
val tElement = element as TElement
|
||||
if (!isApplicable(tElement)) return null
|
||||
return {
|
||||
if (isApplicable(tElement)) { // isApplicableTo availability of the inspection again because something could change
|
||||
inspection.applyTo(tElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun apply(element: E) {
|
||||
intention.applyTo(element, null)
|
||||
}
|
||||
|
||||
override val writeActionNeeded = writeActionNeeded
|
||||
}
|
||||
|
||||
|
||||
inline fun <reified E : PsiElement, I : AbstractApplicabilityBasedInspection<E>> inspectionBasedProcessing(
|
||||
inspection: I,
|
||||
writeActionNeeded: Boolean = true
|
||||
) = object : InspectionLikeProcessingForElement<E>(E::class) {
|
||||
override fun isApplicableTo(element: E, settings: ConverterSettings?): Boolean =
|
||||
inspection.isApplicable(element)
|
||||
|
||||
override fun apply(element: E) {
|
||||
inspection.applyTo(element)
|
||||
}
|
||||
|
||||
override val writeActionNeeded = writeActionNeeded
|
||||
}
|
||||
|
||||
@@ -5,43 +5,28 @@
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.postProcessing
|
||||
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.editor.RangeMarker
|
||||
import com.intellij.psi.PsiElement
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.idea.core.util.range
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||
|
||||
|
||||
interface GeneralPostProcessing {
|
||||
suspend fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext)
|
||||
fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext)
|
||||
}
|
||||
|
||||
abstract class SimplePostProcessing() : GeneralPostProcessing {
|
||||
final override suspend fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
withContext(EDT) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||
runWriteAction {
|
||||
applySimpleProcessing(file, rangeMarker, converterContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun applySimpleProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext)
|
||||
}
|
||||
|
||||
abstract class ElementsBasedPostProcessing() : SimplePostProcessing() {
|
||||
final override fun applySimpleProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
val elements =
|
||||
abstract class ElementsBasedPostProcessing : GeneralPostProcessing {
|
||||
final override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
val elements = runReadAction {
|
||||
rangeMarker?.let { marker ->
|
||||
val range = marker.range ?: return@let emptyList()
|
||||
file.elementsInRange(range)
|
||||
} ?: listOf(file)
|
||||
}
|
||||
runProcessing(elements, converterContext)
|
||||
}
|
||||
|
||||
@@ -54,13 +39,3 @@ data class NamedPostProcessingGroup(
|
||||
val description: String,
|
||||
val processings: List<GeneralPostProcessing>
|
||||
)
|
||||
|
||||
fun postProcessing(
|
||||
action: (file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) -> Unit
|
||||
): GeneralPostProcessing =
|
||||
object : SimplePostProcessing() {
|
||||
override fun applySimpleProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
action(file, rangeMarker, converterContext)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-8
@@ -24,7 +24,7 @@ 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.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.j2k.getContainingClass
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
@@ -272,15 +272,20 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
|
||||
|
||||
|
||||
override fun runProcessing(elements: List<PsiElement>, converterContext: NewJ2kConverterContext) {
|
||||
val classes = elements
|
||||
.descendantsOfType<KtClassOrObject>()
|
||||
.sortedByInheritance()
|
||||
val collectingState = CollectingState()
|
||||
val classesWithPropertiesData = classes.map { klass ->
|
||||
klass to klass.collectPropertiesData(collectingState)
|
||||
val classesWithPropertiesData = runReadAction {
|
||||
elements
|
||||
.descendantsOfType<KtClassOrObject>()
|
||||
.sortedByInheritance()
|
||||
.map { klass ->
|
||||
klass to klass.collectPropertiesData(collectingState)
|
||||
}
|
||||
}
|
||||
for ((klass, propertiesData) in classesWithPropertiesData) {
|
||||
convertClass(klass, propertiesData)
|
||||
if (classesWithPropertiesData.isEmpty()) return
|
||||
runUndoTransparentActionInEdt(inWriteAction = true) {
|
||||
for ((klass, propertiesData) in classesWithPropertiesData) {
|
||||
convertClass(klass, propertiesData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
-15
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.idea.core.setVisibility
|
||||
import org.jetbrains.kotlin.idea.intentions.addUseSiteTarget
|
||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.nj2k.escaped
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.*
|
||||
@@ -122,24 +123,28 @@ class ConvertToDataClassProcessing : ElementsBasedPostProcessing() {
|
||||
}
|
||||
|
||||
private fun convertClass(klass: KtClass) {
|
||||
for (initialization in collectInitializations(klass)) {
|
||||
val statementCommentSaver = CommentSaver(initialization.statement, saveLineBreaks = true)
|
||||
val restoreStatementCommentsTarget: KtExpression
|
||||
when (initialization) {
|
||||
is ConstructorParameterInitialization -> {
|
||||
initialization.mergePropertyAndConstructorParameter()
|
||||
restoreStatementCommentsTarget = initialization.initializer
|
||||
}
|
||||
is LiteralInitialization -> {
|
||||
val (property, initializer, _) = initialization
|
||||
property.initializer = initializer
|
||||
restoreStatementCommentsTarget = property
|
||||
val initialisations = runReadAction { collectInitializations(klass) }
|
||||
if (initialisations.isEmpty()) return
|
||||
runUndoTransparentActionInEdt(inWriteAction = true) {
|
||||
for (initialization in initialisations) {
|
||||
val statementCommentSaver = CommentSaver(initialization.statement, saveLineBreaks = true)
|
||||
val restoreStatementCommentsTarget: KtExpression
|
||||
when (initialization) {
|
||||
is ConstructorParameterInitialization -> {
|
||||
initialization.mergePropertyAndConstructorParameter()
|
||||
restoreStatementCommentsTarget = initialization.initializer
|
||||
}
|
||||
is LiteralInitialization -> {
|
||||
val (property, initializer, _) = initialization
|
||||
property.initializer = initializer
|
||||
restoreStatementCommentsTarget = property
|
||||
}
|
||||
}
|
||||
initialization.statement.delete()
|
||||
statementCommentSaver.restore(restoreStatementCommentsTarget, forceAdjustIndent = false)
|
||||
}
|
||||
initialization.statement.delete()
|
||||
statementCommentSaver.restore(restoreStatementCommentsTarget, forceAdjustIndent = false)
|
||||
klass.removeEmptyInitBlocks()
|
||||
}
|
||||
klass.removeEmptyInitBlocks()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-10
@@ -5,11 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.postProcessing.processings
|
||||
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.editor.RangeMarker
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.idea.core.util.range
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
@@ -29,18 +26,13 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||
|
||||
abstract class InferenceProcessing : GeneralPostProcessing {
|
||||
final override suspend fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
final override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
val elements = if (rangeMarker != null) {
|
||||
val range = rangeMarker.range ?: return
|
||||
runReadAction { file.elementsInRange(range) }.filterIsInstance<KtElement>()
|
||||
} else listOf(file)
|
||||
val resolutionFacade = runReadAction { file.getResolutionFacade() }
|
||||
|
||||
withContext(EDT) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||
createInferenceFacade(resolutionFacade, converterContext).runOn(elements)
|
||||
}
|
||||
}
|
||||
createInferenceFacade(resolutionFacade, converterContext).runOn(elements)
|
||||
}
|
||||
|
||||
abstract fun createInferenceFacade(
|
||||
|
||||
+15
-16
@@ -8,34 +8,33 @@ package org.jetbrains.kotlin.nj2k.postProcessing.processings
|
||||
import com.intellij.openapi.editor.RangeMarker
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.nj2k.ImportStorage
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.SimplePostProcessing
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.GeneralPostProcessing
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.runUndoTransparentActionInEdt
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||
|
||||
class ShortenReferenceProcessing : SimplePostProcessing() {
|
||||
class ShortenReferenceProcessing : GeneralPostProcessing {
|
||||
private val filter = filter@{ element: PsiElement ->
|
||||
when (element) {
|
||||
is KtQualifiedExpression -> {
|
||||
val fqName = element.selectorExpression?.mainReference?.resolve()?.getKotlinFqName()
|
||||
?: return@filter ShortenReferences.FilterResult.PROCESS
|
||||
if (ImportStorage.isImportNeeded(fqName)) ShortenReferences.FilterResult.PROCESS
|
||||
else ShortenReferences.FilterResult.SKIP
|
||||
is KtQualifiedExpression -> when {
|
||||
ImportStorage.isImportNeededForCall(element) -> ShortenReferences.FilterResult.PROCESS
|
||||
else -> ShortenReferences.FilterResult.SKIP
|
||||
}
|
||||
else -> ShortenReferences.FilterResult.PROCESS
|
||||
}
|
||||
}
|
||||
|
||||
override fun applySimpleProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
if (rangeMarker != null) {
|
||||
if (rangeMarker.isValid) {
|
||||
ShortenReferences.DEFAULT.process(file, rangeMarker.startOffset, rangeMarker.endOffset, filter)
|
||||
override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
runUndoTransparentActionInEdt(inWriteAction = false) {
|
||||
if (rangeMarker != null) {
|
||||
if (rangeMarker.isValid) {
|
||||
ShortenReferences.DEFAULT.process(file, rangeMarker.startOffset, rangeMarker.endOffset, filter)
|
||||
}
|
||||
} else {
|
||||
ShortenReferences.DEFAULT.process(file, filter)
|
||||
}
|
||||
} else {
|
||||
ShortenReferences.DEFAULT.process(file, filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+43
-35
@@ -13,10 +13,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.implicitModality
|
||||
import org.jetbrains.kotlin.idea.core.implicitVisibility
|
||||
import org.jetbrains.kotlin.idea.core.replaced
|
||||
import org.jetbrains.kotlin.idea.core.setVisibility
|
||||
import org.jetbrains.kotlin.idea.core.*
|
||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.callName
|
||||
import org.jetbrains.kotlin.idea.inspections.*
|
||||
import org.jetbrains.kotlin.idea.inspections.collections.isCalling
|
||||
@@ -32,7 +29,7 @@ import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.j2k.ConverterSettings
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.ApplicabilityBasedInspectionLikeProcessing
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.InspectionLikeProcessingForElement
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -42,7 +39,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
|
||||
class RemoveExplicitPropertyTypeProcessing : ApplicabilityBasedInspectionLikeProcessing<KtProperty>(KtProperty::class) {
|
||||
class RemoveExplicitPropertyTypeProcessing : InspectionLikeProcessingForElement<KtProperty>(KtProperty::class) {
|
||||
override fun isApplicableTo(element: KtProperty, settings: ConverterSettings?): Boolean {
|
||||
val needFieldTypes = settings?.specifyFieldTypeByDefault == true
|
||||
val needLocalVariablesTypes = settings?.specifyLocalVariableTypeByDefault == true
|
||||
@@ -61,7 +58,7 @@ class RemoveExplicitPropertyTypeProcessing : ApplicabilityBasedInspectionLikePro
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveRedundantNullabilityProcessing : ApplicabilityBasedInspectionLikeProcessing<KtProperty>(KtProperty::class) {
|
||||
class RemoveRedundantNullabilityProcessing : InspectionLikeProcessingForElement<KtProperty>(KtProperty::class) {
|
||||
override fun isApplicableTo(element: KtProperty, settings: ConverterSettings?): Boolean {
|
||||
if (!element.isLocal) return false
|
||||
val typeReference = element.typeReference
|
||||
@@ -87,7 +84,7 @@ class RemoveRedundantNullabilityProcessing : ApplicabilityBasedInspectionLikePro
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveExplicitTypeArgumentsProcessing : ApplicabilityBasedInspectionLikeProcessing<KtTypeArgumentList>(KtTypeArgumentList::class) {
|
||||
class RemoveExplicitTypeArgumentsProcessing : InspectionLikeProcessingForElement<KtTypeArgumentList>(KtTypeArgumentList::class) {
|
||||
override fun isApplicableTo(element: KtTypeArgumentList, settings: ConverterSettings?): Boolean =
|
||||
RemoveExplicitTypeArgumentsIntention.isApplicableTo(element, approximateFlexible = true)
|
||||
|
||||
@@ -99,7 +96,7 @@ class RemoveExplicitTypeArgumentsProcessing : ApplicabilityBasedInspectionLikePr
|
||||
// the types arguments for Stream.collect calls cannot be explicitly specified in Kotlin
|
||||
// but we need them in nullability inference, so we remove it here
|
||||
class RemoveJavaStreamsCollectCallTypeArgumentsProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtCallExpression>(KtCallExpression::class) {
|
||||
InspectionLikeProcessingForElement<KtCallExpression>(KtCallExpression::class) {
|
||||
override fun isApplicableTo(element: KtCallExpression, settings: ConverterSettings?): Boolean {
|
||||
if (element.typeArgumentList == null) return false
|
||||
if (element.callName() != COLLECT_FQ_NAME.shortName().identifier) return false
|
||||
@@ -117,7 +114,7 @@ class RemoveJavaStreamsCollectCallTypeArgumentsProcessing :
|
||||
|
||||
|
||||
class RemoveRedundantOverrideVisibilityProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtCallableDeclaration>(KtCallableDeclaration::class) {
|
||||
InspectionLikeProcessingForElement<KtCallableDeclaration>(KtCallableDeclaration::class) {
|
||||
|
||||
override fun isApplicableTo(element: KtCallableDeclaration, settings: ConverterSettings?): Boolean {
|
||||
if (!element.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return false
|
||||
@@ -130,7 +127,7 @@ class RemoveRedundantOverrideVisibilityProcessing :
|
||||
}
|
||||
}
|
||||
|
||||
class UseExpressionBodyProcessing : ApplicabilityBasedInspectionLikeProcessing<KtPropertyAccessor>(KtPropertyAccessor::class) {
|
||||
class UseExpressionBodyProcessing : InspectionLikeProcessingForElement<KtPropertyAccessor>(KtPropertyAccessor::class) {
|
||||
private val inspection = UseExpressionBodyInspection(convertEmptyToUnit = false)
|
||||
override fun isApplicableTo(element: KtPropertyAccessor, settings: ConverterSettings?): Boolean =
|
||||
inspection.isActiveFor(element)
|
||||
@@ -141,7 +138,7 @@ class UseExpressionBodyProcessing : ApplicabilityBasedInspectionLikeProcessing<K
|
||||
}
|
||||
|
||||
class RemoveRedundantCastToNullableProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtBinaryExpressionWithTypeRHS>(KtBinaryExpressionWithTypeRHS::class) {
|
||||
InspectionLikeProcessingForElement<KtBinaryExpressionWithTypeRHS>(KtBinaryExpressionWithTypeRHS::class) {
|
||||
|
||||
override fun isApplicableTo(element: KtBinaryExpressionWithTypeRHS, settings: ConverterSettings?): Boolean {
|
||||
if (element.right?.typeElement !is KtNullableType) return false
|
||||
@@ -158,7 +155,7 @@ class RemoveRedundantCastToNullableProcessing :
|
||||
}
|
||||
|
||||
class RemoveRedundantSamAdaptersProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtCallExpression>(KtCallExpression::class) {
|
||||
InspectionLikeProcessingForElement<KtCallExpression>(KtCallExpression::class) {
|
||||
|
||||
override fun isApplicableTo(element: KtCallExpression, settings: ConverterSettings?): Boolean =
|
||||
RedundantSamConstructorInspection.samConstructorCallsToBeConverted(element).isNotEmpty()
|
||||
@@ -171,7 +168,7 @@ class RemoveRedundantSamAdaptersProcessing :
|
||||
}
|
||||
|
||||
class UninitializedVariableReferenceFromInitializerToThisReferenceProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtSimpleNameExpression>(KtSimpleNameExpression::class) {
|
||||
InspectionLikeProcessingForElement<KtSimpleNameExpression>(KtSimpleNameExpression::class) {
|
||||
|
||||
override fun isApplicableTo(element: KtSimpleNameExpression, settings: ConverterSettings?): Boolean {
|
||||
val anonymousObject = element.getStrictParentOfType<KtClassOrObject>()?.takeIf { it.name == null } ?: return false
|
||||
@@ -192,7 +189,7 @@ class UninitializedVariableReferenceFromInitializerToThisReferenceProcessing :
|
||||
}
|
||||
|
||||
class UnresolvedVariableReferenceFromInitializerToThisReferenceProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtSimpleNameExpression>(KtSimpleNameExpression::class) {
|
||||
InspectionLikeProcessingForElement<KtSimpleNameExpression>(KtSimpleNameExpression::class) {
|
||||
|
||||
override fun isApplicableTo(element: KtSimpleNameExpression, settings: ConverterSettings?): Boolean {
|
||||
val anonymousObject = element.getStrictParentOfType<KtClassOrObject>() ?: return false
|
||||
@@ -207,7 +204,7 @@ class UnresolvedVariableReferenceFromInitializerToThisReferenceProcessing :
|
||||
}
|
||||
}
|
||||
|
||||
class VarToValProcessing : ApplicabilityBasedInspectionLikeProcessing<KtProperty>(KtProperty::class) {
|
||||
class VarToValProcessing : InspectionLikeProcessingForElement<KtProperty>(KtProperty::class) {
|
||||
private fun KtProperty.hasWriteUsages(): Boolean =
|
||||
ReferencesSearch.search(this, useScope).any { usage ->
|
||||
(usage as? KtSimpleNameReference)?.element?.let { nameReference ->
|
||||
@@ -233,7 +230,7 @@ class VarToValProcessing : ApplicabilityBasedInspectionLikeProcessing<KtProperty
|
||||
}
|
||||
}
|
||||
|
||||
class JavaObjectEqualsToEqOperatorProcessing : ApplicabilityBasedInspectionLikeProcessing<KtCallExpression>(KtCallExpression::class) {
|
||||
class JavaObjectEqualsToEqOperatorProcessing : InspectionLikeProcessingForElement<KtCallExpression>(KtCallExpression::class) {
|
||||
companion object {
|
||||
val CALL_FQ_NAME = FqName("java.util.Objects.equals")
|
||||
}
|
||||
@@ -259,7 +256,7 @@ class JavaObjectEqualsToEqOperatorProcessing : ApplicabilityBasedInspectionLikeP
|
||||
|
||||
|
||||
class RemoveForExpressionLoopParameterTypeProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtForExpression>(KtForExpression::class) {
|
||||
InspectionLikeProcessingForElement<KtForExpression>(KtForExpression::class) {
|
||||
override fun isApplicableTo(element: KtForExpression, settings: ConverterSettings?): Boolean =
|
||||
element.loopParameter?.typeReference?.typeElement != null
|
||||
&& settings?.specifyLocalVariableTypeByDefault != true
|
||||
@@ -270,7 +267,7 @@ class RemoveForExpressionLoopParameterTypeProcessing :
|
||||
}
|
||||
|
||||
class RemoveRedundantConstructorKeywordProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtPrimaryConstructor>(KtPrimaryConstructor::class) {
|
||||
InspectionLikeProcessingForElement<KtPrimaryConstructor>(KtPrimaryConstructor::class) {
|
||||
override fun isApplicableTo(element: KtPrimaryConstructor, settings: ConverterSettings?): Boolean =
|
||||
element.containingClassOrObject is KtClass
|
||||
&& element.getConstructorKeyword() != null
|
||||
@@ -283,7 +280,7 @@ class RemoveRedundantConstructorKeywordProcessing :
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveRedundantModalityModifierProcessing : ApplicabilityBasedInspectionLikeProcessing<KtDeclaration>(KtDeclaration::class) {
|
||||
class RemoveRedundantModalityModifierProcessing : InspectionLikeProcessingForElement<KtDeclaration>(KtDeclaration::class) {
|
||||
override fun isApplicableTo(element: KtDeclaration, settings: ConverterSettings?): Boolean {
|
||||
if (element.hasModifier(KtTokens.FINAL_KEYWORD)) {
|
||||
return !element.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|
||||
@@ -298,7 +295,7 @@ class RemoveRedundantModalityModifierProcessing : ApplicabilityBasedInspectionLi
|
||||
}
|
||||
|
||||
|
||||
class RemoveRedundantVisibilityModifierProcessing : ApplicabilityBasedInspectionLikeProcessing<KtDeclaration>(KtDeclaration::class) {
|
||||
class RemoveRedundantVisibilityModifierProcessing : InspectionLikeProcessingForElement<KtDeclaration>(KtDeclaration::class) {
|
||||
override fun isApplicableTo(element: KtDeclaration, settings: ConverterSettings?) = when {
|
||||
element.hasModifier(KtTokens.PUBLIC_KEYWORD) && element.hasModifier(KtTokens.OVERRIDE_KEYWORD) ->
|
||||
false
|
||||
@@ -314,7 +311,7 @@ class RemoveRedundantVisibilityModifierProcessing : ApplicabilityBasedInspection
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveExplicitOpenInInterfaceProcessing : ApplicabilityBasedInspectionLikeProcessing<KtClass>(KtClass::class) {
|
||||
class RemoveExplicitOpenInInterfaceProcessing : InspectionLikeProcessingForElement<KtClass>(KtClass::class) {
|
||||
override fun isApplicableTo(element: KtClass, settings: ConverterSettings?): Boolean =
|
||||
element.isValid
|
||||
&& element.isInterface()
|
||||
@@ -325,7 +322,7 @@ class RemoveExplicitOpenInInterfaceProcessing : ApplicabilityBasedInspectionLike
|
||||
}
|
||||
}
|
||||
|
||||
class MoveGetterAndSetterAnnotationsToPropertyProcessing : ApplicabilityBasedInspectionLikeProcessing<KtProperty>(KtProperty::class) {
|
||||
class MoveGetterAndSetterAnnotationsToPropertyProcessing : InspectionLikeProcessingForElement<KtProperty>(KtProperty::class) {
|
||||
override fun isApplicableTo(element: KtProperty, settings: ConverterSettings?): Boolean =
|
||||
element.accessors.isNotEmpty()
|
||||
|
||||
@@ -345,16 +342,17 @@ class MoveGetterAndSetterAnnotationsToPropertyProcessing : ApplicabilityBasedIns
|
||||
}
|
||||
}
|
||||
|
||||
class RedundantExplicitTypeInspectionBasedProcessing : ApplicabilityBasedInspectionLikeProcessing<KtProperty>(KtProperty::class) {
|
||||
class RedundantExplicitTypeInspectionBasedProcessing : InspectionLikeProcessingForElement<KtProperty>(KtProperty::class) {
|
||||
override fun isApplicableTo(element: KtProperty, settings: ConverterSettings?): Boolean =
|
||||
RedundantExplicitTypeInspection.hasRedundantType(element)
|
||||
|
||||
override fun apply(element: KtProperty) {
|
||||
element.typeReference = null
|
||||
RemoveExplicitTypeIntention.removeExplicitType(element)
|
||||
}
|
||||
}
|
||||
|
||||
class CanBeValInspectionBasedProcessing : ApplicabilityBasedInspectionLikeProcessing<KtDeclaration>(KtDeclaration::class) {
|
||||
class CanBeValInspectionBasedProcessing : InspectionLikeProcessingForElement<KtDeclaration>(KtDeclaration::class) {
|
||||
override fun isApplicableTo(element: KtDeclaration, settings: ConverterSettings?): Boolean =
|
||||
CanBeValInspection.canBeVal(element, ignoreNotUsedVals = false)
|
||||
|
||||
@@ -365,7 +363,7 @@ class CanBeValInspectionBasedProcessing : ApplicabilityBasedInspectionLikeProces
|
||||
}
|
||||
|
||||
|
||||
class MayBeConstantInspectionBasedProcessing : ApplicabilityBasedInspectionLikeProcessing<KtProperty>(KtProperty::class) {
|
||||
class MayBeConstantInspectionBasedProcessing : InspectionLikeProcessingForElement<KtProperty>(KtProperty::class) {
|
||||
override fun isApplicableTo(element: KtProperty, settings: ConverterSettings?): Boolean =
|
||||
with(MayBeConstantInspection) {
|
||||
val status = element.getStatus()
|
||||
@@ -378,7 +376,7 @@ class MayBeConstantInspectionBasedProcessing : ApplicabilityBasedInspectionLikeP
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveExplicitUnitTypeProcessing : ApplicabilityBasedInspectionLikeProcessing<KtNamedFunction>(KtNamedFunction::class) {
|
||||
class RemoveExplicitUnitTypeProcessing : InspectionLikeProcessingForElement<KtNamedFunction>(KtNamedFunction::class) {
|
||||
override fun isApplicableTo(element: KtNamedFunction, settings: ConverterSettings?): Boolean {
|
||||
val typeReference = element.typeReference?.typeElement ?: return false
|
||||
if (!typeReference.textMatches("Unit")) return false
|
||||
@@ -386,13 +384,13 @@ class RemoveExplicitUnitTypeProcessing : ApplicabilityBasedInspectionLikeProcess
|
||||
}
|
||||
|
||||
override fun apply(element: KtNamedFunction) {
|
||||
RemoveExplicitTypeIntention.removeExplicitType(element)
|
||||
element.typeReference = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class RemoveExplicitGetterInspectionBasedProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtPropertyAccessor>(KtPropertyAccessor::class) {
|
||||
InspectionLikeProcessingForElement<KtPropertyAccessor>(KtPropertyAccessor::class) {
|
||||
override fun isApplicableTo(element: KtPropertyAccessor, settings: ConverterSettings?): Boolean =
|
||||
element.isRedundantGetter()
|
||||
|
||||
@@ -402,7 +400,7 @@ class RemoveExplicitGetterInspectionBasedProcessing :
|
||||
}
|
||||
|
||||
class RemoveExplicitSetterInspectionBasedProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtPropertyAccessor>(KtPropertyAccessor::class) {
|
||||
InspectionLikeProcessingForElement<KtPropertyAccessor>(KtPropertyAccessor::class) {
|
||||
override fun isApplicableTo(element: KtPropertyAccessor, settings: ConverterSettings?): Boolean =
|
||||
element.isRedundantSetter()
|
||||
|
||||
@@ -413,7 +411,7 @@ class RemoveExplicitSetterInspectionBasedProcessing :
|
||||
|
||||
|
||||
class RedundantSemicolonInspectionBasedProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<PsiElement>(PsiElement::class) {
|
||||
InspectionLikeProcessingForElement<PsiElement>(PsiElement::class) {
|
||||
override fun isApplicableTo(element: PsiElement, settings: ConverterSettings?): Boolean =
|
||||
element.node.elementType == KtTokens.SEMICOLON
|
||||
&& RedundantSemicolonInspection.isRedundantSemicolon(element)
|
||||
@@ -425,7 +423,7 @@ class RedundantSemicolonInspectionBasedProcessing :
|
||||
|
||||
|
||||
class RedundantCompanionReferenceInspectionBasedProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtReferenceExpression>(KtReferenceExpression::class) {
|
||||
InspectionLikeProcessingForElement<KtReferenceExpression>(KtReferenceExpression::class) {
|
||||
override fun isApplicableTo(element: KtReferenceExpression, settings: ConverterSettings?): Boolean =
|
||||
RedundantCompanionReferenceInspection.isRedundantCompanionReference(element)
|
||||
|
||||
@@ -435,7 +433,7 @@ class RedundantCompanionReferenceInspectionBasedProcessing :
|
||||
}
|
||||
|
||||
class ExplicitThisInspectionBasedProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtExpression>(KtExpression::class) {
|
||||
InspectionLikeProcessingForElement<KtExpression>(KtExpression::class) {
|
||||
override fun isApplicableTo(element: KtExpression, settings: ConverterSettings?): Boolean =
|
||||
ExplicitThisInspection.hasExplicitThis(element)
|
||||
|
||||
@@ -449,7 +447,7 @@ class ExplicitThisInspectionBasedProcessing :
|
||||
}
|
||||
|
||||
class LiftReturnInspectionBasedProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtExpression>(KtExpression::class) {
|
||||
InspectionLikeProcessingForElement<KtExpression>(KtExpression::class) {
|
||||
override fun isApplicableTo(element: KtExpression, settings: ConverterSettings?): Boolean =
|
||||
LiftReturnOrAssignmentInspection.getState(element, false)?.any {
|
||||
it.liftType == LiftReturnOrAssignmentInspection.Companion.LiftType.LIFT_RETURN_OUT
|
||||
@@ -461,7 +459,7 @@ class LiftReturnInspectionBasedProcessing :
|
||||
}
|
||||
|
||||
class LiftAssignmentInspectionBasedProcessing :
|
||||
ApplicabilityBasedInspectionLikeProcessing<KtExpression>(KtExpression::class) {
|
||||
InspectionLikeProcessingForElement<KtExpression>(KtExpression::class) {
|
||||
override fun isApplicableTo(element: KtExpression, settings: ConverterSettings?): Boolean =
|
||||
LiftReturnOrAssignmentInspection.getState(element, false)?.any {
|
||||
it.liftType == LiftReturnOrAssignmentInspection.Companion.LiftType.LIFT_ASSIGNMENT_OUT
|
||||
@@ -470,4 +468,14 @@ class LiftAssignmentInspectionBasedProcessing :
|
||||
override fun apply(element: KtExpression) {
|
||||
BranchedFoldingUtils.foldToAssignment(element)
|
||||
}
|
||||
}
|
||||
|
||||
class MoveLambdaOutsideParenthesesProcessing :
|
||||
InspectionLikeProcessingForElement<KtCallExpression>(KtCallExpression::class) {
|
||||
override fun isApplicableTo(element: KtCallExpression, settings: ConverterSettings?): Boolean =
|
||||
element.canMoveLambdaOutsideParentheses()
|
||||
|
||||
override fun apply(element: KtCallExpression) {
|
||||
element.moveFunctionLiteralOutsideParentheses()
|
||||
}
|
||||
}
|
||||
+47
-38
@@ -6,58 +6,66 @@
|
||||
package org.jetbrains.kotlin.nj2k.postProcessing.processings
|
||||
|
||||
import com.intellij.codeInsight.actions.OptimizeImportsProcessor
|
||||
import com.intellij.openapi.editor.RangeMarker
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import org.jetbrains.kotlin.idea.core.util.range
|
||||
import org.jetbrains.kotlin.idea.formatter.commitAndUnblockDocument
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.nj2k.asLabel
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.postProcessing
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.GeneralPostProcessing
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.runUndoTransparentActionInEdt
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||
|
||||
val formatCodeProcessing =
|
||||
postProcessing { file, rangeMarker, _ ->
|
||||
file.commitAndUnblockDocument()
|
||||
|
||||
class FormatCodeProcessing : GeneralPostProcessing {
|
||||
override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
val codeStyleManager = CodeStyleManager.getInstance(file.project)
|
||||
if (rangeMarker != null) {
|
||||
if (rangeMarker.isValid) {
|
||||
codeStyleManager.reformatRange(file, rangeMarker.startOffset, rangeMarker.endOffset)
|
||||
}
|
||||
} else {
|
||||
codeStyleManager.reformat(file)
|
||||
}
|
||||
}
|
||||
|
||||
val clearUnknownLabelsProcessing =
|
||||
postProcessing { file, _, _ ->
|
||||
file.clearUndefinedLabels()
|
||||
}
|
||||
|
||||
private fun KtFile.clearUndefinedLabels() {
|
||||
val comments = mutableListOf<PsiComment>()
|
||||
accept(object : PsiElementVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitComment(comment: PsiComment) {
|
||||
if (comment.text.asLabel() != null) {
|
||||
comments += comment
|
||||
runUndoTransparentActionInEdt(inWriteAction = true) {
|
||||
if (rangeMarker != null) {
|
||||
if (rangeMarker.isValid) {
|
||||
codeStyleManager.reformatRange(file, rangeMarker.startOffset, rangeMarker.endOffset)
|
||||
}
|
||||
} else {
|
||||
codeStyleManager.reformat(file)
|
||||
}
|
||||
}
|
||||
})
|
||||
comments.forEach { it.delete() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val optimizeImportsProcessing =
|
||||
postProcessing { file, rangeMarker, _ ->
|
||||
val elements = when {
|
||||
rangeMarker != null && rangeMarker.isValid -> file.elementsInRange(rangeMarker.range!!)
|
||||
rangeMarker != null && !rangeMarker.isValid -> emptyList()
|
||||
else -> file.children.asList()
|
||||
class ClearUnknownLabelsProcessing : GeneralPostProcessing {
|
||||
override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
val comments = mutableListOf<PsiComment>()
|
||||
runUndoTransparentActionInEdt(inWriteAction = true) {
|
||||
file.accept(object : PsiElementVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitComment(comment: PsiComment) {
|
||||
if (comment.text.asLabel() != null) {
|
||||
comments += comment
|
||||
}
|
||||
}
|
||||
})
|
||||
comments.forEach { it.delete() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class OptimizeImportsProcessing : GeneralPostProcessing {
|
||||
override fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
val elements = runReadAction {
|
||||
when {
|
||||
rangeMarker != null && rangeMarker.isValid -> file.elementsInRange(rangeMarker.range!!)
|
||||
rangeMarker != null && !rangeMarker.isValid -> emptyList()
|
||||
else -> file.children.asList()
|
||||
}
|
||||
}
|
||||
val needFormat = elements.any { element ->
|
||||
element is KtElement
|
||||
@@ -65,7 +73,8 @@ val optimizeImportsProcessing =
|
||||
&& element !is KtImportList
|
||||
&& element !is KtPackageDirective
|
||||
}
|
||||
if (needFormat) {
|
||||
if (needFormat) runUndoTransparentActionInEdt(inWriteAction = false) {
|
||||
OptimizeImportsProcessor(file.project, file).run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.postProcessing
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.LocalSearchScope
|
||||
@@ -79,4 +82,16 @@ inline fun <reified T : PsiElement> List<PsiElement>.descendantsOfType(): List<T
|
||||
flatMap { it.collectDescendantsOfType() }
|
||||
|
||||
fun PsiElement.isInRange(outerRange: TextRange) =
|
||||
outerRange.contains(range)
|
||||
outerRange.contains(range)
|
||||
|
||||
internal fun runUndoTransparentActionInEdt(inWriteAction: Boolean, action: () -> Unit) {
|
||||
ApplicationManager.getApplication().invokeAndWait {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||
if (inWriteAction) {
|
||||
runWriteAction(action)
|
||||
} else {
|
||||
action()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,6 @@ internal interface I {
|
||||
internal class C {
|
||||
fun foo(i: I) {
|
||||
val result = i.string
|
||||
if (result != null) {
|
||||
print(result)
|
||||
}
|
||||
result?.let { print(it) }
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,6 @@ internal interface I {
|
||||
internal class C {
|
||||
fun foo(i: I) {
|
||||
val result = i.string
|
||||
if (result != null) {
|
||||
print(result)
|
||||
}
|
||||
result?.let { print(it) }
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,6 @@ internal class C {
|
||||
fun foo(i: I, b: Boolean) {
|
||||
var result = i.string
|
||||
if (b) result = null
|
||||
if (result != null) {
|
||||
print(result)
|
||||
}
|
||||
result?.let { print(it) }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
fun foo(s: String?) {
|
||||
if (s != null) {
|
||||
zoo(s)
|
||||
}
|
||||
s?.let { zoo(it) }
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
// !specifyLocalVariableTypeByDefault: true
|
||||
|
||||
fun bar(): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
val s: String? = bar()
|
||||
if (s != null) {
|
||||
zoo(s)
|
||||
}
|
||||
s?.let { zoo(it) }
|
||||
}
|
||||
+1
-1
@@ -21,6 +21,6 @@ internal class C {
|
||||
}
|
||||
|
||||
fun foo(javaClass: JavaClass): Int {
|
||||
return javaClass.get(0)
|
||||
return javaClass[0]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user