提交 2f3f75b5 编写于 作者: P Pavel Kirpichenkov

Fix local anonymous class name error in K2MetadataCompiler

Extract the logic of approximating to denotable class supertype
from JS/KLIB and use it in metadata compiler.

^KT-20996 In Progress
上级 b82a44fa
......@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.cli.metadata
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
import org.jetbrains.kotlin.serialization.ApproximatingStringTable
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
......@@ -24,4 +25,5 @@ class MetadataSerializerExtension(
override val metadataVersion: BuiltInsBinaryVersion
) : KotlinSerializerExtensionBase(BuiltInSerializerProtocol) {
override fun shouldUseTypeTable(): Boolean = true
override val stringTable = ApproximatingStringTable()
}
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.serialization
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
open class ApproximatingStringTable : StringTableImpl() {
override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? {
return if (descriptor.containingDeclaration is CallableMemberDescriptor) {
val superClassifiers = descriptor.getAllSuperClassifiers()
.mapNotNull { it as ClassifierDescriptorWithTypeParameters }
.filter { it != descriptor }
.toList()
if (superClassifiers.size == 1) {
superClassifiers[0].classId
} else {
val superClass = superClassifiers.find { !DescriptorUtils.isInterface(it) }
superClass?.classId ?: ClassId.topLevel(StandardNames.FqNames.any.toSafe())
}
} else {
super.getLocalClassIdReplacement(descriptor)
}
}
}
exception: java.lang.IllegalStateException: Cannot get FQ name of local class: class <no name provided> defined in private val pVal: <no name provided> defined in root package in file anonymousObjectType.kt
at org.jetbrains.kotlin.serialization.DescriptorAwareStringTable$DefaultImpls.getFqNameIndex(DescriptorAwareStringTable.kt:26)
at org.jetbrains.kotlin.serialization.StringTableImpl.getFqNameIndex(StringTableImpl.kt:25)
at org.jetbrains.kotlin.serialization.DescriptorSerializer.getClassifierId(DescriptorSerializer.kt:741)
at org.jetbrains.kotlin.serialization.DescriptorSerializer.fillFromPossiblyInnerType(DescriptorSerializer.kt:613)
at org.jetbrains.kotlin.serialization.DescriptorSerializer.type$serialization(DescriptorSerializer.kt:580)
at org.jetbrains.kotlin.serialization.DescriptorSerializer.typeId(DescriptorSerializer.kt:547)
at org.jetbrains.kotlin.serialization.DescriptorSerializer.propertyProto(DescriptorSerializer.kt:255)
at org.jetbrains.kotlin.serialization.DescriptorSerializer.packagePartProto(DescriptorSerializer.kt:661)
at org.jetbrains.kotlin.cli.metadata.MetadataSerializer$PackageSerializer.serializeMembers(MetadataSerializer.kt:157)
at org.jetbrains.kotlin.cli.metadata.MetadataSerializer$PackageSerializer.run(MetadataSerializer.kt:136)
at org.jetbrains.kotlin.cli.metadata.MetadataSerializer.performSerialization(MetadataSerializer.kt:94)
at org.jetbrains.kotlin.cli.metadata.MetadataSerializer.serialize(MetadataSerializer.kt:49)
at org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler.doExecute(K2MetadataCompiler.kt:111)
at org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler.doExecute(K2MetadataCompiler.kt:40)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:88)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:44)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:98)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:76)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:45)
at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit(CLITool.kt:227)
at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit$default(CLITool.kt:222)
at org.jetbrains.kotlin.test.CompilerTestUtil.executeCompiler(CompilerTestUtil.kt:41)
at org.jetbrains.kotlin.cli.AbstractCliTest.executeCompilerGrabOutput(AbstractCliTest.java:73)
at org.jetbrains.kotlin.cli.AbstractCliTest.doTest(AbstractCliTest.java:105)
at org.jetbrains.kotlin.cli.AbstractCliTest.doMetadataTest(AbstractCliTest.java:285)
at org.jetbrains.kotlin.test.KotlinTestUtils.lambda$testWithCustomIgnoreDirective$5(KotlinTestUtils.java:572)
at org.jetbrains.kotlin.test.KotlinTestUtils.runTestImpl(KotlinTestUtils.java:542)
at org.jetbrains.kotlin.test.KotlinTestUtils.runTest(KotlinTestUtils.java:485)
at org.jetbrains.kotlin.cli.CliTestGenerated$Metadata.runTest(CliTestGenerated.java:1176)
at org.jetbrains.kotlin.cli.CliTestGenerated$Metadata.testAnonymousObjectType(CliTestGenerated.java:1185)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at junit.framework.TestCase.runTest(TestCase.java:176)
at org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase.lambda$runTest$9(KtUsefulTestCase.java:374)
at org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase.lambda$invokeTestRunnable$10(KtUsefulTestCase.java:407)
at com.intellij.testFramework.EdtTestUtilKt.runInEdtAndWait(EdtTestUtil.kt:63)
at org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase.invokeTestRunnable(KtUsefulTestCase.java:406)
at org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase.runTest(KtUsefulTestCase.java:393)
at org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase.defaultRunBare(KtUsefulTestCase.java:424)
at com.intellij.testFramework.EdtTestUtil$Companion$runInEdtAndWait$1.invoke(EdtTestUtil.kt:18)
at com.intellij.testFramework.EdtTestUtil$Companion$runInEdtAndWait$1.invoke(EdtTestUtil.kt:13)
at com.intellij.testFramework.EdtTestUtilKt$runInEdtAndWait$3.run(EdtTestUtil.kt:67)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:301)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:419)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
INTERNAL_ERROR
OK
package test
import lib.*
val w = W()
val v1 = fn()
val v2 = O.o()
val v3 = w.w()
// private
val e1 = o3
val e2 = w.o7
val e3 = O.o10
package lib
interface I1 {
fun i1() {}
}
interface I2 {
fun i2() {}
}
interface I3 : I2, I1
open class C {
fun c() {}
}
open class G<T> {
fun g() {}
}
private val o1 = object { fun foo() {} }
private val o2 = object : I1 {}
private val o3 = object : I1, I2 {}
private val o4 = object : I3 {}
private val o5 = object : C() {}
private val o6 = object : C(), I1, I2 {}
private val o7 = object : C(), I3 {}
private val o8 = object : G<Int>() {}
private val o9 = object : G<Int>(), I1, I2 {}
private val o10 = object : G<Int>(), I3 {}
fun fn() {
o1.foo()
o2.i1()
o3.i1()
o3.i2()
o4.i1()
o4.i2()
o5.c()
o6.c()
o6.i1()
o6.i2()
o7.c()
o7.i1()
o7.i2()
o8.g()
o9.g()
o9.i1()
o9.i2()
o10.g()
o10.i1()
o10.i2()
}
class W {
private val o1 = object { fun foo() {} }
private val o2 = object : I1 {}
private val o3 = object : I1, I2 {}
private val o4 = object : I3 {}
private val o5 = object : C() {}
private val o6 = object : C(), I1, I2 {}
private val o7 = object : C(), I3 {}
private val o8 = object : G<Int>() {}
private val o9 = object : G<Int>(), I1, I2 {}
private val o10 = object : G<Int>(), I3 {}
fun w() {
o1.foo()
o2.i1()
o3.i1()
o3.i2()
o4.i1()
o4.i2()
o5.c()
o6.c()
o6.i1()
o6.i2()
o7.c()
o7.i1()
o7.i2()
o8.g()
o9.g()
o9.i1()
o9.i2()
o10.g()
o10.i1()
o10.i2()
}
}
object O {
private val o1 = object { fun foo() {} }
private val o2 = object : I1 {}
private val o3 = object : I1, I2 {}
private val o4 = object : I3 {}
private val o5 = object : C() {}
private val o6 = object : C(), I1, I2 {}
private val o7 = object : C(), I3 {}
private val o8 = object : G<Int>() {}
private val o9 = object : G<Int>(), I1, I2 {}
private val o10 = object : G<Int>(), I3 {}
fun o() {
o1.foo()
o2.i1()
o3.i1()
o3.i2()
o4.i1()
o4.i2()
o5.c()
o6.c()
o6.i1()
o6.i2()
o7.c()
o7.i1()
o7.i2()
o8.g()
o9.g()
o9.i1()
o9.i2()
o10.g()
o10.i1()
o10.i2()
}
}
compiler/testData/compileKotlinAgainstCustomBinaries/anonymousObjectTypeMetadata/anonymousObjectTypeMetadata.kt:11:10: error: cannot access 'o3': it is private in file
val e1 = o3
^
compiler/testData/compileKotlinAgainstCustomBinaries/anonymousObjectTypeMetadata/anonymousObjectTypeMetadata.kt:12:12: error: cannot access 'o7': it is private in 'W'
val e2 = w.o7
^
compiler/testData/compileKotlinAgainstCustomBinaries/anonymousObjectTypeMetadata/anonymousObjectTypeMetadata.kt:13:12: error: cannot access 'o10': it is private in 'O'
val e3 = O.o10
^
COMPILATION_ERROR
......@@ -725,6 +725,18 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
loadClassFile("SourceKt", tmpdir, library)
}
fun testAnonymousObjectTypeMetadata() {
val library = compileCommonLibrary(
libraryName = "library",
)
compileKotlin(
"anonymousObjectTypeMetadata.kt",
tmpdir,
listOf(library),
K2MetadataCompiler(),
)
}
private fun loadClassFile(className: String, dir: File, library: File) {
val classLoader = URLClassLoader(arrayOf(dir.toURI().toURL(), library.toURI().toURL()))
val mainClass = classLoader.loadClass(className)
......
......@@ -5,30 +5,6 @@
package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
import org.jetbrains.kotlin.serialization.StringTableImpl
import org.jetbrains.kotlin.serialization.ApproximatingStringTable
class KlibMetadataStringTable : StringTableImpl() {
override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? {
return if (descriptor.containingDeclaration is CallableMemberDescriptor) {
val superClassifiers = descriptor.getAllSuperClassifiers()
.mapNotNull { it as ClassifierDescriptorWithTypeParameters }
.filter { it != descriptor }
.toList()
if (superClassifiers.size == 1) {
superClassifiers[0].classId
} else {
val superClass = superClassifiers.find { !DescriptorUtils.isInterface(it) }
superClass?.classId ?: ClassId.topLevel(StandardNames.FqNames.any.toSafe())
}
} else {
super.getLocalClassIdReplacement(descriptor)
}
}
}
typealias KlibMetadataStringTable = ApproximatingStringTable
......@@ -16,30 +16,6 @@
package org.jetbrains.kotlin.serialization.js
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
import org.jetbrains.kotlin.serialization.StringTableImpl
import org.jetbrains.kotlin.serialization.ApproximatingStringTable
class JavaScriptStringTable : StringTableImpl() {
override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? {
return if (descriptor.containingDeclaration is CallableMemberDescriptor) {
val superClassifiers = descriptor.getAllSuperClassifiers()
.mapNotNull { it as ClassifierDescriptorWithTypeParameters }
.filter { it != descriptor }
.toList()
if (superClassifiers.size == 1) {
superClassifiers[0].classId
} else {
val superClass = superClassifiers.find { !DescriptorUtils.isInterface(it) }
superClass?.classId ?: ClassId.topLevel(StandardNames.FqNames.any.toSafe())
}
} else {
super.getLocalClassIdReplacement(descriptor)
}
}
}
typealias JavaScriptStringTable = ApproximatingStringTable
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册