Java to Kotlin converter: fixed some bugs in switch statement conversion

This commit is contained in:
Valentin Kipyatkov
2014-07-10 18:49:04 +04:00
parent 2df60a27c8
commit d5f0af15c3
4 changed files with 66 additions and 19 deletions
@@ -50,32 +50,36 @@ class SwitchConverter(private val converter: Converter) {
private fun splitToCases(body: PsiCodeBlock?): List<Case> { private fun splitToCases(body: PsiCodeBlock?): List<Case> {
val cases = ArrayList<Case>() val cases = ArrayList<Case>()
var currentCaseStatements = ArrayList<PsiStatement>()
if (body != null) { if (body != null) {
var label: PsiSwitchLabelStatement? = null var currentLabel: PsiSwitchLabelStatement? = null
var currentCaseStatements = ArrayList<PsiStatement>()
fun flushCurrentCase() {
if (currentLabel != null || currentCaseStatements.isNotEmpty()) {
cases.add(Case(currentLabel, currentCaseStatements))
}
}
for (statement in body.getStatements()) { for (statement in body.getStatements()) {
if (statement is PsiSwitchLabelStatement) { if (statement is PsiSwitchLabelStatement) {
if (label != null) { flushCurrentCase()
cases.add(Case(label, currentCaseStatements)) currentLabel = statement
currentCaseStatements = ArrayList() currentCaseStatements = ArrayList()
}
label = statement
} }
else { else {
currentCaseStatements.add(statement) currentCaseStatements.add(statement)
} }
} }
if (label != null || currentCaseStatements.isNotEmpty()) {
cases.add(Case(label, currentCaseStatements)) flushCurrentCase()
}
} }
return cases return cases
} }
private fun convertCaseStatements(statements: List<PsiStatement>): List<Statement> { private fun convertCaseStatements(statements: List<PsiStatement>, allowBlock: Boolean = true): List<Statement> {
val statementsToKeep = statements.filter { !isSwitchBreak(it) } val statementsToKeep = statements.filter { !isSwitchBreak(it) }
if (statementsToKeep.size == 1) { if (allowBlock && statementsToKeep.size == 1) {
val block = statementsToKeep.single() as? PsiBlockStatement val block = statementsToKeep.single() as? PsiBlockStatement
if (block != null) { if (block != null) {
return listOf(converter.convertBlock(block.getCodeBlock(), true, { !isSwitchBreak(it) })) return listOf(converter.convertBlock(block.getCodeBlock(), true, { !isSwitchBreak(it) }))
@@ -84,7 +88,7 @@ class SwitchConverter(private val converter: Converter) {
return statementsToKeep.map { converter.convertStatement(it) } return statementsToKeep.map { converter.convertStatement(it) }
} }
private fun convertCaseStatements(cases: List<Case>, caseIndex: Int): List<Statement> { private fun convertCaseStatements(cases: List<Case>, caseIndex: Int, allowBlock: Boolean = true): List<Statement> {
val case = cases[caseIndex] val case = cases[caseIndex]
val fallsThrough = if (caseIndex == cases.lastIndex) { val fallsThrough = if (caseIndex == cases.lastIndex) {
false false
@@ -94,12 +98,10 @@ class SwitchConverter(private val converter: Converter) {
val statements = if (block != null) block.getCodeBlock().getStatements().toList() else case.statements 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 } !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
convertCaseStatements(case.statements) + convertCaseStatements(cases, caseIndex + 1) convertCaseStatements(case.statements, allowBlock = false) + convertCaseStatements(cases, caseIndex + 1, allowBlock = false)
} else
else { convertCaseStatements(case.statements, allowBlock)
convertCaseStatements(case.statements)
}
} }
private fun convertCaseStatementsToBody(cases: List<Case>, caseIndex: Int): Statement { private fun convertCaseStatementsToBody(cases: List<Case>, caseIndex: Int): Statement {
@@ -2691,6 +2691,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
doTest("j2k/tests/testData/ast/switch/fallDown.java"); doTest("j2k/tests/testData/ast/switch/fallDown.java");
} }
@TestMetadata("fallDownWithBlocks.java")
public void testFallDownWithBlocks() throws Exception {
doTest("j2k/tests/testData/ast/switch/fallDownWithBlocks.java");
}
@TestMetadata("invalidSwitch.java") @TestMetadata("invalidSwitch.java")
public void testInvalidSwitch() throws Exception { public void testInvalidSwitch() throws Exception {
doTest("j2k/tests/testData/ast/switch/invalidSwitch.java"); doTest("j2k/tests/testData/ast/switch/invalidSwitch.java");
@@ -0,0 +1,16 @@
//file
public class C {
public static void main(String[] args) {
switch (args.length) {
case 1: {
int a = 1;
System.out.print("1");
}
case 2: {
int a = 2;
System.out.print("2");
}
}
}
}
@@ -0,0 +1,24 @@
public class C {
class object {
public fun main(args: Array<String>) {
when (args.size) {
1 -> {
run {
val a = 1
System.out.print("1")
}
run {
val a = 2
System.out.print("2")
}
}
2 -> {
val a = 2
System.out.print("2")
}
}
}
}
}
fun main(args: Array<String>) = C.main(args)