Fix for loop conversion when multiple initializers are present
#KT-35074 fixed
This commit is contained in:
@@ -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())
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -81,8 +83,7 @@ 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 {
|
||||
@@ -90,6 +91,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val statements =
|
||||
if (hasNameConflict) {
|
||||
@@ -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())
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -154,7 +154,7 @@ class JKJavaAssertStatement(condition: JKExpression, description: JKExpression)
|
||||
}
|
||||
|
||||
class JKJavaForLoopStatement(
|
||||
initializer: JKStatement,
|
||||
initializers: List<JKStatement>,
|
||||
condition: JKExpression,
|
||||
updaters: List<JKStatement>,
|
||||
body: JKStatement
|
||||
@@ -162,7 +162,7 @@ class JKJavaForLoopStatement(
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
public class SomeClass {
|
||||
void doSomeFor() {
|
||||
int i = 0, u = 0;
|
||||
for (; i < 42; i++) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class SomeClass {
|
||||
fun doSomeFor() {
|
||||
var i = 0
|
||||
val u = 0
|
||||
while (i < 42) {
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class SomeClass {
|
||||
void doSomeFor() {
|
||||
int i, u;
|
||||
for (i = 0, u = 0; i < 42; i++) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class SomeClass {
|
||||
fun doSomeFor() {
|
||||
var i: Int
|
||||
val u: Int
|
||||
i = 0
|
||||
u = 0
|
||||
while (i < 42) {
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
public class SomeClass {
|
||||
void doSomeFor() {
|
||||
for (int i = 0, u = 0; i < 42; i++) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class SomeClass {
|
||||
fun doSomeFor() {
|
||||
var i = 0
|
||||
val u = 0
|
||||
while (i < 42) {
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
@@ -2023,6 +2023,11 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew
|
||||
runTest("nj2k/testData/newJ2k/for/downTo4.java");
|
||||
}
|
||||
|
||||
@TestMetadata("emptyInitializers.java")
|
||||
public void testEmptyInitializers() throws Exception {
|
||||
runTest("nj2k/testData/newJ2k/for/emptyInitializers.java");
|
||||
}
|
||||
|
||||
@TestMetadata("falseArrayIndicesReversed.java")
|
||||
public void testFalseArrayIndicesReversed() throws Exception {
|
||||
runTest("nj2k/testData/newJ2k/for/falseArrayIndicesReversed.java");
|
||||
@@ -2153,6 +2158,16 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew
|
||||
runTest("nj2k/testData/newJ2k/for/infiniteFor.java");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleInitializers.java")
|
||||
public void testMultipleInitializers() throws Exception {
|
||||
runTest("nj2k/testData/newJ2k/for/multipleInitializers.java");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleInitializersWithvariableDeclarations.java")
|
||||
public void testMultipleInitializersWithvariableDeclarations() throws Exception {
|
||||
runTest("nj2k/testData/newJ2k/for/multipleInitializersWithvariableDeclarations.java");
|
||||
}
|
||||
|
||||
@TestMetadata("nameConflict1.java")
|
||||
public void testNameConflict1() throws Exception {
|
||||
runTest("nj2k/testData/newJ2k/for/nameConflict1.java");
|
||||
|
||||
Reference in New Issue
Block a user