New J2K: add conversion progress bar
Relates to #KT-31812
This commit is contained in:
@@ -27,8 +27,8 @@ import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||
import org.jetbrains.kotlin.idea.core.util.range
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.idea.core.util.range
|
||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
@@ -42,6 +42,9 @@ import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||
import java.util.*
|
||||
|
||||
class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
||||
|
||||
override val phasesCount: Int = 1
|
||||
|
||||
override fun insertImport(file: KtFile, fqName: FqName) {
|
||||
ApplicationManager.getApplication().invokeAndWait {
|
||||
runWriteAction {
|
||||
@@ -57,7 +60,12 @@ class J2kPostProcessor(private val formatCode: Boolean) : PostProcessor {
|
||||
PROCESS
|
||||
}
|
||||
|
||||
override fun doAdditionalProcessing(file: KtFile, converterContext: ConverterContext?, rangeMarker: RangeMarker?) =
|
||||
override fun doAdditionalProcessing(
|
||||
file: KtFile,
|
||||
converterContext: ConverterContext?,
|
||||
rangeMarker: RangeMarker?,
|
||||
onPhaseChanged: ((Int, String) -> Unit)?
|
||||
) =
|
||||
runBlocking(EDT.ModalityStateElement(ModalityState.defaultModalityState())) {
|
||||
do {
|
||||
var modificationStamp: Long? = file.modificationStamp
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
package org.jetbrains.kotlin.idea.j2k
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import org.jetbrains.kotlin.j2k.*
|
||||
|
||||
object JavaToKotlinConverterFactory {
|
||||
@@ -20,6 +22,17 @@ object JavaToKotlinConverterFactory {
|
||||
fun createPostProcessor(formatCode: Boolean): PostProcessor =
|
||||
J2kConverterExtension.extension.createPostProcessor(formatCode)
|
||||
|
||||
fun createWithProgressIndicator(
|
||||
progress: ProgressIndicator?,
|
||||
files: List<PsiJavaFile>?,
|
||||
phasesCount: Int
|
||||
): WithProgressProcessor =
|
||||
J2kConverterExtension.extension.createWithProgressProcessor(progress, files, phasesCount)
|
||||
|
||||
|
||||
fun doCheckBeforeConversion(project: Project, module: Module): Boolean =
|
||||
J2kConverterExtension.extension.doCheckBeforeConversion(project, module)
|
||||
|
||||
val isNewJ2k: Boolean
|
||||
get() = J2kConverterExtension.extension.isNewJ2k
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package org.jetbrains.kotlin.idea.j2k
|
||||
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import org.jetbrains.kotlin.j2k.*
|
||||
|
||||
class OldJ2kConverterExtension : J2kConverterExtension() {
|
||||
@@ -15,4 +17,11 @@ class OldJ2kConverterExtension : J2kConverterExtension() {
|
||||
|
||||
override fun createPostProcessor(formatCode: Boolean): PostProcessor =
|
||||
J2kPostProcessor(formatCode)
|
||||
|
||||
override fun createWithProgressProcessor(
|
||||
progress: ProgressIndicator?,
|
||||
files: List<PsiJavaFile>?,
|
||||
phasesCount: Int
|
||||
): WithProgressProcessor =
|
||||
OldWithProgressProcessor(progress, files)
|
||||
}
|
||||
+2
-1
@@ -257,7 +257,8 @@ class KotlinCodeFragmentFactory : CodeFragmentFactory() {
|
||||
.run(
|
||||
convertedFragment!!,
|
||||
conversionContext,
|
||||
range = null
|
||||
range = null,
|
||||
onPhaseChanged = null
|
||||
)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
|
||||
+36
-7
@@ -33,8 +33,8 @@ import org.jetbrains.kotlin.idea.actions.JavaToKotlinAction
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||
import org.jetbrains.kotlin.idea.codeInsight.KotlinCopyPasteReferenceProcessor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.KotlinReferenceData
|
||||
import org.jetbrains.kotlin.idea.core.util.start
|
||||
import org.jetbrains.kotlin.idea.core.util.range
|
||||
import org.jetbrains.kotlin.idea.core.util.start
|
||||
import org.jetbrains.kotlin.idea.editor.KotlinEditorOptions
|
||||
import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices
|
||||
import org.jetbrains.kotlin.idea.j2k.JavaToKotlinConverterFactory
|
||||
@@ -161,12 +161,7 @@ class ConvertJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransferab
|
||||
val newBounds = insertImports(boundsAfterReplace, referenceData, explicitImports)
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
AfterConversionPass(project, JavaToKotlinConverterFactory.createPostProcessor(formatCode = true))
|
||||
.run(
|
||||
targetFile,
|
||||
conversionResult?.converterContext,
|
||||
newBounds
|
||||
)
|
||||
runPostProcessing(project, targetFile, newBounds, conversionResult?.converterContext)
|
||||
|
||||
conversionPerformed = true
|
||||
}
|
||||
@@ -304,3 +299,37 @@ internal fun confirmConvertJavaOnPaste(project: Project, isPlainText: Boolean):
|
||||
return dialog.isOK
|
||||
}
|
||||
|
||||
|
||||
fun runPostProcessing(project: Project, file: KtFile, bounds: TextRange?, converterContext: ConverterContext?) {
|
||||
val postProcessor = JavaToKotlinConverterFactory.createPostProcessor(formatCode = true)
|
||||
if (JavaToKotlinConverterFactory.isNewJ2k) {
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
{
|
||||
val processor =
|
||||
JavaToKotlinConverterFactory.createWithProgressIndicator(
|
||||
ProgressManager.getInstance().progressIndicator!!,
|
||||
emptyList(),
|
||||
postProcessor.phasesCount
|
||||
)
|
||||
AfterConversionPass(project, postProcessor)
|
||||
.run(
|
||||
file,
|
||||
converterContext,
|
||||
bounds
|
||||
) { phase, description ->
|
||||
processor.updateState(0, phase, description)
|
||||
}
|
||||
},
|
||||
"Convert Java to Kotlin",
|
||||
true,
|
||||
project
|
||||
)
|
||||
} else {
|
||||
AfterConversionPass(project, postProcessor)
|
||||
.run(
|
||||
file,
|
||||
converterContext,
|
||||
bounds
|
||||
)
|
||||
}
|
||||
}
|
||||
+1
-8
@@ -36,9 +36,7 @@ import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.editor.KotlinEditorOptions
|
||||
import org.jetbrains.kotlin.idea.j2k.JavaToKotlinConverterFactory
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.j2k.AfterConversionPass
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||
@@ -130,12 +128,7 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
|
||||
}
|
||||
|
||||
psiDocumentManager.commitAllDocuments()
|
||||
AfterConversionPass(project, JavaToKotlinConverterFactory.createPostProcessor(formatCode = true))
|
||||
.run(
|
||||
targetFile,
|
||||
convertedResult.converterContext,
|
||||
newBounds
|
||||
)
|
||||
runPostProcessing(project, targetFile, newBounds, convertedResult.converterContext)
|
||||
|
||||
conversionPerformed = true
|
||||
}
|
||||
|
||||
@@ -18,20 +18,25 @@ package org.jetbrains.kotlin.j2k
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
class AfterConversionPass(val project: Project, val postProcessor: PostProcessor) {
|
||||
fun run(kotlinFile: KtFile, converterContext: ConverterContext?, range: TextRange?) {
|
||||
@JvmOverloads
|
||||
fun run(
|
||||
kotlinFile: KtFile,
|
||||
converterContext: ConverterContext?,
|
||||
range: TextRange?,
|
||||
onPhaseChanged: ((Int, String) -> Unit)? = null
|
||||
) {
|
||||
val rangeMarker = if (range != null) {
|
||||
val document = kotlinFile.viewProvider.document!!
|
||||
val marker = document.createRangeMarker(range.startOffset, range.endOffset)
|
||||
val marker = runReadAction { document.createRangeMarker(range.startOffset, range.endOffset) }
|
||||
marker.isGreedyToLeft = true
|
||||
marker.isGreedyToRight = true
|
||||
marker
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else null
|
||||
|
||||
postProcessor.doAdditionalProcessing(kotlinFile, converterContext, rangeMarker)
|
||||
postProcessor.doAdditionalProcessing(kotlinFile, converterContext, rangeMarker, onPhaseChanged)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ package org.jetbrains.kotlin.j2k
|
||||
import com.intellij.openapi.extensions.AbstractExtensionPointBean
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
|
||||
abstract class J2kConverterExtension : AbstractExtensionPointBean() {
|
||||
abstract val isNewJ2k: Boolean
|
||||
@@ -20,6 +22,12 @@ abstract class J2kConverterExtension : AbstractExtensionPointBean() {
|
||||
open fun doCheckBeforeConversion(project: Project, module: Module): Boolean =
|
||||
true
|
||||
|
||||
abstract fun createWithProgressProcessor(
|
||||
progress: ProgressIndicator?,
|
||||
files: List<PsiJavaFile>?,
|
||||
phasesCount: Int
|
||||
): WithProgressProcessor
|
||||
|
||||
companion object {
|
||||
private fun useNewJ2k() = Registry.`is`("kotlin.use.new.j2k", false)
|
||||
|
||||
|
||||
@@ -40,7 +40,14 @@ import java.util.*
|
||||
interface PostProcessor {
|
||||
fun insertImport(file: KtFile, fqName: FqName)
|
||||
|
||||
fun doAdditionalProcessing(file: KtFile, converterContext: ConverterContext?, rangeMarker: RangeMarker?)
|
||||
val phasesCount: Int
|
||||
|
||||
fun doAdditionalProcessing(
|
||||
file: KtFile,
|
||||
converterContext: ConverterContext?,
|
||||
rangeMarker: RangeMarker?,
|
||||
onPhaseChanged: ((Int, String) -> Unit)?
|
||||
)
|
||||
}
|
||||
|
||||
enum class ParseContext {
|
||||
@@ -73,9 +80,7 @@ abstract class JavaToKotlinConverter {
|
||||
progress: ProgressIndicator = EmptyProgressIndicator()
|
||||
): FilesResult
|
||||
|
||||
fun elementsToKotlin(inputElements: List<PsiElement>): Result {
|
||||
return elementsToKotlin(inputElements, WithProgressProcessor.DEFAULT)
|
||||
}
|
||||
abstract fun elementsToKotlin(inputElements: List<PsiElement>): Result
|
||||
}
|
||||
|
||||
class OldJavaToKotlinConverter(
|
||||
@@ -91,7 +96,7 @@ class OldJavaToKotlinConverter(
|
||||
postProcessor: PostProcessor,
|
||||
progress: ProgressIndicator
|
||||
): FilesResult {
|
||||
val withProgressProcessor = WithProgressProcessor(progress, files)
|
||||
val withProgressProcessor = OldWithProgressProcessor(progress, files)
|
||||
val (results, externalCodeProcessing) = ApplicationManager.getApplication().runReadAction(Computable {
|
||||
elementsToKotlin(files, withProgressProcessor)
|
||||
})
|
||||
@@ -106,7 +111,7 @@ class OldJavaToKotlinConverter(
|
||||
|
||||
result!!.importsToAdd.forEach { postProcessor.insertImport(kotlinFile, it) }
|
||||
|
||||
AfterConversionPass(project, postProcessor).run(kotlinFile, converterContext = null, range = null)
|
||||
AfterConversionPass(project, postProcessor).run(kotlinFile, converterContext = null, range = null, onPhaseChanged = null)
|
||||
|
||||
kotlinFile.text
|
||||
} catch (e: ProcessCanceledException) {
|
||||
@@ -157,6 +162,11 @@ class OldJavaToKotlinConverter(
|
||||
}
|
||||
}
|
||||
|
||||
override fun elementsToKotlin(inputElements: List<PsiElement>): Result {
|
||||
return elementsToKotlin(inputElements, OldWithProgressProcessor.DEFAULT)
|
||||
}
|
||||
|
||||
|
||||
private data class ReferenceInfo(
|
||||
val reference: PsiReference,
|
||||
val target: PsiElement,
|
||||
@@ -252,10 +262,21 @@ class OldJavaToKotlinConverter(
|
||||
}
|
||||
}
|
||||
|
||||
interface WithProgressProcessor {
|
||||
fun <TInputItem, TOutputItem> processItems(
|
||||
fractionPortion: Double,
|
||||
inputItems: Iterable<TInputItem>,
|
||||
processItem: (TInputItem) -> TOutputItem
|
||||
): List<TOutputItem>
|
||||
|
||||
class WithProgressProcessor(private val progress: ProgressIndicator?, private val files: List<PsiJavaFile>?) {
|
||||
fun updateState(fileIndex: Int, phase: Int, description: String)
|
||||
fun <T> process(action: () -> T): T
|
||||
}
|
||||
|
||||
|
||||
class OldWithProgressProcessor(private val progress: ProgressIndicator?, private val files: List<PsiJavaFile>?) : WithProgressProcessor {
|
||||
companion object {
|
||||
val DEFAULT = WithProgressProcessor(null, null)
|
||||
val DEFAULT = OldWithProgressProcessor(null, null)
|
||||
}
|
||||
|
||||
private val progressText = "Converting Java to Kotlin"
|
||||
@@ -264,7 +285,7 @@ class WithProgressProcessor(private val progress: ProgressIndicator?, private va
|
||||
private var fraction = 0.0
|
||||
private var pass = 1
|
||||
|
||||
fun <TInputItem, TOutputItem> processItems(
|
||||
override fun <TInputItem, TOutputItem> processItems(
|
||||
fractionPortion: Double,
|
||||
inputItems: Iterable<TInputItem>,
|
||||
processItem: (TInputItem) -> TOutputItem
|
||||
@@ -291,6 +312,14 @@ class WithProgressProcessor(private val progress: ProgressIndicator?, private va
|
||||
)
|
||||
return outputItems
|
||||
}
|
||||
|
||||
override fun <T> process(action: () -> T): T {
|
||||
throw AbstractMethodError("Should not be called for old J2K")
|
||||
}
|
||||
|
||||
override fun updateState(fileIndex: Int, phase: Int, description: String) {
|
||||
throw AbstractMethodError("Should not be called for old J2K")
|
||||
}
|
||||
}
|
||||
|
||||
private class ProgressPortionReporter(
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package org.jetbrains.kotlin.nj2k
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import org.jetbrains.kotlin.idea.configuration.getAbleToRunConfigurators
|
||||
import org.jetbrains.kotlin.idea.configuration.hasAnyKotlinRuntimeInScope
|
||||
import org.jetbrains.kotlin.idea.configuration.isModuleConfigured
|
||||
@@ -27,6 +29,13 @@ class NewJ2kConverterExtension : J2kConverterExtension() {
|
||||
override fun doCheckBeforeConversion(project: Project, module: Module): Boolean =
|
||||
checkKotlinIsConfigured(project, module)
|
||||
|
||||
override fun createWithProgressProcessor(
|
||||
progress: ProgressIndicator?,
|
||||
files: List<PsiJavaFile>?,
|
||||
phasesCount: Int
|
||||
): WithProgressProcessor =
|
||||
NewJ2kWithProgressProcessor(progress, files, phasesCount)
|
||||
|
||||
private fun checkKotlinIsConfigured(project: Project, module: Module): Boolean {
|
||||
val kotlinIsConfigured =
|
||||
hasAnyKotlinRuntimeInScope(module) || isModuleConfigured(module.toModuleGroup())
|
||||
|
||||
+17
-4
@@ -58,9 +58,17 @@ class NewJ2kPostProcessor : PostProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
override fun doAdditionalProcessing(file: KtFile, converterContext: ConverterContext?, rangeMarker: RangeMarker?) {
|
||||
override val phasesCount = processings.size
|
||||
|
||||
override fun doAdditionalProcessing(
|
||||
file: KtFile,
|
||||
converterContext: ConverterContext?,
|
||||
rangeMarker: RangeMarker?,
|
||||
onPhaseChanged: ((Int, String) -> Unit)?
|
||||
) {
|
||||
runBlocking(EDT.ModalityStateElement(ModalityState.defaultModalityState())) {
|
||||
for (processing in processings) {
|
||||
for ((i, processing) in processings.withIndex()) {
|
||||
onPhaseChanged?.invoke(i, processing.description)
|
||||
processing.runProcessing(file, rangeMarker, converterContext as NewJ2kConverterContext)
|
||||
commitFile(file)
|
||||
}
|
||||
@@ -82,15 +90,20 @@ private val processings: List<GeneralPostProcessing> = listOf(
|
||||
nullabilityProcessing,
|
||||
formatCodeProcessing,
|
||||
shortenReferencesProcessing,
|
||||
InspectionLikeProcessingGroup(VarToValProcessing()),
|
||||
InspectionLikeProcessingGroup(ConvertGettersAndSettersToPropertyProcessing.DESCRIPTION, VarToValProcessing()),
|
||||
ConvertGettersAndSettersToPropertyProcessing(),
|
||||
InspectionLikeProcessingGroup(MoveGetterAndSetterAnnotationsToPropertyProcessing()),
|
||||
InspectionLikeProcessingGroup(
|
||||
ConvertGettersAndSettersToPropertyProcessing.DESCRIPTION,
|
||||
MoveGetterAndSetterAnnotationsToPropertyProcessing()
|
||||
),
|
||||
InspectionLikeProcessingGroup(
|
||||
ConvertGettersAndSettersToPropertyProcessing.DESCRIPTION,
|
||||
generalInspectionBasedProcessing(RedundantGetterInspection()),
|
||||
generalInspectionBasedProcessing(RedundantSetterInspection())
|
||||
),
|
||||
ConvertToDataClassProcessing(),
|
||||
InspectionLikeProcessingGroup(
|
||||
"Cleaning up Kotlin code",
|
||||
RemoveRedundantVisibilityModifierProcessing(),
|
||||
RemoveRedundantModalityModifierProcessing(),
|
||||
RemoveRedundantConstructorKeywordProcessing(),
|
||||
|
||||
+10
-5
@@ -16,8 +16,8 @@ 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.range
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.idea.core.util.range
|
||||
import org.jetbrains.kotlin.idea.formatter.commitAndUnblockDocument
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractApplicabilityBasedInspection
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
|
||||
@@ -28,7 +28,7 @@ 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.*
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||
@@ -36,13 +36,18 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||
import org.jetbrains.kotlin.utils.mapToIndex
|
||||
import java.util.ArrayList
|
||||
import java.util.*
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
|
||||
class InspectionLikeProcessingGroup(val inspectionLikeProcessings: List<InspectionLikeProcessing>) : ProcessingGroup {
|
||||
constructor(vararg inspectionLikeProcessings: InspectionLikeProcessing) : this(inspectionLikeProcessings.toList())
|
||||
class InspectionLikeProcessingGroup(
|
||||
override val description: String,
|
||||
val inspectionLikeProcessings: List<InspectionLikeProcessing>
|
||||
) : ProcessingGroup {
|
||||
|
||||
constructor(description: String, vararg inspectionLikeProcessings: InspectionLikeProcessing) :
|
||||
this(description, inspectionLikeProcessings.toList())
|
||||
|
||||
private val processingsToPriorityMap = inspectionLikeProcessings.mapToIndex()
|
||||
fun priority(processing: InspectionLikeProcessing): Int = processingsToPriorityMap.getValue(processing)
|
||||
|
||||
@@ -18,10 +18,11 @@ import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||
|
||||
|
||||
interface GeneralPostProcessing {
|
||||
val description: String
|
||||
suspend fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext)
|
||||
}
|
||||
|
||||
abstract class SimplePostProcessing : GeneralPostProcessing {
|
||||
abstract class SimplePostProcessing(override val description: String) : GeneralPostProcessing {
|
||||
final override suspend fun runProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
withContext(EDT) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||
@@ -35,7 +36,7 @@ abstract class SimplePostProcessing : GeneralPostProcessing {
|
||||
abstract fun applySimpleProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext)
|
||||
}
|
||||
|
||||
abstract class ElementsBasedPostProcessing : SimplePostProcessing() {
|
||||
abstract class ElementsBasedPostProcessing(description: String) : SimplePostProcessing(description) {
|
||||
final override fun applySimpleProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
val elements =
|
||||
rangeMarker?.let { marker ->
|
||||
@@ -49,8 +50,11 @@ abstract class ElementsBasedPostProcessing : SimplePostProcessing() {
|
||||
|
||||
interface ProcessingGroup : GeneralPostProcessing
|
||||
|
||||
fun postProcessing(action: (file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) -> Unit): GeneralPostProcessing =
|
||||
object : SimplePostProcessing() {
|
||||
fun postProcessing(
|
||||
description: String,
|
||||
action: (file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) -> Unit
|
||||
): GeneralPostProcessing =
|
||||
object : SimplePostProcessing(description) {
|
||||
override fun applySimpleProcessing(file: KtFile, rangeMarker: RangeMarker?, converterContext: NewJ2kConverterContext) {
|
||||
action(file, rangeMarker, converterContext)
|
||||
}
|
||||
|
||||
+12
-4
@@ -11,7 +11,10 @@ import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.setVisibility
|
||||
import org.jetbrains.kotlin.idea.refactoring.isAbstract
|
||||
@@ -21,11 +24,13 @@ 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.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.nj2k.*
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.nj2k.asGetterName
|
||||
import org.jetbrains.kotlin.nj2k.asSetterName
|
||||
import org.jetbrains.kotlin.nj2k.parentOfType
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperclassesWithoutAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
@@ -38,7 +43,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.mapToIndex
|
||||
|
||||
class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing() {
|
||||
class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing(DESCRIPTION) {
|
||||
private fun KtNamedFunction.hasOverrides(): Boolean =
|
||||
toLightMethods().singleOrNull()?.let { lightMethod ->
|
||||
OverridingMethodsSearch.search(lightMethod).findFirst()
|
||||
@@ -520,6 +525,9 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
|
||||
}
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
const val DESCRIPTION = "Converting POJOs to data classes"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierTypeOrDefault
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
|
||||
class ConvertToDataClassProcessing : ElementsBasedPostProcessing() {
|
||||
class ConvertToDataClassProcessing : ElementsBasedPostProcessing(ConvertGettersAndSettersToPropertyProcessing.DESCRIPTION) {
|
||||
private fun KtCallableDeclaration.rename(newName: String) {
|
||||
val factory = KtPsiFactory(this)
|
||||
val escapedName = newName.escaped()
|
||||
|
||||
+4
-4
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.psi.KtPackageDirective
|
||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||
|
||||
val formatCodeProcessing =
|
||||
postProcessing { file, rangeMarker, _ ->
|
||||
postProcessing("Formating code") { file, rangeMarker, _ ->
|
||||
file.commitAndUnblockDocument()
|
||||
val codeStyleManager = CodeStyleManager.getInstance(file.project)
|
||||
if (rangeMarker != null) {
|
||||
@@ -35,7 +35,7 @@ val formatCodeProcessing =
|
||||
}
|
||||
|
||||
val nullabilityProcessing =
|
||||
postProcessing { file, rangeMarker, converterContext ->
|
||||
postProcessing("Inferring declarations nullability") { file, rangeMarker, converterContext ->
|
||||
NullabilityAnalysisFacade(
|
||||
converterContext,
|
||||
getTypeElementNullability = ::nullabilityByUndefinedNullabilityComment,
|
||||
@@ -45,7 +45,7 @@ val nullabilityProcessing =
|
||||
}
|
||||
|
||||
val shortenReferencesProcessing =
|
||||
postProcessing { file, rangeMarker, _ ->
|
||||
postProcessing("Shortening fully-qualified references") { file, rangeMarker, _ ->
|
||||
if (rangeMarker != null) {
|
||||
ShortenReferences.DEFAULT.process(file, rangeMarker.startOffset, rangeMarker.endOffset)
|
||||
} else {
|
||||
@@ -54,7 +54,7 @@ val shortenReferencesProcessing =
|
||||
}
|
||||
|
||||
val optimizeImportsProcessing =
|
||||
postProcessing { file, rangeMarker, _ ->
|
||||
postProcessing("Optimizing imports") { file, rangeMarker, _ ->
|
||||
val elements = if (rangeMarker != null) {
|
||||
file.elementsInRange(TextRange(rangeMarker.startOffset, rangeMarker.endOffset))
|
||||
} else file.children.asList()
|
||||
|
||||
@@ -20,8 +20,10 @@ 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.progress.EmptyProgressIndicator
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Computable
|
||||
import com.intellij.psi.PsiElement
|
||||
@@ -50,13 +52,15 @@ class NewJavaToKotlinConverter(
|
||||
postProcessor: PostProcessor,
|
||||
progress: ProgressIndicator
|
||||
): FilesResult {
|
||||
val withProgressProcessor = WithProgressProcessor(progress, files)
|
||||
val (results, externalCodeProcessing, context) = ApplicationManager.getApplication().runReadAction(Computable {
|
||||
elementsToKotlin(files, withProgressProcessor)
|
||||
})
|
||||
val phasesCount = postProcessor.phasesCount + 1
|
||||
val withProgressProcessor = NewJ2kWithProgressProcessor(progress, files, phasesCount)
|
||||
val (results, externalCodeProcessing, context) = withProgressProcessor.process {
|
||||
ApplicationManager.getApplication().runReadAction(Computable {
|
||||
elementsToKotlin(files, withProgressProcessor)
|
||||
})
|
||||
}
|
||||
|
||||
val texts = withProgressProcessor.processItems(0.5, results.withIndex()) { pair ->
|
||||
val (i, result) = pair
|
||||
val texts = results.mapIndexed { i, result ->
|
||||
try {
|
||||
val kotlinFile = ApplicationManager.getApplication().runReadAction(Computable {
|
||||
KtPsiFactory(project).createFileWithLightClassSupport("dummy.kt", result!!.text, files[i])
|
||||
@@ -71,9 +75,15 @@ class NewJavaToKotlinConverter(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AfterConversionPass(project, postProcessor).run(kotlinFile, context, range = null)
|
||||
|
||||
withProgressProcessor.process {
|
||||
AfterConversionPass(project, postProcessor).run(
|
||||
kotlinFile,
|
||||
context,
|
||||
range = null,
|
||||
onPhaseChanged = { phase, description ->
|
||||
withProgressProcessor.updateState(i, phase + 1, description)
|
||||
})
|
||||
}
|
||||
kotlinFile.text
|
||||
} catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
@@ -87,12 +97,19 @@ class NewJavaToKotlinConverter(
|
||||
}
|
||||
|
||||
override fun elementsToKotlin(inputElements: List<PsiElement>, processor: WithProgressProcessor): Result {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val processor = processor as NewJ2kWithProgressProcessor
|
||||
|
||||
val phaseDescription = "Converting Java code to Kotlin code"
|
||||
val symbolProvider = JKSymbolProvider()
|
||||
symbolProvider.preBuildTree(inputElements)
|
||||
val importStorage = ImportStorage()
|
||||
val treeBuilder = JavaToJKTreeBuilder(symbolProvider, converterServices, importStorage)
|
||||
val asts = inputElements.map { element ->
|
||||
element to treeBuilder.buildTree(element)
|
||||
val asts = processor.process {
|
||||
inputElements.mapIndexed { i, element ->
|
||||
processor.updateState(i, 1, phaseDescription)
|
||||
element to treeBuilder.buildTree(element)
|
||||
}
|
||||
}
|
||||
|
||||
val context = NewJ2kConverterContext(
|
||||
@@ -102,22 +119,69 @@ class NewJavaToKotlinConverter(
|
||||
importStorage,
|
||||
JKElementInfoStorage()
|
||||
)
|
||||
|
||||
ConversionsRunner.doApply(asts.mapNotNull { it.second }, context)
|
||||
val results = asts.map { (element, ast) ->
|
||||
if (ast == null) return@map null
|
||||
val code = NewCodeBuilder(context).run { printCodeOut(ast) }
|
||||
val parseContext = when (element) {
|
||||
is PsiStatement, is PsiExpression -> ParseContext.CODE_BLOCK
|
||||
else -> ParseContext.TOP_LEVEL
|
||||
processor.process {
|
||||
ConversionsRunner.doApply(asts.withIndex().mapNotNull { (i, ast) ->
|
||||
processor.updateState(i, 1, phaseDescription)
|
||||
ast.second
|
||||
}, context)
|
||||
}
|
||||
val results = processor.process {
|
||||
asts.mapIndexed { i, elementWithAst ->
|
||||
processor.updateState(i, 1, phaseDescription)
|
||||
val (element, ast) = elementWithAst
|
||||
if (ast == null) return@mapIndexed null
|
||||
val code = NewCodeBuilder(context).run { printCodeOut(ast) }
|
||||
val parseContext = when (element) {
|
||||
is PsiStatement, is PsiExpression -> ParseContext.CODE_BLOCK
|
||||
else -> ParseContext.TOP_LEVEL
|
||||
}
|
||||
ElementResult(
|
||||
code,
|
||||
importsToAdd = importStorage.getImports(),
|
||||
parseContext = parseContext
|
||||
)
|
||||
}
|
||||
ElementResult(
|
||||
code,
|
||||
importsToAdd = importStorage.getImports(),
|
||||
parseContext = parseContext
|
||||
)
|
||||
}
|
||||
|
||||
return Result(results, null, context)
|
||||
}
|
||||
|
||||
override fun elementsToKotlin(inputElements: List<PsiElement>): Result {
|
||||
return elementsToKotlin(inputElements, NewJ2kWithProgressProcessor.DEFAULT)
|
||||
}
|
||||
}
|
||||
|
||||
class NewJ2kWithProgressProcessor(
|
||||
private val progress: ProgressIndicator?,
|
||||
private val files: List<PsiJavaFile>?,
|
||||
private val phasesCount: Int
|
||||
) : WithProgressProcessor {
|
||||
companion object {
|
||||
val DEFAULT = NewJ2kWithProgressProcessor(null, null, 0)
|
||||
}
|
||||
|
||||
override fun updateState(fileIndex: Int, phase: Int, description: String) {
|
||||
progress?.checkCanceled()
|
||||
progress?.fraction = phase / phasesCount.toDouble()
|
||||
progress?.text = "$description - phase $phase of $phasesCount"
|
||||
if (files != null && files.isNotEmpty()) {
|
||||
progress?.text2 = files[fileIndex].virtualFile.presentableUrl
|
||||
}
|
||||
}
|
||||
|
||||
override fun <TInputItem, TOutputItem> processItems(
|
||||
fractionPortion: Double,
|
||||
inputItems: Iterable<TInputItem>,
|
||||
processItem: (TInputItem) -> TOutputItem
|
||||
): List<TOutputItem> {
|
||||
throw AbstractMethodError("Should not be called for new J2K")
|
||||
}
|
||||
|
||||
override fun <T> process(action: () -> T): T {
|
||||
// we use special process with EmptyProgressIndicator to avoid changing text in our progress by inheritors search inside etc
|
||||
var result: T? = null
|
||||
ProgressManager.getInstance().runProcess({ result = action() }, EmptyProgressIndicator())
|
||||
return result!!
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user