From 962b971f074c9fc3ab54db60732ebbc0f7a635f8 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 17 Jan 2019 19:17:10 +0300 Subject: [PATCH] New J2K: Add conflicts handling in for conversion --- .../kotlin/j2k/conversions/ForConversion.kt | 52 ++++++++++++++++--- .../org/jetbrains/kotlin/j2k/expressions.kt | 13 ++++- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ForConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ForConversion.kt index 1cb0254415f..acd53734884 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ForConversion.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ForConversion.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.j2k.conversions import com.intellij.psi.* +import com.intellij.util.IncorrectOperationException import org.jetbrains.kotlin.j2k.* -import org.jetbrains.kotlin.j2k.ast.Mutability import org.jetbrains.kotlin.j2k.tree.* import org.jetbrains.kotlin.j2k.tree.impl.* import org.jetbrains.kotlin.lexer.KtTokens @@ -42,10 +42,21 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl loopStatement::initializer.detached(), whileStatement ) + val notNeedParentBlock = loopStatement.parent is JKBlock || loopStatement.parent is JKLabeledStatement && loopStatement.parent?.parent is JKBlock - return if (notNeedParentBlock) convertedFromForLoopSyntheticWhileStatement - else blockStatement(convertedFromForLoopSyntheticWhileStatement) + + return when { + loopStatement.hasNameConflict() -> + JKExpressionStatementImpl( + runExpression( + convertedFromForLoopSyntheticWhileStatement, + context.symbolProvider + ) + ) + !notNeedParentBlock -> blockStatement(convertedFromForLoopSyntheticWhileStatement) + else -> convertedFromForLoopSyntheticWhileStatement + } } private fun createWhileBody(loopStatement: JKJavaForLoopStatement): JKStatement { @@ -70,15 +81,14 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl 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 == loopVar.name + it is JKLocalVariable && it.name.value == loopVar.name.value } } } val statements = if (hasNameConflict) { - - listOf(body) + loopStatement::updaters.detached() + listOf(JKExpressionStatementImpl(runExpression(body, context.symbolProvider))) + loopStatement::updaters.detached() } else { body.block::statements.detached() + loopStatement::updaters.detached() } @@ -262,6 +272,36 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl return JKQualifiedExpressionImpl(javaSizeCall::receiver.detached(), javaSizeCall.operator, selector) } + private fun JKJavaForLoopStatement.hasNameConflict(): Boolean { + val names = initializer.declaredVariableNames() + if (names.isEmpty()) return false + + val factory = PsiElementFactory.SERVICE.getInstance(context.project) + for (name in names) { + val refExpr = try { + factory.createExpressionFromText(name, psi) as? PsiReferenceExpression ?: return true + } catch (e: IncorrectOperationException) { + return true + } + if (refExpr.resolve() != null) return true + } + + return (parent as? JKBlock) + ?.statements + ?.takeLastWhile { it != this } + ?.any { + it.declaredVariableNames().any { it in names } + } == true + } + + private fun JKStatement.declaredVariableNames(): Collection = + when (this) { + is JKDeclarationStatement -> + declaredStatements.filterIsInstance().map { it.name.value } + is JKJavaForLoopStatement -> initializer.declaredVariableNames() + else -> emptyList() + } + private fun JKExpression.isVariableIncrementOrDecrement(variable: JKLocalVariable): JKOperator? { val pair = when (this) { diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt index fc5538470bf..32d0702b5e0 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt @@ -462,4 +462,15 @@ fun JKClass.getOrCreateCompainonObject(): JKClass = emptyList(), Visibility.PUBLIC, Modality.FINAL - ).also { classBody.declarations += it } \ No newline at end of file + ).also { classBody.declarations += it } + +fun runExpression(body: JKStatement, symbolProvider: JKSymbolProvider): JKExpression { + val lambda = JKLambdaExpressionImpl( + body, + emptyList() + ) + return JKKtCallExpressionImpl( + symbolProvider.provideByFqNameMulti("kotlin.run"), + JKExpressionListImpl(listOf(lambda)) + ) +} \ No newline at end of file