From be90db7fca7c590012f96c073197afb10da94848 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 18 Dec 2018 14:37:57 +0300 Subject: [PATCH] New J2K: Add ParameterModificationInMethodCallsConversion --- ...eterModificationInMethodCallsConversion.kt | 33 ++++++++++++++++ .../org/jetbrains/kotlin/j2k/expressions.kt | 39 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ParameterModificationInMethodCallsConversion.kt diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ParameterModificationInMethodCallsConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ParameterModificationInMethodCallsConversion.kt new file mode 100644 index 00000000000..08fbb33b055 --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ParameterModificationInMethodCallsConversion.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.j2k.conversions + +import org.jetbrains.kotlin.j2k.ConversionContext +import org.jetbrains.kotlin.j2k.asAssignmentFromTarget +import org.jetbrains.kotlin.j2k.findUsages +import org.jetbrains.kotlin.j2k.hasWritableUsages +import org.jetbrains.kotlin.j2k.tree.* +import org.jetbrains.kotlin.j2k.tree.impl.* + + +class ParameterModificationInMethodCallsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() { + override fun applyToElement(element: JKTreeElement): JKTreeElement { + if (element !is JKMethod) return recurse(element) + val newVariables = + element.parameters.mapNotNull { parameter -> + if (parameter.hasWritableUsages(element.block, context)) { + JKLocalVariableImpl( + JKTypeElementImpl(parameter.type.type), + JKNameIdentifierImpl(parameter.name.value), + JKFieldAccessExpressionImpl(context.symbolProvider.provideUniverseSymbol(parameter)), + Mutability.MUTABLE + ) + } else null + } + element.block.statements = listOf(JKDeclarationStatementImpl(newVariables)) + element.block.statements + return recurse(element) + } +} \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt index f157d86dc53..fcf5709202d 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/expressions.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.j2k import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.j2k.ast.Nullability +import org.jetbrains.kotlin.j2k.conversions.RecursiveApplicableConversionBase import org.jetbrains.kotlin.j2k.conversions.multiResolveFqName import org.jetbrains.kotlin.j2k.conversions.resolveFqName import org.jetbrains.kotlin.j2k.tree.* @@ -220,3 +221,41 @@ fun throwAnnotation(throws: List, symbolProvider: JKSymbolProvider) = } ) ) + +fun JKVariable.findUsages(scope: JKTreeElement, context: ConversionContext): List { + val symbol = context.symbolProvider.provideUniverseSymbol(this) + val usages = mutableListOf() + val searcher = object : RecursiveApplicableConversionBase() { + override fun applyToElement(element: JKTreeElement): JKTreeElement { + if (element is JKExpression) { + element.unboxFieldReference()?.also { + if (it.identifier == symbol) { + usages += it + } + } + } + return recurse(element) + } + } + searcher.runConversion(scope, context) + return usages +} + +fun JKExpression.unboxFieldReference(): JKFieldAccessExpression? = when { + this is JKFieldAccessExpression -> this + this is JKQualifiedExpression && receiver is JKThisExpression -> selector as? JKFieldAccessExpression + else -> null +} + +fun JKFieldAccessExpression.asAssignmentFromTarget(): JKKtAssignmentStatement? = + (parent as? JKKtAssignmentStatement) + ?.takeIf { it.field == this } + +fun JKFieldAccessExpression.isInDecrementOrIncrement(): Boolean = + (parent as? JKUnaryExpression)?.operator?.token?.text in listOf("++", "--") + +fun JKVariable.hasWritableUsages(scope: JKTreeElement, context: ConversionContext): Boolean = + findUsages(scope, context).any { + it.asAssignmentFromTarget() != null + || it.isInDecrementOrIncrement() + } \ No newline at end of file