From 911f234ba449086ecf9e447d91e8eaef4653059a Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 7 Aug 2018 07:02:40 +0300 Subject: [PATCH] New J2K: Implement basic default argument converter --- .../jetbrains/kotlin/j2k/ConversionsRunner.kt | 1 + .../conversions/DefaultArgumentsConversion.kt | 82 +++++++++++++++++++ j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt | 1 - .../org/jetbrains/kotlin/j2k/tree/jk.kt | 1 + j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt | 2 - 5 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/DefaultArgumentsConversion.kt diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt index f907fb0592c..48e26403ebd 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt @@ -24,6 +24,7 @@ object ConversionsRunner { private fun createConversions(context: ConversionContext) = listOf( ModalityConversion(context), ImplicitInitializerConversion(), + DefaultArgumentsConversion(context), TypeMappingConversion(context), FieldToPropertyConversion(), AssignmentAsExpressionToAlsoConversion(context), diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/DefaultArgumentsConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/DefaultArgumentsConversion.kt new file mode 100644 index 00000000000..94db7824eea --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/DefaultArgumentsConversion.kt @@ -0,0 +1,82 @@ +/* + * 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.tree.* +import org.jetbrains.kotlin.j2k.tree.impl.JKKtFieldAccessExpressionImpl +import org.jetbrains.kotlin.j2k.tree.impl.JKUniverseMethodSymbol +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +class DefaultArgumentsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() { + override fun applyToElement(element: JKTreeElement): JKTreeElement { + // TODO: Declaration list owner + if (element !is JKClass) return recurse(element) + + val methods = element.declarationList.filterIsInstance().sortedBy { it.parameters.size } + + checkMethod@ for (method in methods) { + val block = method.block as? JKBlock ?: continue + val singleStatement = block.statements.singleOrNull() + + val call = + singleStatement.safeAs()?.expression?.safeAs() + ?: singleStatement.safeAs()?.expression?.safeAs() + ?: continue + val callee = call.identifier as? JKUniverseMethodSymbol ?: continue + val calledMethod = callee.target + if (calledMethod.parent != method.parent + || callee.name != method.name.value + || calledMethod.returnType.type != method.returnType.type + || call.arguments.expressions.size <= method.parameters.size + ) { + continue + } + + + // TODO: Filter by annotations, visibility, modality, modifiers like synchronized + + for (i in method.parameters.indices) { + val parameter = method.parameters[i] + val targetParameter = calledMethod.parameters[i] + val argument = call.arguments.expressions[i] + if (parameter.name.value != targetParameter.name.value) continue@checkMethod + if (parameter.type.type != targetParameter.type.type) continue@checkMethod + if (argument !is JKFieldAccessExpression || argument.identifier.target != parameter) continue@checkMethod + } + + + call.arguments.invalidate() + val defaults = call.arguments.expressions + .zip(calledMethod.parameters) + .drop(method.parameters.size) + + for ((defaultValue, parameter) in defaults) { + fun remapParameterSymbol(on: JKTreeElement): JKTreeElement { + if (on is JKFieldAccessExpression) { + val target = on.identifier.target + if (target is JKParameter) { + val newSymbol = + context.symbolProvider.provideUniverseSymbol(calledMethod.parameters[method.parameters.indexOf(target)]) + return JKKtFieldAccessExpressionImpl(newSymbol) + } + } + + return applyRecursive(on, ::remapParameterSymbol) + } + + parameter.initializer = remapParameterSymbol(defaultValue) as JKExpression + } + + element.declarationList -= method + } + + return recurse(element) + + } + + +} diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt index d451b92661c..32ec6345063 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.j2k.tree.impl.JKMethodSymbol interface JKJavaField : JKField, JKBranchElement interface JKJavaMethod : JKMethod, JKBranchElement { - val block: JKBlock } interface JKJavaMethodCallExpression : JKMethodCallExpression diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt index fb8d582e017..6fb99c2af70 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt @@ -58,6 +58,7 @@ interface JKMethod : JKDeclaration, JKModifierListOwner { val name: JKNameIdentifier var parameters: List val returnType: JKTypeElement + var block: JKBlock } interface JKField : JKDeclaration, JKModifierListOwner { diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt index b0c94c5f712..fa86d0f1ae8 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt @@ -22,13 +22,11 @@ interface JKKtProperty : JKField { } interface JKKtFunction : JKMethod { - val block: JKBlock } interface JKKtConstructor : JKDeclaration, JKModifierListOwner, JKMethod, JKBranchElement { override var name: JKNameIdentifier override var parameters: List - var block: JKBlock var delegationCall: JKExpression }