New J2K: Add conflicts handling in for conversion
This commit is contained in:
committed by
Ilya Kirillov
parent
e43eb4da03
commit
962b971f07
@@ -6,8 +6,8 @@
|
|||||||
package org.jetbrains.kotlin.j2k.conversions
|
package org.jetbrains.kotlin.j2k.conversions
|
||||||
|
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
|
import com.intellij.util.IncorrectOperationException
|
||||||
import org.jetbrains.kotlin.j2k.*
|
import org.jetbrains.kotlin.j2k.*
|
||||||
import org.jetbrains.kotlin.j2k.ast.Mutability
|
|
||||||
import org.jetbrains.kotlin.j2k.tree.*
|
import org.jetbrains.kotlin.j2k.tree.*
|
||||||
import org.jetbrains.kotlin.j2k.tree.impl.*
|
import org.jetbrains.kotlin.j2k.tree.impl.*
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
@@ -42,10 +42,21 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl
|
|||||||
loopStatement::initializer.detached(),
|
loopStatement::initializer.detached(),
|
||||||
whileStatement
|
whileStatement
|
||||||
)
|
)
|
||||||
|
|
||||||
val notNeedParentBlock = loopStatement.parent is JKBlock
|
val notNeedParentBlock = loopStatement.parent is JKBlock
|
||||||
|| loopStatement.parent is JKLabeledStatement && loopStatement.parent?.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 {
|
private fun createWhileBody(loopStatement: JKJavaForLoopStatement): JKStatement {
|
||||||
@@ -70,15 +81,14 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl
|
|||||||
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 {
|
||||||
it is JKLocalVariable && it.name == loopVar.name
|
it is JKLocalVariable && it.name.value == loopVar.name.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val statements =
|
val statements =
|
||||||
if (hasNameConflict) {
|
if (hasNameConflict) {
|
||||||
|
listOf(JKExpressionStatementImpl(runExpression(body, context.symbolProvider))) + loopStatement::updaters.detached()
|
||||||
listOf(body) + loopStatement::updaters.detached()
|
|
||||||
} else {
|
} else {
|
||||||
body.block::statements.detached() + loopStatement::updaters.detached()
|
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)
|
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<String> =
|
||||||
|
when (this) {
|
||||||
|
is JKDeclarationStatement ->
|
||||||
|
declaredStatements.filterIsInstance<JKVariable>().map { it.name.value }
|
||||||
|
is JKJavaForLoopStatement -> initializer.declaredVariableNames()
|
||||||
|
else -> emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun JKExpression.isVariableIncrementOrDecrement(variable: JKLocalVariable): JKOperator? {
|
private fun JKExpression.isVariableIncrementOrDecrement(variable: JKLocalVariable): JKOperator? {
|
||||||
val pair = when (this) {
|
val pair = when (this) {
|
||||||
|
|||||||
@@ -463,3 +463,14 @@ fun JKClass.getOrCreateCompainonObject(): JKClass =
|
|||||||
Visibility.PUBLIC,
|
Visibility.PUBLIC,
|
||||||
Modality.FINAL
|
Modality.FINAL
|
||||||
).also { classBody.declarations += it }
|
).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))
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user