New J2K: Add FunctionAsAnonymousObjectToLambdaConversion & ReturnStatementInLambdaExpressionConversion conversions

This commit is contained in:
Ilya Kirillov
2019-02-13 13:02:50 +03:00
committed by Ilya Kirillov
parent a659fcd6af
commit ef89a249f2
6 changed files with 123 additions and 3 deletions
@@ -29,6 +29,8 @@ object ConversionsRunner {
+AnnotationClassConversion(context)
+AnnotationConversion(context)
+ModalityConversion(context)
+FunctionAsAnonymousObjectToLambdaConversion()
+ReturnStatementInLambdaExpressionConversion()
+BoxedTypeOperationsConversion(context)
+AssignmentAsExpressionToAlsoConversion(context)
+AssignmentStatementValCreationConversion(context)
@@ -695,7 +695,9 @@ class NewCodeBuilder {
}
override fun visitReturnStatement(returnStatement: JKReturnStatement) {
printer.print("return ")
printer.print("return")
returnStatement.label.accept(this)
printer.print(" ")
returnStatement.expression.accept(this)
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2019 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.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.JKBlockStatementImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKClassSymbol
import org.jetbrains.kotlin.nj2k.tree.impl.JKLambdaExpressionImpl
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class FunctionAsAnonymousObjectToLambdaConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaNewExpression) return recurse(element)
if (element.isAnonymousClass()
&& element.classSymbol.isKtFunction()
) {
val invokeFunction = element.classBody.declarations.singleOrNull()
?.safeAs<JKMethod>()
?.takeIf { it.name.value == "invoke" }
?: return recurse(element)
return recurse(
JKLambdaExpressionImpl(
JKBlockStatementImpl(invokeFunction::block.detached()),
invokeFunction::parameters.detached()
)
)
}
return recurse(element)
}
private fun JKClassSymbol.isKtFunction() =
fqName.matches("""kotlin\.Function(\d+)""".toRegex())
|| fqName.matches("""kotlin\.jvm\.functions\.Function(\d+)""".toRegex())
}
@@ -0,0 +1,74 @@
/*
* Copyright 2010-2019 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.nj2k.asStatement
import org.jetbrains.kotlin.nj2k.copyTreeAndDetach
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.JKLabelTextImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKLabeledStatementImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKNameIdentifierImpl
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class ReturnStatementInLambdaExpressionConversion : RecursiveApplicableConversionBase() {
companion object {
const val DEFAULT_LABEL_NAME = "label"
}
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKLambdaExpression) return recurse(element)
val statement = element.statement
if (statement is JKReturnStatement) {
element.statement = statement::expression.detached().asStatement()
return recurse(element)
}
if (statement is JKBlockStatement) {
val statements = statement.block.statements
val last = statements.lastOrNull()
if (last is JKReturnStatement) {
statement.block.statements -= last
statement.block.statements += last::expression.detached().asStatement()
}
}
val parentMethodName = element.parent?.parent?.parent.safeAs<JKMethodCallExpression>()?.identifier?.name
if (parentMethodName == null) {
val atLeastOneReturnStatementExists = applyLabelToAllReturnStatements(statement, element, DEFAULT_LABEL_NAME)
return if (atLeastOneReturnStatementExists) {
JKLabeledStatementImpl(
recurse(element.copyTreeAndDetach()).asStatement(),
listOf(JKNameIdentifierImpl(DEFAULT_LABEL_NAME))
)
} else recurse(element)
}
applyLabelToAllReturnStatements(statement, element, parentMethodName)
return recurse(element)
}
private fun applyLabelToAllReturnStatements(
statement: JKStatement,
lambdaExpression: JKLambdaExpression,
label: String
): Boolean {
var atLeastOneReturnStatementExists = false
fun addLabelToReturnStatement(returnStatement: JKReturnStatement) {
if (returnStatement.label is JKLabelEmpty && returnStatement.parentOfType<JKLambdaExpression>() == lambdaExpression) {
atLeastOneReturnStatementExists = true
returnStatement.label = JKLabelTextImpl(JKNameIdentifierImpl(label))
}
}
fun fixAllReturnStatements(element: JKTreeElement): JKTreeElement {
if (element !is JKReturnStatement) return applyRecursive(element, ::fixAllReturnStatements)
addLabelToReturnStatement(element)
return applyRecursive(element, ::fixAllReturnStatements)
}
applyRecursive(statement, ::fixAllReturnStatements)
return atLeastOneReturnStatementExists
}
}
@@ -269,7 +269,7 @@ object JKJavaVoidType : JKType {
set(it) {}
}
class JKJavaArrayTypeImpl(override val type: JKType, override var nullability: Nullability = Nullability.Default) : JKJavaArrayType {
data class JKJavaArrayTypeImpl(override val type: JKType, override var nullability: Nullability = Nullability.Default) : JKJavaArrayType {
}
class JKJavaDisjunctionTypeImpl(
@@ -277,10 +277,14 @@ class JKJavaDisjunctionTypeImpl(
override val nullability: Nullability = Nullability.Default
) : JKJavaDisjunctionType
class JKReturnStatementImpl(expression: JKExpression) : JKBranchElementBase(), JKReturnStatement, PsiOwner by PsiOwnerImpl() {
class JKReturnStatementImpl(
expression: JKExpression,
label: JKLabel = JKLabelEmptyImpl()
) : JKBranchElementBase(), JKReturnStatement, PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitReturnStatement(this, data)
override val expression by child(expression)
override var label by child(label)
}
class JKJavaAssertStatementImpl(condition: JKExpression, description: JKExpression) : JKJavaAssertStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
@@ -63,6 +63,7 @@ interface JKJavaLiteralExpression : JKLiteralExpression
interface JKReturnStatement : JKStatement {
val expression: JKExpression
var label: JKLabel
}
interface JKJavaAssertStatement : JKStatement {