diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt index 79155c60214..ca4dcce779f 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt @@ -29,6 +29,8 @@ object ConversionsRunner { +AnnotationClassConversion(context) +AnnotationConversion(context) +ModalityConversion(context) + +FunctionAsAnonymousObjectToLambdaConversion() + +ReturnStatementInLambdaExpressionConversion() +BoxedTypeOperationsConversion(context) +AssignmentAsExpressionToAlsoConversion(context) +AssignmentStatementValCreationConversion(context) diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt index 5fee13007c8..7e62621e4dd 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt @@ -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) } diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/FunctionAsAnonymousObjectToLambdaConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/FunctionAsAnonymousObjectToLambdaConversion.kt new file mode 100644 index 00000000000..01c6c39003b --- /dev/null +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/FunctionAsAnonymousObjectToLambdaConversion.kt @@ -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() + ?.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()) +} \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ReturnStatementInLambdaExpressionConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ReturnStatementInLambdaExpressionConversion.kt new file mode 100644 index 00000000000..8214f09e59f --- /dev/null +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ReturnStatementInLambdaExpressionConversion.kt @@ -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()?.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() == 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 + } +} \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/j.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/j.kt index 8c326436ca6..eba73721bfb 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/j.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/j.kt @@ -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 accept(visitor: JKVisitor, 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() { diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/j.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/j.kt index 925a596dc0e..b04fe89dffb 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/j.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/j.kt @@ -63,6 +63,7 @@ interface JKJavaLiteralExpression : JKLiteralExpression interface JKReturnStatement : JKStatement { val expression: JKExpression + var label: JKLabel } interface JKJavaAssertStatement : JKStatement {