From a7d2238af4a0bc1ac74eb27aae90965e575d37af Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 13 Mar 2019 14:46:02 +0300 Subject: [PATCH] New J2K: Add IDEA integration of J2k --- .../evaluate/KotlinCodeFragmentFactory.kt | 4 +- idea/resources/META-INF/extensions/ide.xml | 13 + .../resources/META-INF/extensions/ide.xml.191 | 13 + .../META-INF/extensions/ide.xml.as33 | 13 + .../META-INF/extensions/ide.xml.as34 | 12 + .../kotlin/idea/actions/JavaToKotlinAction.kt | 18 +- .../idea/actions/JavaToKotlinAction.kt.181 | 17 +- .../idea/actions/JavaToKotlinAction.kt.as32 | 18 +- .../copy/ConvertJavaCopyPasteProcessor.kt | 12 +- .../copy/ConvertTextJavaCopyPasteProcessor.kt | 4 +- .../idea/j2k/JavaToKotlinConverterFactory.kt | 21 ++ .../idea/j2k/OldJ2kConveterExtension.kt | 18 ++ .../idea/refactoring/kotlinRefactoringUtil.kt | 12 +- .../kotlin/j2k/AfterConversionPass.kt | 3 +- .../kotlin/j2k/J2KConverterExtension.kt | 29 ++ .../kotlin/j2k/JavaToKotlinConverter.kt | 289 +++++++++--------- .../kotlin/j2k/JavaToKotlinTranslator.kt | 2 +- ...tractJavaToKotlinConverterMultiFileTest.kt | 2 +- ...ractJavaToKotlinConverterSingleFileTest.kt | 2 +- nj2k/build.gradle.kts | 5 +- nj2k/nj2k-services/build.gradle.kts | 2 + .../kotlin/nj2k/NewJ2kConveterExtension.kt | 18 ++ .../jetbrains/kotlin/nj2k/JKSymbolProvider.kt | 4 +- .../kotlin/nj2k/NewJavaToKotlinConverter.kt | 39 +-- ...tNewJavaToKotlinConverterSingleFileTest.kt | 17 +- 25 files changed, 378 insertions(+), 209 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/j2k/JavaToKotlinConverterFactory.kt create mode 100644 idea/src/org/jetbrains/kotlin/idea/j2k/OldJ2kConveterExtension.kt create mode 100644 j2k/src/org/jetbrains/kotlin/j2k/J2KConverterExtension.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/NewJ2kConveterExtension.kt diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt index 873c6312e06..7a9eeef095b 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt @@ -43,7 +43,7 @@ import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils import org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider import org.jetbrains.kotlin.idea.debugger.evaluate.compilation.DebugLabelPropertyDescriptorProvider -import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor +import org.jetbrains.kotlin.idea.j2k.JavaToKotlinConverterFactory import org.jetbrains.kotlin.idea.refactoring.j2k import org.jetbrains.kotlin.idea.refactoring.j2kText import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers @@ -253,7 +253,7 @@ class KotlinCodeFragmentFactory : CodeFragmentFactory() { kotlinCodeFragment.context ) - AfterConversionPass(project, J2kPostProcessor(formatCode = false)).run(convertedFragment!!, range = null) + AfterConversionPass(project, JavaToKotlinConverterFactory.createPostProcessor(formatCode = false)).run(convertedFragment!!, range = null) } } catch (e: Throwable) { // ignored because text can be invalid diff --git a/idea/resources/META-INF/extensions/ide.xml b/idea/resources/META-INF/extensions/ide.xml index 2132e30276e..c08ba05f9da 100644 --- a/idea/resources/META-INF/extensions/ide.xml +++ b/idea/resources/META-INF/extensions/ide.xml @@ -57,6 +57,9 @@ + + @@ -88,5 +91,15 @@ + + + + + + + diff --git a/idea/resources/META-INF/extensions/ide.xml.191 b/idea/resources/META-INF/extensions/ide.xml.191 index 45a7f3e9b27..2f30ab333f4 100644 --- a/idea/resources/META-INF/extensions/ide.xml.191 +++ b/idea/resources/META-INF/extensions/ide.xml.191 @@ -49,6 +49,9 @@ + + @@ -80,5 +83,15 @@ + + + + + + + diff --git a/idea/resources/META-INF/extensions/ide.xml.as33 b/idea/resources/META-INF/extensions/ide.xml.as33 index 45a7f3e9b27..a11d3f1db76 100644 --- a/idea/resources/META-INF/extensions/ide.xml.as33 +++ b/idea/resources/META-INF/extensions/ide.xml.as33 @@ -47,6 +47,9 @@ interface="org.jetbrains.kotlin.synthetic.SyntheticScopeProviderExtension" area="IDEA_PROJECT"/> + + @@ -80,5 +83,15 @@ + + + + + + + diff --git a/idea/resources/META-INF/extensions/ide.xml.as34 b/idea/resources/META-INF/extensions/ide.xml.as34 index 45a7f3e9b27..77fe8a3901a 100644 --- a/idea/resources/META-INF/extensions/ide.xml.as34 +++ b/idea/resources/META-INF/extensions/ide.xml.as34 @@ -47,6 +47,9 @@ interface="org.jetbrains.kotlin.synthetic.SyntheticScopeProviderExtension" area="IDEA_PROJECT"/> + + @@ -80,5 +83,14 @@ + + + + + + diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt index e07c0b69e7d..ff7f2223ed8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt @@ -44,14 +44,14 @@ import com.intellij.psi.PsiManager import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices -import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor +import org.jetbrains.kotlin.idea.j2k.JavaToKotlinConverterFactory import org.jetbrains.kotlin.idea.refactoring.toPsiFile import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.progressIndicatorNullable import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.isRunningInCidrIde import org.jetbrains.kotlin.j2k.ConverterSettings -import org.jetbrains.kotlin.j2k.JavaToKotlinConverter +import org.jetbrains.kotlin.j2k.FilesResult import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.UserDataProperty import java.io.File @@ -110,12 +110,18 @@ class JavaToKotlinAction : AnAction() { enableExternalCodeProcessing: Boolean = true, askExternalCodeProcessing: Boolean = true ): List { - var converterResult: JavaToKotlinConverter.FilesResult? = null + var converterResult: FilesResult? = null fun convert() { - val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices) + val converter = + JavaToKotlinConverterFactory.createJavaToKotlinConverter( + project, + ConverterSettings.defaultSettings, + IdeaJavaToKotlinServices + ) converterResult = converter.filesToKotlin( - javaFiles, J2kPostProcessor(formatCode = true), - ProgressManager.getInstance().progressIndicatorNullable!! + javaFiles, + JavaToKotlinConverterFactory.createPostProcessor(formatCode = true), + progress = ProgressManager.getInstance().progressIndicatorNullable!! ) } diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt.181 b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt.181 index 51490e9cb58..2bf704fc118 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt.181 +++ b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt.181 @@ -31,7 +31,6 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.ui.MessageType import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.ex.MessagesEx -import com.intellij.openapi.util.Key import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VirtualFile @@ -44,13 +43,13 @@ import com.intellij.psi.PsiManager import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices -import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor +import org.jetbrains.kotlin.idea.j2k.JavaToKotlinConverterFactory import org.jetbrains.kotlin.idea.refactoring.toPsiFile import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.progressIndicatorNullable import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.j2k.ConverterSettings -import org.jetbrains.kotlin.j2k.JavaToKotlinConverter +import org.jetbrains.kotlin.j2k.FilesResult import org.jetbrains.kotlin.psi.KtFile import java.io.File import java.io.IOException @@ -105,11 +104,17 @@ class JavaToKotlinAction : AnAction() { enableExternalCodeProcessing: Boolean = true, askExternalCodeProcessing: Boolean = true ): List { - var converterResult: JavaToKotlinConverter.FilesResult? = null + var converterResult: FilesResult? = null fun convert() { - val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices) + val converter = + JavaToKotlinConverterFactory.createJavaToKotlinConverter( + project, + ConverterSettings.defaultSettings, + IdeaJavaToKotlinServices + ) converterResult = converter.filesToKotlin( - javaFiles, J2kPostProcessor(formatCode = true), + javaFiles, + JavaToKotlinConverterFactory.createPostProcessor(formatCode = true), ProgressManager.getInstance().progressIndicatorNullable!! ) } diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt.as32 b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt.as32 index 44d226ba474..9ac647b95cc 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt.as32 +++ b/idea/src/org/jetbrains/kotlin/idea/actions/JavaToKotlinAction.kt.as32 @@ -43,13 +43,13 @@ import com.intellij.psi.PsiManager import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices -import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor +import org.jetbrains.kotlin.idea.j2k.JavaToKotlinConverterFactory import org.jetbrains.kotlin.idea.refactoring.toPsiFile import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.progressIndicatorNullable import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.j2k.ConverterSettings -import org.jetbrains.kotlin.j2k.JavaToKotlinConverter +import org.jetbrains.kotlin.j2k.FilesResult import org.jetbrains.kotlin.psi.KtFile import java.io.File import java.io.IOException @@ -104,12 +104,18 @@ class JavaToKotlinAction : AnAction() { enableExternalCodeProcessing: Boolean = true, askExternalCodeProcessing: Boolean = true ): List { - var converterResult: JavaToKotlinConverter.FilesResult? = null + var converterResult: FilesResult? = null fun convert() { - val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices) + val converter = + JavaToKotlinConverterFactory.createJavaToKotlinConverter( + project, + ConverterSettings.defaultSettings, + IdeaJavaToKotlinServices + ) converterResult = converter.filesToKotlin( - javaFiles, J2kPostProcessor(formatCode = true), - ProgressManager.getInstance().progressIndicatorNullable!! + javaFiles, + JavaToKotlinConverterFactory.createPostProcessor(formatCode = true), + progress = ProgressManager.getInstance().progressIndicatorNullable!! ) } diff --git a/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt index 2b7d80ac401..72baa92a36e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertJavaCopyPasteProcessor.kt @@ -35,13 +35,12 @@ import org.jetbrains.kotlin.idea.codeInsight.KotlinCopyPasteReferenceProcessor import org.jetbrains.kotlin.idea.codeInsight.KotlinReferenceData import org.jetbrains.kotlin.idea.editor.KotlinEditorOptions import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices -import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor +import org.jetbrains.kotlin.idea.j2k.JavaToKotlinConverterFactory import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.j2k.AfterConversionPass import org.jetbrains.kotlin.j2k.ConverterSettings -import org.jetbrains.kotlin.j2k.JavaToKotlinConverter import org.jetbrains.kotlin.j2k.ParseContext import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName @@ -154,7 +153,7 @@ class ConvertJavaCopyPasteProcessor : CopyPastePostProcessor() val results = ProgressManager.getInstance().runProcessWithProgressSynchronously( - ThrowableComputable { + ThrowableComputable { runReadAction { converter.elementsToKotlin(inputElements) } }, JavaToKotlinAction.title, diff --git a/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertTextJavaCopyPasteProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertTextJavaCopyPasteProcessor.kt index e2b79d04625..db770cd3924 100644 --- a/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertTextJavaCopyPasteProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/conversion/copy/ConvertTextJavaCopyPasteProcessor.kt @@ -36,7 +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.J2kPostProcessor +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 @@ -129,7 +129,7 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor("org.jetbrains.kotlin.j2kConverterExtension") + + val extension: J2kConverterExtension + get() = EP_NAME.extensions.first { it.isNewJ2k == useNewJ2k() } + } +} + diff --git a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt index 771c02f753b..f120af14046 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinConverter.kt @@ -47,35 +47,37 @@ enum class ParseContext { CODE_BLOCK } -class JavaToKotlinConverter( - private val project: Project, - private val settings: ConverterSettings, - private val services: JavaToKotlinConverterServices -) { +interface ExternalCodeProcessing { + fun prepareWriteOperation(progress: ProgressIndicator): () -> Unit +} + + +data class ElementResult(val text: String, val importsToAdd: Set, val parseContext: ParseContext) + +data class Result(val results: List, val externalCodeProcessing: ExternalCodeProcessing?) + +data class FilesResult(val results: List, val externalCodeProcessing: ExternalCodeProcessing?) + +abstract class JavaToKotlinConverter(private val project: Project) { + protected abstract fun elementsToKotlin(inputElements: List, processor: WithProgressProcessor): Result + private val LOG = Logger.getInstance("#org.jetbrains.kotlin.j2k.JavaToKotlinConverter") - interface ExternalCodeProcessing { - fun prepareWriteOperation(progress: ProgressIndicator): () -> Unit - } - - data class ElementResult(val text: String, val importsToAdd: Set, val parseContext: ParseContext) - - data class Result(val results: List, val externalCodeProcessing: ExternalCodeProcessing?) - - data class FilesResult(val results: List, val externalCodeProcessing: ExternalCodeProcessing?) - - fun filesToKotlin(files: List, postProcessor: PostProcessor, progress: ProgressIndicator = EmptyProgressIndicator()): FilesResult { + fun filesToKotlin( + files: List, + postProcessor: PostProcessor, + progress: ProgressIndicator = EmptyProgressIndicator() + ): FilesResult { val withProgressProcessor = WithProgressProcessor(progress, files) val (results, externalCodeProcessing) = ApplicationManager.getApplication().runReadAction(Computable { elementsToKotlin(files, withProgressProcessor) }) - val texts = withProgressProcessor.processItems(0.5, results.withIndex()) { pair -> val (i, result) = pair try { val kotlinFile = ApplicationManager.getApplication().runReadAction(Computable { - KtPsiFactory(project).createAnalyzableFile("dummy.kt", result!!.text, files[i]) + KtPsiFactory(project).createFileWithLightClassSupport("dummy.kt", result!!.text, files[i]) }) result!!.importsToAdd.forEach { postProcessor.insertImport(kotlinFile, it) } @@ -83,11 +85,9 @@ class JavaToKotlinConverter( AfterConversionPass(project, postProcessor).run(kotlinFile, range = null) kotlinFile.text - } - catch(e: ProcessCanceledException) { + } catch (e: ProcessCanceledException) { throw e - } - catch(t: Throwable) { + } catch (t: Throwable) { LOG.error(t) result!!.text } @@ -99,16 +99,22 @@ class JavaToKotlinConverter( fun elementsToKotlin(inputElements: List): Result { return elementsToKotlin(inputElements, WithProgressProcessor.DEFAULT) } +} - private fun elementsToKotlin(inputElements: List, processor: WithProgressProcessor): Result { +class OldJavaToKotlinConverter( + project: Project, + private val settings: ConverterSettings, + private val services: JavaToKotlinConverterServices +) : JavaToKotlinConverter(project) { + + protected override fun elementsToKotlin(inputElements: List, processor: WithProgressProcessor): Result { try { val usageProcessings = LinkedHashMap>() val usageProcessingCollector: (UsageProcessing) -> Unit = { usageProcessings.getOrPut(it.targetElement, { ArrayList() }).add(it) } - fun inConversionScope(element: PsiElement) - = inputElements.any { it.isAncestor(element, strict = false) } + fun inConversionScope(element: PsiElement) = inputElements.any { it.isAncestor(element, strict = false) } val intermediateResults = processor.processItems(0.25, inputElements) { inputElement -> @@ -127,14 +133,12 @@ class JavaToKotlinConverter( val externalCodeProcessing = buildExternalCodeProcessing(usageProcessings, ::inConversionScope) return Result(results, externalCodeProcessing) - } - catch(e: ElementCreationStackTraceRequiredException) { + } catch (e: ElementCreationStackTraceRequiredException) { // if we got this exception then we need to turn element creation stack traces on to get better diagnostic Element.saveCreationStacktraces = true try { return elementsToKotlin(inputElements) - } - finally { + } finally { Element.saveCreationStacktraces = false } } @@ -162,7 +166,7 @@ class JavaToKotlinConverter( .groupBy { it.targetElement } if (map.isEmpty()) return null - return object: ExternalCodeProcessing { + return object : ExternalCodeProcessing { override fun prepareWriteOperation(progress: ProgressIndicator): () -> Unit { val refs = ArrayList() @@ -183,7 +187,8 @@ class JavaToKotlinConverter( .filterNot { inConversionScope(it.element) } .mapTo(refs) { ReferenceInfo(it, psiElement, it.element.containingFile, processings) } }, - ProgressPortionReporter(progress, i / map.size.toDouble(), 1.0 / map.size)) + ProgressPortionReporter(progress, i / map.size.toDouble(), 1.0 / map.size) + ) } @@ -232,86 +237,89 @@ class JavaToKotlinConverter( return -info1.offset.compareTo(info2.offset) } } +} - private class WithProgressProcessor(private val progress: ProgressIndicator?, private val files: List?) { - companion object { - val DEFAULT = WithProgressProcessor(null, null) - } - private val progressText = "Converting Java to Kotlin" - private val fileCount = files?.size ?: 0 - private val fileCountText = fileCount.toString() + " " + if (fileCount > 1) "files" else "file" - private var fraction = 0.0 - private var pass = 1 - - fun processItems( - fractionPortion: Double, - inputItems: Iterable, - processItem: (TInputItem) -> TOutputItem - ): List { - val outputItems = ArrayList() - // we use special process with EmptyProgressIndicator to avoid changing text in our progress by inheritors search inside etc - ProgressManager.getInstance().runProcess( - { - progress?.text = "$progressText ($fileCountText) - pass $pass of 3" - - for ((i, item) in inputItems.withIndex()) { - progress?.checkCanceled() - progress?.fraction = fraction + fractionPortion * i / fileCount - - progress?.text2 = files!![i].virtualFile.presentableUrl - - outputItems.add(processItem(item)) - } - - pass++ - fraction += fractionPortion - }, - EmptyProgressIndicator()) - return outputItems - } +class WithProgressProcessor(private val progress: ProgressIndicator?, private val files: List?) { + companion object { + val DEFAULT = WithProgressProcessor(null, null) } - private class ProgressPortionReporter( - indicator: ProgressIndicator, - private val start: Double, - private val portion: Double - ) : DelegatingProgressIndicator(indicator) { + private val progressText = "Converting Java to Kotlin" + private val fileCount = files?.size ?: 0 + private val fileCountText = fileCount.toString() + " " + if (fileCount > 1) "files" else "file" + private var fraction = 0.0 + private var pass = 1 - init { - fraction = 0.0 - } + fun processItems( + fractionPortion: Double, + inputItems: Iterable, + processItem: (TInputItem) -> TOutputItem + ): List { + val outputItems = ArrayList() + // we use special process with EmptyProgressIndicator to avoid changing text in our progress by inheritors search inside etc + ProgressManager.getInstance().runProcess( + { + progress?.text = "$progressText ($fileCountText) - pass $pass of 3" - override fun start() { - fraction = 0.0 - } + for ((i, item) in inputItems.withIndex()) { + progress?.checkCanceled() + progress?.fraction = fraction + fractionPortion * i / fileCount - override fun stop() { - fraction = portion - } + progress?.text2 = files!![i].virtualFile.presentableUrl - override fun setFraction(fraction: Double) { - super.setFraction(start + (fraction * portion)) - } + outputItems.add(processItem(item)) + } - override fun getFraction(): Double { - return (super.getFraction() - start) / portion - } + pass++ + fraction += fractionPortion + }, + EmptyProgressIndicator() + ) + return outputItems + } +} - override fun setText(text: String?) { - } +private class ProgressPortionReporter( + indicator: ProgressIndicator, + private val start: Double, + private val portion: Double +) : DelegatingProgressIndicator(indicator) { - override fun setText2(text: String?) { - } + init { + fraction = 0.0 } - // Copied from com.intellij.ide.util.DelegatingProgressIndicator - private open class DelegatingProgressIndicator : WrappedProgressIndicator, StandardProgressIndicator { - protected val delegate: ProgressIndicator + override fun start() { + fraction = 0.0 + } - constructor(indicator: ProgressIndicator) { - delegate = indicator - } + override fun stop() { + fraction = portion + } + + override fun setFraction(fraction: Double) { + super.setFraction(start + (fraction * portion)) + } + + override fun getFraction(): Double { + return (super.getFraction() - start) / portion + } + + override fun setText(text: String?) { + } + + override fun setText2(text: String?) { + } +} + +// Copied from com.intellij.ide.util.DelegatingProgressIndicator +open class DelegatingProgressIndicator : WrappedProgressIndicator, StandardProgressIndicator { + protected val delegate: ProgressIndicator + + constructor(indicator: ProgressIndicator) { + delegate = indicator + } constructor() { // BUNCH: 181 @@ -320,49 +328,48 @@ class JavaToKotlinConverter( delegate = indicator ?: EmptyProgressIndicator() } - override fun start() = delegate.start() - override fun stop() = delegate.stop() - override fun isRunning() = delegate.isRunning - override fun cancel() = delegate.cancel() - override fun isCanceled() = delegate.isCanceled + override fun start() = delegate.start() + override fun stop() = delegate.stop() + override fun isRunning() = delegate.isRunning + override fun cancel() = delegate.cancel() + override fun isCanceled() = delegate.isCanceled - override fun setText(text: String?) { - delegate.text = text - } - - override fun getText() = delegate.text - - override fun setText2(text: String?) { - delegate.text2 = text - } - - override fun getText2() = delegate.text2 - override fun getFraction() = delegate.fraction - - override fun setFraction(fraction: Double) { - delegate.fraction = fraction - } - - override fun pushState() = delegate.pushState() - override fun popState() = delegate.popState() - override fun startNonCancelableSection() = delegate.startNonCancelableSection() - override fun finishNonCancelableSection() = delegate.finishNonCancelableSection() - override fun isModal() = delegate.isModal - override fun getModalityState() = delegate.modalityState - - override fun setModalityProgress(modalityProgress: ProgressIndicator?) { - delegate.setModalityProgress(modalityProgress) - } - - override fun isIndeterminate() = delegate.isIndeterminate - - override fun setIndeterminate(indeterminate: Boolean) { - delegate.isIndeterminate = indeterminate - } - - override fun checkCanceled() = delegate.checkCanceled() - override fun getOriginalProgressIndicator() = delegate - override fun isPopupWasShown() = delegate.isPopupWasShown - override fun isShowing() = delegate.isShowing + override fun setText(text: String?) { + delegate.text = text } -} + + override fun getText() = delegate.text + + override fun setText2(text: String?) { + delegate.text2 = text + } + + override fun getText2() = delegate.text2 + override fun getFraction() = delegate.fraction + + override fun setFraction(fraction: Double) { + delegate.fraction = fraction + } + + override fun pushState() = delegate.pushState() + override fun popState() = delegate.popState() + override fun startNonCancelableSection() = delegate.startNonCancelableSection() + override fun finishNonCancelableSection() = delegate.finishNonCancelableSection() + override fun isModal() = delegate.isModal + override fun getModalityState() = delegate.modalityState + + override fun setModalityProgress(modalityProgress: ProgressIndicator?) { + delegate.setModalityProgress(modalityProgress) + } + + override fun isIndeterminate() = delegate.isIndeterminate + + override fun setIndeterminate(indeterminate: Boolean) { + delegate.isIndeterminate = indeterminate + } + + override fun checkCanceled() = delegate.checkCanceled() + override fun getOriginalProgressIndicator() = delegate + override fun isPopupWasShown() = delegate.isPopupWasShown + override fun isShowing() = delegate.isShowing +} \ No newline at end of file diff --git a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinTranslator.kt b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinTranslator.kt index 183728004c6..28118366cc7 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinTranslator.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/JavaToKotlinTranslator.kt @@ -45,7 +45,7 @@ object JavaToKotlinTranslator { fun generateKotlinCode(javaCode: String, project: Project): String { val file = createFile(javaCode, project) if (file is PsiJavaFile) { - val converter = JavaToKotlinConverter(file.project, ConverterSettings.defaultSettings, EmptyJavaToKotlinServices) + val converter = OldJavaToKotlinConverter(file.project, ConverterSettings.defaultSettings, EmptyJavaToKotlinServices) return prettify(converter.elementsToKotlin(listOf(file)).results.single()!!.text) //TODO: imports } return "" diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterMultiFileTest.kt b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterMultiFileTest.kt index 19166fc34cd..56e41f7e74c 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterMultiFileTest.kt +++ b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterMultiFileTest.kt @@ -53,7 +53,7 @@ abstract class AbstractJavaToKotlinConverterMultiFileTest : AbstractJavaToKotlin assert(psiFile is PsiJavaFile || psiFile is KtFile) } - val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices) + val converter = OldJavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices) val (results, externalCodeProcessor) = converter.filesToKotlin(psiFilesToConvert, J2kPostProcessor(formatCode = true)) val process = externalCodeProcessor?.prepareWriteOperation(EmptyProgressIndicator()) diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt index 313eb5a27ea..b99b28e6097 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt +++ b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt @@ -110,7 +110,7 @@ abstract class AbstractJavaToKotlinConverterSingleFileTest : AbstractJavaToKotli protected open fun fileToKotlin(text: String, settings: ConverterSettings, project: Project): String { val file = createJavaFile(text) - val converter = JavaToKotlinConverter(project, settings, IdeaJavaToKotlinServices) + val converter = OldJavaToKotlinConverter(project, settings, IdeaJavaToKotlinServices) return converter.filesToKotlin(listOf(file), J2kPostProcessor(formatCode = true)).results.single() } diff --git a/nj2k/build.gradle.kts b/nj2k/build.gradle.kts index 1bbc3866d83..b1a57ce6602 100644 --- a/nj2k/build.gradle.kts +++ b/nj2k/build.gradle.kts @@ -20,7 +20,7 @@ dependencies { compileOnly(intellijCoreDep()) { includeJars("intellij-core") } testCompile(project(":idea")) - compile(project(":nj2k:nj2k-services")) + testCompile(project(":nj2k:nj2k-services")) testCompile(projectTests(":idea:idea-test-framework")) testCompile(project(":compiler:light-classes")) testCompile(project(":kotlin-test:kotlin-test-junit")) @@ -93,3 +93,6 @@ fun configureFreeCompilerArg(isEnabled: Boolean, compilerArgument: String) { } } } + +ideaPlugin() + diff --git a/nj2k/nj2k-services/build.gradle.kts b/nj2k/nj2k-services/build.gradle.kts index 7736c710da2..fd38bdcfceb 100644 --- a/nj2k/nj2k-services/build.gradle.kts +++ b/nj2k/nj2k-services/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { compile(project(":compiler:plugin-api")) compile(project(":eval4j")) compile(project(":j2k")) + compile(project(":nj2k")) compile(project(":idea")) compile(project(":idea:formatter")) compile(project(":idea:fir-view")) @@ -74,3 +75,4 @@ sourceSets { "main" { projectDefault() } } +ideaPlugin() diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/NewJ2kConveterExtension.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/NewJ2kConveterExtension.kt new file mode 100644 index 00000000000..68bcec8ce98 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/NewJ2kConveterExtension.kt @@ -0,0 +1,18 @@ +package org.jetbrains.kotlin.nj2k + +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.j2k.* + +class NewJ2kConverterExtension : J2kConverterExtension() { + override val isNewJ2k = true + + override fun createJavaToKotlinConverter( + project: Project, + settings: ConverterSettings, + services: JavaToKotlinConverterServices + ): JavaToKotlinConverter = + NewJavaToKotlinConverter(project, settings, services) + + override fun createPostProcessor(formatCode: Boolean, settings: ConverterSettings): PostProcessor = + NewJ2kPostProcessor(formatCode, settings) +} \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/JKSymbolProvider.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/JKSymbolProvider.kt index 1062bac221d..c59056c3e87 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/JKSymbolProvider.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/JKSymbolProvider.kt @@ -28,8 +28,8 @@ class JKSymbolProvider { private val elementVisitor = ElementVisitor() - fun preBuildTree(files: List) { - files.forEach { it.accept(elementVisitor) } + fun preBuildTree(inputElements: List) { + inputElements.forEach { it.accept(elementVisitor) } } private fun symbolForNonKotlinElement(psi: PsiElement) = diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverter.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverter.kt index 74d8a8b2746..909052966b9 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverter.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverter.kt @@ -16,20 +16,21 @@ package org.jetbrains.kotlin.nj2k -import com.intellij.openapi.progress.EmptyProgressIndicator -import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement -import com.intellij.psi.PsiJavaFile -import org.jetbrains.kotlin.j2k.ConverterSettings +import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.nj2k.tree.JKTreeElement import org.jetbrains.kotlin.nj2k.tree.prettyDebugPrintTree +import org.jetbrains.kotlin.psi.KtPsiFactory class NewJavaToKotlinConverter( val project: Project, val settings: ConverterSettings, - val converterServices: NewJavaToKotlinServices -) { + val oldConverterServices: JavaToKotlinConverterServices +) : JavaToKotlinConverter(project) { + val converterServices = object : NewJavaToKotlinServices { + override val oldServices = oldConverterServices + } private fun List.prettyPrintTrees() = buildString { for (tree in this@prettyPrintTrees) { @@ -39,25 +40,25 @@ class NewJavaToKotlinConverter( } } - fun filesToKotlin(files: List, progressIndicator: ProgressIndicator = EmptyProgressIndicator()): List { + override fun elementsToKotlin(inputElements: List, processor: WithProgressProcessor): Result { val symbolProvider = JKSymbolProvider() - symbolProvider.preBuildTree(files) + symbolProvider.preBuildTree(inputElements) val treeBuilder = JavaToJKTreeBuilder(symbolProvider, converterServices) - val fileTrees = files.mapNotNull(treeBuilder::buildTree) - -// println(fileTrees.prettyPrintTrees()) + val asts = inputElements.mapNotNull(treeBuilder::buildTree) + val factory = KtPsiFactory(project, true) val context = ConversionContext( symbolProvider, this, - { it: PsiElement -> it.containingFile in files } + { it.containingFile in inputElements } + ) + ConversionsRunner.doApply(asts, context) + val kotlinCodes = asts.map { NewCodeBuilder().run { printCodeOut(it) } } + return Result( + kotlinCodes.map { code -> + ElementResult(code, emptySet(), ParseContext.TOP_LEVEL) + }, + null ) - - ConversionsRunner.doApply(fileTrees, context) - -// val resultTree = fileTrees.prettyPrintTrees() -// println(resultTree) - - return fileTrees.map { NewCodeBuilder().run { printCodeOut(it) } } } } \ No newline at end of file diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterSingleFileTest.kt b/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterSingleFileTest.kt index 3983edb57e8..032103d7eae 100644 --- a/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterSingleFileTest.kt +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterSingleFileTest.kt @@ -18,7 +18,7 @@ package org.jetbrains.kotlin.nj2k import com.intellij.openapi.command.CommandProcessor import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.idea.nj2k.NewJ2kPostProcessor +import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterSingleFileTest import org.jetbrains.kotlin.j2k.ConverterSettings import org.jetbrains.kotlin.psi.KtPsiFactory @@ -32,14 +32,15 @@ abstract class AbstractNewJavaToKotlinConverterSingleFileTest : AbstractJavaToKo val postProcessor = NewJ2kPostProcessor(true, settings) - return NewJavaToKotlinConverter(project, settings, IdeaNewJavaToKotlinServices).filesToKotlin(listOf(file)).map { - factory.createFileWithLightClassSupport("Dummy.kt", it, file) - }.map { - CommandProcessor.getInstance().runUndoTransparentAction { - postProcessor.doAdditionalProcessing(it, null) + return NewJavaToKotlinConverter(project, settings, IdeaJavaToKotlinServices) + .filesToKotlin(listOf(file), NewJ2kPostProcessor(true, settings)).let { (results, _) -> + factory.createFileWithLightClassSupport("Dummy.kt", results.single(), file) + }.let { + CommandProcessor.getInstance().runUndoTransparentAction { + postProcessor.doAdditionalProcessing(it, null) + } + it.text } - it.text - }.single() } override fun provideExpectedFile(javaPath: String): File =