diff --git a/compiler/testData/loadJava/compiledKotlin/memberOrder/callablesNameClash.kt b/compiler/testData/loadJava/compiledKotlin/memberOrder/callablesNameClash.kt new file mode 100644 index 00000000000..00a32ce44e5 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/memberOrder/callablesNameClash.kt @@ -0,0 +1,18 @@ +//ALLOW_AST_ACCESS +package test + +val a = 0 +val c = 0 + +fun a() = 0 +fun b() = 0 +fun c() = 0 + +class A { + val a = 0 + val c = 0 + + fun a() = 0 + fun b() = 0 + fun c() = 0 +} \ No newline at end of file diff --git a/compiler/testData/loadJava/compiledKotlin/memberOrder/callablesNameClash.txt b/compiler/testData/loadJava/compiledKotlin/memberOrder/callablesNameClash.txt new file mode 100644 index 00000000000..6ae2b3a27dc --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/memberOrder/callablesNameClash.txt @@ -0,0 +1,20 @@ +package test + +internal val a: kotlin.Int = 0 + internal fun (): kotlin.Int +internal val c: kotlin.Int = 0 + internal fun (): kotlin.Int +internal fun a(): kotlin.Int +internal fun b(): kotlin.Int +internal fun c(): kotlin.Int + +internal final class A { + /*primary*/ public constructor A() + internal final val a: kotlin.Int = 0 + internal final fun (): kotlin.Int + internal final val c: kotlin.Int = 0 + internal final fun (): kotlin.Int + internal final fun a(): kotlin.Int + internal final fun b(): kotlin.Int + internal final fun c(): kotlin.Int +} diff --git a/compiler/testData/loadJava/compiledKotlin/memberOrder/extensionPropertiesNameClash.kt b/compiler/testData/loadJava/compiledKotlin/memberOrder/extensionPropertiesNameClash.kt new file mode 100644 index 00000000000..c5c1ea0339d --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/memberOrder/extensionPropertiesNameClash.kt @@ -0,0 +1,10 @@ +//ALLOW_AST_ACCESS +package test + +class A { + val a: Int = 3 + val c: Int = 3 + val Int.a: Int get() = 3 + val Int.b: Int get() = 4 + val Int.c: Int get() = 4 +} \ No newline at end of file diff --git a/compiler/testData/loadJava/compiledKotlin/memberOrder/extensionPropertiesNameClash.txt b/compiler/testData/loadJava/compiledKotlin/memberOrder/extensionPropertiesNameClash.txt new file mode 100644 index 00000000000..30b4e374294 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/memberOrder/extensionPropertiesNameClash.txt @@ -0,0 +1,15 @@ +package test + +internal final class A { + /*primary*/ public constructor A() + internal final val a: kotlin.Int = 3 + internal final fun (): kotlin.Int + internal final val c: kotlin.Int = 3 + internal final fun (): kotlin.Int + internal final val kotlin.Int.a: kotlin.Int + internal final fun kotlin.Int.(): kotlin.Int + internal final val kotlin.Int.b: kotlin.Int + internal final fun kotlin.Int.(): kotlin.Int + internal final val kotlin.Int.c: kotlin.Int + internal final fun kotlin.Int.(): kotlin.Int +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 3befc052fa7..66a86ad5ed3 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -4139,6 +4139,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlin/memberOrder"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("callablesNameClash.kt") + public void testCallablesNameClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/callablesNameClash.kt"); + doTestCompiledKotlin(fileName); + } + @TestMetadata("enumEntries.kt") public void testEnumEntries() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/enumEntries.kt"); @@ -4151,6 +4157,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledKotlin(fileName); } + @TestMetadata("extensionPropertiesNameClash.kt") + public void testExtensionPropertiesNameClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/extensionPropertiesNameClash.kt"); + doTestCompiledKotlin(fileName); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/innerClasses.kt"); diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java index d1603329c9a..16e552d84f2 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java @@ -2371,6 +2371,12 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlin/memberOrder"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("callablesNameClash.kt") + public void testCallablesNameClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/callablesNameClash.kt"); + doTest(fileName); + } + @TestMetadata("enumEntries.kt") public void testEnumEntries() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/enumEntries.kt"); @@ -2383,6 +2389,12 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso doTest(fileName); } + @TestMetadata("extensionPropertiesNameClash.kt") + public void testExtensionPropertiesNameClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/extensionPropertiesNameClash.kt"); + doTest(fileName); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/innerClasses.kt"); diff --git a/core/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedMemberScope.kt b/core/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedMemberScope.kt index 593f9e622f4..4db213a0f6b 100644 --- a/core/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedMemberScope.kt +++ b/core/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedMemberScope.kt @@ -27,47 +27,60 @@ import org.jetbrains.jet.utils.Printer import java.util.* import org.jetbrains.jet.utils.toReadOnlyList import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter +import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.CallableKind public abstract class DeserializedMemberScope protected( private val context: DeserializationContextWithTypes, membersList: Collection) : JetScope { - private val membersProtos = context.storageManager.createLazyValue { groupByName(filteredMemberProtos(membersList)) } + private data class ProtoKey(val name: Name, val kind: Kind, val isExtension: Boolean) + private enum class Kind { FUNCTION PROPERTY } + + private fun CallableKind.toKind(): Kind { + return when (this) { + CallableKind.FUN -> Kind.FUNCTION + CallableKind.VAL, CallableKind.VAR -> Kind.PROPERTY + else -> throw IllegalStateException("Unexpected CallableKind $this") + } + } + + private val membersProtos = context.storageManager.createLazyValue { groupByKey(filteredMemberProtos(membersList)) } private val functions = context.storageManager.createMemoizedFunction> { computeFunctions(it) } private val properties = context.storageManager.createMemoizedFunction> { computeProperties(it) } protected open fun filteredMemberProtos(allMemberProtos: Collection): Collection = allMemberProtos - private fun groupByName(membersList: Collection): Map> { - val map = LinkedHashMap>() + private fun groupByKey(membersList: Collection): Map> { + val map = LinkedHashMap>() for (memberProto in membersList) { - val name = context.nameResolver.getName(memberProto.getName()) - var protos = map[name] + val key = ProtoKey( + context.nameResolver.getName(memberProto.getName()), + Flags.CALLABLE_KIND[memberProto.getFlags()].toKind(), + memberProto.hasReceiverType() + ) + var protos = map[key] if (protos == null) { protos = ArrayList(1) - map.put(name, protos) + map.put(key, protos) } protos!!.add(memberProto) } return map } - private fun computeMembersByName(name: Name, callableKind: (ProtoBuf.Callable.CallableKind) -> Boolean): LinkedHashSet { - val memberProtos = membersProtos()[name] ?: return LinkedHashSet() + private fun computeMembers(name: Name, kind: Kind): LinkedHashSet { + val memberProtos = membersProtos()[ProtoKey(name, kind, isExtension = false)].orEmpty() + + membersProtos()[ProtoKey(name, kind, isExtension = true)].orEmpty() - val descriptors = LinkedHashSet(memberProtos.size()) - for (memberProto in memberProtos) { - if (callableKind(Flags.CALLABLE_KIND[memberProto.getFlags()])) { - [suppress("UNCHECKED_CAST")] - descriptors.add(context.deserializer.loadCallable(memberProto) as D) - } + [suppress("UNCHECKED_CAST")] + return memberProtos.mapTo(LinkedHashSet()) { memberProto -> + context.deserializer.loadCallable(memberProto) as D } - return descriptors } private fun computeFunctions(name: Name): Collection { - val descriptors = computeMembersByName(name) { it == ProtoBuf.Callable.CallableKind.FUN } + val descriptors = computeMembers(name, Kind.FUNCTION) computeNonDeclaredFunctions(name, descriptors) return descriptors.toReadOnlyList() } @@ -78,7 +91,7 @@ public abstract class DeserializedMemberScope protected( override fun getFunctions(name: Name): Collection = functions(name) private fun computeProperties(name: Name): Collection { - val descriptors = computeMembersByName(name) { it == ProtoBuf.Callable.CallableKind.VAL || it == ProtoBuf.Callable.CallableKind.VAR } + val descriptors = computeMembers(name, Kind.PROPERTY) computeNonDeclaredProperties(name, descriptors) return descriptors.toReadOnlyList() } @@ -134,33 +147,27 @@ public abstract class DeserializedMemberScope protected( return } - val names = membersProtos().keySet().filter(nameFilter) + val keys = membersProtos().keySet().filter { nameFilter(it.name) } if (acceptsProperties) { - addMembers(names, result) { getProperties(it) } + addMembers(result, keys, Kind.PROPERTY) { getProperties(it) } } if (acceptsFunctions) { - addMembers(names, result) { getFunctions(it) } + addMembers(result, keys, Kind.FUNCTION) { getFunctions(it) } } } private fun addMembers( - names: List, result: MutableCollection, - getMembers: (Name) -> Collection) { - val extensions = ArrayList() - val nonExtensions = ArrayList() - names.forEach { name -> - getMembers(name).forEach { member -> - if (member.getExtensionReceiverParameter() == null) { - nonExtensions.add(member) - } - else { - extensions.add(member) - } - } + keys: Collection, + kind: Kind, + getMembers: (Name) -> Collection + ) { + val filteredByKind = keys.filter { it.kind == kind } + listOf(false, true).forEach { isExtension -> + filteredByKind.filter { it.isExtension == isExtension } + .flatMap { getMembers(it.name) } + .filterTo(result) { (it.getExtensionReceiverParameter() != null) == isExtension } } - result.addAll(nonExtensions) - result.addAll(extensions) } protected abstract fun addNonDeclaredDescriptors(result: MutableCollection) diff --git a/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java index d4e60636182..924feac8159 100644 --- a/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java @@ -2368,6 +2368,12 @@ public class LazyResolveByStubTestGenerated extends AbstractLazyResolveByStubTes JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlin/memberOrder"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("callablesNameClash.kt") + public void testCallablesNameClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/callablesNameClash.kt"); + doTest(fileName); + } + @TestMetadata("enumEntries.kt") public void testEnumEntries() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/enumEntries.kt"); @@ -2380,6 +2386,12 @@ public class LazyResolveByStubTestGenerated extends AbstractLazyResolveByStubTes doTest(fileName); } + @TestMetadata("extensionPropertiesNameClash.kt") + public void testExtensionPropertiesNameClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/extensionPropertiesNameClash.kt"); + doTest(fileName); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/innerClasses.kt");