Improve J2K progress reporting

This commit is contained in:
Simon Ogorodnik
2020-07-27 14:34:53 +03:00
parent 8bcf1000f6
commit dc963e4ff6
6 changed files with 95 additions and 18 deletions
@@ -298,6 +298,7 @@ interface WithProgressProcessor {
): List<TOutputItem>
fun updateState(fileIndex: Int?, phase: Int, description: String)
fun updateState(phase: Int, subPhase: Int, subPhaseCount: Int, fileIndex: Int?, description: String)
fun <T> process(action: () -> T): T
}
@@ -348,6 +349,16 @@ class OldWithProgressProcessor(private val progress: ProgressIndicator?, private
override fun updateState(fileIndex: Int?, phase: Int, description: String) {
throw AbstractMethodError("Should not be called for old J2K")
}
override fun updateState(
phase: Int,
subPhase: Int,
subPhaseCount: Int,
fileIndex: Int?,
description: String
) {
error("Should not be called for old J2K")
}
}
class ProgressPortionReporter(
@@ -54,7 +54,7 @@ class NewJ2kPostProcessor : PostProcessor {
) {
if (converterContext !is NewJ2kConverterContext) error("Invalid converter context for new J2K")
for ((i, group) in processings.withIndex()) {
onPhaseChanged?.invoke(i + 1, group.description)
onPhaseChanged?.invoke(i, group.description)
for (processing in group.processings) {
try {
processing.runProcessingConsideringOptions(target, converterContext)
@@ -1,4 +1,5 @@
progress.text={0} - phase {1,number,#} of {2,number,#}
subphase.progress.text={0} ({1,number,#}/{2,number,#}) - phase {3,number,#} of {4,number,#}
progress.searching.usages.to.update=Searching usages to update...
phase.converting.j2k=Converting Java code to Kotlin code
@@ -18,13 +18,13 @@ interface Conversion {
val typeFactory: JKTypeFactory
get() = context.typeFactory
fun runConversion(treeRoots: List<JKTreeElement>, context: NewJ2kConverterContext): Boolean
fun runConversion(treeRoots: Sequence<JKTreeElement>, context: NewJ2kConverterContext): Boolean
}
interface SequentialBaseConversion : Conversion {
fun runConversion(treeRoot: JKTreeElement, context: NewJ2kConverterContext): Boolean
override fun runConversion(treeRoots: List<JKTreeElement>, context: NewJ2kConverterContext): Boolean {
override fun runConversion(treeRoots: Sequence<JKTreeElement>, context: NewJ2kConverterContext): Boolean {
return treeRoots.asSequence().map { runConversion(it, context) }.max() ?: false
}
}
@@ -85,10 +85,20 @@ object ConversionsRunner {
AddElementsInfoConversion(context)
)
fun doApply(trees: List<JKTreeRoot>, context: NewJ2kConverterContext) {
fun doApply(
trees: List<JKTreeRoot>,
context: NewJ2kConverterContext,
updateProgress: (conversionIndex: Int, conversionCount: Int, fileIndex: Int, String) -> Unit
) {
val conversions = createConversions(context)
for (conversion in conversions) {
conversion.runConversion(trees, context)
for ((conversionIndex, conversion) in conversions.withIndex()) {
val treeSequence = trees.asSequence().onEachIndexed { index, _ ->
updateProgress(conversionIndex, conversions.size, index, conversion::class.simpleName ?: "Converting...")
}
conversion.runConversion(treeSequence, context)
}
}
}
@@ -52,14 +52,15 @@ class NewJavaToKotlinConverter(
private val LOG = Logger.getInstance("#org.jetbrains.kotlin.j2k.JavaToKotlinConverter")
private val phasesCount = J2KConversionPhase.values().size
override fun filesToKotlin(
files: List<PsiJavaFile>,
postProcessor: PostProcessor,
progress: ProgressIndicator
): FilesResult {
progress.isIndeterminate = false
val phasesCount = postProcessor.phasesCount + 1
val withProgressProcessor = NewJ2kWithProgressProcessor(progress, files, phasesCount)
val withProgressProcessor = NewJ2kWithProgressProcessor(progress, files, postProcessor.phasesCount + phasesCount)
return withProgressProcessor.process {
val (results, externalCodeProcessing, context) =
ApplicationManager.getApplication().runReadAction(Computable {
@@ -69,6 +70,11 @@ class NewJavaToKotlinConverter(
val kotlinFiles = results.mapIndexed { i, result ->
runUndoTransparentActionInEdt(inWriteAction = true) {
val javaFile = files[i]
withProgressProcessor.updateState(
fileIndex = i,
phase = J2KConversionPhase.CREATE_FILES,
description = "Creating files..."
)
KtPsiFactory(project).createFileWithLightClassSupport(
javaFile.name.replace(".java", ".kt"),
result!!.text,
@@ -84,7 +90,7 @@ class NewJavaToKotlinConverter(
JKMultipleFilesPostProcessingTarget(kotlinFiles),
context
) { phase, description ->
withProgressProcessor.updateState(fileIndex = null, phase = phase + 1, description = description)
withProgressProcessor.updateState(fileIndex = null, phase = phase + phasesCount, description = description)
}
FilesResult(kotlinFiles.map { it.text }, externalCodeProcessing)
}
@@ -103,7 +109,7 @@ class NewJavaToKotlinConverter(
if (importList == null) {
addImportList(createdImportList)
} else {
val updatedList = if(importList.firstChild != null) {
val updatedList = if (importList.firstChild != null) {
createdImportList.addRangeBefore(importList.firstChild, importList.lastChild, createdImportList.firstChild)
} else createdImportList
importList.replace(updatedList)
@@ -149,7 +155,7 @@ class NewJavaToKotlinConverter(
}
val asts = inputElements.mapIndexed { i, element ->
processor.updateState(i, 1, phaseDescription)
processor.updateState(i, J2KConversionPhase.BUILD_AST, phaseDescription)
element to treeBuilder.buildTree(element, saveImports)
}
val inConversionContext = { element: PsiElement ->
@@ -172,13 +178,18 @@ class NewJavaToKotlinConverter(
externalCodeProcessing,
languageVersion.supportsFeature(LanguageFeature.FunctionalInterfaceConversion)
)
ConversionsRunner.doApply(asts.withIndex().mapNotNull { (i, ast) ->
processor.updateState(i, 1, phaseDescription)
ast.second
}, context)
ConversionsRunner.doApply(asts.mapNotNull { it.second }, context) { conversionIndex, conversionCount, i, desc ->
processor.updateState(
J2KConversionPhase.RUN_CONVERSIONS.phaseNumber,
conversionIndex,
conversionCount,
i,
desc
)
}
val results = asts.mapIndexed { i, elementWithAst ->
processor.updateState(i, 1, phaseDescription)
processor.updateState(i, J2KConversionPhase.PRINT_CODE, phaseDescription)
val (element, ast) = elementWithAst
if (ast == null) return@mapIndexed null
val code = JKCodeBuilder(context).run { printCodeOut(ast) }
@@ -215,9 +226,42 @@ class NewJ2kWithProgressProcessor(
}
override fun updateState(fileIndex: Int?, phase: Int, description: String) {
if (fileIndex == null)
updateState(phase, 1, 1, fileIndex, description)
else
updateState(phase, 0, 1, fileIndex, description)
}
override fun updateState(
phase: Int,
subPhase: Int,
subPhaseCount: Int,
fileIndex: Int?,
description: String
) {
progress?.checkCanceled()
progress?.fraction = phase / phasesCount.toDouble()
progress?.text = KotlinNJ2KBundle.message("progress.text", description, phase, phasesCount)
val singlePhaseFraction = 1.0 / phasesCount.toDouble()
val singleSubPhaseFraction = singlePhaseFraction / subPhaseCount.toDouble()
var resultFraction = phase * singlePhaseFraction + subPhase * singleSubPhaseFraction
if (files != null && fileIndex != null && files.isNotEmpty()) {
val fileFraction = singleSubPhaseFraction / files.size.toDouble()
resultFraction += fileFraction * fileIndex
}
progress?.fraction = resultFraction
if (subPhaseCount > 1) {
progress?.text = KotlinNJ2KBundle.message(
"subphase.progress.text",
description,
subPhase,
subPhaseCount,
phase + 1,
phasesCount
)
} else {
progress?.text = KotlinNJ2KBundle.message("progress.text", description, phase + 1, phasesCount)
}
progress?.text2 = when {
files != null && files.isNotEmpty() && fileIndex != null -> files[fileIndex].virtualFile.presentableUrl + if (files.size > 1) " ($fileIndex/${files.size})" else ""
else -> ""
@@ -238,4 +282,15 @@ class NewJ2kWithProgressProcessor(
return result!!
}
}
internal fun WithProgressProcessor.updateState(fileIndex: Int?, phase: J2KConversionPhase, description: String) {
updateState(fileIndex, phase.phaseNumber, description)
}
internal enum class J2KConversionPhase(val phaseNumber: Int) {
BUILD_AST(0),
RUN_CONVERSIONS(1),
PRINT_CODE(2),
CREATE_FILES(3)
}