Fix wrong deserialization order
For case when property and function have the same name or extension and non-extension member have the same name
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
internal val a: kotlin.Int = 0
|
||||||
|
internal fun <get-a>(): kotlin.Int
|
||||||
|
internal val c: kotlin.Int = 0
|
||||||
|
internal fun <get-c>(): 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 <get-a>(): kotlin.Int
|
||||||
|
internal final val c: kotlin.Int = 0
|
||||||
|
internal final fun <get-c>(): kotlin.Int
|
||||||
|
internal final fun a(): kotlin.Int
|
||||||
|
internal final fun b(): kotlin.Int
|
||||||
|
internal final fun c(): kotlin.Int
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
internal final class A {
|
||||||
|
/*primary*/ public constructor A()
|
||||||
|
internal final val a: kotlin.Int = 3
|
||||||
|
internal final fun <get-a>(): kotlin.Int
|
||||||
|
internal final val c: kotlin.Int = 3
|
||||||
|
internal final fun <get-c>(): kotlin.Int
|
||||||
|
internal final val kotlin.Int.a: kotlin.Int
|
||||||
|
internal final fun kotlin.Int.<get-a>(): kotlin.Int
|
||||||
|
internal final val kotlin.Int.b: kotlin.Int
|
||||||
|
internal final fun kotlin.Int.<get-b>(): kotlin.Int
|
||||||
|
internal final val kotlin.Int.c: kotlin.Int
|
||||||
|
internal final fun kotlin.Int.<get-c>(): kotlin.Int
|
||||||
|
}
|
||||||
@@ -4139,6 +4139,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlin/memberOrder"), Pattern.compile("^(.+)\\.kt$"), true);
|
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")
|
@TestMetadata("enumEntries.kt")
|
||||||
public void testEnumEntries() throws Exception {
|
public void testEnumEntries() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/enumEntries.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/enumEntries.kt");
|
||||||
@@ -4151,6 +4157,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
doTestCompiledKotlin(fileName);
|
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")
|
@TestMetadata("innerClasses.kt")
|
||||||
public void testInnerClasses() throws Exception {
|
public void testInnerClasses() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/innerClasses.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/innerClasses.kt");
|
||||||
|
|||||||
+12
@@ -2371,6 +2371,12 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlin/memberOrder"), Pattern.compile("^(.+)\\.kt$"), true);
|
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")
|
@TestMetadata("enumEntries.kt")
|
||||||
public void testEnumEntries() throws Exception {
|
public void testEnumEntries() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/enumEntries.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/enumEntries.kt");
|
||||||
@@ -2383,6 +2389,12 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("innerClasses.kt")
|
||||||
public void testInnerClasses() throws Exception {
|
public void testInnerClasses() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/innerClasses.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/innerClasses.kt");
|
||||||
|
|||||||
+42
-35
@@ -27,47 +27,60 @@ import org.jetbrains.jet.utils.Printer
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import org.jetbrains.jet.utils.toReadOnlyList
|
import org.jetbrains.jet.utils.toReadOnlyList
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.CallableKind
|
||||||
|
|
||||||
public abstract class DeserializedMemberScope protected(
|
public abstract class DeserializedMemberScope protected(
|
||||||
private val context: DeserializationContextWithTypes,
|
private val context: DeserializationContextWithTypes,
|
||||||
membersList: Collection<ProtoBuf.Callable>)
|
membersList: Collection<ProtoBuf.Callable>)
|
||||||
: JetScope {
|
: 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<Name, Collection<FunctionDescriptor>> { computeFunctions(it) }
|
private val functions = context.storageManager.createMemoizedFunction<Name, Collection<FunctionDescriptor>> { computeFunctions(it) }
|
||||||
private val properties = context.storageManager.createMemoizedFunction<Name, Collection<VariableDescriptor>> { computeProperties(it) }
|
private val properties = context.storageManager.createMemoizedFunction<Name, Collection<VariableDescriptor>> { computeProperties(it) }
|
||||||
|
|
||||||
protected open fun filteredMemberProtos(allMemberProtos: Collection<ProtoBuf.Callable>): Collection<ProtoBuf.Callable> = allMemberProtos
|
protected open fun filteredMemberProtos(allMemberProtos: Collection<ProtoBuf.Callable>): Collection<ProtoBuf.Callable> = allMemberProtos
|
||||||
|
|
||||||
private fun groupByName(membersList: Collection<ProtoBuf.Callable>): Map<Name, List<ProtoBuf.Callable>> {
|
private fun groupByKey(membersList: Collection<ProtoBuf.Callable>): Map<ProtoKey, List<ProtoBuf.Callable>> {
|
||||||
val map = LinkedHashMap<Name, MutableList<ProtoBuf.Callable>>()
|
val map = LinkedHashMap<ProtoKey, MutableList<ProtoBuf.Callable>>()
|
||||||
for (memberProto in membersList) {
|
for (memberProto in membersList) {
|
||||||
val name = context.nameResolver.getName(memberProto.getName())
|
val key = ProtoKey(
|
||||||
var protos = map[name]
|
context.nameResolver.getName(memberProto.getName()),
|
||||||
|
Flags.CALLABLE_KIND[memberProto.getFlags()].toKind(),
|
||||||
|
memberProto.hasReceiverType()
|
||||||
|
)
|
||||||
|
var protos = map[key]
|
||||||
if (protos == null) {
|
if (protos == null) {
|
||||||
protos = ArrayList(1)
|
protos = ArrayList(1)
|
||||||
map.put(name, protos)
|
map.put(key, protos)
|
||||||
}
|
}
|
||||||
protos!!.add(memberProto)
|
protos!!.add(memberProto)
|
||||||
}
|
}
|
||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D : CallableMemberDescriptor> computeMembersByName(name: Name, callableKind: (ProtoBuf.Callable.CallableKind) -> Boolean): LinkedHashSet<D> {
|
private fun <D : CallableMemberDescriptor> computeMembers(name: Name, kind: Kind): LinkedHashSet<D> {
|
||||||
val memberProtos = membersProtos()[name] ?: return LinkedHashSet()
|
val memberProtos = membersProtos()[ProtoKey(name, kind, isExtension = false)].orEmpty() +
|
||||||
|
membersProtos()[ProtoKey(name, kind, isExtension = true)].orEmpty()
|
||||||
|
|
||||||
val descriptors = LinkedHashSet<D>(memberProtos.size())
|
[suppress("UNCHECKED_CAST")]
|
||||||
for (memberProto in memberProtos) {
|
return memberProtos.mapTo(LinkedHashSet<D>()) { memberProto ->
|
||||||
if (callableKind(Flags.CALLABLE_KIND[memberProto.getFlags()])) {
|
context.deserializer.loadCallable(memberProto) as D
|
||||||
[suppress("UNCHECKED_CAST")]
|
|
||||||
descriptors.add(context.deserializer.loadCallable(memberProto) as D)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return descriptors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeFunctions(name: Name): Collection<FunctionDescriptor> {
|
private fun computeFunctions(name: Name): Collection<FunctionDescriptor> {
|
||||||
val descriptors = computeMembersByName<FunctionDescriptor>(name) { it == ProtoBuf.Callable.CallableKind.FUN }
|
val descriptors = computeMembers<FunctionDescriptor>(name, Kind.FUNCTION)
|
||||||
computeNonDeclaredFunctions(name, descriptors)
|
computeNonDeclaredFunctions(name, descriptors)
|
||||||
return descriptors.toReadOnlyList()
|
return descriptors.toReadOnlyList()
|
||||||
}
|
}
|
||||||
@@ -78,7 +91,7 @@ public abstract class DeserializedMemberScope protected(
|
|||||||
override fun getFunctions(name: Name): Collection<FunctionDescriptor> = functions(name)
|
override fun getFunctions(name: Name): Collection<FunctionDescriptor> = functions(name)
|
||||||
|
|
||||||
private fun computeProperties(name: Name): Collection<VariableDescriptor> {
|
private fun computeProperties(name: Name): Collection<VariableDescriptor> {
|
||||||
val descriptors = computeMembersByName<PropertyDescriptor>(name) { it == ProtoBuf.Callable.CallableKind.VAL || it == ProtoBuf.Callable.CallableKind.VAR }
|
val descriptors = computeMembers<PropertyDescriptor>(name, Kind.PROPERTY)
|
||||||
computeNonDeclaredProperties(name, descriptors)
|
computeNonDeclaredProperties(name, descriptors)
|
||||||
return descriptors.toReadOnlyList()
|
return descriptors.toReadOnlyList()
|
||||||
}
|
}
|
||||||
@@ -134,33 +147,27 @@ public abstract class DeserializedMemberScope protected(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val names = membersProtos().keySet().filter(nameFilter)
|
val keys = membersProtos().keySet().filter { nameFilter(it.name) }
|
||||||
if (acceptsProperties) {
|
if (acceptsProperties) {
|
||||||
addMembers(names, result) { getProperties(it) }
|
addMembers(result, keys, Kind.PROPERTY) { getProperties(it) }
|
||||||
}
|
}
|
||||||
if (acceptsFunctions) {
|
if (acceptsFunctions) {
|
||||||
addMembers(names, result) { getFunctions(it) }
|
addMembers(result, keys, Kind.FUNCTION) { getFunctions(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addMembers(
|
private fun addMembers(
|
||||||
names: List<Name>,
|
|
||||||
result: MutableCollection<DeclarationDescriptor>,
|
result: MutableCollection<DeclarationDescriptor>,
|
||||||
getMembers: (Name) -> Collection<CallableDescriptor>) {
|
keys: Collection<ProtoKey>,
|
||||||
val extensions = ArrayList<DeclarationDescriptor>()
|
kind: Kind,
|
||||||
val nonExtensions = ArrayList<DeclarationDescriptor>()
|
getMembers: (Name) -> Collection<CallableDescriptor>
|
||||||
names.forEach { name ->
|
) {
|
||||||
getMembers(name).forEach { member ->
|
val filteredByKind = keys.filter { it.kind == kind }
|
||||||
if (member.getExtensionReceiverParameter() == null) {
|
listOf(false, true).forEach { isExtension ->
|
||||||
nonExtensions.add(member)
|
filteredByKind.filter { it.isExtension == isExtension }
|
||||||
}
|
.flatMap { getMembers(it.name) }
|
||||||
else {
|
.filterTo(result) { (it.getExtensionReceiverParameter() != null) == isExtension }
|
||||||
extensions.add(member)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result.addAll(nonExtensions)
|
|
||||||
result.addAll(extensions)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun addNonDeclaredDescriptors(result: MutableCollection<DeclarationDescriptor>)
|
protected abstract fun addNonDeclaredDescriptors(result: MutableCollection<DeclarationDescriptor>)
|
||||||
|
|||||||
@@ -2368,6 +2368,12 @@ public class LazyResolveByStubTestGenerated extends AbstractLazyResolveByStubTes
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlin/memberOrder"), Pattern.compile("^(.+)\\.kt$"), true);
|
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")
|
@TestMetadata("enumEntries.kt")
|
||||||
public void testEnumEntries() throws Exception {
|
public void testEnumEntries() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/enumEntries.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/enumEntries.kt");
|
||||||
@@ -2380,6 +2386,12 @@ public class LazyResolveByStubTestGenerated extends AbstractLazyResolveByStubTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("innerClasses.kt")
|
||||||
public void testInnerClasses() throws Exception {
|
public void testInnerClasses() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/innerClasses.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/memberOrder/innerClasses.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user