Java to Kotlin converter: code refactoring

This commit is contained in:
Valentin Kipyatkov
2014-07-08 19:44:32 +04:00
parent 139b7cdd27
commit 28e003e79f
@@ -25,15 +25,56 @@ class SwitchConverter(private val converter: Converter) {
public fun convert(statement: PsiSwitchStatement): WhenStatement public fun convert(statement: PsiSwitchStatement): WhenStatement
= WhenStatement(converter.convertExpression(statement.getExpression()), switchBodyToWhenEntries(statement.getBody())) = WhenStatement(converter.convertExpression(statement.getExpression()), switchBodyToWhenEntries(statement.getBody()))
private class Case(val label: PsiSwitchLabelStatement?, val statements: List<PsiStatement>)
private fun switchBodyToWhenEntries(body: PsiCodeBlock?): List<WhenEntry> { private fun switchBodyToWhenEntries(body: PsiCodeBlock?): List<WhenEntry> {
//TODO: this code is to be changed when continue in when is supported by Kotlin //TODO: this code is to be changed when continue in when is supported by Kotlin
val cases = splitToCases(body) val cases = splitToCases(body)
fun isSwitchBreak(statement: PsiStatement) = statement is PsiBreakStatement && statement.getLabelIdentifier() == null val result = ArrayList<WhenEntry>()
var pendingSelectors = ArrayList<WhenEntrySelector>()
for ((i, case) in cases.withIndices()) {
if (case.label == null) { // invalid switch - no case labels
result.add(WhenEntry(listOf(ValueWhenEntrySelector(Expression.Empty).assignNoPrototype()), convertCaseStatementsToBody(cases, i)).assignNoPrototype())
continue
}
pendingSelectors.add(converter.convertStatement(case.label) as WhenEntrySelector)
if (case.statements.isNotEmpty()) {
result.add(WhenEntry(pendingSelectors, convertCaseStatementsToBody(cases, i)).assignNoPrototype())
pendingSelectors = ArrayList()
}
}
return result
}
fun convertStatements(statements: List<PsiStatement>): List<Statement> { private fun splitToCases(body: PsiCodeBlock?): List<Case> {
val statementsToKeep = statements.filterNot(::isSwitchBreak) val cases = ArrayList<Case>()
var currentCaseStatements = ArrayList<PsiStatement>()
if (body != null) {
var label: PsiSwitchLabelStatement? = null
for (statement in body.getStatements()) {
if (statement is PsiSwitchLabelStatement) {
if (label != null) {
cases.add(Case(label, currentCaseStatements))
currentCaseStatements = ArrayList()
}
label = statement
}
else {
currentCaseStatements.add(statement)
}
}
if (label != null || currentCaseStatements.isNotEmpty()) {
cases.add(Case(label, currentCaseStatements))
}
}
return cases
}
private fun convertCaseStatements(statements: List<PsiStatement>): List<Statement> {
val statementsToKeep = statements.filter { !isSwitchBreak(it) }
if (statementsToKeep.size == 1) { if (statementsToKeep.size == 1) {
val block = statementsToKeep.single() as? PsiBlockStatement val block = statementsToKeep.single() as? PsiBlockStatement
if (block != null) { if (block != null) {
@@ -43,7 +84,7 @@ class SwitchConverter(private val converter: Converter) {
return statementsToKeep.map { converter.convertStatement(it) } return statementsToKeep.map { converter.convertStatement(it) }
} }
fun convertCaseStatements(caseIndex: Int): List<Statement> { private fun convertCaseStatements(cases: List<Case>, caseIndex: Int): List<Statement> {
val case = cases[caseIndex] val case = cases[caseIndex]
val fallsThrough = if (caseIndex == cases.lastIndex) { val fallsThrough = if (caseIndex == cases.lastIndex) {
false false
@@ -54,63 +95,22 @@ class SwitchConverter(private val converter: Converter) {
!statements.any { it is PsiBreakStatement || it is PsiContinueStatement || it is PsiReturnStatement || it is PsiThrowStatement } !statements.any { it is PsiBreakStatement || it is PsiContinueStatement || it is PsiReturnStatement || it is PsiThrowStatement }
} }
return if (fallsThrough) { // we fall through into the next case return if (fallsThrough) { // we fall through into the next case
convertStatements(case.statements) + convertCaseStatements(caseIndex + 1) convertCaseStatements(case.statements) + convertCaseStatements(cases, caseIndex + 1)
} }
else { else {
convertStatements(case.statements) convertCaseStatements(case.statements)
} }
} }
fun convertCaseStatementsToBody(caseIndex: Int): Statement { private fun convertCaseStatementsToBody(cases: List<Case>, caseIndex: Int): Statement {
val statements = convertCaseStatements(caseIndex) val statements = convertCaseStatements(cases, caseIndex)
return if (statements.size == 1) return if (statements.size == 1)
statements.single() statements.single()
else else
Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype() Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype()
} }
val result = ArrayList<WhenEntry>() private fun isSwitchBreak(statement: PsiStatement) = statement is PsiBreakStatement && statement.getLabelIdentifier() == null
var pendingSelectors = ArrayList<WhenEntrySelector>()
for ((i, case) in cases.withIndices()) {
if (case.label == null) { // invalid switch - no case labels
result.add(WhenEntry(listOf(ValueWhenEntrySelector(Expression.Empty).assignNoPrototype()), convertCaseStatementsToBody(i)).assignNoPrototype())
continue
}
pendingSelectors.add(converter.convertStatement(case.label) as WhenEntrySelector)
if (case.statements.isNotEmpty()) {
result.add(WhenEntry(pendingSelectors, convertCaseStatementsToBody(i)).assignNoPrototype())
pendingSelectors = ArrayList()
}
}
return result
}
private data class SwitchCase(val label: PsiSwitchLabelStatement?, val statements: List<PsiStatement>)
private fun splitToCases(body: PsiCodeBlock?): List<SwitchCase> {
val cases = ArrayList<SwitchCase>()
var currentCaseStatements = ArrayList<PsiStatement>()
if (body != null) {
var label: PsiSwitchLabelStatement? = null
for (statement in body.getStatements()) {
if (statement is PsiSwitchLabelStatement) {
if (label != null) {
cases.add(SwitchCase(label, currentCaseStatements))
currentCaseStatements = ArrayList()
}
label = statement
}
else {
currentCaseStatements.add(statement)
}
}
if (label != null || currentCaseStatements.isNotEmpty()) {
cases.add(SwitchCase(label, currentCaseStatements))
}
}
return cases
}
private fun <T: Any> List<T>.singleOrNull2(): T? = if (size == 1) this[0] else null private fun <T: Any> List<T>.singleOrNull2(): T? = if (size == 1) this[0] else null
} }