diff --git a/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/concurrentMapRemove.kt b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/concurrentMapRemove.kt new file mode 100644 index 00000000000..4aa05ef5a0c --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/concurrentMapRemove.kt @@ -0,0 +1,20 @@ +import java.util.concurrent.* + +val concurrent: ConcurrentMap = null!! +val concurrentHash: ConcurrentHashMap = null!! + +fun foo() { + // TODO: Too permissive + concurrent.remove("", 1) + concurrent.remove("", "") + concurrentHash.remove("", 1) + concurrentHash.remove("", "") + + // Flexible types + concurrent.remove(null, 1) + concurrent.remove(null, null) + + // @PurelyImplements + concurrentHash.remove(null, 1) + concurrentHash.remove(null, null) +} diff --git a/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/concurrentMapRemove.txt b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/concurrentMapRemove.txt new file mode 100644 index 00000000000..ed718cdd974 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/concurrentMapRemove.txt @@ -0,0 +1,5 @@ +package + +public val concurrent: java.util.concurrent.ConcurrentMap +public val concurrentHash: java.util.concurrent.ConcurrentHashMap +public fun foo(): kotlin.Unit diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJava8TestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJava8TestGenerated.java index 430800ad8b6..6adfad31513 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJava8TestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJava8TestGenerated.java @@ -121,6 +121,12 @@ public class DiagnosticsWithJava8TestGenerated extends AbstractDiagnosticsWithFu KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("concurrentMapRemove.kt") + public void testConcurrentMapRemove() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/concurrentMapRemove.kt"); + doTest(fileName); + } + @TestMetadata("forEachRemainingNullability.kt") public void testForEachRemainingNullability() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.kt"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt index a7bfa82caec..11d6c5019c2 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt @@ -133,6 +133,7 @@ class LazyJavaClassMemberScope( private fun SimpleFunctionDescriptor.doesOverrideRenamedBuiltins(): Boolean { return BuiltinMethodsWithDifferentJvmName.getBuiltinFunctionNamesByJvmName(name).any { + // e.g. 'removeAt' or 'toInt' builtinName -> val builtinSpecialFromSuperTypes = getFunctionsFromSupertypes(builtinName).filter { it.doesOverrideBuiltinWithDifferentJvmName() } @@ -140,7 +141,7 @@ class LazyJavaClassMemberScope( val methodDescriptor = this.createRenamedCopy(builtinName) - builtinSpecialFromSuperTypes.any { isOverridableRenamedDescriptor(it, methodDescriptor) } + builtinSpecialFromSuperTypes.any { doesOverrideRenamedDescriptor(it, methodDescriptor) } } } @@ -151,7 +152,10 @@ class LazyJavaClassMemberScope( setPreserveSourceElement() }.build()!! - private fun isOverridableRenamedDescriptor(superDescriptor: FunctionDescriptor, subDescriptor: FunctionDescriptor): Boolean { + private fun doesOverrideRenamedDescriptor( + superDescriptor: SimpleFunctionDescriptor, + subDescriptor: FunctionDescriptor + ): Boolean { // if we check 'removeAt', get original sub-descriptor to distinct `remove(int)` and `remove(E)` in Java val subDescriptorToCheck = if (superDescriptor.isRemoveAtByIndex) subDescriptor.original else subDescriptor @@ -292,7 +296,7 @@ class LazyJavaClassMemberScope( for (method in functions(Name.identifier(nameInJava))) { val renamedCopy = method.createRenamedCopy(name) - if (isOverridableRenamedDescriptor(overriddenBuiltin, renamedCopy)) { + if (doesOverrideRenamedDescriptor(overriddenBuiltin, renamedCopy)) { result.add( renamedCopy.createHiddenCopyIfBuiltinAlreadyAccidentallyOverridden(overriddenBuiltin, alreadyDeclaredFunctions)) break diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/specialBuiltinMembers.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/specialBuiltinMembers.kt index 3ab8412852d..a88103c3fa7 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/specialBuiltinMembers.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/specialBuiltinMembers.kt @@ -24,19 +24,30 @@ import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature. import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getBuiltinSpecialPropertyGetterName import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor +import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents +import org.jetbrains.kotlin.load.kotlin.computeJvmSignature +import org.jetbrains.kotlin.load.kotlin.signatures import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.* +import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES as BUILTIN_NAMES private fun FqName.child(name: String): FqName = child(Name.identifier(name)) private fun FqNameUnsafe.childSafe(name: String): FqName = child(Name.identifier(name)).toSafe() +private data class NameAndSignature(val name: Name, val signature: String) + +private fun String.method(name: String, parameters: String, returnType: String) = + NameAndSignature( + Name.identifier(name), + SignatureBuildingComponents.signature(this@method, "$name($parameters)$returnType")) + object BuiltinSpecialProperties { - private val PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP = mapOf( + private val PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP = mapOf( BUILTIN_NAMES._enum.childSafe("name") to Name.identifier("name"), BUILTIN_NAMES._enum.childSafe("ordinal") to Name.identifier("ordinal"), BUILTIN_NAMES.collection.child("size") to Name.identifier("size"), @@ -48,7 +59,9 @@ object BuiltinSpecialProperties { ) private val GETTER_JVM_NAME_TO_PROPERTIES_SHORT_NAME_MAP: Map> = - PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.getInversedShortNamesMap() + PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.entries + .map { Pair(it.key.shortName(), it.value) } + .groupBy({ it.second }, { it.first }) private val SPECIAL_FQ_NAMES = PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.keys internal val SPECIAL_SHORT_NAMES = SPECIAL_FQ_NAMES.map { it.shortName() }.toSet() @@ -60,7 +73,7 @@ object BuiltinSpecialProperties { } private fun CallableMemberDescriptor.hasBuiltinSpecialPropertyFqNameImpl(): Boolean { - if (fqNameOrNull() in SPECIAL_FQ_NAMES) return true + if (fqNameOrNull() in SPECIAL_FQ_NAMES && valueParameters.isEmpty()) return true if (!isFromBuiltins()) return false return overriddenDescriptors.any { hasBuiltinSpecialPropertyFqName(it) } @@ -78,37 +91,52 @@ object BuiltinSpecialProperties { } object BuiltinMethodsWithSpecialGenericSignature { - private val ERASED_COLLECTION_PARAMETER_FQ_NAMES = setOf( - BUILTIN_NAMES.collection.child("containsAll"), - BUILTIN_NAMES.mutableCollection.child("removeAll"), - BUILTIN_NAMES.mutableCollection.child("retainAll") - ) + private val ERASED_COLLECTION_PARAMETER_NAME_AND_SIGNATURES = setOf( + "containsAll", "removeAll", "retainAll" + ).map { "java/util/Collection".method(it, "Ljava/util/Collection;", JvmPrimitiveType.BOOLEAN.desc) } + + private val ERASED_COLLECTION_PARAMETER_SIGNATURES = ERASED_COLLECTION_PARAMETER_NAME_AND_SIGNATURES.map { it.signature } enum class DefaultValue(val value: Any?) { NULL(null), INDEX(-1), FALSE(false) } - private val GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP = mapOf( - BUILTIN_NAMES.collection.child("contains") to DefaultValue.FALSE, - BUILTIN_NAMES.mutableCollection.child("remove") to DefaultValue.FALSE, - BUILTIN_NAMES.map.child("containsKey") to DefaultValue.FALSE, - BUILTIN_NAMES.map.child("containsValue") to DefaultValue.FALSE, + private val GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP = + signatures { + mapOf( + javaUtil("Collection") + .method("contains", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to DefaultValue.FALSE, + javaUtil("Collection") + .method("remove", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to DefaultValue.FALSE, + javaUtil("Map") + .method("containsKey", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to DefaultValue.FALSE, + javaUtil("Map") + .method("containsValue", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to DefaultValue.FALSE, - BUILTIN_NAMES.map.child("get") to DefaultValue.NULL, - BUILTIN_NAMES.mutableMap.child("remove") to DefaultValue.NULL, + javaUtil("Map") + .method("get", "Ljava/lang/Object;", "Ljava/lang/Object;") to DefaultValue.NULL, + javaUtil("Map") + .method("remove", "Ljava/lang/Object;", "Ljava/lang/Object;") to DefaultValue.NULL, - BUILTIN_NAMES.list.child("indexOf") to DefaultValue.INDEX, - BUILTIN_NAMES.list.child("lastIndexOf") to DefaultValue.INDEX - ) + javaUtil("List") + .method("indexOf", "Ljava/lang/Object;", JvmPrimitiveType.INT.desc) to DefaultValue.INDEX, + javaUtil("List") + .method("lastIndexOf", "Ljava/lang/Object;", JvmPrimitiveType.INT.desc) to DefaultValue.INDEX + ) + } - private val ERASED_VALUE_PARAMETERS_FQ_NAMES = - GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP.keys + ERASED_COLLECTION_PARAMETER_FQ_NAMES + private val SIGNATURE_TO_DEFAULT_VALUES_MAP = GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP.mapKeys { it.key.signature } + private val ERASED_VALUE_PARAMETERS_SHORT_NAMES: Set + private val ERASED_VALUE_PARAMETERS_SIGNATURES: Set - private val ERASED_VALUE_PARAMETERS_SHORT_NAMES = - ERASED_VALUE_PARAMETERS_FQ_NAMES.map { it.shortName() }.toSet() + init { + val allMethods = GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP.keys + ERASED_COLLECTION_PARAMETER_NAME_AND_SIGNATURES + ERASED_VALUE_PARAMETERS_SHORT_NAMES = allMethods.map { it.name }.toSet() + ERASED_VALUE_PARAMETERS_SIGNATURES = allMethods.map { it.signature }.toSet() + } private val CallableMemberDescriptor.hasErasedValueParametersInJava: Boolean - get() = fqNameOrNull() in ERASED_VALUE_PARAMETERS_FQ_NAMES + get() = computeJvmSignature() in ERASED_VALUE_PARAMETERS_SIGNATURES @JvmStatic fun getOverriddenBuiltinFunctionWithErasedValueParametersInJava( @@ -122,8 +150,8 @@ object BuiltinMethodsWithSpecialGenericSignature { fun getDefaultValueForOverriddenBuiltinFunction(functionDescriptor: FunctionDescriptor): DefaultValue? { if (functionDescriptor.name !in ERASED_VALUE_PARAMETERS_SHORT_NAMES) return null return functionDescriptor.firstOverridden { - it.fqNameOrNull() in GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP.keys - }?.let { GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP[it.fqNameSafe] } + it.computeJvmSignature() in SIGNATURE_TO_DEFAULT_VALUES_MAP.keys + }?.let { SIGNATURE_TO_DEFAULT_VALUES_MAP[it.computeJvmSignature()] } } val Name.sameAsBuiltinMethodWithErasedValueParameters: Boolean @@ -144,12 +172,12 @@ object BuiltinMethodsWithSpecialGenericSignature { fun CallableMemberDescriptor.getSpecialSignatureInfo(): SpecialSignatureInfo? { if (name !in ERASED_VALUE_PARAMETERS_SHORT_NAMES) return null - val builtinFqName = firstOverridden { it is FunctionDescriptor && it.hasErasedValueParametersInJava }?.fqNameOrNull() + val builtinSignature = firstOverridden { it is FunctionDescriptor && it.hasErasedValueParametersInJava }?.computeJvmSignature() ?: return null - if (builtinFqName in ERASED_COLLECTION_PARAMETER_FQ_NAMES) return SpecialSignatureInfo.ONE_COLLECTION_PARAMETER + if (builtinSignature in ERASED_COLLECTION_PARAMETER_SIGNATURES) return SpecialSignatureInfo.ONE_COLLECTION_PARAMETER - val defaultValue = GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP[builtinFqName]!! + val defaultValue = SIGNATURE_TO_DEFAULT_VALUES_MAP[builtinSignature]!! return if (defaultValue == DefaultValue.NULL) // return type is some generic type as 'Map.get' @@ -160,42 +188,56 @@ object BuiltinMethodsWithSpecialGenericSignature { } object BuiltinMethodsWithDifferentJvmName { - val REMOVE_AT_FQ_NAME = BUILTIN_NAMES.mutableList.child("removeAt") + // Note that signatures here are not real, + // e.g. 'java/lang/CharSequence.get(I)C' does not actually exist in JDK + // But it doesn't matter here, because signatures are only used to distinguish overloaded built-in definitions + private val REMOVE_AT_NAME_AND_SIGNATURE = + "java/util/List".method("removeAt", JvmPrimitiveType.INT.desc, "Ljava/lang/Object;") - val FQ_NAMES_TO_JVM_MAP: Map = mapOf( - BUILTIN_NAMES.number.childSafe("toByte") to Name.identifier("byteValue"), - BUILTIN_NAMES.number.childSafe("toShort") to Name.identifier("shortValue"), - BUILTIN_NAMES.number.childSafe("toInt") to Name.identifier("intValue"), - BUILTIN_NAMES.number.childSafe("toLong") to Name.identifier("longValue"), - BUILTIN_NAMES.number.childSafe("toFloat") to Name.identifier("floatValue"), - BUILTIN_NAMES.number.childSafe("toDouble") to Name.identifier("doubleValue"), - REMOVE_AT_FQ_NAME to Name.identifier("remove"), - BUILTIN_NAMES.charSequence.childSafe("get") to Name.identifier("charAt") - ) + private val NAME_AND_SIGNATURE_TO_JVM_REPRESENTATION_NAME_MAP: Map = signatures { + mapOf( + javaLang("Number").method("toByte", "", JvmPrimitiveType.BYTE.desc) to Name.identifier("byteValue"), + javaLang("Number").method("toShort", "", JvmPrimitiveType.SHORT.desc) to Name.identifier("shortValue"), + javaLang("Number").method("toInt", "", JvmPrimitiveType.INT.desc) to Name.identifier("intValue"), + javaLang("Number").method("toLong", "", JvmPrimitiveType.LONG.desc) to Name.identifier("longValue"), + javaLang("Number").method("toFloat", "", JvmPrimitiveType.FLOAT.desc) to Name.identifier("floatValue"), + javaLang("Number").method("toDouble", "", JvmPrimitiveType.DOUBLE.desc) to Name.identifier("doubleValue"), + REMOVE_AT_NAME_AND_SIGNATURE to Name.identifier("remove"), + javaLang("CharSequence") + .method("get", JvmPrimitiveType.INT.desc, JvmPrimitiveType.CHAR.desc) to Name.identifier("charAt") + ) + } - val ORIGINAL_SHORT_NAMES: List = FQ_NAMES_TO_JVM_MAP.keys.map { it.shortName() } + private val SIGNATURE_TO_JVM_REPRESENTATION_NAME: Map = + NAME_AND_SIGNATURE_TO_JVM_REPRESENTATION_NAME_MAP.mapKeys { it.key.signature } - val JVM_SHORT_NAME_TO_BUILTIN_SHORT_NAMES_MAP: Map> = FQ_NAMES_TO_JVM_MAP.getInversedShortNamesMap() + val ORIGINAL_SHORT_NAMES: List = NAME_AND_SIGNATURE_TO_JVM_REPRESENTATION_NAME_MAP.keys.map { it.name } + + private val JVM_SHORT_NAME_TO_BUILTIN_SHORT_NAMES_MAP: Map> = + NAME_AND_SIGNATURE_TO_JVM_REPRESENTATION_NAME_MAP.entries + .map { Pair(it.key.name, it.value) } + .groupBy({ it.second }, { it.first }) val Name.sameAsRenamedInJvmBuiltin: Boolean get() = this in ORIGINAL_SHORT_NAMES - fun getJvmName(callableMemberDescriptor: CallableMemberDescriptor): Name? { - return FQ_NAMES_TO_JVM_MAP[callableMemberDescriptor.fqNameOrNull() ?: return null] + fun getJvmName(functionDescriptor: SimpleFunctionDescriptor): Name? { + return SIGNATURE_TO_JVM_REPRESENTATION_NAME[functionDescriptor.computeJvmSignature() ?: return null] } - fun isBuiltinFunctionWithDifferentNameInJvm(callableMemberDescriptor: CallableMemberDescriptor): Boolean { - if (!callableMemberDescriptor.isFromBuiltins()) return false - val fqName = callableMemberDescriptor.fqNameOrNull() ?: return false - return callableMemberDescriptor.firstOverridden { FQ_NAMES_TO_JVM_MAP.containsKey(fqName) } != null + fun isBuiltinFunctionWithDifferentNameInJvm(functionDescriptor: SimpleFunctionDescriptor): Boolean { + if (!functionDescriptor.isFromBuiltins()) return false + return functionDescriptor.firstOverridden { + SIGNATURE_TO_JVM_REPRESENTATION_NAME.containsKey(functionDescriptor.computeJvmSignature()) + } != null } fun getBuiltinFunctionNamesByJvmName(name: Name): List = JVM_SHORT_NAME_TO_BUILTIN_SHORT_NAMES_MAP[name] ?: emptyList() - val CallableMemberDescriptor.isRemoveAtByIndex: Boolean - get() = name.asString() == "removeAt" && fqNameOrNull() == REMOVE_AT_FQ_NAME + val SimpleFunctionDescriptor.isRemoveAtByIndex: Boolean + get() = name.asString() == "removeAt" && computeJvmSignature() == REMOVE_AT_NAME_AND_SIGNATURE.signature } @Suppress("UNCHECKED_CAST") @@ -206,7 +248,11 @@ fun T.getOverriddenBuiltinWithDifferentJvmName(): return when (this) { is PropertyDescriptor, is PropertyAccessorDescriptor -> firstOverridden { BuiltinSpecialProperties.hasBuiltinSpecialPropertyFqName(it.propertyIfAccessor) } as T? - else -> firstOverridden { BuiltinMethodsWithDifferentJvmName.isBuiltinFunctionWithDifferentNameInJvm(it) } as T? + is SimpleFunctionDescriptor -> + firstOverridden { + BuiltinMethodsWithDifferentJvmName.isBuiltinFunctionWithDifferentNameInJvm(it as SimpleFunctionDescriptor) + } as T? + else -> null } } @@ -244,7 +290,8 @@ fun getJvmMethodNameIfSpecial(callableMemberDescriptor: CallableMemberDescriptor ?: return null return when (overriddenBuiltin) { is PropertyDescriptor -> overriddenBuiltin.getBuiltinSpecialPropertyGetterName() - else -> BuiltinMethodsWithDifferentJvmName.getJvmName(overriddenBuiltin)?.asString() + is SimpleFunctionDescriptor -> BuiltinMethodsWithDifferentJvmName.getJvmName(overriddenBuiltin)?.asString() + else -> null } } @@ -296,6 +343,3 @@ fun CallableMemberDescriptor.isFromBuiltins(): Boolean { } fun CallableMemberDescriptor.isFromJavaOrBuiltins() = isFromJava || isFromBuiltins() - -private fun Map.getInversedShortNamesMap(): Map> = - entries.groupBy { it.value }.mapValues { entry -> entry.value.map { it.key.shortName() } } \ No newline at end of file diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureBuilding.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureBuilding.kt index fd4512d3d51..0830cfc8282 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureBuilding.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureBuilding.kt @@ -16,10 +16,11 @@ package org.jetbrains.kotlin.load.kotlin -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.name.ClassId import java.util.* -fun signatures(block: SignatureBuildingComponents.() -> T) = with(SignatureBuildingComponents, block) +inline fun signatures(block: SignatureBuildingComponents.() -> T) = with(SignatureBuildingComponents, block) object SignatureBuildingComponents { fun javaLang(name: String) = "java/lang/$name" @@ -33,5 +34,6 @@ object SignatureBuildingComponents { fun inClass(internalName: String, vararg signatures: String) = signatures.mapTo(LinkedHashSet()) { internalName + "." + it } fun signature(classDescriptor: ClassDescriptor, jvmDescriptor: String) = signature(classDescriptor.internalName, jvmDescriptor) + fun signature(classId: ClassId, jvmDescriptor: String) = signature(classId.internalName, jvmDescriptor) fun signature(internalName: String, jvmDescriptor: String) = internalName + "." + jvmDescriptor } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt index 094d37fa658..0d8584d2130 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt @@ -16,11 +16,10 @@ package org.jetbrains.kotlin.load.kotlin -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.platform.JavaToKotlinClassMap +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType @@ -45,8 +44,20 @@ fun FunctionDescriptor.computeJvmDescriptor() } }.toString() +// This method only returns not-null for class methods +internal fun CallableDescriptor.computeJvmSignature(): String? = signatures { + if (DescriptorUtils.isLocal(this@computeJvmSignature)) return null -val ClassDescriptor.internalName: String + val classDescriptor = containingDeclaration as? ClassDescriptor ?: return null + if (classDescriptor.name.isSpecial) return null + + signature( + classDescriptor, + (original as? SimpleFunctionDescriptor ?: return null).computeJvmDescriptor() + ) +} + +internal val ClassDescriptor.internalName: String get() { JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqNameSafe.toUnsafe())?.let { return JvmClassName.byClassId(it).internalName @@ -55,6 +66,11 @@ val ClassDescriptor.internalName: String return computeInternalName(this) } +internal val ClassId.internalName: String + get() { + return JvmClassName.byClassId(JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(asSingleFqName().toUnsafe()) ?: this).internalName + } + private fun StringBuilder.appendErasedType(type: KotlinType) { append( JvmTypeFactoryImpl.toString(