Java to Kotlin converter: better and more correct code

This commit is contained in:
Valentin Kipyatkov
2014-07-10 19:46:10 +04:00
parent 3765a67a72
commit fea36048f5
3 changed files with 19 additions and 14 deletions
+3
View File
@@ -136,3 +136,6 @@ fun PsiModifierListOwner.accessModifier(): String = when {
}
fun PsiMethod.isMainMethod(): Boolean = PsiMethodUtil.isMainMethod(this)
fun <T: Any> List<T>.singleOrNull2(): T? = if (size == 1) this[0] else null
fun <T: Any> Array<T>.singleOrNull2(): T? = if (size == 1) this[0] else null
@@ -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())
@@ -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 <T: Any> List<T>.singleOrNull2(): T? = if (size == 1) this[0] else null
}