Skip to content

Commit

Permalink
Fix for loop conversion when multiple initializers are present
Browse files Browse the repository at this point in the history
#KT-35074 fixed
  • Loading branch information
darthorimar committed Nov 25, 2019
1 parent 2da4cc2 commit 6b773bc
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 29 deletions.
18 changes: 10 additions & 8 deletions nj2k/src/org/jetbrains/kotlin/nj2k/JavaToJKTreeBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,14 @@ class JavaToJKTreeBuilder constructor(
}
}

fun PsiStatement?.asJKStatementsList() = when (this) {
null -> emptyList()
is PsiExpressionListStatement -> expressionList.expressions.map { expression ->
JKExpressionStatement(with(expressionTreeMapper) { expression.toJK() })
}
else -> listOf(toJK())
}

fun PsiStatement?.toJK(): JKStatement {
return when (this) {
null -> JKExpressionStatement(JKStubExpression())
Expand All @@ -909,15 +917,9 @@ class JavaToJKTreeBuilder constructor(


is PsiForStatement -> JKJavaForLoopStatement(
initialization.toJK(),
initialization.asJKStatementsList(),
with(expressionTreeMapper) { condition.toJK() },
when (update) {
is PsiExpressionListStatement ->
(update as PsiExpressionListStatement).expressionList.expressions.map {
JKExpressionStatement(with(expressionTreeMapper) { it.toJK() })
}
else -> listOf(update.toJK())
},
update.asJKStatementsList(),
body.toJK()
)
is PsiForeachStatement ->
Expand Down
18 changes: 10 additions & 8 deletions nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ForConversion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
else JKLiteralExpression("true", JKLiteralExpression.LiteralType.BOOLEAN)
val whileStatement = JKWhileStatement(condition, whileBody)

if (loopStatement.initializer is JKEmptyStatement) return whileStatement
if (loopStatement.initializers.isEmpty()
|| loopStatement.initializers.singleOrNull() is JKEmptyStatement
) return whileStatement

val convertedFromForLoopSyntheticWhileStatement =
JKKtConvertedFromForLoopSyntheticWhileStatement(
loopStatement::initializer.detached(),
loopStatement::initializers.detached(),
whileStatement
)

Expand Down Expand Up @@ -81,15 +83,15 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
val body = continueStatementConverter.applyToElement(loopStatement::body.detached())

if (body is JKBlockStatement) {
val initializer = loopStatement.initializer
val hasNameConflict =
val hasNameConflict = loopStatement.initializers.any { initializer ->
initializer is JKDeclarationStatement && initializer.declaredStatements.any { loopVar ->
loopVar is JKLocalVariable && body.statements.any { statement ->
statement is JKDeclarationStatement && statement.declaredStatements.any {
it is JKLocalVariable && it.name.value == loopVar.name.value
}
}
}
}

val statements =
if (hasNameConflict) {
Expand All @@ -106,8 +108,8 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
}

private fun convertToForeach(loopStatement: JKJavaForLoopStatement): JKForInStatement? {
val loopVar =
(loopStatement.initializer as? JKDeclarationStatement)?.declaredStatements?.singleOrNull() as? JKLocalVariable ?: return null
val initializer = loopStatement.initializers.singleOrNull() ?: return null
val loopVar = (initializer as? JKDeclarationStatement)?.declaredStatements?.singleOrNull() as? JKLocalVariable ?: return null
val loopVarPsi = loopVar.psi<PsiLocalVariable>() ?: return null
val condition = loopStatement.condition as? JKBinaryExpression ?: return null
if (!loopVarPsi.hasWriteAccesses(referenceSearcher, loopStatement.body.psi())
Expand Down Expand Up @@ -276,7 +278,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
}

private fun JKJavaForLoopStatement.hasNameConflict(): Boolean {
val names = initializer.declaredVariableNames()
val names = initializers.flatMap { it.declaredVariableNames() }
if (names.isEmpty()) return false

val factory = PsiElementFactory.SERVICE.getInstance(context.project)
Expand All @@ -301,7 +303,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
when (this) {
is JKDeclarationStatement ->
declaredStatements.filterIsInstance<JKVariable>().map { it.name.value }
is JKJavaForLoopStatement -> initializer.declaredVariableNames()
is JKJavaForLoopStatement -> initializers.flatMap { it.declaredVariableNames() }
else -> emptyList()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs


class LabeledStatementConversion(context : NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
class LabeledStatementConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKExpressionStatement) return recurse(element)
val labeledStatement = element.expression as? JKLabeledExpression ?: return recurse(element)
Expand All @@ -26,13 +26,11 @@ class LabeledStatementConversion(context : NewJ2kConverterContext) : RecursiveAp

return recurse(
JKBlockStatementWithoutBrackets(
listOf(
convertedFromForLoopSyntheticWhileStatement::variableDeclaration.detached(),
JKLabeledExpression(
convertedFromForLoopSyntheticWhileStatement::whileStatement.detached(),
labeledStatement::labels.detached()
).asStatement()
)
convertedFromForLoopSyntheticWhileStatement::variableDeclarations.detached() +
JKLabeledExpression(
convertedFromForLoopSyntheticWhileStatement::whileStatement.detached(),
labeledStatement::labels.detached()
).asStatement()
)
)
}
Expand Down
6 changes: 5 additions & 1 deletion nj2k/src/org/jetbrains/kotlin/nj2k/printing/JKCodeBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,11 @@ internal class JKCodeBuilder(context: NewJ2kConverterContext) {
override fun visitKtConvertedFromForLoopSyntheticWhileStatementRaw(
ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement
) {
ktConvertedFromForLoopSyntheticWhileStatement.variableDeclaration.accept(this)
printer.renderList(
ktConvertedFromForLoopSyntheticWhileStatement.variableDeclarations,
{ printer.println() }) {
it.accept(this)
}
printer.println()
ktConvertedFromForLoopSyntheticWhileStatement.whileStatement.accept(this)
}
Expand Down
8 changes: 4 additions & 4 deletions nj2k/src/org/jetbrains/kotlin/nj2k/tree/statements.kt
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ class JKKtWhenStatement(
}

class JKKtConvertedFromForLoopSyntheticWhileStatement(
variableDeclaration: JKStatement,
variableDeclarations: List<JKStatement>,
whileStatement: JKWhileStatement
) : JKStatement() {
var variableDeclaration: JKStatement by child(variableDeclaration)
var variableDeclarations: List<JKStatement> by children(variableDeclarations)
var whileStatement: JKWhileStatement by child(whileStatement)
override fun accept(visitor: JKVisitor) = visitor.visitKtConvertedFromForLoopSyntheticWhileStatement(this)
}
Expand Down Expand Up @@ -154,15 +154,15 @@ class JKJavaAssertStatement(condition: JKExpression, description: JKExpression)
}

class JKJavaForLoopStatement(
initializer: JKStatement,
initializers: List<JKStatement>,
condition: JKExpression,
updaters: List<JKStatement>,
body: JKStatement
) : JKLoopStatement() {
override var body by child(body)
var updaters by children(updaters)
var condition by child(condition)
var initializer by child(initializer)
var initializers by children(initializers)

override fun accept(visitor: JKVisitor) = visitor.visitJavaForLoopStatement(this)
}
Expand Down
7 changes: 7 additions & 0 deletions nj2k/testData/newJ2k/for/emptyInitializers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
public class SomeClass {
void doSomeFor() {
int i = 0, u = 0;
for (; i < 42; i++) {
}
}
}
9 changes: 9 additions & 0 deletions nj2k/testData/newJ2k/for/emptyInitializers.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class SomeClass {
fun doSomeFor() {
var i = 0
val u = 0
while (i < 42) {
i++
}
}
}
7 changes: 7 additions & 0 deletions nj2k/testData/newJ2k/for/multipleInitializers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
public class SomeClass {
void doSomeFor() {
int i, u;
for (i = 0, u = 0; i < 42; i++) {
}
}
}
11 changes: 11 additions & 0 deletions nj2k/testData/newJ2k/for/multipleInitializers.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class SomeClass {
fun doSomeFor() {
var i: Int
val u: Int
i = 0
u = 0
while (i < 42) {
i++
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public class SomeClass {
void doSomeFor() {
for (int i = 0, u = 0; i < 42; i++) {
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class SomeClass {
fun doSomeFor() {
var i = 0
val u = 0
while (i < 42) {
i++
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6b773bc

Please sign in to comment.