From 5e231db631865d28146649b0495c457ff5a9c2bf Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Wed, 16 Dec 2015 12:04:52 +0300 Subject: [PATCH] J2K: convert method from Map (Java8) with cast to java.util.Map #KT-10400 Fixed --- .../org/jetbrains/kotlin/j2k/SpecialMethod.kt | 63 +++++++++++++++++++ .../org/jetbrains/kotlin/j2k/TypeConverter.kt | 2 +- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/j2k/src/org/jetbrains/kotlin/j2k/SpecialMethod.kt b/j2k/src/org/jetbrains/kotlin/j2k/SpecialMethod.kt index 1c79e9cbdca..8c44f02efd2 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/SpecialMethod.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/SpecialMethod.kt @@ -46,6 +46,51 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String = convertMethodCallToPropertyUse(codeConverter, qualifier, "keys") }, + MAP_PUT_IF_ABSENT(Map::class.java.name, "putIfAbsent", 2) { + override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) + = convertMethodCallWithReceiverCast(qualifier, arguments, typeArgumentsConverted, codeConverter) + }, + + MAP_REMOVE(Map::class.java.name, "remove", 2) { + override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) + = convertMethodCallWithReceiverCast(qualifier, arguments, typeArgumentsConverted, codeConverter) + }, + + MAP_REPLACE(Map::class.java.name, "replace", 3) { + override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) + = convertMethodCallWithReceiverCast(qualifier, arguments, typeArgumentsConverted, codeConverter) + }, + + MAP_REPLACE_ALL(Map::class.java.name, "replaceAll", 1) { + override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) + = convertMethodCallWithReceiverCast(qualifier, arguments, typeArgumentsConverted, codeConverter) + }, + + MAP_COMPUTE(Map::class.java.name, "compute", 2) { + override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) + = convertMethodCallWithReceiverCast(qualifier, arguments, typeArgumentsConverted, codeConverter) + }, + + MAP_COMPUTE_IF_ABSENT(Map::class.java.name, "computeIfAbsent", 2) { + override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) + = convertMethodCallWithReceiverCast(qualifier, arguments, typeArgumentsConverted, codeConverter) + }, + + MAP_COMPUTE_IF_PRESENT(Map::class.java.name, "computeIfPresent", 2) { + override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) + = convertMethodCallWithReceiverCast(qualifier, arguments, typeArgumentsConverted, codeConverter) + }, + + MAP_MERGE(Map::class.java.name, "merge", 3) { + override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) + = convertMethodCallWithReceiverCast(qualifier, arguments, typeArgumentsConverted, codeConverter) + }, + + MAP_GET_OR_DEFAULT(Map::class.java.name, "getOrDefault", 2) { + override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) + = convertMethodCallWithReceiverCast(qualifier, arguments, typeArgumentsConverted, codeConverter) + }, + MAP_VALUES(Map::class.java.name, "values", 0) { override fun convertCall(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) = convertMethodCallToPropertyUse(codeConverter, qualifier) @@ -384,6 +429,24 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String protected fun convertWithChangedName(name: String, qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter) = MethodCallExpression.buildNotNull(codeConverter.convertExpression(qualifier), name, codeConverter.convertExpressions(arguments), typeArgumentsConverted) + protected fun convertMethodCallWithReceiverCast(qualifier: PsiExpression?, arguments: Array, typeArgumentsConverted: List, codeConverter: CodeConverter): MethodCallExpression? { + val convertedArguments = arguments.map { codeConverter.convertExpression(it) } + val qualifierWithCast = castQualifierToType(codeConverter, qualifier!!, qualifiedClassName!!) + if (qualifierWithCast != null) { + return MethodCallExpression.build(qualifierWithCast, methodName, convertedArguments, typeArgumentsConverted, false) + } + return null + } + + private fun castQualifierToType(codeConverter: CodeConverter, qualifier: PsiExpression, type: String): TypeCastExpression? { + val convertedQualifier = codeConverter.convertExpression(qualifier) + val qualifierType = codeConverter.typeConverter.convertType(qualifier.type) + val typeArgs = if (qualifierType is ClassType) qualifierType.referenceElement.typeArgs else emptyList() + val referenceElement = ReferenceElement(Identifier(type).assignNoPrototype(), typeArgs).assignNoPrototype() + val newType = ClassType(referenceElement, Nullability.Default, codeConverter.settings).assignNoPrototype() + return TypeCastExpression(newType, convertedQualifier).assignNoPrototype() + } + companion object { private val valuesByName = values().groupBy { it.methodName } diff --git a/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt index d3c6410fbf7..a133fbcab97 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt @@ -427,7 +427,7 @@ class TypeConverter(val converter: Converter) { ) private val modificationMethodNames = setOf( - "add", "remove", "set", "addAll", "removeAll", "retainAll", "clear", "put", "putAll" + "add", "remove", "set", "addAll", "removeAll", "retainAll", "clear", "put", "putAll", "putIfAbsent", "replace", "replaceAll", "merge", "compute", "computeIfAbsent", "computeIfPresent" ) private val mutableKotlinClasses = TypeVisitor.toKotlinMutableTypesMap.values.toSet()