diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt index 027686d7d3d..984e59729f6 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt @@ -206,67 +206,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito } override fun visitSwitchStatement(statement: PsiSwitchStatement) { - result = WhenStatement(converter.convertExpression(statement.getExpression()), switchBodyToWhenEntries(statement.getBody())) - } - - 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()) - continue - } - pendingSelectors.add(converter.convertStatement(case.label) as WhenEntrySelector) - if (case.statements.isNotEmpty()) { - result.add(WhenEntry(pendingSelectors, convertCaseStatementsToBody(i)).assignNoPrototype()) - pendingSelectors = ArrayList() - } - } - return result + result = SwitchConverter(converter).convert(statement) } override fun visitSynchronizedStatement(statement: PsiSynchronizedStatement) { @@ -381,40 +321,10 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito (this is PsiPrefixExpression && this.getOperationTokenType() == JavaTokenType.PLUSPLUS) } - private data class SwitchCase(val label: PsiSwitchLabelStatement?, val statements: List) - - 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)) - currentCaseStatements = ArrayList() - } - label = statement - } - else { - currentCaseStatements.add(statement) - } - } - if (label != null || currentCaseStatements.isNotEmpty()) { - cases.add(SwitchCase(label, currentCaseStatements)) - } - } - - return cases - } - private fun convertStatementOrBlock(statement: PsiStatement?): Statement { return if (statement is PsiBlockStatement) converter.convertBlock(statement.getCodeBlock()) else converter.convertStatement(statement) } - - private fun List.singleOrNull2(): T? - = if (size == 1) this[0] else null } diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt new file mode 100644 index 00000000000..26a3abc5893 --- /dev/null +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/SwitchConverter.kt @@ -0,0 +1,116 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.j2k.visitors + +import com.intellij.psi.* +import org.jetbrains.jet.j2k.ast.* +import org.jetbrains.jet.j2k.Converter +import java.util.ArrayList + +class SwitchConverter(private val converter: Converter) { + public fun convert(statement: PsiSwitchStatement): WhenStatement + = WhenStatement(converter.convertExpression(statement.getExpression()), switchBodyToWhenEntries(statement.getBody())) + + 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()) + 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) + + 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)) + currentCaseStatements = ArrayList() + } + label = statement + } + else { + currentCaseStatements.add(statement) + } + } + if (label != null || currentCaseStatements.isNotEmpty()) { + cases.add(SwitchCase(label, currentCaseStatements)) + } + } + + return cases + } + + private fun List.singleOrNull2(): T? = if (size == 1) this[0] else null +} \ No newline at end of file