KT-5959 Imports should be inserted on paste from java with conversion to Kotlin

#KT-5959 Fixed
This commit is contained in:
Valentin Kipyatkov
2015-04-03 15:55:56 +03:00
parent 754567af07
commit 506f84fb8a
41 changed files with 462 additions and 172 deletions
+18 -7
View File
@@ -72,15 +72,26 @@ class Converter private(
private fun createDefaultCodeConverter() = CodeConverter(this, DefaultExpressionConverter(), DefaultStatementConverter(), null)
public fun convert(): ((Map<PsiElement, UsageProcessing>) -> String)? {
val element = convertTopElement(elementToConvert) ?: return null
return { usageProcessings ->
unfoldDeferredElements(usageProcessings)
public data class IntermediateResult(
val codeGenerator: (Map<PsiElement, UsageProcessing>) -> String,
val parseContext: ParseContext
)
val builder = CodeBuilder(elementToConvert)
builder.append(element)
builder.result
public fun convert(): IntermediateResult? {
val element = convertTopElement(elementToConvert) ?: return null
val parseContext = when (elementToConvert) {
is PsiStatement, is PsiExpression -> ParseContext.CODE_BLOCK
else -> ParseContext.TOP_LEVEL
}
return IntermediateResult(
{ usageProcessings ->
unfoldDeferredElements(usageProcessings)
val builder = CodeBuilder(elementToConvert)
builder.append(element)
builder.result
},
parseContext)
}
private fun convertTopElement(element: PsiElement): Element? = when (element) {
@@ -63,6 +63,11 @@ public trait PostProcessor {
public fun doAdditionalProcessing(file: JetFile, rangeMarker: RangeMarker?)
}
public enum class ParseContext {
TOP_LEVEL
CODE_BLOCK
}
public class JavaToKotlinConverter(private val project: Project,
private val settings: ConverterSettings,
private val referenceSearcher: ReferenceSearcher,
@@ -75,13 +80,15 @@ public class JavaToKotlinConverter(private val project: Project,
val postProcessingContext: PsiElement?
)
public data class Result(val text: String, val parseContext: ParseContext)
public fun elementsToKotlin(
inputElements: List<InputElement>,
progress: ProgressIndicator = EmptyProgressIndicator()
): List<String> {
): List<Result?> {
try {
val elementCount = inputElements.size()
val intermediateResults = ArrayList<((Map<PsiElement, UsageProcessing>) -> String)?>(elementCount)
val intermediateResults = ArrayList<(Converter.IntermediateResult)?>(elementCount)
val usageProcessings = HashMap<PsiElement, UsageProcessing>()
val usageProcessingCollector: (UsageProcessing) -> Unit = { usageProcessing ->
assert(!usageProcessings.containsKey(usageProcessing.targetElement))
@@ -130,21 +137,27 @@ public class JavaToKotlinConverter(private val project: Project,
intermediateResults.add(result)
}
val results = ArrayList<String>(elementCount)
val results = ArrayList<Result?>(elementCount)
processFilesWithProgress(0.25) { i ->
val result = intermediateResults[i]
results.add(if (result != null) result(usageProcessings) else "")
results.add(if (result != null)
Result(result.codeGenerator(usageProcessings), result.parseContext)
else
null)
intermediateResults[i] = null // to not hold unused objects in the heap
}
val finalResults = ArrayList<String>(elementCount)
if (postProcessor == null) return results
val finalResults = ArrayList<Result?>(elementCount)
processFilesWithProgress(0.5) { i ->
val result = results[i]
if (postProcessor != null) {
if (result != null) {
try {
val kotlinFile = JetPsiFactory(project).createAnalyzableFile("dummy.kt", result, inputElements[i].postProcessingContext!!)
//TODO: post processing does not work correctly for ParseContext different from TOP_LEVEL
val kotlinFile = JetPsiFactory(project).createAnalyzableFile("dummy.kt", result.text, inputElements[i].postProcessingContext!!)
AfterConversionPass(project, postProcessor).run(kotlinFile, null)
finalResults.add(kotlinFile.getText())
finalResults.add(Result(kotlinFile.getText(), result.parseContext))
}
catch(e: ProcessCanceledException) {
throw e
@@ -155,7 +168,7 @@ public class JavaToKotlinConverter(private val project: Project,
}
}
else {
finalResults.add(result)
finalResults.add(null)
}
}
@@ -135,7 +135,7 @@ public object JavaToKotlinTranslator {
val file = createFile(javaCode)
if (file is PsiJavaFile) {
val converter = JavaToKotlinConverter(file.getProject(), ConverterSettings.defaultSettings, EmptyReferenceSearcher, EmptyResolverForConverter, null)
return prettify(converter.elementsToKotlin(listOf(JavaToKotlinConverter.InputElement(file, null))).single())
return prettify(converter.elementsToKotlin(listOf(JavaToKotlinConverter.InputElement(file, null))).single()!!.text)
}
return ""
}
@@ -46,7 +46,7 @@ public abstract class AbstractJavaToKotlinConverterMultiFileTest : AbstractJavaT
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings,
IdeaReferenceSearcher, IdeaResolverForConverter, J2kPostProcessor(formatCode = true))
val inputElements = psiFiles.map { JavaToKotlinConverter.InputElement(it, it) }
val results: List<String> = converter.elementsToKotlin(inputElements)
val results: List<String> = converter.elementsToKotlin(inputElements).map { it!!.text }
fun expectedFile(i: Int) = File(javaFiles[i].getPath().replace(".java", ".kt"))
@@ -109,7 +109,7 @@ public abstract class AbstractJavaToKotlinConverterSingleFileTest : AbstractJava
val converter = JavaToKotlinConverter(project, settings,
IdeaReferenceSearcher, IdeaResolverForConverter, J2kPostProcessor(formatCode = false))
val inputElements = listOf(JavaToKotlinConverter.InputElement(file, file))
return converter.elementsToKotlin(inputElements).single()
return converter.elementsToKotlin(inputElements).single()!!.text
}
private fun methodToKotlin(text: String, settings: ConverterSettings, project: Project): String {