Java to Kotlin converter: code refactoring
This commit is contained in:
@@ -25,77 +25,38 @@ 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
|
|
||||||
|
|
||||||
fun convertStatements(statements: List<PsiStatement>): List<Statement> {
|
|
||||||
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<Statement> {
|
|
||||||
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<WhenEntry>()
|
val result = ArrayList<WhenEntry>()
|
||||||
var pendingSelectors = ArrayList<WhenEntrySelector>()
|
var pendingSelectors = ArrayList<WhenEntrySelector>()
|
||||||
for ((i, case) in cases.withIndices()) {
|
for ((i, case) in cases.withIndices()) {
|
||||||
if (case.label == null) { // invalid switch - no case labels
|
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
|
continue
|
||||||
}
|
}
|
||||||
pendingSelectors.add(converter.convertStatement(case.label) as WhenEntrySelector)
|
pendingSelectors.add(converter.convertStatement(case.label) as WhenEntrySelector)
|
||||||
if (case.statements.isNotEmpty()) {
|
if (case.statements.isNotEmpty()) {
|
||||||
result.add(WhenEntry(pendingSelectors, convertCaseStatementsToBody(i)).assignNoPrototype())
|
result.add(WhenEntry(pendingSelectors, convertCaseStatementsToBody(cases, i)).assignNoPrototype())
|
||||||
pendingSelectors = ArrayList()
|
pendingSelectors = ArrayList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class SwitchCase(val label: PsiSwitchLabelStatement?, val statements: List<PsiStatement>)
|
private fun splitToCases(body: PsiCodeBlock?): List<Case> {
|
||||||
|
val cases = ArrayList<Case>()
|
||||||
private fun splitToCases(body: PsiCodeBlock?): List<SwitchCase> {
|
|
||||||
val cases = ArrayList<SwitchCase>()
|
|
||||||
var currentCaseStatements = ArrayList<PsiStatement>()
|
var currentCaseStatements = ArrayList<PsiStatement>()
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
var label: PsiSwitchLabelStatement? = null
|
var label: PsiSwitchLabelStatement? = null
|
||||||
for (statement in body.getStatements()) {
|
for (statement in body.getStatements()) {
|
||||||
if (statement is PsiSwitchLabelStatement) {
|
if (statement is PsiSwitchLabelStatement) {
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
cases.add(SwitchCase(label, currentCaseStatements))
|
cases.add(Case(label, currentCaseStatements))
|
||||||
currentCaseStatements = ArrayList()
|
currentCaseStatements = ArrayList()
|
||||||
}
|
}
|
||||||
label = statement
|
label = statement
|
||||||
@@ -105,12 +66,51 @@ class SwitchConverter(private val converter: Converter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (label != null || currentCaseStatements.isNotEmpty()) {
|
if (label != null || currentCaseStatements.isNotEmpty()) {
|
||||||
cases.add(SwitchCase(label, currentCaseStatements))
|
cases.add(Case(label, currentCaseStatements))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cases
|
return cases
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun convertCaseStatements(statements: List<PsiStatement>): List<Statement> {
|
||||||
|
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<Case>, caseIndex: Int): List<Statement> {
|
||||||
|
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<Case>, 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 <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
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user