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 {
|
fun PsiStatement?.toJK(): JKStatement {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
null -> JKExpressionStatement(JKStubExpression())
|
null -> JKExpressionStatement(JKStubExpression())
|
||||||
@@ -909,15 +917,9 @@ class JavaToJKTreeBuilder constructor(
|
|||||||
|
|
||||||
|
|
||||||
is PsiForStatement -> JKJavaForLoopStatement(
|
is PsiForStatement -> JKJavaForLoopStatement(
|
||||||
initialization.toJK(),
|
initialization.asJKStatementsList(),
|
||||||
with(expressionTreeMapper) { condition.toJK() },
|
with(expressionTreeMapper) { condition.toJK() },
|
||||||
when (update) {
|
update.asJKStatementsList(),
|
||||||
is PsiExpressionListStatement ->
|
|
||||||
(update as PsiExpressionListStatement).expressionList.expressions.map {
|
|
||||||
JKExpressionStatement(with(expressionTreeMapper) { it.toJK() })
|
|
||||||
}
|
|
||||||
else -> listOf(update.toJK())
|
|
||||||
},
|
|
||||||
body.toJK()
|
body.toJK()
|
||||||
)
|
)
|
||||||
is PsiForeachStatement ->
|
is PsiForeachStatement ->
|
||||||
|
|||||||
@@ -40,11 +40,13 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
|
|||||||
else JKLiteralExpression("true", JKLiteralExpression.LiteralType.BOOLEAN)
|
else JKLiteralExpression("true", JKLiteralExpression.LiteralType.BOOLEAN)
|
||||||
val whileStatement = JKWhileStatement(condition, whileBody)
|
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 =
|
val convertedFromForLoopSyntheticWhileStatement =
|
||||||
JKKtConvertedFromForLoopSyntheticWhileStatement(
|
JKKtConvertedFromForLoopSyntheticWhileStatement(
|
||||||
loopStatement::initializer.detached(),
|
loopStatement::initializers.detached(),
|
||||||
whileStatement
|
whileStatement
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -81,8 +83,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
|
|||||||
val body = continueStatementConverter.applyToElement(loopStatement::body.detached())
|
val body = continueStatementConverter.applyToElement(loopStatement::body.detached())
|
||||||
|
|
||||||
if (body is JKBlockStatement) {
|
if (body is JKBlockStatement) {
|
||||||
val initializer = loopStatement.initializer
|
val hasNameConflict = loopStatement.initializers.any { initializer ->
|
||||||
val hasNameConflict =
|
|
||||||
initializer is JKDeclarationStatement && initializer.declaredStatements.any { loopVar ->
|
initializer is JKDeclarationStatement && initializer.declaredStatements.any { loopVar ->
|
||||||
loopVar is JKLocalVariable && body.statements.any { statement ->
|
loopVar is JKLocalVariable && body.statements.any { statement ->
|
||||||
statement is JKDeclarationStatement && statement.declaredStatements.any {
|
statement is JKDeclarationStatement && statement.declaredStatements.any {
|
||||||
@@ -90,6 +91,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val statements =
|
val statements =
|
||||||
if (hasNameConflict) {
|
if (hasNameConflict) {
|
||||||
@@ -106,8 +108,8 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun convertToForeach(loopStatement: JKJavaForLoopStatement): JKForInStatement? {
|
private fun convertToForeach(loopStatement: JKJavaForLoopStatement): JKForInStatement? {
|
||||||
val loopVar =
|
val initializer = loopStatement.initializers.singleOrNull() ?: return null
|
||||||
(loopStatement.initializer as? JKDeclarationStatement)?.declaredStatements?.singleOrNull() as? JKLocalVariable ?: return null
|
val loopVar = (initializer as? JKDeclarationStatement)?.declaredStatements?.singleOrNull() as? JKLocalVariable ?: return null
|
||||||
val loopVarPsi = loopVar.psi<PsiLocalVariable>() ?: return null
|
val loopVarPsi = loopVar.psi<PsiLocalVariable>() ?: return null
|
||||||
val condition = loopStatement.condition as? JKBinaryExpression ?: return null
|
val condition = loopStatement.condition as? JKBinaryExpression ?: return null
|
||||||
if (!loopVarPsi.hasWriteAccesses(referenceSearcher, loopStatement.body.psi())
|
if (!loopVarPsi.hasWriteAccesses(referenceSearcher, loopStatement.body.psi())
|
||||||
@@ -276,7 +278,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun JKJavaForLoopStatement.hasNameConflict(): Boolean {
|
private fun JKJavaForLoopStatement.hasNameConflict(): Boolean {
|
||||||
val names = initializer.declaredVariableNames()
|
val names = initializers.flatMap { it.declaredVariableNames() }
|
||||||
if (names.isEmpty()) return false
|
if (names.isEmpty()) return false
|
||||||
|
|
||||||
val factory = PsiElementFactory.SERVICE.getInstance(context.project)
|
val factory = PsiElementFactory.SERVICE.getInstance(context.project)
|
||||||
@@ -301,7 +303,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
|
|||||||
when (this) {
|
when (this) {
|
||||||
is JKDeclarationStatement ->
|
is JKDeclarationStatement ->
|
||||||
declaredStatements.filterIsInstance<JKVariable>().map { it.name.value }
|
declaredStatements.filterIsInstance<JKVariable>().map { it.name.value }
|
||||||
is JKJavaForLoopStatement -> initializer.declaredVariableNames()
|
is JKJavaForLoopStatement -> initializers.flatMap { it.declaredVariableNames() }
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.nj2k.tree.*
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
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 {
|
override fun applyToElement(element: JKTreeElement): JKTreeElement {
|
||||||
if (element !is JKExpressionStatement) return recurse(element)
|
if (element !is JKExpressionStatement) return recurse(element)
|
||||||
val labeledStatement = element.expression as? JKLabeledExpression ?: return recurse(element)
|
val labeledStatement = element.expression as? JKLabeledExpression ?: return recurse(element)
|
||||||
@@ -26,13 +26,11 @@ class LabeledStatementConversion(context : NewJ2kConverterContext) : RecursiveAp
|
|||||||
|
|
||||||
return recurse(
|
return recurse(
|
||||||
JKBlockStatementWithoutBrackets(
|
JKBlockStatementWithoutBrackets(
|
||||||
listOf(
|
convertedFromForLoopSyntheticWhileStatement::variableDeclarations.detached() +
|
||||||
convertedFromForLoopSyntheticWhileStatement::variableDeclaration.detached(),
|
JKLabeledExpression(
|
||||||
JKLabeledExpression(
|
convertedFromForLoopSyntheticWhileStatement::whileStatement.detached(),
|
||||||
convertedFromForLoopSyntheticWhileStatement::whileStatement.detached(),
|
labeledStatement::labels.detached()
|
||||||
labeledStatement::labels.detached()
|
).asStatement()
|
||||||
).asStatement()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -548,7 +548,11 @@ internal class JKCodeBuilder(context: NewJ2kConverterContext) {
|
|||||||
override fun visitKtConvertedFromForLoopSyntheticWhileStatementRaw(
|
override fun visitKtConvertedFromForLoopSyntheticWhileStatementRaw(
|
||||||
ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement
|
ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement
|
||||||
) {
|
) {
|
||||||
ktConvertedFromForLoopSyntheticWhileStatement.variableDeclaration.accept(this)
|
printer.renderList(
|
||||||
|
ktConvertedFromForLoopSyntheticWhileStatement.variableDeclarations,
|
||||||
|
{ printer.println() }) {
|
||||||
|
it.accept(this)
|
||||||
|
}
|
||||||
printer.println()
|
printer.println()
|
||||||
ktConvertedFromForLoopSyntheticWhileStatement.whileStatement.accept(this)
|
ktConvertedFromForLoopSyntheticWhileStatement.whileStatement.accept(this)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,10 +83,10 @@ class JKKtWhenStatement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class JKKtConvertedFromForLoopSyntheticWhileStatement(
|
class JKKtConvertedFromForLoopSyntheticWhileStatement(
|
||||||
variableDeclaration: JKStatement,
|
variableDeclarations: List<JKStatement>,
|
||||||
whileStatement: JKWhileStatement
|
whileStatement: JKWhileStatement
|
||||||
) : JKStatement() {
|
) : JKStatement() {
|
||||||
var variableDeclaration: JKStatement by child(variableDeclaration)
|
var variableDeclarations: List<JKStatement> by children(variableDeclarations)
|
||||||
var whileStatement: JKWhileStatement by child(whileStatement)
|
var whileStatement: JKWhileStatement by child(whileStatement)
|
||||||
override fun accept(visitor: JKVisitor) = visitor.visitKtConvertedFromForLoopSyntheticWhileStatement(this)
|
override fun accept(visitor: JKVisitor) = visitor.visitKtConvertedFromForLoopSyntheticWhileStatement(this)
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ class JKJavaAssertStatement(condition: JKExpression, description: JKExpression)
|
|||||||
}
|
}
|
||||||
|
|
||||||
class JKJavaForLoopStatement(
|
class JKJavaForLoopStatement(
|
||||||
initializer: JKStatement,
|
initializers: List<JKStatement>,
|
||||||
condition: JKExpression,
|
condition: JKExpression,
|
||||||
updaters: List<JKStatement>,
|
updaters: List<JKStatement>,
|
||||||
body: JKStatement
|
body: JKStatement
|
||||||
@@ -162,7 +162,7 @@ class JKJavaForLoopStatement(
|
|||||||
override var body by child(body)
|
override var body by child(body)
|
||||||
var updaters by children(updaters)
|
var updaters by children(updaters)
|
||||||
var condition by child(condition)
|
var condition by child(condition)
|
||||||
var initializer by child(initializer)
|
var initializers by children(initializers)
|
||||||
|
|
||||||
override fun accept(visitor: JKVisitor) = visitor.visitJavaForLoopStatement(this)
|
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");
|
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")
|
@TestMetadata("falseArrayIndicesReversed.java")
|
||||||
public void testFalseArrayIndicesReversed() throws Exception {
|
public void testFalseArrayIndicesReversed() throws Exception {
|
||||||
runTest("nj2k/testData/newJ2k/for/falseArrayIndicesReversed.java");
|
runTest("nj2k/testData/newJ2k/for/falseArrayIndicesReversed.java");
|
||||||
@@ -2153,6 +2158,16 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew
|
|||||||
runTest("nj2k/testData/newJ2k/for/infiniteFor.java");
|
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")
|
@TestMetadata("nameConflict1.java")
|
||||||
public void testNameConflict1() throws Exception {
|
public void testNameConflict1() throws Exception {
|
||||||
runTest("nj2k/testData/newJ2k/for/nameConflict1.java");
|
runTest("nj2k/testData/newJ2k/for/nameConflict1.java");
|
||||||
|
|||||||
Reference in New Issue
Block a user