diff --git a/compiler/testData/builtin-classes/java8/kotlin-collections.txt b/compiler/testData/builtin-classes/java8/kotlin-collections.txt index 52b3bada663..af61f1ddbe6 100644 --- a/compiler/testData/builtin-classes/java8/kotlin-collections.txt +++ b/compiler/testData/builtin-classes/java8/kotlin-collections.txt @@ -2,7 +2,7 @@ package-fragment kotlin.collections public abstract class BooleanIterator : kotlin.collections.Iterator { /*primary*/ public constructor BooleanIterator() - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public final override /*1*/ fun next(): kotlin.Boolean public abstract fun nextBoolean(): kotlin.Boolean @@ -10,7 +10,7 @@ public abstract class BooleanIterator : kotlin.collections.Iterator { /*primary*/ public constructor ByteIterator() - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public final override /*1*/ fun next(): kotlin.Byte public abstract fun nextByte(): kotlin.Byte @@ -18,7 +18,7 @@ public abstract class ByteIterator : kotlin.collections.Iterator { public abstract class CharIterator : kotlin.collections.Iterator { /*primary*/ public constructor CharIterator() - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public final override /*1*/ fun next(): kotlin.Char public abstract fun nextChar(): kotlin.Char @@ -39,7 +39,7 @@ public interface Collection : kotlin.collections.Iterable { public abstract class DoubleIterator : kotlin.collections.Iterator { /*primary*/ public constructor DoubleIterator() - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public final override /*1*/ fun next(): kotlin.Double public abstract fun nextDouble(): kotlin.Double @@ -47,7 +47,7 @@ public abstract class DoubleIterator : kotlin.collections.Iterator { /*primary*/ public constructor FloatIterator() - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public final override /*1*/ fun next(): kotlin.Float public abstract fun nextFloat(): kotlin.Float @@ -55,7 +55,7 @@ public abstract class FloatIterator : kotlin.collections.Iterator public abstract class IntIterator : kotlin.collections.Iterator { /*primary*/ public constructor IntIterator() - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public final override /*1*/ fun next(): kotlin.Int public abstract fun nextInt(): kotlin.Int @@ -68,7 +68,7 @@ public interface Iterable { } public interface Iterator { - public open fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract operator fun hasNext(): kotlin.Boolean public abstract operator fun next(): T } @@ -93,7 +93,7 @@ public interface List : kotlin.collections.Collection { } public interface ListIterator : kotlin.collections.Iterator { - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ fun hasNext(): kotlin.Boolean public abstract fun hasPrevious(): kotlin.Boolean public abstract override /*1*/ fun next(): T @@ -104,7 +104,7 @@ public interface ListIterator : kotlin.collections.Iterator { public abstract class LongIterator : kotlin.collections.Iterator { /*primary*/ public constructor LongIterator() - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public final override /*1*/ fun next(): kotlin.Long public abstract fun nextLong(): kotlin.Long @@ -161,7 +161,7 @@ public interface MutableIterable : kotlin.collections.Iterable { } public interface MutableIterator : kotlin.collections.Iterator { - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public abstract override /*1*/ /*fake_override*/ fun next(): T public abstract fun remove(): kotlin.Unit @@ -201,7 +201,7 @@ public interface MutableList : kotlin.collections.List, kotlin.colle public interface MutableListIterator : kotlin.collections.ListIterator, kotlin.collections.MutableIterator { public abstract fun add(/*0*/ element: T): kotlin.Unit - public open override /*2*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*2*/ fun hasNext(): kotlin.Boolean public abstract override /*1*/ /*fake_override*/ fun hasPrevious(): kotlin.Boolean public abstract override /*2*/ fun next(): T @@ -285,7 +285,7 @@ public interface Set : kotlin.collections.Collection { public abstract class ShortIterator : kotlin.collections.Iterator { /*primary*/ public constructor ShortIterator() - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public final override /*1*/ fun next(): kotlin.Short public abstract fun nextShort(): kotlin.Short diff --git a/compiler/testData/builtin-classes/java8/kotlin-ranges.txt b/compiler/testData/builtin-classes/java8/kotlin-ranges.txt index bdf77ec551f..8c77e127966 100644 --- a/compiler/testData/builtin-classes/java8/kotlin-ranges.txt +++ b/compiler/testData/builtin-classes/java8/kotlin-ranges.txt @@ -31,7 +31,7 @@ internal final class CharProgressionIterator : kotlin.collections.CharIterator { private final fun (/*0*/ : kotlin.Int): kotlin.Unit public final val step: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public open override /*1*/ fun hasNext(): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun next(): kotlin.Char public open override /*1*/ fun nextChar(): kotlin.Char @@ -102,7 +102,7 @@ internal final class IntProgressionIterator : kotlin.collections.IntIterator { private final fun (/*0*/ : kotlin.Int): kotlin.Unit public final val step: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public open override /*1*/ fun hasNext(): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun next(): kotlin.Int public open override /*1*/ fun nextInt(): kotlin.Int @@ -164,7 +164,7 @@ internal final class LongProgressionIterator : kotlin.collections.LongIterator { private final fun (/*0*/ : kotlin.Long): kotlin.Unit public final val step: kotlin.Long public final fun (): kotlin.Long - public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit public open override /*1*/ fun hasNext(): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun next(): kotlin.Long public open override /*1*/ fun nextLong(): kotlin.Long diff --git a/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.kt b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.kt new file mode 100644 index 00000000000..02a97209289 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.kt @@ -0,0 +1,39 @@ +import java.util.function.Consumer + +abstract class MyIt1 : Iterator { + override fun forEachRemaining(x: Consumer) {} +} + +abstract class MyIt2 : Iterator { + override fun forEachRemaining(x: Consumer) {} +} + +abstract class MyIt3 : Iterator { + override fun forEachRemaining(x: Consumer?) {} +} + +abstract class MyIt4 : Iterator { + override fun forEachRemaining(x: Consumer) {} +} + +abstract class MyIt5 : Iterator { + override fun forEachRemaining(x: Consumer) {} +} + +abstract class MyIt6 : Iterator { + override fun forEachRemaining(x: Consumer) {} +} + +abstract class MyIt7 : Iterator { + override fun forEachRemaining(x: Consumer) {} +} + + +fun foo(x: Iterator, y: Iterator) { + x.forEachRemaining(null) + + x.forEachRemaining { it -> it.length } + x.forEachRemaining { it -> it?.length } + y.forEachRemaining { it -> it.length } + y.forEachRemaining { it -> it?.length } +} diff --git a/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.txt b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.txt new file mode 100644 index 00000000000..a94dd4576eb --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.txt @@ -0,0 +1,77 @@ +package + +public fun foo(/*0*/ x: kotlin.collections.Iterator, /*1*/ y: kotlin.collections.Iterator): kotlin.Unit + +public abstract class MyIt1 : kotlin.collections.Iterator { + public constructor MyIt1() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun forEachRemaining(/*0*/ x: java.util.function.Consumer): kotlin.Unit + public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun next(): T + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class MyIt2 : kotlin.collections.Iterator { + public constructor MyIt2() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit + public open fun forEachRemaining(/*0*/ x: java.util.function.Consumer): kotlin.Unit + public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun next(): T + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class MyIt3 : kotlin.collections.Iterator { + public constructor MyIt3() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit + public open fun forEachRemaining(/*0*/ x: java.util.function.Consumer?): kotlin.Unit + public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun next(): T + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class MyIt4 : kotlin.collections.Iterator { + public constructor MyIt4() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun forEachRemaining(/*0*/ x: java.util.function.Consumer): kotlin.Unit + public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun next(): kotlin.String? + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class MyIt5 : kotlin.collections.Iterator { + public constructor MyIt5() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun forEachRemaining(/*0*/ x: java.util.function.Consumer): kotlin.Unit + public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun next(): kotlin.String + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class MyIt6 : kotlin.collections.Iterator { + public constructor MyIt6() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun forEachRemaining(/*0*/ x: java.util.function.Consumer): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit + public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun next(): kotlin.String? + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class MyIt7 : kotlin.collections.Iterator { + public constructor MyIt7() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun forEachRemaining(/*0*/ p0: java.util.function.Consumer): kotlin.Unit + public open fun forEachRemaining(/*0*/ x: java.util.function.Consumer): kotlin.Unit + public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun next(): kotlin.String + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} 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 14545743c30..430800ad8b6 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("forEachRemainingNullability.kt") + public void testForEachRemainingNullability() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.kt"); + doTest(fileName); + } + @TestMetadata("removeIf.kt") public void testRemoveIf() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/removeIf.kt"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/predefinedEnhancementInfo.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/predefinedEnhancementInfo.kt new file mode 100644 index 00000000000..4832f24a0a9 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/predefinedEnhancementInfo.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.load.java.typeEnhancement + +import org.jetbrains.kotlin.load.kotlin.signatures + +class TypeEnhancementInfo(val map: Map) { + constructor(vararg pairs: Pair) : this(mapOf(*pairs)) +} + +class PredefinedFunctionEnhancementInfo( + val returnTypeInfo: TypeEnhancementInfo? = null, + val parametersInfo: List = emptyList() +) + +private val NOT_NULLABLE = JavaTypeQualifiers(NullabilityQualifier.NOT_NULL, null, isNotNullTypeParameter = false) + +val PREDEFINED_FUNCTION_ENHANCEMENT_INFO_BY_SIGNATURE = signatures { + mapOf( + signature(javaUtil("Iterator"), "forEachRemaining(Ljava/util/function/Consumer;)V") to + PredefinedFunctionEnhancementInfo( + parametersInfo = listOf( + TypeEnhancementInfo( + 0 to NOT_NULLABLE, + 1 to NOT_NULLABLE + ) + ) + ), + signature("java/util/function/Consumer", "accept($objectType)V") to + PredefinedFunctionEnhancementInfo(parametersInfo = listOf(TypeEnhancementInfo(0 to NOT_NULLABLE))) + ) +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt index a4c43fa0a3a..e3a22a43600 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt @@ -17,7 +17,11 @@ package org.jetbrains.kotlin.load.java.typeEnhancement import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor +import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor +import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents +import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor import org.jetbrains.kotlin.types.KotlinType fun enhanceSignatures(platformSignatures: Collection): Collection { @@ -41,11 +45,26 @@ private fun D.enhanceSignature(): D { parts(isCovariant = false) { it.extensionReceiverParameter!!.type }.enhance() else null - val valueParameterEnhancements = valueParameters.map { - p -> parts(isCovariant = false) { it.valueParameters[p.index].type }.enhance() + + val predefinedEnhancementInfo = + if (this is JavaMethodDescriptor) + PREDEFINED_FUNCTION_ENHANCEMENT_INFO_BY_SIGNATURE[ + SignatureBuildingComponents.signature(this.containingDeclaration as ClassDescriptor, this.computeJvmDescriptor())] + else null + + predefinedEnhancementInfo?.let { + assert(it.parametersInfo.size == valueParameters.size) { + "Predefined enhancement info for $this has ${it.parametersInfo.size}, but ${valueParameters.size} expected" + } } - val returnTypeEnhancement = parts(isCovariant = true) { it.returnType!! }.enhance() + val valueParameterEnhancements = valueParameters.map { + p -> + parts(isCovariant = false) { it.valueParameters[p.index].type } + .enhance(predefinedEnhancementInfo?.parametersInfo?.getOrNull(p.index)) + } + + val returnTypeEnhancement = parts(isCovariant = true) { it.returnType!! }.enhance(predefinedEnhancementInfo?.returnTypeInfo) if ((receiverTypeEnhancement?.wereChanges ?: false) || returnTypeEnhancement.wereChanges || valueParameterEnhancements.any { it.wereChanges }) { @@ -61,9 +80,16 @@ private class SignatureParts( val fromOverridden: Collection, val isCovariant: Boolean ) { - fun enhance(): PartEnhancementResult { + fun enhance(predefined: TypeEnhancementInfo? = null): PartEnhancementResult { val qualifiers = fromOverride.computeIndexedQualifiersForOverride(this.fromOverridden, isCovariant) - return fromOverride.enhance(qualifiers)?.let { + + val qualifiersWithPredefined: ((Int) -> JavaTypeQualifiers)? = predefined?.let { + { + index -> predefined.map[index] ?: qualifiers(index) + } + } + + return fromOverride.enhance(qualifiersWithPredefined ?: qualifiers)?.let { enhanced -> PartEnhancementResult(enhanced, wereChanges = true) } ?: PartEnhancementResult(fromOverride, wereChanges = false) } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsAdditionalClassPartsProvider.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsAdditionalClassPartsProvider.kt index 5ec002d43c3..65868113f9f 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsAdditionalClassPartsProvider.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsAdditionalClassPartsProvider.kt @@ -149,10 +149,10 @@ open class JvmBuiltInsAdditionalClassPartsProvider( } ) { javaClassDescriptor -> - signature(javaClassDescriptor, jvmDescriptor) in BLACK_LIST_METHOD_SIGNATURES + SignatureBuildingComponents.signature(javaClassDescriptor, jvmDescriptor) in BLACK_LIST_METHOD_SIGNATURES }) return true - if ((signature(owner, jvmDescriptor) in MUTABLE_METHOD_SIGNATURES) xor isMutable) return true + if ((SignatureBuildingComponents.signature(owner, jvmDescriptor) in MUTABLE_METHOD_SIGNATURES) xor isMutable) return true return DFS.ifAny( listOf(this), @@ -164,8 +164,6 @@ open class JvmBuiltInsAdditionalClassPartsProvider( } } - private fun signature(javaClassDescriptor: ClassDescriptor, jvmDescriptor: String) = javaClassDescriptor.internalName + "." + jvmDescriptor - private fun ClassDescriptor.getJavaAnalogue(): LazyJavaClassDescriptor? { // Prevents recursive dependency: memberScope(Any) -> memberScope(Object) -> memberScope(Any) // No additional members should be added to Any @@ -197,7 +195,7 @@ open class JvmBuiltInsAdditionalClassPartsProvider( defaultKotlinVersion.constructors.none { it.isEffectivelyTheSameAs(javaConstructor) } && !javaConstructor.isTrivialCopyConstructorFor(classDescriptor) && !KotlinBuiltIns.isDeprecated(javaConstructor) && - signature(javaAnalogueDescriptor, javaConstructor.computeJvmDescriptor()) !in BLACK_LIST_CONSTRUCTOR_SIGNATURES + SignatureBuildingComponents.signature(javaAnalogueDescriptor, javaConstructor.computeJvmDescriptor()) !in BLACK_LIST_CONSTRUCTOR_SIGNATURES }.map { javaConstructor -> javaConstructor.newCopyBuilder().apply { @@ -230,6 +228,7 @@ open class JvmBuiltInsAdditionalClassPartsProvider( } private val BLACK_LIST_METHOD_SIGNATURES: Set = + signatures { buildPrimitiveValueMethodsSet() + "java/lang/annotation/Annotation.annotationType()${javaLang("Class").t}" + @@ -261,17 +260,21 @@ open class JvmBuiltInsAdditionalClassPartsProvider( inJavaLang("Float", "isInfinite()Z", "isNaN()Z") + inJavaUtil("Collection", "toArray([$objectType)[$objectType", "toArray()[$objectType") + } private fun buildPrimitiveValueMethodsSet(): Set = + signatures { JvmPrimitiveType.values().flatMapTo(LinkedHashSet()) { inJavaLang(it.wrapperFqName.shortName().asString(), "${it.javaKeywordName}Value()${it.desc}") } + } private val MUTABLE_METHOD_SIGNATURES: Set = + signatures { inJavaUtil("Collection", "removeIf(Ljava/util/function/Predicate;)Z") + inJavaUtil("List", - "sort(Ljava/util/Comparator;)V", "replaceAll(Ljava/util/function/UnaryOperator;)V") + + "sort(Ljava/util/Comparator;)V", "replaceAll(Ljava/util/function/UnaryOperator;)V") + inJavaUtil("Map", "computeIfAbsent(${objectType}Ljava/util/function/Function;)$objectType", @@ -282,8 +285,10 @@ open class JvmBuiltInsAdditionalClassPartsProvider( "remove($objectType$objectType)Z", "replaceAll(Ljava/util/function/BiFunction;)V", "replace($objectType$objectType)$objectType", "replace($objectType$objectType$objectType)Z") + } private val BLACK_LIST_CONSTRUCTOR_SIGNATURES: Set = + signatures { buildPrimitiveStringConstructorsSet() + inJavaLang("Float", *constructors("D")) + inJavaLang("String", *constructors( @@ -295,28 +300,15 @@ open class JvmBuiltInsAdditionalClassPartsProvider( "Ljava/lang/StringBuffer;", "Ljava/lang/StringBuilder;" )) + } private fun buildPrimitiveStringConstructorsSet(): Set = + signatures { JvmPrimitiveType.values().flatMapTo(LinkedHashSet()) { inJavaLang(it.wrapperFqName.shortName().asString(), *constructors(stringType)) } + } } } private val ClassDescriptor.isAny: Boolean get() = fqNameUnsafe == KotlinBuiltIns.FQ_NAMES.any - -private val String.t: String - get() = "L$this;" - -private val stringType = javaLang("String").t -private val objectType = javaLang("Object").t - -private fun javaLang(name: String) = "java/lang/$name" -private fun javaUtil(name: String) = "java/util/$name" - -private fun constructors(vararg signatures: String) = signatures.map { "($it)V" }.toTypedArray() - -private fun inJavaLang(name: String, vararg signatures: String) = inClass(javaLang(name), *signatures) -private fun inJavaUtil(name: String, vararg signatures: String) = inClass(javaUtil(name), *signatures) - -private fun inClass(internalName: String, vararg signatures: String) = signatures.mapTo(LinkedHashSet()) { internalName + "." + it } 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 new file mode 100644 index 00000000000..89dab032b21 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureBuilding.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.load.kotlin + +import org.jetbrains.kotlin.descriptors.* +import java.util.* + +fun signatures(block: SignatureBuildingComponents.() -> T) = with(SignatureBuildingComponents, block) + +object SignatureBuildingComponents { + + val stringType = javaLang("String").t + val objectType = javaLang("Object").t + + val String.t: String + get() = "L$this;" + + fun javaLang(name: String) = "java/lang/$name" + fun javaUtil(name: String) = "java/util/$name" + + fun constructors(vararg signatures: String) = signatures.map { "($it)V" }.toTypedArray() + + fun inJavaLang(name: String, vararg signatures: String) = inClass(javaLang(name), *signatures) + fun inJavaUtil(name: String, vararg signatures: String) = inClass(javaUtil(name), *signatures) + + fun inClass(internalName: String, vararg signatures: String) = signatures.mapTo(LinkedHashSet()) { internalName + "." + it } + + fun signature(classDescriptor: ClassDescriptor, jvmDescriptor: String) = signature(classDescriptor.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 06d48c4d4d3..094d37fa658 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 @@ -20,6 +20,8 @@ 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.platform.JavaToKotlinClassMap +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.types.KotlinType @@ -46,6 +48,10 @@ fun FunctionDescriptor.computeJvmDescriptor() val ClassDescriptor.internalName: String get() { + JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqNameSafe.toUnsafe())?.let { + return JvmClassName.byClassId(it).internalName + } + return computeInternalName(this) }