From fea36048f56b33c0b397dded24c4616c064fc3a0 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Thu, 10 Jul 2014 19:46:10 +0400 Subject: [PATCH] Java to Kotlin converter: better and more correct code --- j2k/src/org/jetbrains/jet/j2k/Utils.kt | 3 +++ .../jet/j2k/visitors/StatementVisitor.kt | 27 ++++++++++--------- .../jet/j2k/visitors/SwitchConverter.kt | 3 +-- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/j2k/src/org/jetbrains/jet/j2k/Utils.kt b/j2k/src/org/jetbrains/jet/j2k/Utils.kt index 4d93f29f830..4d230d79981 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Utils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Utils.kt @@ -136,3 +136,6 @@ fun PsiModifierListOwner.accessModifier(): String = when { } fun PsiMethod.isMainMethod(): Boolean = PsiMethodUtil.isMainMethod(this) + +fun List.singleOrNull2(): T? = if (size == 1) this[0] else null +fun Array.singleOrNull2(): T? = if (size == 1) this[0] else null diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt index 4e92df51a20..eda3dd5585e 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt @@ -24,6 +24,7 @@ import java.util.ArrayList import org.jetbrains.jet.j2k.hasWriteAccesses import org.jetbrains.jet.j2k.isInSingleLine import com.intellij.psi.tree.IElementType +import org.jetbrains.jet.j2k.singleOrNull2 open class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { public var result: Statement = Statement.Empty @@ -102,12 +103,11 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito val condition = statement.getCondition() val body = statement.getBody() - if (initialization is PsiDeclarationStatement && initialization.getFirstChild()!!.getNextSibling() == null) { - val loopVar = initialization.getFirstChild() as? PsiLocalVariable + if (initialization is PsiDeclarationStatement) { + val loopVar = initialization.getDeclaredElements().singleOrNull2() as? PsiLocalVariable if (loopVar != null && !loopVar.hasWriteAccesses(body) && !loopVar.hasWriteAccesses(condition) - && loopVar.countWriteAccesses(update) == 1 && condition is PsiBinaryExpression) { val operationTokenType = condition.getOperationTokenType() val lowerBound = condition.getLOperand() @@ -117,10 +117,8 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito lowerBound.resolve() == loopVar && upperBound != null) { val start = loopVar.getInitializer() - if (start != null - && update != null - && update.getChildren().size == 1 - && update.getChildren().single().isPlusPlusExpression()) { + if (start != null && + (update as? PsiExpressionStatement)?.getExpression()?.isVariablePlusPlus(loopVar) ?: false) { val range = forIterationRange(start, upperBound, operationTokenType).assignNoPrototype() val explicitType = if (converter.settings.specifyLocalVariableTypeByDefault) PrimitiveType(Identifier("Int").assignNoPrototype()).assignNoPrototype() else null result = ForeachStatement(loopVar.declarationIdentifier(), explicitType, range, convertStatementOrBlock(body), statement.isInSingleLine()) @@ -173,6 +171,16 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito } } + private fun PsiElement.isVariablePlusPlus(variable: PsiVariable): Boolean { + //TODO: simplify code when KT-5453 fixed + val pair = when (this) { + is PsiPostfixExpression -> getOperationTokenType() to getOperand() + is PsiPrefixExpression -> getOperationTokenType() to getOperand() + else -> return false + } + return pair.first == JavaTokenType.PLUSPLUS && (pair.second as? PsiReferenceExpression)?.resolve() == variable + } + private fun forIterationRange(start: PsiExpression, upperBound: PsiExpression, comparisonTokenType: IElementType): Expression { if (start is PsiLiteralExpression && start.getValue() == 0 @@ -337,11 +345,6 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito result = Statement.Empty } - private fun PsiElement.isPlusPlusExpression(): Boolean { - return (this is PsiPostfixExpression && this.getOperationTokenType() == JavaTokenType.PLUSPLUS) || - (this is PsiPrefixExpression && this.getOperationTokenType() == JavaTokenType.PLUSPLUS) - } - private fun convertStatementOrBlock(statement: PsiStatement?): Statement { return if (statement is PsiBlockStatement) converter.convertBlock(statement.getCodeBlock()) diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt index 2b9f5e8fff7..5cb62366431 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt @@ -20,6 +20,7 @@ import com.intellij.psi.* import org.jetbrains.jet.j2k.ast.* import org.jetbrains.jet.j2k.Converter import java.util.ArrayList +import org.jetbrains.jet.j2k.singleOrNull2 class SwitchConverter(private val converter: Converter) { public fun convert(statement: PsiSwitchStatement): WhenStatement @@ -113,6 +114,4 @@ class SwitchConverter(private val converter: Converter) { } private fun isSwitchBreak(statement: PsiStatement) = statement is PsiBreakStatement && statement.getLabelIdentifier() == null - - private fun List.singleOrNull2(): T? = if (size == 1) this[0] else null } \ No newline at end of file