diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt index 26a3abc5893..0536490fe4a 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt @@ -25,77 +25,38 @@ class SwitchConverter(private val converter: Converter) { public fun convert(statement: PsiSwitchStatement): WhenStatement = WhenStatement(converter.convertExpression(statement.getExpression()), switchBodyToWhenEntries(statement.getBody())) + private class Case(val label: PsiSwitchLabelStatement?, val statements: List) + private fun switchBodyToWhenEntries(body: PsiCodeBlock?): List { //TODO: this code is to be changed when continue in when is supported by Kotlin val cases = splitToCases(body) - fun isSwitchBreak(statement: PsiStatement) = statement is PsiBreakStatement && statement.getLabelIdentifier() == null - - fun convertStatements(statements: List): List { - val statementsToKeep = statements.filterNot(::isSwitchBreak) - if (statementsToKeep.size == 1) { - val block = statementsToKeep.single() as? PsiBlockStatement - if (block != null) { - return listOf(converter.convertBlock(block.getCodeBlock(), true, { !isSwitchBreak(it) })) - } - } - return statementsToKeep.map { converter.convertStatement(it) } - } - - fun convertCaseStatements(caseIndex: Int): List { - val case = cases[caseIndex] - val fallsThrough = if (caseIndex == cases.lastIndex) { - false - } - else { - val block = case.statements.singleOrNull2() as? PsiBlockStatement - val statements = if (block != null) block.getCodeBlock().getStatements().toList() else case.statements - !statements.any { it is PsiBreakStatement || it is PsiContinueStatement || it is PsiReturnStatement || it is PsiThrowStatement } - } - return if (fallsThrough) { // we fall through into the next case - convertStatements(case.statements) + convertCaseStatements(caseIndex + 1) - } - else { - convertStatements(case.statements) - } - } - - fun convertCaseStatementsToBody(caseIndex: Int): Statement { - val statements = convertCaseStatements(caseIndex) - return if (statements.size == 1) - statements.single() - else - Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype() - } - val result = ArrayList() var pendingSelectors = ArrayList() 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()) + 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(i)).assignNoPrototype()) + result.add(WhenEntry(pendingSelectors, convertCaseStatementsToBody(cases, i)).assignNoPrototype()) pendingSelectors = ArrayList() } } return result } - private data class SwitchCase(val label: PsiSwitchLabelStatement?, val statements: List) - - private fun splitToCases(body: PsiCodeBlock?): List { - val cases = ArrayList() + private fun splitToCases(body: PsiCodeBlock?): List { + val cases = ArrayList() var currentCaseStatements = ArrayList() if (body != null) { var label: PsiSwitchLabelStatement? = null for (statement in body.getStatements()) { if (statement is PsiSwitchLabelStatement) { if (label != null) { - cases.add(SwitchCase(label, currentCaseStatements)) + cases.add(Case(label, currentCaseStatements)) currentCaseStatements = ArrayList() } label = statement @@ -105,12 +66,51 @@ class SwitchConverter(private val converter: Converter) { } } if (label != null || currentCaseStatements.isNotEmpty()) { - cases.add(SwitchCase(label, currentCaseStatements)) + cases.add(Case(label, currentCaseStatements)) } } return cases } + private fun convertCaseStatements(statements: List): List { + val statementsToKeep = statements.filter { !isSwitchBreak(it) } + if (statementsToKeep.size == 1) { + val block = statementsToKeep.single() as? PsiBlockStatement + if (block != null) { + return listOf(converter.convertBlock(block.getCodeBlock(), true, { !isSwitchBreak(it) })) + } + } + return statementsToKeep.map { converter.convertStatement(it) } + } + + private fun convertCaseStatements(cases: List, caseIndex: Int): List { + val case = cases[caseIndex] + val fallsThrough = if (caseIndex == cases.lastIndex) { + false + } + else { + val block = case.statements.singleOrNull2() as? PsiBlockStatement + val statements = if (block != null) block.getCodeBlock().getStatements().toList() else case.statements + !statements.any { it is PsiBreakStatement || it is PsiContinueStatement || it is PsiReturnStatement || it is PsiThrowStatement } + } + return if (fallsThrough) { // we fall through into the next case + convertCaseStatements(case.statements) + convertCaseStatements(cases, caseIndex + 1) + } + else { + convertCaseStatements(case.statements) + } + } + + private fun convertCaseStatementsToBody(cases: List, caseIndex: Int): Statement { + val statements = convertCaseStatements(cases, caseIndex) + return if (statements.size == 1) + statements.single() + else + Block(statements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype() + } + + 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