From ed61aac4fd905bdc85e89db87e6aba0682b9da4d Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Sat, 13 Oct 2018 23:12:30 +0300 Subject: [PATCH] New J2K: Add Java `for` loop to Kotlin `while` or `for in` loop conversion --- .../jetbrains/kotlin/j2k/ConversionsRunner.kt | 1 + .../jetbrains/kotlin/j2k/JKSymbolProvider.kt | 2 + .../jetbrains/kotlin/j2k/NewCodeBuilder.kt | 16 ++ .../kotlin/j2k/conversions/ForConversion.kt | 261 ++++++++++++++++++ .../kotlin/j2k/conversions/expressions.kt | 57 ++++ .../org/jetbrains/kotlin/j2k/tree/impl/j.kt | 1 + .../org/jetbrains/kotlin/j2k/tree/impl/jk.kt | 8 +- .../org/jetbrains/kotlin/j2k/tree/impl/k.kt | 24 ++ .../jetbrains/kotlin/j2k/tree/impl/symbols.kt | 11 +- j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt | 1 + j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt | 14 + .../org/jetbrains/kotlin/j2k/tree/markers.kt | 3 + .../kotlin/j2k/tree/visitors/JKVisitor.kt | 3 + .../kotlin/j2k/tree/visitors/JKVisitorVoid.kt | 6 + 14 files changed, 406 insertions(+), 2 deletions(-) create mode 100644 j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ForConversion.kt create mode 100644 j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/expressions.kt diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt index 0dad9a66135..c266a0a9593 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt @@ -50,6 +50,7 @@ object ConversionsRunner { +BinaryExpressionConversion() +SwitchStatementConversion(context) +InstanceofConversion() + +ForConversion(context) } fun doApply(trees: List, context: ConversionContext) { diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/JKSymbolProvider.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/JKSymbolProvider.kt index 620f6e442df..afcce7a7426 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/JKSymbolProvider.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/JKSymbolProvider.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.utils.addToStdlib.safeAs +import org.jetbrains.kotlin.psi.KtProperty class JKSymbolProvider { @@ -36,6 +37,7 @@ class JKSymbolProvider { is PsiMethod -> JKMultiverseMethodSymbol(psi, this) is PsiField -> JKMultiverseFieldSymbol(psi) is KtNamedFunction -> JKMultiverseFunctionSymbol(psi) + is KtProperty -> JKMultiversePropertySymbol(psi) else -> TODO(psi::class.toString()) } } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt index 87b916322c1..3bd54e28ac2 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt @@ -45,6 +45,15 @@ class NewCodeBuilder { printer.print("/* !!! Hit visitElement for element type: ${treeElement::class} !!! */") } + override fun visitKtForInStatement(ktForInStatement: JKKtForInStatement) { + printer.printWithNoIndent("for (") + printer.printWithNoIndent(ktForInStatement.variableIdentifier.value) + printer.printWithNoIndent(" in ") + ktForInStatement.iterationExpression.accept(this) + printer.printWithNoIndent(") ") + ktForInStatement.body.accept(this) + } + override fun visitDoWhileStatement(doWhileStatement: JKDoWhileStatement) { printer.printWithNoIndent("do") doWhileStatement.body.accept(this) @@ -226,6 +235,13 @@ class NewCodeBuilder { } } + override fun visitKtOperatorExpression(ktOperatorExpression: JKKtOperatorExpression) { + ktOperatorExpression.receiver.accept(this) + printer.printWithNoIndent(" ") + printer.printWithNoIndent(ktOperatorExpression.identifier.name) + printer.printWithNoIndent(" ") + ktOperatorExpression.argument.accept(this) + } override fun visitIfElseExpression(ifElseExpression: JKIfElseExpression) { printer.printWithNoIndent("if (") diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ForConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ForConversion.kt new file mode 100644 index 00000000000..8452c037931 --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ForConversion.kt @@ -0,0 +1,261 @@ +/* + * 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.j2k.conversions + +import com.intellij.psi.* +import jdk.nashorn.internal.ir.BlockStatement +import org.jetbrains.kotlin.j2k.ConversionContext +import org.jetbrains.kotlin.j2k.ReferenceSearcher +import org.jetbrains.kotlin.j2k.ast.* +import org.jetbrains.kotlin.j2k.hasWriteAccesses +import org.jetbrains.kotlin.j2k.isInSingleLine +import org.jetbrains.kotlin.j2k.tree.* +import org.jetbrains.kotlin.j2k.tree.impl.* +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.name.ClassId + + +class ForConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() { + private val referenceSearcher: ReferenceSearcher + get() = context.converter.converterServices.oldServices.referenceSearcher + + override fun applyToElement(element: JKTreeElement): JKTreeElement { + if (element !is JKJavaForLoopStatement) return recurse(element) + + convertToForeach(element)?.also { return recurse(it) } + convertToWhile(element)?.also { return recurse(it) } + + return recurse(element) + } + + private fun convertToWhile(loopStatement: JKJavaForLoopStatement): JKStatement? { + val whileBody = createWhileBody(loopStatement) + + val whileStatement = + JKWhileStatementImpl( + if (loopStatement.condition !is JKStubExpression) loopStatement.condition.detached() + else JKKtLiteralExpressionImpl("true", JKLiteralExpression.LiteralType.BOOLEAN), + whileBody + ) + val whileStatement = JKWhileStatementImpl(condition, whileBody) + + if (loopStatement.initializer is JKEmptyStatement) return whileStatement + //TODO check for error conflict + return JKBlockStatementImpl(JKBlockImpl(listOf(loopStatement.initializer.detached(), whileStatement))) + } + + private fun createWhileBody(loopStatement: JKJavaForLoopStatement): JKStatement { + if (loopStatement.updater is JKEmptyStatement) return loopStatement::body.detached() + val continueStatementConverter = object : RecursiveApplicableConversionBase() { + override fun applyToElement(element: JKTreeElement): JKTreeElement { + if (element !is JKJavaContinueStatement) return recurse(element) + //TODO ??? if (statement.findContinuedStatement()?.toContinuedLoop() != this@ForConverter.statement) return null + val statements = listOf(loopStatement.updater, element) + return recurse(JKBlockStatementImpl(JKBlockImpl(statements))) + } + + } + + val body = loopStatement.body + + if (body is JKBlockStatement) { + val initializer = loopStatement.initializer + val hasNameConflict = + initializer is JKDeclarationStatement && initializer.declaredStatements.any { loopVar -> + loopVar is JKLocalVariable && body.statements.any { statement -> + statement is JKDeclarationStatement && statement.declaredStatements.any { + it is JKLocalVariable && it.name == loopVar.name + } + } + } + + val statements = + if (hasNameConflict) { + listOf(continueStatementConverter.applyToElement(body) as JKStatement, loopStatement.updater) + } else { + body.block.statements + loopStatement.updater + } + return JKBlockStatementImpl(JKBlockImpl(statements.map { it.detached() })) + } else { + val statements = + listOf(continueStatementConverter.applyToElement(body) as JKStatement, loopStatement::updater.detached()) + return JKBlockStatementImpl(JKBlockImpl(statements.map { it.detached() })) + } + } + + private fun convertToForeach(loopStatement: JKJavaForLoopStatement): JKKtForInStatement? { + val loopVar = + (loopStatement.initializer as? JKDeclarationStatement)?.declaredStatements?.singleOrNull() as? JKLocalVariable ?: return null + val loopVarPsi = loopVar.psi() ?: return null + val condition = loopStatement.condition as? JKBinaryExpression ?: return null + if (!loopVarPsi.hasWriteAccesses(referenceSearcher, loopStatement.body.psi()) + && !loopVarPsi.hasWriteAccesses(referenceSearcher, loopStatement.condition.psi()) + ) { + val left = condition.left as? JKFieldAccessExpression ?: return null + val right = condition.right + if (right.psi()?.type in listOf(PsiType.DOUBLE, PsiType.FLOAT, PsiType.CHAR)) return null + if (left.identifier.target != loopVar) return null + val start = loopVar.initializer + val operationType = + (loopStatement.updater as? JKExpressionStatement)?.expression?.isVariableIncrementOrDecrement(loopVar) + val reversed = when ((operationType as? JKJavaOperatorImpl)?.token) { + JavaTokenType.PLUSPLUS -> false + JavaTokenType.MINUSMINUS -> true + else -> return null + } + val inclusive = when ((condition.operator as? JKJavaOperatorImpl)?.token ?: (condition.operator as? JKKtOperatorImpl)?.token) { + JavaTokenType.LT, KtTokens.LT -> if (reversed) return null else false + JavaTokenType.LE, KtTokens.LTEQ -> if (reversed) return null else true + JavaTokenType.GT, KtTokens.GT -> if (reversed) false else return null + JavaTokenType.GE, KtTokens.GTEQ -> if (reversed) true else return null + JavaTokenType.NE, KtTokens.EXCLEQ -> false + else -> return null + } + val range = forIterationRange(start, right, reversed, inclusive, loopVarPsi) + //TODO for loop explicitType +// val explicitType = if (context.converter.settings.specifyLocalVariableTypeByDefault) +// JKJavaPrimitiveTypeImpl.INT +// else null + return JKKtForInStatementImpl( + loopVar.name.detached(), + range.detached(), + loopStatement.body.detached() + ) + + } + return null + } + + private fun forIterationRange( + start: JKExpression, + bound: JKExpression, + reversed: Boolean, + inclusiveComparison: Boolean, + psiContext: PsiElement + ): JKExpression { + indicesIterationRange(start, bound, reversed, inclusiveComparison)?.also { return it } + if (start.parent != null) start.detach(start.parent!!) + if (bound.parent != null) bound.detach(bound.parent!!) + return when { + reversed -> downToExpression( + start, + convertBound(bound, if (inclusiveComparison) 0 else +1), + context, + psiContext + ) + bound !is JKKtLiteralExpression && !inclusiveComparison -> + untilToExpression( + start, + convertBound(bound, 0), + context, + psiContext + ) + else -> JKBinaryExpressionImpl( + start, + convertBound(bound, if (inclusiveComparison) 0 else -1), + JKKtOperatorImpl.tokenToOperator[KtTokens.RANGE]!! + ) + } + } + + private fun convertBound(bound: JKExpression, correction: Int): JKExpression { + if (correction == 0) return bound + + if (bound is JKLiteralExpression && bound.type == JKLiteralExpression.LiteralType.INT) { + val value = bound.literal.toInt() + return JKKtLiteralExpressionImpl((value + correction).toString(), bound.type) + } + + val sign = if (correction > 0) KtTokens.PLUS else KtTokens.MINUS + return JKBinaryExpressionImpl( + bound, + JKKtLiteralExpressionImpl(Math.abs(correction).toString(), JKLiteralExpression.LiteralType.INT), + JKKtOperatorImpl.tokenToOperator[sign]!! + ) + } + + private fun indicesIterationRange( + start: JKExpression, + bound: JKExpression, + reversed: Boolean, + inclusiveComparison: Boolean + ): JKExpression? { + val collectionSizeExpression = + if (reversed) { + if (!inclusiveComparison) return null + + if ((bound as? JKLiteralExpression)?.literal?.toIntOrNull() != 0) return null + + if (start !is JKBinaryExpression) return null + if ((start.operator as? JKKtOperatorImpl)?.token != KtTokens.MINUS) return null + if ((start.right as? JKLiteralExpression)?.literal?.toIntOrNull() != 1) return null + start.left + } else { + if (inclusiveComparison) return null + if ((start as? JKLiteralExpression)?.literal?.toIntOrNull() != 0) return null + bound + } as? JKQualifiedExpression ?: return null + + val indices = indicesByCollectionSize(collectionSizeExpression) + ?: indicesByArrayLength(collectionSizeExpression) + ?: return null + + val psiContext = collectionSizeExpression.psi() ?: return null + return if (reversed) { + val reversedSymbol = context.symbolProvider.provideDirectSymbol( + multiResolveFqName(ClassId.fromString("kotlin/collections/reversed"), psiContext).first() + ) as JKMethodSymbol + JKQualifiedExpressionImpl( + indices.detached(), + JKKtQualifierImpl.DOT, + JKJavaMethodCallExpressionImpl(reversedSymbol, JKExpressionListImpl()) + ) + } else indices + } + + + private fun indicesByCollectionSize(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? { + val methodCall = javaSizeCall.selector as? JKMethodCallExpression ?: return null + //TODO check if receiver type is Collection + if (methodCall.identifier.name == "size" && methodCall.arguments.expressions.isEmpty()) { + return toIndicesCall(javaSizeCall) + } + return null + } + + private fun indicesByArrayLength(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? { + val methodCall = javaSizeCall.selector as? JKFieldAccessExpression ?: return null + val receiverType = javaSizeCall.receiver.type(context) + //TODO check if receiver type is kotlin.array + if (methodCall.identifier.name == "length" && receiverType is JKJavaArrayType) { + return toIndicesCall(javaSizeCall) + } + return null + } + + private fun toIndicesCall(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? { + val psiContext = javaSizeCall.psi() ?: return null + val indiciesSymbol = context.symbolProvider.provideDirectSymbol( + multiResolveFqName(ClassId.fromString("kotlin/collections/indices"), psiContext).first() + ) as JKMultiversePropertySymbol + javaSizeCall.selector = JKFieldAccessExpressionImpl(indiciesSymbol) + return javaSizeCall + } + + + private fun JKExpression.isVariableIncrementOrDecrement(variable: JKLocalVariable): JKOperator? { + val pair = when (this) { + is JKPostfixExpression -> operator to expression + is JKPrefixExpression -> operator to expression + else -> return null + } + if ((pair.second as? JKFieldAccessExpression)?.identifier?.target != variable) return null + return pair.first + } + + private inline fun JKElement.psi() = + context.backAnnotator(this) as? ElementType +} \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/expressions.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/expressions.kt new file mode 100644 index 00000000000..1af9aed66cd --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/expressions.kt @@ -0,0 +1,57 @@ +/* + * 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.j2k.conversions + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.j2k.ConversionContext +import org.jetbrains.kotlin.j2k.tree.JKExpression +import org.jetbrains.kotlin.j2k.tree.JKKtOperatorExpression +import org.jetbrains.kotlin.j2k.tree.impl.JKKtOperatorExpressionImpl +import org.jetbrains.kotlin.j2k.tree.impl.JKMethodSymbol +import org.jetbrains.kotlin.name.ClassId + +fun untilToExpression( + from: JKExpression, + to: JKExpression, + conversionContext: ConversionContext, + psiContext: PsiElement +): JKKtOperatorExpression = + rangeExpression( + from, + to, + "until", + conversionContext, + psiContext + ) + +fun downToExpression( + from: JKExpression, + to: JKExpression, + conversionContext: ConversionContext, + psiContext: PsiElement +): JKKtOperatorExpression = + rangeExpression( + from, + to, + "downTo", + conversionContext, + psiContext + ) + +fun rangeExpression( + from: JKExpression, + to: JKExpression, + operatorName: String, + conversionContext: ConversionContext, + psiContext: PsiElement +): JKKtOperatorExpressionImpl { + val symbol = conversionContext.symbolProvider.provideDirectSymbol( + multiResolveFqName(ClassId.fromString("kotlin/ranges/$operatorName"), psiContext).first() + ) as JKMethodSymbol + if (from.parent != null) from.detach(from.parent!!) + if (to.parent != null) to.detach(to.parent!!) + return JKKtOperatorExpressionImpl(from, symbol, to) +} \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt index 053d707742b..01f95fa922f 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt @@ -70,6 +70,7 @@ class JKJavaOperatorImpl private constructor(val token: IElementType) : JKOperat JavaTokenType.MINUSMINUS -> "--" JavaTokenType.PLUSPLUS -> "++" JavaTokenType.EXCL -> "!" + JavaTokenType.ASTERISKEQ -> "*=" else -> TODO("TODO $token") } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt index 995798b5809..a2711ab4b42 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt @@ -375,4 +375,10 @@ class JKDelegationConstructorCallImpl( class JKFieldAccessExpressionImpl(override var identifier: JKFieldSymbol) : JKFieldAccessExpression, JKElementBase() { override fun accept(visitor: JKVisitor, data: D): R = visitor.visitFieldAccessExpression(this, data) -} \ No newline at end of file +} +val JKStatement.statements: List + get() = + when (this) { + is JKBlockStatement -> block.statements + else -> listOf(this) + } \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt index 8dd5a372bb6..363bea5e465 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.j2k.tree.* import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.utils.addToStdlib.assertedCast import org.jetbrains.kotlin.utils.addToStdlib.cast class JKKtPropertyImpl( @@ -265,4 +266,27 @@ fun JKClass.getOrCreateInitDeclaration(): JKKtInitDeclaration { val newDeclaration = JKKtInitDeclarationImpl(JKBlockImpl()) declarationList += newDeclaration return newDeclaration +} + +class JKKtForInStatementImpl(variableIdentifier: JKNameIdentifier, iterationExpression: JKExpression, body: JKStatement) : + JKKtForInStatement, + JKBranchElementBase() { + override var variableIdentifier: JKNameIdentifier by child(variableIdentifier) + override var iterationExpression: JKExpression by child(iterationExpression) + override var body: JKStatement by child(body) + override fun accept(visitor: JKVisitor, data: D): R = visitor.visitKtForInStatement(this, data) +} + +class JKKtOperatorExpressionImpl( + receiver: JKExpression, + override var identifier: JKMethodSymbol, + argument: JKExpression +) : JKKtOperatorExpression, JKBranchElementBase() { + override var receiver: JKExpression by child(receiver) + override var argument: JKExpression by child(argument) + override fun accept(visitor: JKVisitor, data: D): R = visitor.visitKtOperatorExpression(this, data) +} + +class JKJavaContinueStatementImpl() : JKJavaContinueStatement, JKElementBase() { + override fun accept(visitor: JKVisitor, data: D): R = visitor.visitJavaContinueStatement(this, data) } \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/symbols.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/symbols.kt index 0bf8b19942a..72f16ee7477 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/symbols.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/symbols.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.j2k.tree.JKMethod import org.jetbrains.kotlin.j2k.tree.JKTreeElement import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtProperty interface JKSymbol { val target: Any @@ -120,13 +121,21 @@ class JKMultiverseFieldSymbol(override val target: PsiField) : JKFieldSymbol { get() = target.name // TODO("Fix this") } +class JKMultiversePropertySymbol(override val target: KtProperty) : JKFieldSymbol { + override val name: String + get() = target.name!! + override val declaredIn: JKSymbol + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + override val fqName: String + get() = target.name!! // TODO("Fix this") +} + class JKUnresolvedField(override val target: String) : JKFieldSymbol { constructor(target: PsiReference) : this(target.canonicalText) override val declaredIn: JKSymbol get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. override val fqName: String = target - override val name: String get() = target } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt index 5ea067a6c4c..817bb7c1c9a 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt @@ -107,3 +107,4 @@ interface JKJavaLabelSwitchCase : JKJavaSwitchCase { var label: JKExpression } +interface JKJavaContinueStatement: JKStatement \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt index 2570ef9a14c..206cf3d0fa2 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt @@ -16,6 +16,8 @@ package org.jetbrains.kotlin.j2k.tree +import org.jetbrains.kotlin.j2k.tree.impl.JKMethodSymbol + interface JKKtProperty : JKField { val getter: JKBlock val setter: JKBlock @@ -83,4 +85,16 @@ interface JKKtIsExpression : JKExpression { interface JKKtInitDeclaration : JKDeclaration { var block: JKBlock +} + +interface JKKtForInStatement : JKStatement { + var variableIdentifier: JKNameIdentifier + var iterationExpression: JKExpression + var body: JKStatement +} + +interface JKKtOperatorExpression : JKExpression { + var receiver: JKExpression + var identifier: JKMethodSymbol + var argument: JKExpression } \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/markers.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/markers.kt index 71136104a8d..da50272c391 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/markers.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/markers.kt @@ -81,3 +81,6 @@ inline fun JKElement.getParentOfType(): T? { p = p.parent } } + +fun T.detached() = + also { if (parent != null) detach(parent!!) } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt index d09b261cfdc..45e374e5f1a 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt @@ -69,6 +69,7 @@ interface JKVisitor { fun visitJavaInstanceOfExpression(javaInstanceOfExpression: JKJavaInstanceOfExpression, data: D): R = visitExpression(javaInstanceOfExpression, data) fun visitJavaPolyadicExpression(javaPolyadicExpression: JKJavaPolyadicExpression, data: D): R = visitExpression(javaPolyadicExpression, data) fun visitJavaAssignmentExpression(javaAssignmentExpression: JKJavaAssignmentExpression, data: D): R = visitExpression(javaAssignmentExpression, data) + fun visitJavaContinueStatement(javaContinueStatement: JKJavaContinueStatement, data: D): R = visitStatement(javaContinueStatement, data) fun visitJavaSwitchStatement(javaSwitchStatement: JKJavaSwitchStatement, data: D): R = visitStatement(javaSwitchStatement, data) fun visitJavaSwitchCase(javaSwitchCase: JKJavaSwitchCase, data: D): R = visitTreeElement(javaSwitchCase, data) fun visitJavaDefaultSwitchCase(javaDefaultSwitchCase: JKJavaDefaultSwitchCase, data: D): R = visitJavaSwitchCase(javaDefaultSwitchCase, data) @@ -90,4 +91,6 @@ interface JKVisitor { fun visitKtValueWhenLabel(ktValueWhenLabel: JKKtValueWhenLabel, data: D): R = visitKtWhenLabel(ktValueWhenLabel, data) fun visitKtIsExpression(ktIsExpression: JKKtIsExpression, data: D): R = visitExpression(ktIsExpression, data) fun visitKtInitDeclaration(ktInitDeclaration: JKKtInitDeclaration, data: D): R = visitDeclaration(ktInitDeclaration, data) + fun visitKtForInStatement(ktForInStatement: JKKtForInStatement, data: D): R = visitStatement(ktForInStatement, data) + fun visitKtOperatorExpression(ktOperatorExpression: JKKtOperatorExpression, data: D): R = visitExpression(ktOperatorExpression, data) } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt index 97b76cefc66..a2a01acf171 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt @@ -143,6 +143,8 @@ interface JKVisitorVoid : JKVisitor { override fun visitJavaDefaultSwitchCase(javaDefaultSwitchCase: JKJavaDefaultSwitchCase, data: Nothing?) = visitJavaDefaultSwitchCase(javaDefaultSwitchCase) fun visitJavaLabelSwitchCase(javaLabelSwitchCase: JKJavaLabelSwitchCase) = visitJavaSwitchCase(javaLabelSwitchCase, null) override fun visitJavaLabelSwitchCase(javaLabelSwitchCase: JKJavaLabelSwitchCase, data: Nothing?) = visitJavaLabelSwitchCase(javaLabelSwitchCase) + fun visitJavaContinueStatement(javaContinueStatement: JKJavaContinueStatement) = visitStatement(javaContinueStatement, null) + override fun visitJavaContinueStatement(javaContinueStatement: JKJavaContinueStatement, data: Nothing?) = visitJavaContinueStatement(javaContinueStatement) fun visitKtProperty(ktProperty: JKKtProperty) = visitField(ktProperty, null) override fun visitKtProperty(ktProperty: JKKtProperty, data: Nothing?) = visitKtProperty(ktProperty) fun visitKtFunction(ktFunction: JKKtFunction) = visitMethod(ktFunction, null) @@ -177,4 +179,8 @@ interface JKVisitorVoid : JKVisitor { override fun visitKtIsExpression(ktIsExpression: JKKtIsExpression, data: Nothing?) = visitKtIsExpression(ktIsExpression) fun visitKtInitDeclaration(ktInitDeclaration: JKKtInitDeclaration) = visitDeclaration(ktInitDeclaration, null) override fun visitKtInitDeclaration(ktInitDeclaration: JKKtInitDeclaration, data: Nothing?) = visitKtInitDeclaration(ktInitDeclaration) + fun visitKtForInStatement(ktForInStatement: JKKtForInStatement) = visitStatement(ktForInStatement, null) + override fun visitKtForInStatement(ktForInStatement: JKKtForInStatement, data: Nothing?) = visitKtForInStatement(ktForInStatement) + fun visitKtOperatorExpression(ktOperatorExpression: JKKtOperatorExpression) = visitExpression(ktOperatorExpression, null) + override fun visitKtOperatorExpression(ktOperatorExpression: JKKtOperatorExpression, data: Nothing?) = visitKtOperatorExpression(ktOperatorExpression) }