From ae3920d53546e902e1b0d377ef082c086de29502 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 8 Apr 2019 20:32:43 +0300 Subject: [PATCH] New J2K: Finish DefaultArgumentsConversion --- .../conversions/DefaultArgumentsConversion.kt | 67 +++++++++++++++++-- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/DefaultArgumentsConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/DefaultArgumentsConversion.kt index 03ce66a77f8..65f3007fe77 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/DefaultArgumentsConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/DefaultArgumentsConversion.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.nj2k.conversions import org.jetbrains.kotlin.nj2k.ConversionContext +import org.jetbrains.kotlin.nj2k.copyTreeAndDetach import org.jetbrains.kotlin.nj2k.jvmAnnotation import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.impl.JKFieldAccessExpressionImpl @@ -25,10 +26,9 @@ class DefaultArgumentsConversion(private val context: ConversionContext) : Recur override fun applyToElement(element: JKTreeElement): JKTreeElement { - // TODO: Declaration list owner - if (element !is JKClass) return recurse(element) + if (element !is JKClassBody) return recurse(element) - val methods = element.declarationList.filterIsInstance().sortedBy { it.parameters.size } + val methods = element.declarations.filterIsInstance().sortedBy { it.parameters.size } checkMethod@ for (method in methods) { val block = method.block as? JKBlock ?: continue @@ -47,7 +47,6 @@ class DefaultArgumentsConversion(private val context: ConversionContext) : Recur } - // TODO: Filter by annotations, visibility, modality, extraModifiers like synchronized if (calledMethod.visibility != method.visibility) continue@checkMethod if (calledMethod.canNotBeMerged()) continue @@ -58,6 +57,28 @@ class DefaultArgumentsConversion(private val context: ConversionContext) : Recur 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 + if (parameter.initializer !is JKStubExpression + && targetParameter.initializer !is JKStubExpression + && !areTheSameExpressions(targetParameter.initializer, parameter.initializer) + ) continue@checkMethod + } + + for (i in method.parameters.indices) { + val parameter = method.parameters[i] + val targetParameter = calledMethod.parameters[i] + if (parameter.initializer !is JKStubExpression + && targetParameter.initializer is JKStubExpression + ) { + targetParameter.initializer = parameter.initializer.copyTreeAndDetach() + } + } + + + + for (index in (method.parameters.lastIndex + 1)..calledMethod.parameters.lastIndex) { + val calleeExpression = call.arguments.arguments[index].value + val defaultArgument = calledMethod.parameters[index].initializer.takeIf { it !is JKStubExpression } ?: continue + if (!areTheSameExpressions(calleeExpression, defaultArgument)) continue@checkMethod } @@ -67,6 +88,7 @@ class DefaultArgumentsConversion(private val context: ConversionContext) : Recur .zip(calledMethod.parameters) .drop(method.parameters.size) + for ((defaultValue, parameter) in defaults) { fun remapParameterSymbol(on: JKTreeElement): JKTreeElement { if (on is JKFieldAccessExpression) { @@ -83,12 +105,14 @@ class DefaultArgumentsConversion(private val context: ConversionContext) : Recur parameter.initializer = remapParameterSymbol(defaultValue) as JKExpression } - element.classBody.declarations -= method + element.declarations -= method } - for (method in element.declarationList) { + for (method in element.declarations) { if (method !is JKJavaMethod) continue - if (method.hasParametersWithDefaultValues() && (method.visibility == Visibility.PUBLIC || method.visibility == Visibility.INTERNAL)) { + if (method.hasParametersWithDefaultValues() + && (method.visibility == Visibility.PUBLIC || method.visibility == Visibility.INTERNAL) + ) { method.annotationList.annotations += jvmAnnotation("JvmOverloads", context.symbolProvider) } } @@ -97,6 +121,35 @@ class DefaultArgumentsConversion(private val context: ConversionContext) : Recur } + private fun areTheSameExpressions(first: JKElement, second: JKElement): Boolean { + if (first::class != second::class) return false + if (first is JKNameIdentifier && second is JKNameIdentifier) return first.value == second.value + if (first is JKLiteralExpression && second is JKLiteralExpression) return first.literal == second.literal + if (first is JKFieldAccessExpression && second is JKFieldAccessExpression && first.identifier != second.identifier) return false + if (first is JKMethodCallExpression && second is JKMethodCallExpression && first.identifier != second.identifier) return false + return if (first is JKBranchElement && second is JKBranchElement) { + first.children.zip(second.children) { childOfFirst, childOfSecond -> + when { + childOfFirst is JKBranchElement && childOfSecond is JKBranchElement -> { + areTheSameExpressions( + childOfFirst, + childOfSecond + ) + } + childOfFirst is List<*> && childOfSecond is List<*> -> { + childOfFirst.zip(childOfSecond) { child1, child2 -> + areTheSameExpressions( + child1 as JKElement, + child2 as JKElement + ) + }.reduce(Boolean::and) + } + else -> false + } + }.reduce(Boolean::and) + } else false + } + private fun JKMethod.hasParametersWithDefaultValues() = parameters.any { it.initializer !is JKStubExpression }