Java to Kotlin converter: minor refactoring of switch conversion + no need for empty else

This commit is contained in:
Valentin Kipyatkov
2014-07-04 22:05:27 +04:00
parent e84c753e99
commit 6bd5a12498
4 changed files with 23 additions and 31 deletions
@@ -149,32 +149,34 @@ class CatchStatement(val variable: Parameter, val block: Block) : Statement() {
} }
} }
// Switch -------------------------------------------------------------------------------------------------- // when --------------------------------------------------------------------------------------------------
class SwitchContainer(val expression: Expression, val caseContainers: List<CaseContainer>) : Statement() { class WhenStatement(val subject: Expression, val caseContainers: List<WhenEntry>) : Statement() {
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
builder.append("when (").append(expression).append(") {\n").append(caseContainers, "\n").append("\n}") builder.append("when (").append(subject).append(") {\n").append(caseContainers, "\n").append("\n}")
} }
} }
class CaseContainer(val caseStatement: List<Element>, statements: List<Statement>) : Statement() { class WhenEntry(val selectors: List<WhenEntrySelector>, statements: List<Statement>) : Statement() {
private val block = run { private val block = run {
val filteredStatements = statements.filterNot { it is BreakStatement || it is ContinueStatement } val filteredStatements = statements.filterNot { it is BreakStatement || it is ContinueStatement }
Block(filteredStatements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype() Block(filteredStatements, LBrace().assignNoPrototype(), RBrace().assignNoPrototype(), true).assignNoPrototype()
} }
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
builder.append(caseStatement, ", ").append(" -> ").append(block) builder.append(selectors, ", ").append(" -> ").append(block)
} }
} }
class SwitchLabelStatement(val expression: Expression) : Statement() { abstract class WhenEntrySelector : Statement()
class ValueWhenEntrySelector(val expression: Expression) : WhenEntrySelector() {
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
builder.append(expression) builder.append(expression)
} }
} }
class DefaultSwitchLabelStatement() : Statement() { class ElseWhenEntrySelector() : WhenEntrySelector() {
override fun generateCode(builder: CodeBuilder) { override fun generateCode(builder: CodeBuilder) {
builder.append("else") builder.append("else")
} }
@@ -200,57 +200,50 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
override fun visitSwitchLabelStatement(statement: PsiSwitchLabelStatement) { override fun visitSwitchLabelStatement(statement: PsiSwitchLabelStatement) {
result = if (statement.isDefaultCase()) result = if (statement.isDefaultCase())
DefaultSwitchLabelStatement() ElseWhenEntrySelector()
else else
SwitchLabelStatement(converter.convertExpression(statement.getCaseValue())) ValueWhenEntrySelector(converter.convertExpression(statement.getCaseValue()))
} }
override fun visitSwitchStatement(statement: PsiSwitchStatement) { override fun visitSwitchStatement(statement: PsiSwitchStatement) {
result = SwitchContainer(converter.convertExpression(statement.getExpression()), result = WhenStatement(converter.convertExpression(statement.getExpression()), switchBodyToWhenEntries(statement.getBody()))
switchBodyToCases(statement.getBody()))
} }
private fun switchBodyToCases(body: PsiCodeBlock?): List<CaseContainer> { private fun switchBodyToWhenEntries(body: PsiCodeBlock?): List<WhenEntry> {
val cases: List<List<PsiElement>> = splitToCases(body) val cases: List<List<PsiElement>> = splitToCases(body)
val allSwitchStatements = ArrayList<PsiElement>() val allSwitchStatements = ArrayList<PsiElement>()
if (body != null) { if (body != null) {
allSwitchStatements.addAll(body.getStatements()) allSwitchStatements.addAll(body.getStatements())
} }
val result = ArrayList<CaseContainer>() val result = ArrayList<WhenEntry>()
var pendingLabels = ArrayList<Element>() var pendingSelectors = ArrayList<WhenEntrySelector>()
var i = 0 var i = 0
var hasDefaultCase = false var hasDefaultCase = false
for (ls in cases) { for (ls in cases) {
if (ls.size() > 0) { if (ls.isNotEmpty()) {
var label = ls[0] as PsiSwitchLabelStatement val label = ls[0] as PsiSwitchLabelStatement
hasDefaultCase = hasDefaultCase || label.isDefaultCase() hasDefaultCase = hasDefaultCase || label.isDefaultCase()
// TODO assert {(label is PsiSwitchLabelStatement?)} // TODO assert {(label is PsiSwitchLabelStatement?)}
// TODO assert("not a right index") {allSwitchStatements?.get(i) == label} // TODO assert("not a right index") {allSwitchStatements?.get(i) == label}
pendingSelectors.add(converter.convertStatement(label) as WhenEntrySelector)
if (ls.size() > 1) { if (ls.size() > 1) {
pendingLabels.add(converter.convertStatement(label)) val slice = ls.drop(1)
val slice = ls.subList(1, (ls.size()))
fun convertStatements(elements: List<PsiElement>): List<Statement> fun convertStatements(elements: List<PsiElement>): List<Statement>
= elements.map { if (it is PsiStatement) converter.convertStatement(it) else null }.filterNotNull() = elements.map { if (it is PsiStatement) converter.convertStatement(it) else null }.filterNotNull()
if (!containsBreak(slice)) { if (!containsBreak(slice)) {
val statements = convertStatements(slice) + convertStatements(getAllToNextBreak(allSwitchStatements, i + ls.size())) val statements = convertStatements(slice) + convertStatements(getAllToNextBreak(allSwitchStatements, i + ls.size()))
result.add(CaseContainer(pendingLabels, statements).assignNoPrototype()) result.add(WhenEntry(pendingSelectors, statements).assignNoPrototype())
} }
else { else {
result.add(CaseContainer(pendingLabels, convertStatements(slice)).assignNoPrototype()) result.add(WhenEntry(pendingSelectors, convertStatements(slice)).assignNoPrototype())
} }
pendingLabels = ArrayList() pendingSelectors = ArrayList()
}
else {
pendingLabels.add(converter.convertStatement(label))
} }
i += ls.size() i += ls.size()
} }
} }
if (!hasDefaultCase) {
result.add(CaseContainer(listOf(DefaultSwitchLabelStatement().assignNoPrototype()), listOf()).assignNoPrototype())
}
return result return result
} }
+1 -2
View File
@@ -5,8 +5,7 @@ public class NonDefault {
val value = 3 val value = 3
val valueString = "" val valueString = ""
when (value) { when (value) {
else -> {
}
} }
System.out.println(valueString) System.out.println(valueString)
} }
@@ -14,8 +14,6 @@ public class NonDefault {
3 -> { 3 -> {
valueString = "THREE" valueString = "THREE"
} }
else -> {
}
} }
System.out.println(valueString) System.out.println(valueString)
} }