Introduce binary representation for annotations
Will be used where annotations can't be stored elsewhere: for example, built-ins, JS, type annotations on JDK<8
This commit is contained in:
@@ -21,7 +21,7 @@ import com.intellij.openapi.util.Disposer
|
||||
import org.jetbrains.jet.config.CompilerConfiguration
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment
|
||||
import org.jetbrains.jet.descriptors.serialization.*
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.*
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import java.io.ByteArrayOutputStream
|
||||
import org.jetbrains.jet.lang.types.lang.BuiltInsSerializationUtil
|
||||
@@ -29,7 +29,6 @@ import com.intellij.openapi.Disposable
|
||||
import org.jetbrains.jet.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.jet.config.CommonConfigurationKeys
|
||||
import org.jetbrains.jet.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||
import org.jetbrains.jet.utils.recursePostOrder
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
@@ -41,9 +40,15 @@ import org.jetbrains.jet.analyzer.ModuleContent
|
||||
import org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils
|
||||
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.jet.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys
|
||||
|
||||
private object BuiltInsSerializerExtension : SerializerExtension() {
|
||||
override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder, stringTable: StringTable) {
|
||||
for (annotation in descriptor.getAnnotations()) {
|
||||
proto.addExtension(BuiltInsProtoBuf.classAnnotation, AnnotationSerializer.serializeAnnotation(annotation, stringTable))
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializePackage(
|
||||
packageFragments: Collection<PackageFragmentDescriptor>,
|
||||
proto: ProtoBuf.Package.Builder,
|
||||
@@ -57,16 +62,41 @@ private object BuiltInsSerializerExtension : SerializerExtension() {
|
||||
proto.addExtension(BuiltInsProtoBuf.className, stringTable.getSimpleNameIndex(descriptor.getName()))
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeCallable(
|
||||
callable: CallableMemberDescriptor,
|
||||
proto: ProtoBuf.Callable.Builder,
|
||||
stringTable: StringTable
|
||||
) {
|
||||
for (annotation in callable.getAnnotations()) {
|
||||
proto.addExtension(BuiltInsProtoBuf.callableAnnotation, AnnotationSerializer.serializeAnnotation(annotation, stringTable))
|
||||
}
|
||||
}
|
||||
|
||||
override fun serializeValueParameter(
|
||||
descriptor: ValueParameterDescriptor,
|
||||
proto: ProtoBuf.Callable.ValueParameter.Builder,
|
||||
stringTable: StringTable
|
||||
) {
|
||||
for (annotation in descriptor.getAnnotations()) {
|
||||
proto.addExtension(BuiltInsProtoBuf.parameterAnnotation, AnnotationSerializer.serializeAnnotation(annotation, stringTable))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BuiltInsSerializer(private val dependOnOldBuiltIns: Boolean) {
|
||||
private var totalSize = 0
|
||||
private var totalFiles = 0
|
||||
|
||||
public fun serialize(destDir: File, srcDirs: Collection<File>, onComplete: (totalSize: Int, totalFiles: Int) -> Unit) {
|
||||
public fun serialize(
|
||||
destDir: File,
|
||||
srcDirs: Collection<File>,
|
||||
extraClassPath: Collection<File>,
|
||||
onComplete: (totalSize: Int, totalFiles: Int) -> Unit
|
||||
) {
|
||||
val rootDisposable = Disposer.newDisposable()
|
||||
try {
|
||||
serialize(rootDisposable, destDir, srcDirs)
|
||||
serialize(rootDisposable, destDir, srcDirs, extraClassPath)
|
||||
onComplete(totalSize, totalFiles)
|
||||
}
|
||||
finally {
|
||||
@@ -81,13 +111,17 @@ public class BuiltInsSerializer(private val dependOnOldBuiltIns: Boolean) {
|
||||
if (dependOnOldBuiltIns) ModuleInfo.DependenciesOnBuiltins.LAST else ModuleInfo.DependenciesOnBuiltins.NONE
|
||||
}
|
||||
|
||||
fun serialize(disposable: Disposable, destDir: File, srcDirs: Collection<File>) {
|
||||
fun serialize(disposable: Disposable, destDir: File, srcDirs: Collection<File>, extraClassPath: Collection<File>) {
|
||||
val configuration = CompilerConfiguration()
|
||||
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
|
||||
|
||||
val sourceRoots = srcDirs map { it.path }
|
||||
configuration.put(CommonConfigurationKeys.SOURCE_ROOTS_KEY, sourceRoots)
|
||||
|
||||
for (path in extraClassPath) {
|
||||
configuration.add(JVMConfigurationKeys.CLASSPATH_KEY, path)
|
||||
}
|
||||
|
||||
val environment = JetCoreEnvironment.createForTests(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
|
||||
val files = environment.getSourceFiles()
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.io.File
|
||||
fun main(args: Array<String>) {
|
||||
System.setProperty("java.awt.headless", "true")
|
||||
|
||||
if (args.size < 2) {
|
||||
if (args.size() < 2) {
|
||||
println(
|
||||
"""Kotlin built-ins serializer
|
||||
|
||||
@@ -42,7 +42,7 @@ found top-level declarations to <destination dir> (files such as
|
||||
val missing = srcDirs filterNot { it.exists() }
|
||||
assert(missing.isEmpty()) { "These source directories are missing: $missing" }
|
||||
|
||||
BuiltInsSerializer(dependOnOldBuiltIns = false).serialize(destDir, srcDirs) { (totalSize, totalFiles) ->
|
||||
BuiltInsSerializer(dependOnOldBuiltIns = false).serialize(destDir, srcDirs, listOf()) { (totalSize, totalFiles) ->
|
||||
println("Total bytes written: $totalSize to $totalFiles files")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
annotation class Empty
|
||||
|
||||
annotation class JustAnnotation(val annotation: Empty)
|
||||
|
||||
annotation class AnnotationArray(val annotationArray: Array<JustAnnotation>)
|
||||
|
||||
JustAnnotation(Empty())
|
||||
AnnotationArray(array())
|
||||
class C1
|
||||
|
||||
AnnotationArray(array(JustAnnotation(Empty()), JustAnnotation(Empty())))
|
||||
class C2
|
||||
@@ -0,0 +1,23 @@
|
||||
package test
|
||||
|
||||
internal final annotation class AnnotationArray : kotlin.Annotation {
|
||||
public constructor AnnotationArray(/*0*/ annotationArray: kotlin.Array<test.JustAnnotation>)
|
||||
internal final val annotationArray: kotlin.Array<test.JustAnnotation>
|
||||
}
|
||||
|
||||
test.JustAnnotation(annotation = test.Empty(): test.Empty) test.AnnotationArray(annotationArray = {}: kotlin.Array<test.JustAnnotation>) internal final class C1 {
|
||||
public constructor C1()
|
||||
}
|
||||
|
||||
test.AnnotationArray(annotationArray = {test.JustAnnotation(annotation = test.Empty(): test.Empty), test.JustAnnotation(annotation = test.Empty(): test.Empty)}: kotlin.Array<test.JustAnnotation>) internal final class C2 {
|
||||
public constructor C2()
|
||||
}
|
||||
|
||||
internal final annotation class Empty : kotlin.Annotation {
|
||||
public constructor Empty()
|
||||
}
|
||||
|
||||
internal final annotation class JustAnnotation : kotlin.Annotation {
|
||||
public constructor JustAnnotation(/*0*/ annotation: test.Empty)
|
||||
internal final val annotation: test.Empty
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package test
|
||||
|
||||
enum class Weapon {
|
||||
ROCK
|
||||
PAPER
|
||||
SCISSORS
|
||||
}
|
||||
|
||||
annotation class JustEnum(val weapon: Weapon)
|
||||
|
||||
annotation class EnumArray(val enumArray: Array<Weapon>)
|
||||
|
||||
JustEnum(Weapon.SCISSORS)
|
||||
EnumArray(array())
|
||||
class C1
|
||||
|
||||
EnumArray(array(Weapon.PAPER, Weapon.ROCK))
|
||||
class C2
|
||||
@@ -0,0 +1,72 @@
|
||||
package test
|
||||
|
||||
test.JustEnum(weapon = Weapon.SCISSORS: test.Weapon) test.EnumArray(enumArray = {}: kotlin.Array<test.Weapon>) internal final class C1 {
|
||||
public constructor C1()
|
||||
}
|
||||
|
||||
test.EnumArray(enumArray = {Weapon.PAPER, Weapon.ROCK}: kotlin.Array<test.Weapon>) internal final class C2 {
|
||||
public constructor C2()
|
||||
}
|
||||
|
||||
internal final annotation class EnumArray : kotlin.Annotation {
|
||||
public constructor EnumArray(/*0*/ enumArray: kotlin.Array<test.Weapon>)
|
||||
internal final val enumArray: kotlin.Array<test.Weapon>
|
||||
}
|
||||
|
||||
internal final annotation class JustEnum : kotlin.Annotation {
|
||||
public constructor JustEnum(/*0*/ weapon: test.Weapon)
|
||||
internal final val weapon: test.Weapon
|
||||
}
|
||||
|
||||
internal final enum class Weapon : kotlin.Enum<test.Weapon> {
|
||||
public enum entry ROCK : test.Weapon {
|
||||
private constructor ROCK()
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.Weapon): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
|
||||
|
||||
public class object <class-object-for-ROCK> : test.Weapon.ROCK {
|
||||
private constructor <class-object-for-ROCK>()
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.Weapon): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
|
||||
}
|
||||
}
|
||||
|
||||
public enum entry PAPER : test.Weapon {
|
||||
private constructor PAPER()
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.Weapon): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
|
||||
|
||||
public class object <class-object-for-PAPER> : test.Weapon.PAPER {
|
||||
private constructor <class-object-for-PAPER>()
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.Weapon): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
|
||||
}
|
||||
}
|
||||
|
||||
public enum entry SCISSORS : test.Weapon {
|
||||
private constructor SCISSORS()
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.Weapon): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
|
||||
|
||||
public class object <class-object-for-SCISSORS> : test.Weapon.SCISSORS {
|
||||
private constructor <class-object-for-SCISSORS>()
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.Weapon): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
|
||||
}
|
||||
}
|
||||
|
||||
private constructor Weapon()
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.Weapon): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun name(): kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.Weapon
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<test.Weapon>
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package test
|
||||
|
||||
annotation class PrimitiveArrays(
|
||||
val byteArray: ByteArray
|
||||
val charArray: CharArray,
|
||||
val shortArray: ShortArray,
|
||||
val intArray: IntArray,
|
||||
val longArray: LongArray,
|
||||
val floatArray: FloatArray,
|
||||
val doubleArray: DoubleArray,
|
||||
val booleanArray: BooleanArray
|
||||
)
|
||||
|
||||
PrimitiveArrays(
|
||||
byteArray = byteArray(-7, 7),
|
||||
charArray = charArray('%', 'z'),
|
||||
shortArray = shortArray(239),
|
||||
intArray = intArray(239017, -1),
|
||||
longArray = longArray(123456789123456789L),
|
||||
floatArray = floatArray(2.72f, 0f),
|
||||
doubleArray = doubleArray(-3.14),
|
||||
booleanArray = booleanArray(true, false, true)
|
||||
)
|
||||
class C1
|
||||
|
||||
PrimitiveArrays(
|
||||
byteArray = byteArray(),
|
||||
charArray = charArray(),
|
||||
shortArray = shortArray(),
|
||||
intArray = intArray(),
|
||||
longArray = longArray(),
|
||||
floatArray = floatArray(),
|
||||
doubleArray = doubleArray(),
|
||||
booleanArray = booleanArray()
|
||||
)
|
||||
class C2
|
||||
@@ -0,0 +1,21 @@
|
||||
package test
|
||||
|
||||
test.PrimitiveArrays(booleanArray = {true, false, true}: kotlin.BooleanArray, byteArray = {-7.toByte(), 7.toByte()}: kotlin.ByteArray, charArray = {\u0025 ('%'), \u007A ('z')}: kotlin.CharArray, doubleArray = {-3.14.toDouble()}: kotlin.DoubleArray, floatArray = {2.72.toFloat(), 0.0.toFloat()}: kotlin.FloatArray, intArray = {239017, -1}: kotlin.IntArray, longArray = {123456789123456789.toLong()}: kotlin.LongArray, shortArray = {239.toShort()}: kotlin.ShortArray) internal final class C1 {
|
||||
public constructor C1()
|
||||
}
|
||||
|
||||
test.PrimitiveArrays(booleanArray = {}: kotlin.BooleanArray, byteArray = {}: kotlin.ByteArray, charArray = {}: kotlin.CharArray, doubleArray = {}: kotlin.DoubleArray, floatArray = {}: kotlin.FloatArray, intArray = {}: kotlin.IntArray, longArray = {}: kotlin.LongArray, shortArray = {}: kotlin.ShortArray) internal final class C2 {
|
||||
public constructor C2()
|
||||
}
|
||||
|
||||
internal final annotation class PrimitiveArrays : kotlin.Annotation {
|
||||
public constructor PrimitiveArrays(/*0*/ byteArray: kotlin.ByteArray, /*1*/ charArray: kotlin.CharArray, /*2*/ shortArray: kotlin.ShortArray, /*3*/ intArray: kotlin.IntArray, /*4*/ longArray: kotlin.LongArray, /*5*/ floatArray: kotlin.FloatArray, /*6*/ doubleArray: kotlin.DoubleArray, /*7*/ booleanArray: kotlin.BooleanArray)
|
||||
internal final val booleanArray: kotlin.BooleanArray
|
||||
internal final val byteArray: kotlin.ByteArray
|
||||
internal final val charArray: kotlin.CharArray
|
||||
internal final val doubleArray: kotlin.DoubleArray
|
||||
internal final val floatArray: kotlin.FloatArray
|
||||
internal final val intArray: kotlin.IntArray
|
||||
internal final val longArray: kotlin.LongArray
|
||||
internal final val shortArray: kotlin.ShortArray
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package test
|
||||
|
||||
annotation class Primitives(
|
||||
val byte: Byte,
|
||||
val char: Char,
|
||||
val short: Short,
|
||||
val int: Int,
|
||||
val long: Long,
|
||||
val float: Float,
|
||||
val double: Double,
|
||||
val boolean: Boolean
|
||||
)
|
||||
|
||||
Primitives(
|
||||
byte = 7,
|
||||
char = '%',
|
||||
short = 239,
|
||||
int = 239017,
|
||||
long = 123456789123456789L,
|
||||
float = 2.72f,
|
||||
double = -3.14,
|
||||
boolean = true
|
||||
)
|
||||
class C
|
||||
@@ -0,0 +1,17 @@
|
||||
package test
|
||||
|
||||
test.Primitives(boolean = true: kotlin.Boolean, byte = 7.toByte(): kotlin.Byte, char = \u0025 ('%'): kotlin.Char, double = -3.14.toDouble(): kotlin.Double, float = 2.72.toFloat(): kotlin.Float, int = 239017: kotlin.Int, long = 123456789123456789.toLong(): kotlin.Long, short = 239.toShort(): kotlin.Short) internal final class C {
|
||||
public constructor C()
|
||||
}
|
||||
|
||||
internal final annotation class Primitives : kotlin.Annotation {
|
||||
public constructor Primitives(/*0*/ byte: kotlin.Byte, /*1*/ char: kotlin.Char, /*2*/ short: kotlin.Short, /*3*/ int: kotlin.Int, /*4*/ long: kotlin.Long, /*5*/ float: kotlin.Float, /*6*/ double: kotlin.Double, /*7*/ boolean: kotlin.Boolean)
|
||||
internal final val boolean: kotlin.Boolean
|
||||
internal final val byte: kotlin.Byte
|
||||
internal final val char: kotlin.Char
|
||||
internal final val double: kotlin.Double
|
||||
internal final val float: kotlin.Float
|
||||
internal final val int: kotlin.Int
|
||||
internal final val long: kotlin.Long
|
||||
internal final val short: kotlin.Short
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
annotation class JustString(val string: String)
|
||||
|
||||
annotation class StringArray(val stringArray: Array<String>)
|
||||
|
||||
JustString("kotlin")
|
||||
StringArray(array())
|
||||
class C1
|
||||
|
||||
StringArray(array("java", ""))
|
||||
class C2
|
||||
@@ -0,0 +1,19 @@
|
||||
package test
|
||||
|
||||
test.JustString(string = "kotlin": kotlin.String) test.StringArray(stringArray = {}: kotlin.Array<kotlin.String>) internal final class C1 {
|
||||
public constructor C1()
|
||||
}
|
||||
|
||||
test.StringArray(stringArray = {"java", ""}: kotlin.Array<kotlin.String>) internal final class C2 {
|
||||
public constructor C2()
|
||||
}
|
||||
|
||||
internal final annotation class JustString : kotlin.Annotation {
|
||||
public constructor JustString(/*0*/ string: kotlin.String)
|
||||
internal final val string: kotlin.String
|
||||
}
|
||||
|
||||
internal final annotation class StringArray : kotlin.Annotation {
|
||||
public constructor StringArray(/*0*/ stringArray: kotlin.Array<kotlin.String>)
|
||||
internal final val stringArray: kotlin.Array<kotlin.String>
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package test
|
||||
|
||||
annotation class anno(val x: String)
|
||||
|
||||
|
||||
anno("top level function")
|
||||
fun f1(anno("top level function parameter") p: Int) {}
|
||||
|
||||
anno("top level property")
|
||||
val p1 = null
|
||||
|
||||
anno("extension function")
|
||||
fun Long.f2(anno("extension function parameter") p: Int) {}
|
||||
|
||||
anno("extension property")
|
||||
val Double.p2: Double get() = null
|
||||
|
||||
anno("top level class")
|
||||
class C1 [anno("constructor")] () {
|
||||
anno("member function")
|
||||
fun f3(anno("member function parameter") p: Int) {}
|
||||
|
||||
anno("member property")
|
||||
val p3 = null
|
||||
|
||||
anno("member extension function")
|
||||
fun String.f4() {}
|
||||
|
||||
anno("member extension property")
|
||||
val Int.v4: Int get() = this
|
||||
|
||||
anno("nested class")
|
||||
class C2
|
||||
|
||||
anno("class object")
|
||||
class object {}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package test
|
||||
|
||||
test.anno(x = "top level property": kotlin.String) internal val p1: kotlin.Nothing?
|
||||
test.anno(x = "extension property": kotlin.String) internal val kotlin.Double.p2: kotlin.Double
|
||||
test.anno(x = "top level function": kotlin.String) internal fun f1(/*0*/ test.anno(x = "top level function parameter": kotlin.String) p: kotlin.Int): kotlin.Unit
|
||||
test.anno(x = "extension function": kotlin.String) internal fun kotlin.Long.f2(/*0*/ test.anno(x = "extension function parameter": kotlin.String) p: kotlin.Int): kotlin.Unit
|
||||
|
||||
test.anno(x = "top level class": kotlin.String) internal final class C1 {
|
||||
test.anno(x = "constructor": kotlin.String) public constructor C1()
|
||||
test.anno(x = "member property": kotlin.String) internal final val p3: kotlin.Nothing?
|
||||
test.anno(x = "member extension property": kotlin.String) internal final val kotlin.Int.v4: kotlin.Int
|
||||
test.anno(x = "member function": kotlin.String) internal final fun f3(/*0*/ test.anno(x = "member function parameter": kotlin.String) p: kotlin.Int): kotlin.Unit
|
||||
test.anno(x = "member extension function": kotlin.String) internal final fun kotlin.String.f4(): kotlin.Unit
|
||||
|
||||
test.anno(x = "class object": kotlin.String) internal class object <class-object-for-C1> {
|
||||
private constructor <class-object-for-C1>()
|
||||
}
|
||||
|
||||
test.anno(x = "nested class": kotlin.String) internal final class C2 {
|
||||
public constructor C2()
|
||||
}
|
||||
}
|
||||
|
||||
internal final annotation class anno : kotlin.Annotation {
|
||||
public constructor anno(/*0*/ x: kotlin.String)
|
||||
internal final val x: kotlin.String
|
||||
}
|
||||
+31
-3
@@ -26,20 +26,24 @@ import org.jetbrains.jet.JetTestUtils
|
||||
import java.io.FileInputStream
|
||||
import org.jetbrains.jet.test.util.RecursiveDescriptorComparator
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.codegen.forTestCompile.ForTestCompileRuntime
|
||||
|
||||
public class BuiltInsSerializerTest : TestCaseWithTmpdir() {
|
||||
private fun doTest(fileName: String) {
|
||||
val source = "compiler/testData/serialization/$fileName"
|
||||
BuiltInsSerializer(dependOnOldBuiltIns = true).serialize(
|
||||
tmpdir,
|
||||
listOf(File(source)),
|
||||
{ totalSize, totalFiles -> }
|
||||
srcDirs = listOf(File(source)),
|
||||
extraClassPath = listOf(ForTestCompileRuntime.runtimeJarForTests()),
|
||||
onComplete = { totalSize, totalFiles -> }
|
||||
)
|
||||
|
||||
val module = JetTestUtils.createEmptyModule("<module>")
|
||||
|
||||
val packageFragment = BuiltinsPackageFragment(TEST_PACKAGE_FQNAME, LockBasedStorageManager(), module) {
|
||||
path -> FileInputStream(File(tmpdir, path))
|
||||
path ->
|
||||
val file = File(tmpdir, path)
|
||||
if (file.exists()) FileInputStream(file) else null
|
||||
}
|
||||
|
||||
module.initialize(packageFragment.provider)
|
||||
@@ -57,4 +61,28 @@ public class BuiltInsSerializerTest : TestCaseWithTmpdir() {
|
||||
fun testSimple() {
|
||||
doTest("simple.kt")
|
||||
}
|
||||
|
||||
fun testAnnotationTargets() {
|
||||
doTest("annotationTargets.kt")
|
||||
}
|
||||
|
||||
fun testPrimitives() {
|
||||
doTest("annotationArguments/primitives.kt")
|
||||
}
|
||||
|
||||
fun testPrimitiveArrays() {
|
||||
doTest("annotationArguments/primitiveArrays.kt")
|
||||
}
|
||||
|
||||
fun testString() {
|
||||
doTest("annotationArguments/string.kt")
|
||||
}
|
||||
|
||||
fun testAnnotation() {
|
||||
doTest("annotationArguments/annotation.kt")
|
||||
}
|
||||
|
||||
fun testEnum() {
|
||||
doTest("annotationArguments/enum.kt")
|
||||
}
|
||||
}
|
||||
|
||||
+52
-2
@@ -8,6 +8,9 @@ public final class DebugBuiltInsProtoBuf {
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistry registry) {
|
||||
registry.add(org.jetbrains.jet.descriptors.serialization.DebugBuiltInsProtoBuf.className);
|
||||
registry.add(org.jetbrains.jet.descriptors.serialization.DebugBuiltInsProtoBuf.classAnnotation);
|
||||
registry.add(org.jetbrains.jet.descriptors.serialization.DebugBuiltInsProtoBuf.callableAnnotation);
|
||||
registry.add(org.jetbrains.jet.descriptors.serialization.DebugBuiltInsProtoBuf.parameterAnnotation);
|
||||
}
|
||||
public static final int CLASS_NAME_FIELD_NUMBER = 150;
|
||||
/**
|
||||
@@ -20,6 +23,39 @@ public final class DebugBuiltInsProtoBuf {
|
||||
.newFileScopedGeneratedExtension(
|
||||
java.lang.Integer.class,
|
||||
null);
|
||||
public static final int CLASS_ANNOTATION_FIELD_NUMBER = 150;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.jet.descriptors.serialization.Class { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
com.google.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Class,
|
||||
java.util.List<org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Annotation>> classAnnotation = com.google.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Annotation.class,
|
||||
org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Annotation.getDefaultInstance());
|
||||
public static final int CALLABLE_ANNOTATION_FIELD_NUMBER = 150;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.jet.descriptors.serialization.Callable { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
com.google.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Callable,
|
||||
java.util.List<org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Annotation>> callableAnnotation = com.google.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Annotation.class,
|
||||
org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Annotation.getDefaultInstance());
|
||||
public static final int PARAMETER_ANNOTATION_FIELD_NUMBER = 150;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.jet.descriptors.serialization.Callable.ValueParameter { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
com.google.protobuf.GeneratedMessage.GeneratedExtension<
|
||||
org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Callable.ValueParameter,
|
||||
java.util.List<org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Annotation>> parameterAnnotation = com.google.protobuf.GeneratedMessage
|
||||
.newFileScopedGeneratedExtension(
|
||||
org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Annotation.class,
|
||||
org.jetbrains.jet.descriptors.serialization.DebugProtoBuf.Annotation.getDefaultInstance());
|
||||
|
||||
public static com.google.protobuf.Descriptors.FileDescriptor
|
||||
getDescriptor() {
|
||||
@@ -34,8 +70,19 @@ public final class DebugBuiltInsProtoBuf {
|
||||
"ialization\032.core/serialization/src/descr" +
|
||||
"iptors.debug.proto:M\n\nclass_name\0224.org.j" +
|
||||
"etbrains.jet.descriptors.serialization.P" +
|
||||
"ackage\030\226\001 \003(\005B\002\020\001B\027B\025DebugBuiltInsProtoB" +
|
||||
"uf"
|
||||
"ackage\030\226\001 \003(\005B\002\020\001:\206\001\n\020class_annotation\0222" +
|
||||
".org.jetbrains.jet.descriptors.serializa" +
|
||||
"tion.Class\030\226\001 \003(\01327.org.jetbrains.jet.de" +
|
||||
"scriptors.serialization.Annotation:\214\001\n\023c" +
|
||||
"allable_annotation\0225.org.jetbrains.jet.d",
|
||||
"escriptors.serialization.Callable\030\226\001 \003(\013" +
|
||||
"27.org.jetbrains.jet.descriptors.seriali" +
|
||||
"zation.Annotation:\234\001\n\024parameter_annotati" +
|
||||
"on\022D.org.jetbrains.jet.descriptors.seria" +
|
||||
"lization.Callable.ValueParameter\030\226\001 \003(\0132" +
|
||||
"7.org.jetbrains.jet.descriptors.serializ" +
|
||||
"ation.AnnotationB\027B\025DebugBuiltInsProtoBu" +
|
||||
"f"
|
||||
};
|
||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
||||
@@ -43,6 +90,9 @@ public final class DebugBuiltInsProtoBuf {
|
||||
com.google.protobuf.Descriptors.FileDescriptor root) {
|
||||
descriptor = root;
|
||||
className.internalInit(descriptor.getExtensions().get(0));
|
||||
classAnnotation.internalInit(descriptor.getExtensions().get(1));
|
||||
callableAnnotation.internalInit(descriptor.getExtensions().get(2));
|
||||
parameterAnnotation.internalInit(descriptor.getExtensions().get(3));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+2
-5
@@ -22,16 +22,12 @@ import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.AnnotationArra
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils
|
||||
import org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.javaClassIdToKotlinClassId
|
||||
import org.jetbrains.jet.storage.StorageManager
|
||||
|
||||
import java.util.*
|
||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.*
|
||||
import org.jetbrains.jet.lang.resolve.name.ClassId
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import org.jetbrains.jet.lang.resolve.constants.ArrayValue
|
||||
import org.jetbrains.jet.lang.descriptors.ClassKind
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.constants.EnumValue
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.jet.lang.resolve.constants.ErrorValue
|
||||
@@ -112,6 +108,7 @@ public class BinaryClassAnnotationAndConstantLoaderImpl(
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: see analogous code in AnnotationDeserializer
|
||||
private fun enumEntryValue(enumClassId: ClassId, name: Name): CompileTimeConstant<*> {
|
||||
val enumClass = resolveClass(enumClassId)
|
||||
if (enumClass.getKind() == ClassKind.ENUM_CLASS) {
|
||||
|
||||
@@ -32,6 +32,8 @@ public class ArrayValue extends CompileTimeConstant<List<CompileTimeConstant<?>>
|
||||
boolean canBeUsedInAnnotations,
|
||||
boolean usesVariableAsConstant) {
|
||||
super(value, canBeUsedInAnnotations, false, usesVariableAsConstant);
|
||||
assert KotlinBuiltIns.getInstance().isArray(type) ||
|
||||
KotlinBuiltIns.getInstance().isPrimitiveArray(type) : "Type should be an array, but was " + type + ": " + value;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.jet.lang.types.lang
|
||||
|
||||
import org.jetbrains.jet.descriptors.serialization.*
|
||||
import org.jetbrains.jet.descriptors.serialization.descriptors.*
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
|
||||
|
||||
class BuiltInsAnnotationAndConstantLoader(
|
||||
module: ModuleDescriptor
|
||||
) : AnnotationAndConstantLoader<AnnotationDescriptor, CompileTimeConstant<*>> {
|
||||
private val deserializer = AnnotationDeserializer(module)
|
||||
|
||||
override fun loadClassAnnotations(
|
||||
classProto: ProtoBuf.Class,
|
||||
nameResolver: NameResolver
|
||||
): List<AnnotationDescriptor> {
|
||||
val annotations = classProto.getExtension(BuiltInsProtoBuf.classAnnotation).orEmpty()
|
||||
return annotations.map { proto -> deserializer.deserializeAnnotation(proto, nameResolver) }
|
||||
}
|
||||
|
||||
override fun loadCallableAnnotations(
|
||||
container: ProtoContainer,
|
||||
proto: ProtoBuf.Callable,
|
||||
nameResolver: NameResolver,
|
||||
kind: AnnotatedCallableKind
|
||||
): List<AnnotationDescriptor> {
|
||||
val annotations = proto.getExtension(BuiltInsProtoBuf.callableAnnotation).orEmpty()
|
||||
return annotations.map { proto -> deserializer.deserializeAnnotation(proto, nameResolver) }
|
||||
}
|
||||
|
||||
override fun loadValueParameterAnnotations(
|
||||
container: ProtoContainer,
|
||||
callable: ProtoBuf.Callable,
|
||||
nameResolver: NameResolver,
|
||||
kind: AnnotatedCallableKind,
|
||||
proto: ProtoBuf.Callable.ValueParameter
|
||||
): List<AnnotationDescriptor> {
|
||||
val annotations = proto.getExtension(BuiltInsProtoBuf.parameterAnnotation).orEmpty()
|
||||
return annotations.map { proto -> deserializer.deserializeAnnotation(proto, nameResolver) }
|
||||
}
|
||||
|
||||
override fun loadPropertyConstant(
|
||||
container: ProtoContainer,
|
||||
proto: ProtoBuf.Callable,
|
||||
nameResolver: NameResolver,
|
||||
kind: AnnotatedCallableKind
|
||||
): CompileTimeConstant<*>? {
|
||||
// TODO: support deserialization of compile time constants in built-ins when needed
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.jet.lang.types.lang
|
||||
|
||||
import org.jetbrains.jet.descriptors.serialization.*
|
||||
import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationAndConstantLoader
|
||||
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPackageMemberScope
|
||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.PackageFragmentProvider
|
||||
@@ -59,7 +58,8 @@ public class BuiltinsPackageFragment(
|
||||
proto,
|
||||
nameResolver,
|
||||
DeserializationComponents(
|
||||
storageManager, module, BuiltInsClassDataFinder(), AnnotationAndConstantLoader.UNSUPPORTED, // TODO: support annotations
|
||||
storageManager, module, BuiltInsClassDataFinder(),
|
||||
BuiltInsAnnotationAndConstantLoader(getContainingDeclaration()),
|
||||
provider, FlexibleTypeCapabilitiesDeserializer.ThrowException
|
||||
),
|
||||
{ readClassNames(proto) }
|
||||
@@ -99,7 +99,7 @@ public class BuiltinsPackageFragment(
|
||||
val metadataPath = BuiltInsSerializationUtil.getClassMetadataPath(classId) ?: return null
|
||||
val stream = loadResource(metadataPath) ?: return null
|
||||
|
||||
val classProto = ProtoBuf.Class.parseFrom(stream)
|
||||
val classProto = ProtoBuf.Class.parseFrom(stream, extensionRegistry)
|
||||
|
||||
val expectedShortName = classId.getRelativeClassName().shortName()
|
||||
val actualShortName = nameResolver.getClassId(classProto.getFqName()).getRelativeClassName().shortName()
|
||||
|
||||
@@ -25,3 +25,15 @@ extend Package {
|
||||
// id in StringTable
|
||||
repeated int32 class_name = 150 [packed = true];
|
||||
}
|
||||
|
||||
extend Class {
|
||||
repeated Annotation class_annotation = 150;
|
||||
}
|
||||
|
||||
extend Callable {
|
||||
repeated Annotation callable_annotation = 150;
|
||||
}
|
||||
|
||||
extend Callable.ValueParameter {
|
||||
repeated Annotation parameter_annotation = 150;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,62 @@ message QualifiedNameTable {
|
||||
repeated QualifiedName qualified_name = 1;
|
||||
}
|
||||
|
||||
message Annotation {
|
||||
message Argument {
|
||||
message Value {
|
||||
enum Type {
|
||||
BYTE = 0;
|
||||
CHAR = 1;
|
||||
SHORT = 2;
|
||||
INT = 3;
|
||||
LONG = 4;
|
||||
FLOAT = 5;
|
||||
DOUBLE = 6;
|
||||
BOOLEAN = 7;
|
||||
|
||||
STRING = 8;
|
||||
CLASS = 9;
|
||||
ENUM = 10;
|
||||
ANNOTATION = 11;
|
||||
ARRAY = 12;
|
||||
}
|
||||
|
||||
// Note: a *Value* has a Type, not an Argument! This is done for future language features which may involve using arrays
|
||||
// of elements of different types. Such entries are allowed in the constant pool of JVM class files.
|
||||
// However, to save space, this field is optional: in case of homogeneous arrays, only the type of the first element is required
|
||||
optional Type type = 1;
|
||||
|
||||
// Only one of the following values should be present. Consider using `oneof` instead when we upgrade to protobuf 2.6.0+
|
||||
|
||||
optional sint64 int_value = 2;
|
||||
optional float float_value = 3;
|
||||
optional double double_value = 4;
|
||||
|
||||
// id in StringTable
|
||||
optional int32 string_value = 5;
|
||||
|
||||
// If type = CLASS, FQ name id of the referenced class; if type = ENUM, FQ name id of the enum class
|
||||
optional int32 class_id = 6;
|
||||
|
||||
// id in StringTable
|
||||
optional int32 enum_value_id = 7;
|
||||
|
||||
optional Annotation annotation = 8;
|
||||
|
||||
repeated Value array_element = 9;
|
||||
}
|
||||
|
||||
// id in StringTable
|
||||
required int32 name_id = 1;
|
||||
required Value value = 2;
|
||||
}
|
||||
|
||||
// Class FQ name id
|
||||
required int32 id = 1;
|
||||
|
||||
repeated Argument argument = 2;
|
||||
}
|
||||
|
||||
message Type {
|
||||
message Constructor {
|
||||
enum Kind {
|
||||
@@ -151,6 +207,8 @@ message Class {
|
||||
// This field is present if and only if the class has a primary constructor
|
||||
optional PrimaryConstructor primary_constructor = 13;
|
||||
// todo: other constructors?
|
||||
|
||||
extensions 100 to 199;
|
||||
}
|
||||
|
||||
message Package {
|
||||
@@ -189,7 +247,7 @@ message Callable {
|
||||
optional int32 flags = 1;
|
||||
optional string extra_visibility = 2; // for things like java-specific visibilities
|
||||
|
||||
/*
|
||||
/*
|
||||
isNotDefault
|
||||
Visibility
|
||||
Modality
|
||||
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.jet.descriptors.serialization
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation
|
||||
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation.Argument
|
||||
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation.Argument.Value
|
||||
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation.Argument.Value.Type
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import org.jetbrains.jet.lang.resolve.constants.*
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.name.ClassId
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils
|
||||
import org.jetbrains.jet.lang.descriptors.ClassKind
|
||||
|
||||
public class AnnotationDeserializer(private val module: ModuleDescriptor) {
|
||||
private val builtIns: KotlinBuiltIns
|
||||
get() = module.builtIns
|
||||
|
||||
public fun deserializeAnnotation(proto: Annotation, nameResolver: NameResolver): AnnotationDescriptor {
|
||||
val annotationClass = resolveClass(nameResolver.getClassId(proto.getId()))
|
||||
|
||||
val arguments = if (proto.getArgumentCount() == 0 || ErrorUtils.isError(annotationClass)) {
|
||||
mapOf()
|
||||
}
|
||||
else {
|
||||
val parameterByName = annotationClass.getConstructors().single().getValueParameters().toMap { it.getName() }
|
||||
val arguments = proto.getArgumentList().map { resolveArgument(it, parameterByName, nameResolver) }.filterNotNull()
|
||||
arguments.toMap()
|
||||
}
|
||||
|
||||
return AnnotationDescriptorImpl(annotationClass.getDefaultType(), arguments)
|
||||
}
|
||||
|
||||
private fun resolveArgument(
|
||||
proto: Argument,
|
||||
parameterByName: Map<Name, ValueParameterDescriptor>,
|
||||
nameResolver: NameResolver
|
||||
): Pair<ValueParameterDescriptor, CompileTimeConstant<*>>? {
|
||||
val parameter = parameterByName[nameResolver.getName(proto.getNameId())] ?: return null
|
||||
return Pair(parameter, resolveValue(parameter.getType(), proto.getValue(), nameResolver))
|
||||
}
|
||||
|
||||
private fun resolveValue(
|
||||
expectedType: JetType,
|
||||
value: ProtoBuf.Annotation.Argument.Value,
|
||||
nameResolver: NameResolver
|
||||
): CompileTimeConstant<*> {
|
||||
val result = when (value.getType()) {
|
||||
Type.BYTE -> ByteValue(value.getIntValue().toByte(), true, true, true)
|
||||
Type.CHAR -> CharValue(value.getIntValue().toChar(), true, true, true)
|
||||
Type.SHORT -> ShortValue(value.getIntValue().toShort(), true, true, true)
|
||||
Type.INT -> IntValue(value.getIntValue().toInt(), true, true, true)
|
||||
Type.LONG -> LongValue(value.getIntValue(), true, true, true)
|
||||
Type.FLOAT -> FloatValue(value.getFloatValue(), true, true)
|
||||
Type.DOUBLE -> DoubleValue(value.getDoubleValue(), true, true)
|
||||
Type.BOOLEAN -> BooleanValue(value.getIntValue() != 0L, true, true)
|
||||
Type.STRING -> {
|
||||
StringValue(nameResolver.getString(value.getStringValue()), true, true)
|
||||
}
|
||||
Type.CLASS -> {
|
||||
// TODO: support class literals
|
||||
error("Class literal annotation arguments are not supported yet (${nameResolver.getClassId(value.getClassId())})")
|
||||
}
|
||||
Type.ENUM -> {
|
||||
resolveEnumValue(nameResolver.getClassId(value.getClassId()), nameResolver.getName(value.getEnumValueId()))
|
||||
}
|
||||
Type.ANNOTATION -> {
|
||||
AnnotationValue(deserializeAnnotation(value.getAnnotation(), nameResolver))
|
||||
}
|
||||
Type.ARRAY -> {
|
||||
if (!KotlinBuiltIns.isArray(expectedType) &&
|
||||
!KotlinBuiltIns.isPrimitiveArray(expectedType)) return ErrorValue.create("Unexpected argument value")
|
||||
|
||||
val arrayElements = value.getArrayElementList()
|
||||
|
||||
val actualArrayType =
|
||||
if (arrayElements.isNotEmpty()) {
|
||||
val actualElementType = resolveArrayElementType(arrayElements.first(), nameResolver)
|
||||
builtIns.getPrimitiveArrayJetTypeByPrimitiveJetType(actualElementType) ?: builtIns.getArrayType(actualElementType)
|
||||
}
|
||||
else {
|
||||
// In the case of empty array, no element has the element type, so we fall back to the expected type.
|
||||
// This is not very accurate when annotation class has been changed without recompiling clients,
|
||||
// but should not in fact matter because the value is empty anyway
|
||||
expectedType
|
||||
}
|
||||
|
||||
val expectedElementType = builtIns.getArrayElementType(expectedType)
|
||||
|
||||
ArrayValue(
|
||||
arrayElements.map { resolveValue(expectedElementType, it, nameResolver) },
|
||||
actualArrayType,
|
||||
true, true
|
||||
)
|
||||
}
|
||||
else -> error("Unsupported annotation argument type: ${value.getType()} (expected $expectedType)")
|
||||
}
|
||||
|
||||
if (result.getType(builtIns) != expectedType) {
|
||||
// This means that an annotation class has been changed incompatibly without recompiling clients
|
||||
return ErrorValue.create("Unexpected argument value")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// NOTE: see analogous code in BinaryClassAnnotationAndConstantLoaderImpl
|
||||
private fun resolveEnumValue(enumClassId: ClassId, enumEntryName: Name): CompileTimeConstant<*> {
|
||||
val enumClass = resolveClass(enumClassId)
|
||||
if (enumClass.getKind() == ClassKind.ENUM_CLASS) {
|
||||
val enumEntry = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(enumEntryName)
|
||||
if (enumEntry is ClassDescriptor) {
|
||||
return EnumValue(enumEntry, true)
|
||||
}
|
||||
}
|
||||
return ErrorValue.create("Unresolved enum entry: $enumClassId.$enumEntryName")
|
||||
}
|
||||
|
||||
private fun resolveArrayElementType(value: Value, nameResolver: NameResolver): JetType =
|
||||
with(builtIns) {
|
||||
when (value.getType()) {
|
||||
Type.BYTE -> getByteType()
|
||||
Type.CHAR -> getCharType()
|
||||
Type.SHORT -> getShortType()
|
||||
Type.INT -> getIntType()
|
||||
Type.LONG -> getLongType()
|
||||
Type.FLOAT -> getFloatType()
|
||||
Type.DOUBLE -> getDoubleType()
|
||||
Type.BOOLEAN -> getBooleanType()
|
||||
Type.STRING -> getStringType()
|
||||
Type.CLASS -> error("Arrays of class literals are not supported yet") // TODO: support arrays of class literals
|
||||
Type.ENUM -> resolveClass(nameResolver.getClassId(value.getClassId())).getDefaultType()
|
||||
Type.ANNOTATION -> resolveClass(nameResolver.getClassId(value.getAnnotation().getId())).getDefaultType()
|
||||
Type.ARRAY -> error("Array of arrays is impossible")
|
||||
else -> error("Unknown type: ${value.getType()}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveClass(classId: ClassId): ClassDescriptor {
|
||||
return module.findClassAcrossModuleDependencies(classId)
|
||||
?: ErrorUtils.createErrorClass(classId.asSingleFqName().asString())
|
||||
}
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.jet.descriptors.serialization
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor
|
||||
import org.jetbrains.jet.lang.resolve.constants.*
|
||||
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation.Argument.Value
|
||||
import org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation.Argument.Value.Type
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
|
||||
public object AnnotationSerializer {
|
||||
public fun serializeAnnotation(annotation: AnnotationDescriptor, stringTable: StringTable): ProtoBuf.Annotation {
|
||||
return with(ProtoBuf.Annotation.newBuilder()) {
|
||||
val annotationClass = annotation.getType().getConstructor().getDeclarationDescriptor() as? ClassDescriptor
|
||||
?: error("Annotation type is not a class: ${annotation.getType()}")
|
||||
|
||||
setId(stringTable.getFqNameIndex(annotationClass))
|
||||
|
||||
for ((parameter, value) in annotation.getAllValueArguments()) {
|
||||
val argument = ProtoBuf.Annotation.Argument.newBuilder()
|
||||
argument.setNameId(stringTable.getSimpleNameIndex(parameter.getName()))
|
||||
argument.setValue(valueProto(value, parameter.getType(), stringTable))
|
||||
addArgument(argument)
|
||||
}
|
||||
|
||||
build()
|
||||
}
|
||||
}
|
||||
|
||||
fun valueProto(constant: CompileTimeConstant<*>, type: JetType, nameTable: StringTable): Value.Builder = with(Value.newBuilder()) {
|
||||
constant.accept(object : AnnotationArgumentVisitor<Unit, Unit> {
|
||||
override fun visitAnnotationValue(value: AnnotationValue, data: Unit) {
|
||||
setType(Type.ANNOTATION)
|
||||
setAnnotation(serializeAnnotation(value.getValue(), nameTable))
|
||||
}
|
||||
|
||||
override fun visitArrayValue(value: ArrayValue, data: Unit) {
|
||||
setType(Type.ARRAY)
|
||||
for (element in value.getValue()) {
|
||||
addArrayElement(valueProto(element, KotlinBuiltIns.getInstance().getArrayElementType(type), nameTable).build())
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitBooleanValue(value: BooleanValue, data: Unit) {
|
||||
setType(Type.BOOLEAN)
|
||||
setIntValue(if (value.getValue()) 1 else 0)
|
||||
}
|
||||
|
||||
override fun visitByteValue(value: ByteValue, data: Unit) {
|
||||
setType(Type.BYTE)
|
||||
setIntValue(value.getValue().toLong())
|
||||
}
|
||||
|
||||
override fun visitCharValue(value: CharValue, data: Unit) {
|
||||
setType(Type.CHAR)
|
||||
setIntValue(value.getValue().toLong())
|
||||
}
|
||||
|
||||
override fun visitDoubleValue(value: DoubleValue, data: Unit) {
|
||||
setType(Type.DOUBLE)
|
||||
setDoubleValue(value.getValue())
|
||||
}
|
||||
|
||||
override fun visitEnumValue(value: EnumValue, data: Unit) {
|
||||
setType(Type.ENUM)
|
||||
val enumEntry = value.getValue()
|
||||
setClassId(nameTable.getFqNameIndex(enumEntry.getContainingDeclaration() as ClassDescriptor))
|
||||
setEnumValueId(nameTable.getSimpleNameIndex(enumEntry.getName()))
|
||||
}
|
||||
|
||||
override fun visitErrorValue(value: ErrorValue, data: Unit) {
|
||||
throw UnsupportedOperationException("Error value: $value")
|
||||
}
|
||||
|
||||
override fun visitFloatValue(value: FloatValue, data: Unit) {
|
||||
setType(Type.FLOAT)
|
||||
setFloatValue(value.getValue())
|
||||
}
|
||||
|
||||
override fun visitIntValue(value: IntValue, data: Unit) {
|
||||
setType(Type.INT)
|
||||
setIntValue(value.getValue().toLong())
|
||||
}
|
||||
|
||||
override fun visitJavaClassValue(value: JavaClassValue, data: Unit) {
|
||||
// TODO: support class literals
|
||||
throw UnsupportedOperationException("Class literal annotation arguments are not yet supported: $value")
|
||||
}
|
||||
|
||||
override fun visitLongValue(value: LongValue, data: Unit) {
|
||||
setType(Type.LONG)
|
||||
setIntValue(value.getValue())
|
||||
}
|
||||
|
||||
override fun visitNullValue(value: NullValue, data: Unit) {
|
||||
throw UnsupportedOperationException("Null should not appear in annotation arguments")
|
||||
}
|
||||
|
||||
override fun visitNumberTypeValue(constant: IntegerValueTypeConstant, data: Unit) {
|
||||
// TODO: IntegerValueTypeConstant should not occur in annotation arguments
|
||||
val number = constant.getValue(type)
|
||||
val specificConstant = with(KotlinBuiltIns.getInstance()) {
|
||||
when (type) {
|
||||
getLongType() -> LongValue(number.toLong(), true, true, true)
|
||||
getIntType() -> IntValue(number.toInt(), true, true, true)
|
||||
getShortType() -> ShortValue(number.toShort(), true, true, true)
|
||||
getByteType() -> ByteValue(number.toByte(), true, true, true)
|
||||
else -> throw IllegalStateException("Integer constant $constant has non-integer type $type")
|
||||
}
|
||||
}
|
||||
|
||||
specificConstant.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitShortValue(value: ShortValue, data: Unit) {
|
||||
setType(Type.SHORT)
|
||||
setIntValue(value.getValue().toLong())
|
||||
}
|
||||
|
||||
override fun visitStringValue(value: StringValue, data: Unit) {
|
||||
setType(Type.STRING)
|
||||
setStringValue(nameTable.getStringIndex(value.getValue()))
|
||||
}
|
||||
}, Unit)
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
+48
@@ -8,6 +8,9 @@ public final class BuiltInsProtoBuf {
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistryLite registry) {
|
||||
registry.add(org.jetbrains.jet.descriptors.serialization.BuiltInsProtoBuf.className);
|
||||
registry.add(org.jetbrains.jet.descriptors.serialization.BuiltInsProtoBuf.classAnnotation);
|
||||
registry.add(org.jetbrains.jet.descriptors.serialization.BuiltInsProtoBuf.callableAnnotation);
|
||||
registry.add(org.jetbrains.jet.descriptors.serialization.BuiltInsProtoBuf.parameterAnnotation);
|
||||
}
|
||||
public static final int CLASS_NAME_FIELD_NUMBER = 150;
|
||||
/**
|
||||
@@ -24,6 +27,51 @@ public final class BuiltInsProtoBuf {
|
||||
150,
|
||||
com.google.protobuf.WireFormat.FieldType.INT32,
|
||||
true);
|
||||
public static final int CLASS_ANNOTATION_FIELD_NUMBER = 150;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.jet.descriptors.serialization.Class { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
com.google.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||
org.jetbrains.jet.descriptors.serialization.ProtoBuf.Class,
|
||||
java.util.List<org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation>> classAnnotation = com.google.protobuf.GeneratedMessageLite
|
||||
.newRepeatedGeneratedExtension(
|
||||
org.jetbrains.jet.descriptors.serialization.ProtoBuf.Class.getDefaultInstance(),
|
||||
org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation.getDefaultInstance(),
|
||||
null,
|
||||
150,
|
||||
com.google.protobuf.WireFormat.FieldType.MESSAGE,
|
||||
false);
|
||||
public static final int CALLABLE_ANNOTATION_FIELD_NUMBER = 150;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.jet.descriptors.serialization.Callable { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
com.google.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||
org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable,
|
||||
java.util.List<org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation>> callableAnnotation = com.google.protobuf.GeneratedMessageLite
|
||||
.newRepeatedGeneratedExtension(
|
||||
org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.getDefaultInstance(),
|
||||
org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation.getDefaultInstance(),
|
||||
null,
|
||||
150,
|
||||
com.google.protobuf.WireFormat.FieldType.MESSAGE,
|
||||
false);
|
||||
public static final int PARAMETER_ANNOTATION_FIELD_NUMBER = 150;
|
||||
/**
|
||||
* <code>extend .org.jetbrains.jet.descriptors.serialization.Callable.ValueParameter { ... }</code>
|
||||
*/
|
||||
public static final
|
||||
com.google.protobuf.GeneratedMessageLite.GeneratedExtension<
|
||||
org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.ValueParameter,
|
||||
java.util.List<org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation>> parameterAnnotation = com.google.protobuf.GeneratedMessageLite
|
||||
.newRepeatedGeneratedExtension(
|
||||
org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable.ValueParameter.getDefaultInstance(),
|
||||
org.jetbrains.jet.descriptors.serialization.ProtoBuf.Annotation.getDefaultInstance(),
|
||||
null,
|
||||
150,
|
||||
com.google.protobuf.WireFormat.FieldType.MESSAGE,
|
||||
false);
|
||||
|
||||
static {
|
||||
}
|
||||
|
||||
+2
@@ -135,6 +135,8 @@ public class DescriptorSerializer {
|
||||
builder.setClassObject(classObjectProto(classObject));
|
||||
}
|
||||
|
||||
extension.serializeClass(classDescriptor, builder, stringTable);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+8
@@ -18,12 +18,20 @@ package org.jetbrains.jet.descriptors.serialization;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class SerializerExtension {
|
||||
public void serializeClass(
|
||||
@NotNull ClassDescriptor descriptor,
|
||||
@NotNull ProtoBuf.Class.Builder proto,
|
||||
@NotNull StringTable stringTable
|
||||
) {
|
||||
}
|
||||
|
||||
public void serializePackage(
|
||||
@NotNull Collection<PackageFragmentDescriptor> packageFragments,
|
||||
@NotNull ProtoBuf.Package.Builder proto,
|
||||
|
||||
-53
@@ -20,63 +20,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.descriptors.serialization.NameResolver;
|
||||
import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface AnnotationAndConstantLoader<A, C> {
|
||||
AnnotationAndConstantLoader<AnnotationDescriptor, CompileTimeConstant<?>> UNSUPPORTED =
|
||||
new AnnotationAndConstantLoader<AnnotationDescriptor, CompileTimeConstant<?>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<AnnotationDescriptor> loadClassAnnotations(
|
||||
@NotNull ProtoBuf.Class classProto,
|
||||
@NotNull NameResolver nameResolver
|
||||
) {
|
||||
return annotationsNotSupported();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<AnnotationDescriptor> loadCallableAnnotations(
|
||||
@NotNull ProtoContainer container,
|
||||
@NotNull ProtoBuf.Callable proto,
|
||||
@NotNull NameResolver nameResolver,
|
||||
@NotNull AnnotatedCallableKind kind
|
||||
) {
|
||||
return annotationsNotSupported();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<AnnotationDescriptor> loadValueParameterAnnotations(
|
||||
@NotNull ProtoContainer container,
|
||||
@NotNull ProtoBuf.Callable callable,
|
||||
@NotNull NameResolver nameResolver,
|
||||
@NotNull AnnotatedCallableKind kind,
|
||||
@NotNull ProtoBuf.Callable.ValueParameter proto
|
||||
) {
|
||||
return annotationsNotSupported();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CompileTimeConstant<?> loadPropertyConstant(
|
||||
@NotNull ProtoContainer container,
|
||||
@NotNull ProtoBuf.Callable proto,
|
||||
@NotNull NameResolver nameResolver,
|
||||
@NotNull AnnotatedCallableKind kind
|
||||
) {
|
||||
throw new UnsupportedOperationException("Constants are not supported");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<AnnotationDescriptor> annotationsNotSupported() {
|
||||
throw new UnsupportedOperationException("Annotations are not supported");
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
List<A> loadClassAnnotations(
|
||||
@NotNull ProtoBuf.Class classProto,
|
||||
|
||||
Reference in New Issue
Block a user