New J2K: Move println conversion functionality to BuiltinMembersConversion

This commit is contained in:
Ilya Kirillov
2019-03-29 15:03:56 +03:00
committed by Ilya Kirillov
parent ce666295f7
commit ddee0deeca
3 changed files with 35 additions and 53 deletions
@@ -54,7 +54,6 @@ object ConversionsRunner {
+StaticInitDeclarationConversion() +StaticInitDeclarationConversion()
+ImplicitInitializerConversion(context) +ImplicitInitializerConversion(context)
+ParameterModificationInMethodCallsConversion(context) +ParameterModificationInMethodCallsConversion(context)
+PrintlnConversion(context)
+BlockToRunConversion(context) +BlockToRunConversion(context)
+PrimaryConstructorDetectConversion(context) +PrimaryConstructorDetectConversion(context)
+InsertDefaultPrimaryConstructorConversion(context) +InsertDefaultPrimaryConstructorConversion(context)
@@ -43,10 +43,17 @@ class BuiltinMembersConversion(private val context: ConversionContext) : Recursi
private fun JKExpression.getConversion(): Conversion? = when (this) { private fun JKExpression.getConversion(): Conversion? = when (this) {
is JKMethodCallExpression -> is JKMethodCallExpression ->
conversions[identifier.deepestFqName()]?.firstOrNull { conversion -> conversions[identifier.deepestFqName()]?.firstOrNull { conversion ->
conversion.from is Method && conversion.byArgumentsFilter?.invoke(arguments.arguments.map { it.value }) ?: true if (conversion.from !is Method) return@firstOrNull false
if (conversion.filter?.invoke(this) == false) return@firstOrNull false
if (conversion.byArgumentsFilter?.invoke(arguments.arguments.map { it.value }) == false) return@firstOrNull false
true
} }
is JKFieldAccessExpression -> is JKFieldAccessExpression ->
conversions[identifier.deepestFqName()]?.firstOrNull { conversion -> conversion.from is Field } conversions[identifier.deepestFqName()]?.firstOrNull { conversion ->
if (conversion.from !is Field) return@firstOrNull false
if (conversion.filter?.invoke(this) == false) return@firstOrNull false
true
}
else -> null else -> null
} }
@@ -150,6 +157,7 @@ class BuiltinMembersConversion(private val context: ConversionContext) : Recursi
val from: SymbolInfo, val from: SymbolInfo,
val to: Info, val to: Info,
val replaceType: ReplaceType = ReplaceType.REPLACE_SELECTOR, val replaceType: ReplaceType = ReplaceType.REPLACE_SELECTOR,
val filter: ((JKExpression) -> Boolean)? = null,
val byArgumentsFilter: ((List<JKExpression>) -> Boolean)? = null, val byArgumentsFilter: ((List<JKExpression>) -> Boolean)? = null,
val argumentsProvider: ((JKArgumentList) -> JKArgumentList)? = null, val argumentsProvider: ((JKArgumentList) -> JKArgumentList)? = null,
val actionAfter: ((JKExpression) -> JKExpression)? = null val actionAfter: ((JKExpression) -> JKExpression)? = null
@@ -161,6 +169,9 @@ class BuiltinMembersConversion(private val context: ConversionContext) : Recursi
private infix fun Conversion.withReplaceType(replaceType: ReplaceType) = private infix fun Conversion.withReplaceType(replaceType: ReplaceType) =
copy(replaceType = replaceType) copy(replaceType = replaceType)
private infix fun Conversion.withFilter(filter: (JKExpression) -> Boolean) =
copy(filter = filter)
private infix fun Conversion.withByArgumentsFilter(filter: (List<JKExpression>) -> Boolean) = private infix fun Conversion.withByArgumentsFilter(filter: (List<JKExpression>) -> Boolean) =
copy(byArgumentsFilter = filter) copy(byArgumentsFilter = filter)
@@ -168,12 +179,20 @@ class BuiltinMembersConversion(private val context: ConversionContext) : Recursi
copy(argumentsProvider = argumentsProvider) copy(argumentsProvider = argumentsProvider)
private infix fun Conversion.andAfter(actionAfter: (JKExpression) -> JKExpression) = private infix fun Conversion.andAfter(actionAfter: (JKExpression) -> JKExpression) =
copy(actionAfter = actionAfter) copy(actionAfter = actionAfter).also { println() }
private val conversions: Map<String, List<Conversion>> = private val conversions: Map<String, List<Conversion>> =
listOf( listOf(
Method("java.lang.Integer.intValue") convertTo Method("kotlin.Int.toInt"),//TODO do not list all variants Method("java.lang.Integer.intValue") convertTo Method("kotlin.Int.toInt"),//TODO do not list all variants
Method("java.io.PrintStream.println") convertTo Method("kotlin.io.println")
withReplaceType ReplaceType.FULL_REPLACE
withFilter ::isSystemOutCall,
Method("java.io.PrintStream.print") convertTo Method("kotlin.io.print")
withReplaceType ReplaceType.FULL_REPLACE
withFilter ::isSystemOutCall,
Method("java.lang.Object.getClass") convertTo Field("kotlin.jvm.javaClass"), Method("java.lang.Object.getClass") convertTo Field("kotlin.jvm.javaClass"),
Method("java.util.Map.entrySet") convertTo Field("kotlin.collections.Map.entries"), Method("java.util.Map.entrySet") convertTo Field("kotlin.collections.Map.entries"),
@@ -378,6 +397,19 @@ class BuiltinMembersConversion(private val context: ConversionContext) : Recursi
private fun JKExpression.callOn(symbol: JKMethodSymbol, vararg arguments: JKExpression) = private fun JKExpression.callOn(symbol: JKMethodSymbol, vararg arguments: JKExpression) =
callOn(symbol, arguments.map { JKArgumentImpl(it) }) callOn(symbol, arguments.map { JKArgumentImpl(it) })
private fun isSystemOutCall(expression: JKExpression): Boolean =
expression.parent
?.safeAs<JKQualifiedExpression>()
?.receiver
?.let { receiver ->
when (receiver) {
is JKFieldAccessExpression -> receiver
is JKQualifiedExpression -> receiver.selector as? JKFieldAccessExpression
else -> null
}
}?.identifier
?.deepestFqName() == "java.lang.System.out"
private fun JKExpression.castToTypedArray() = private fun JKExpression.castToTypedArray() =
callOn(context.symbolProvider.provideByFqName("kotlin.collections.toTypedArray", multiResolve = true)) callOn(context.symbolProvider.provideByFqName("kotlin.collections.toTypedArray", multiResolve = true))
@@ -1,49 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.nj2k.conversions
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.nj2k.ConversionContext
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.JKKtCallExpressionImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKMethodSymbol
import org.jetbrains.kotlin.nj2k.tree.impl.psi
// TODO: Full special methods conversion
class PrintlnConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
return if (element is JKQualifiedExpression) {
recurse(processQualified(element))
} else {
recurse(element)
}
}
private fun processQualified(element: JKQualifiedExpression): JKExpression {
val receiver = element.receiver as? JKQualifiedExpression ?: return element
val classReference = receiver.receiver as? JKClassAccessExpression ?: return element
if (classReference.identifier.fqName != "java.lang.System") return element
val fieldReference = receiver.selector as? JKFieldAccessExpression ?: return element
if (fieldReference.identifier.name != "out") return element
val selector = element.selector as? JKMethodCallExpression ?: return element
val functionName = selector.identifier.name
if (functionName != "println" && functionName != "print") return element
val contextElement = element.parentOfType<JKClass>() ?: return element
val targetElements = multiResolveFqName(ClassId.fromString("kotlin/io/$functionName"), contextElement.psi!!)
if (targetElements.isEmpty()) return element
selector.invalidate()
return JKKtCallExpressionImpl(
context.symbolProvider.provideDirectSymbol(targetElements.first()) as JKMethodSymbol,
selector.arguments
).withNonCodeElementsFrom(element).also {
it.leftNonCodeElements += element.receiver.commentsFromInside()
}
}
}