Implement raw types (de)serialization via special TypeCapabilities

This commit is contained in:
Denis Zharkov
2015-08-03 17:52:05 +03:00
parent 3593356e1a
commit 32c23728b3
21 changed files with 215 additions and 21 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.load.java.lazy.types.RawTypeCapabilities;
import org.jetbrains.kotlin.load.kotlin.SignatureDeserializer;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
@@ -89,6 +90,10 @@ public class JvmSerializerExtension extends SerializerExtension {
for (AnnotationDescriptor annotation : type.getAnnotations()) {
proto.addExtension(JvmProtoBuf.typeAnnotation, annotationSerializer.serializeAnnotation(annotation, stringTable));
}
if (type.getCapabilities() instanceof RawTypeCapabilities) {
proto.setExtension(JvmProtoBuf.isRaw, true);
}
}
@Override
@@ -0,0 +1,9 @@
package test;
import java.util.*;
public class A<T> {
A<List<T>> bar(List<Map<String, Integer>> x) { return null; }
static A rawField = null;
}
@@ -0,0 +1,7 @@
package test
val strList: List<String> = null!!
fun foo1() = A.rawField
val foo2 = A.rawField.bar(strList).bar(strList)
@@ -0,0 +1,4 @@
package test
fun foo3() = foo1().bar(strList)
val foo4 = foo2.bar(strList)
@@ -0,0 +1,2 @@
OK
OK
@@ -141,6 +141,36 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
}
}
public void testRawTypes() throws Exception {
JetTestUtils.compileJavaFiles(
Collections.singletonList(
new File(getTestDataDirectory() + "/library/test/A.java")
),
Arrays.asList("-d", tmpdir.getPath())
);
File libSrc = new File(getTestDataDirectory(), "library/test/lib.kt");
Pair<String, ExitCode> pair1 = CliBaseTest.executeCompilerGrabOutput(new K2JVMCompiler(), Arrays.asList(
libSrc.getPath(),
"-classpath", tmpdir.getPath(),
"-d", tmpdir.getPath()
));
String outputLib = CliBaseTest.getNormalizedCompilerOutput(pair1.first, pair1.second, getTestDataDirectory().getPath());
File mainSrc = new File(getTestDataDirectory(), "main.kt");
Pair<String, ExitCode> pair2 = CliBaseTest.executeCompilerGrabOutput(new K2JVMCompiler(), Arrays.asList(
mainSrc.getPath(),
"-classpath", tmpdir.getPath(),
"-d", tmpdir.getPath()
));
String outputMain = CliBaseTest.getNormalizedCompilerOutput(pair2.first, pair2.second, getTestDataDirectory().getPath());
JetTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), outputLib + "\n" + outputMain);
}
public void testDuplicateObjectInBinaryAndSources() throws Exception {
Collection<DeclarationDescriptor> allDescriptors = analyzeAndGetAllDescriptors(compileLibrary("library"));
@@ -11,6 +11,7 @@ public final class DebugJvmProtoBuf {
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.propertySignature);
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.implClassName);
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.typeAnnotation);
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.isRaw);
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.index);
registry.add(org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf.classAnnotation);
}
@@ -3775,6 +3776,17 @@ public final class DebugJvmProtoBuf {
.newFileScopedGeneratedExtension(
org.jetbrains.kotlin.serialization.DebugProtoBuf.Annotation.class,
org.jetbrains.kotlin.serialization.DebugProtoBuf.Annotation.getDefaultInstance());
public static final int IS_RAW_FIELD_NUMBER = 101;
/**
* <code>extend .org.jetbrains.kotlin.serialization.Type { ... }</code>
*/
public static final
com.google.protobuf.GeneratedMessage.GeneratedExtension<
org.jetbrains.kotlin.serialization.DebugProtoBuf.Type,
java.lang.Boolean> isRaw = com.google.protobuf.GeneratedMessage
.newFileScopedGeneratedExtension(
java.lang.Boolean.class,
null);
public static final int INDEX_FIELD_NUMBER = 100;
/**
* <code>extend .org.jetbrains.kotlin.serialization.Callable.ValueParameter { ... }</code>
@@ -3865,13 +3877,14 @@ public final class DebugJvmProtoBuf {
"otlin.serialization.Callable\030f \001(\005B\004\210\265\030\001" +
":q\n\017type_annotation\022(.org.jetbrains.kotl" +
"in.serialization.Type\030d \003(\0132..org.jetbra" +
"ins.kotlin.serialization.Annotation:J\n\005i",
"ndex\022;.org.jetbrains.kotlin.serializatio" +
"n.Callable.ValueParameter\030d \001(\005:s\n\020class" +
"_annotation\022).org.jetbrains.kotlin.seria" +
"lization.Class\030d \003(\0132..org.jetbrains.kot" +
"lin.serialization.AnnotationB\022B\020DebugJvm" +
"ProtoBuf"
"ins.kotlin.serialization.Annotation:8\n\006i",
"s_raw\022(.org.jetbrains.kotlin.serializati" +
"on.Type\030e \001(\010:J\n\005index\022;.org.jetbrains.k" +
"otlin.serialization.Callable.ValueParame" +
"ter\030d \001(\005:s\n\020class_annotation\022).org.jetb" +
"rains.kotlin.serialization.Class\030d \003(\0132." +
".org.jetbrains.kotlin.serialization.Anno" +
"tationB\022B\020DebugJvmProtoBuf"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -3906,8 +3919,9 @@ public final class DebugJvmProtoBuf {
propertySignature.internalInit(descriptor.getExtensions().get(1));
implClassName.internalInit(descriptor.getExtensions().get(2));
typeAnnotation.internalInit(descriptor.getExtensions().get(3));
index.internalInit(descriptor.getExtensions().get(4));
classAnnotation.internalInit(descriptor.getExtensions().get(5));
isRaw.internalInit(descriptor.getExtensions().get(4));
index.internalInit(descriptor.getExtensions().get(5));
classAnnotation.internalInit(descriptor.getExtensions().get(6));
com.google.protobuf.ExtensionRegistry registry =
com.google.protobuf.ExtensionRegistry.newInstance();
registry.add(org.jetbrains.kotlin.serialization.DebugExtOptionsProtoBuf.fqNameIdInTable);
@@ -88,6 +88,7 @@ extend org.jetbrains.kotlin.serialization.Callable {
extend org.jetbrains.kotlin.serialization.Type {
repeated Annotation type_annotation = 100;
optional bool is_raw = 101;
}
extend org.jetbrains.kotlin.serialization.Callable.ValueParameter {
@@ -259,8 +259,8 @@ class LazyJavaTypeResolver(
}
}
override fun computeCustomSubstitution() = if (isRaw()) RawSubstitution else null
override fun getCapabilities(): TypeCapabilities = if (isRaw()) RawTypeCapabilities else TypeCapabilities.NONE
private val nullable = c.storageManager.createLazyValue l@ {
when (attr.flexibility) {
FLEXIBLE_LOWER_BOUND -> return@l false
@@ -22,6 +22,20 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.load.java.components.TypeUsage
import org.jetbrains.kotlin.types.*
public object RawTypeCapabilities : TypeCapabilities {
private object RawSubstitutionCapability : CustomSubstitutionCapability {
override val substitution = RawSubstitution
}
override fun <T : TypeCapability> getCapability(capabilityClass: Class<T>): T? {
@suppress("UNCHECKED_CAST")
return when(capabilityClass) {
javaClass<CustomSubstitutionCapability>() -> RawSubstitutionCapability as T
else -> null
}
}
}
private object RawSubstitution : TypeSubstitution() {
override fun get(key: JetType) = TypeProjectionImpl(eraseType(key))
@@ -64,7 +78,8 @@ private object RawSubstitution : TypeSubstitution() {
computeProjection(parameter, attr)
},
RawSubstitution,
declaration.getMemberScope(RawSubstitution)
declaration.getMemberScope(RawSubstitution),
RawTypeCapabilities
)
}
@@ -110,7 +110,8 @@ private fun JetType.enhanceInflexible(qualifiers: (Int) -> JavaTypeQualifiers, i
newSubstitution,
if (enhancedClassifier is ClassDescriptor)
enhancedClassifier.getMemberScope(newSubstitution)
else enhancedClassifier.getDefaultType().getMemberScope()
else enhancedClassifier.getDefaultType().getMemberScope(),
capabilities
)
return Result(enhancedType, globalArgIndex - index)
}
@@ -38,7 +38,7 @@ public class DeserializationComponentsForJava(
val localClassResolver = LocalClassResolverImpl()
components = DeserializationComponents(
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider,
localClassResolver, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY
localClassResolver, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY, JavaTypeCapabilitiesLoader
)
localClassResolver.setDeserializationComponents(components)
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.load.java.lazy.types.RawTypeCapabilities
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.TypeCapabilitiesLoader
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
import org.jetbrains.kotlin.types.TypeCapabilities
public object JavaTypeCapabilitiesLoader : TypeCapabilitiesLoader() {
override fun loadCapabilities(type: ProtoBuf.Type): TypeCapabilities =
if (type.hasExtension(JvmProtoBuf.isRaw)) RawTypeCapabilities else TypeCapabilities.NONE
}
@@ -11,6 +11,7 @@ public final class JvmProtoBuf {
registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.propertySignature);
registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.implClassName);
registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.typeAnnotation);
registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.isRaw);
registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.index);
registry.add(org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.classAnnotation);
}
@@ -2866,6 +2867,21 @@ public final class JvmProtoBuf {
100,
com.google.protobuf.WireFormat.FieldType.MESSAGE,
false);
public static final int IS_RAW_FIELD_NUMBER = 101;
/**
* <code>extend .org.jetbrains.kotlin.serialization.Type { ... }</code>
*/
public static final
com.google.protobuf.GeneratedMessageLite.GeneratedExtension<
org.jetbrains.kotlin.serialization.ProtoBuf.Type,
java.lang.Boolean> isRaw = com.google.protobuf.GeneratedMessageLite
.newSingularGeneratedExtension(
org.jetbrains.kotlin.serialization.ProtoBuf.Type.getDefaultInstance(),
false,
null,
null,
101,
com.google.protobuf.WireFormat.FieldType.BOOL);
public static final int INDEX_FIELD_NUMBER = 100;
/**
* <code>extend .org.jetbrains.kotlin.serialization.Callable.ValueParameter { ... }</code>
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -34,7 +36,7 @@ public abstract class AbstractLazyType(storageManager: StorageManager) : Abstrac
override fun getSubstitution() = computeCustomSubstitution() ?: IndexedParametersSubstitution(constructor, getArguments())
protected open fun computeCustomSubstitution(): TypeSubstitution? = null
protected open fun computeCustomSubstitution(): TypeSubstitution? = getCapability<CustomSubstitutionCapability>()?.substitution
private val memberScope = storageManager.createLazyValue { computeMemberScope() }
override fun getMemberScope() = memberScope()
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.scopes.JetScope
import kotlin.platform.platformStatic
public class JetTypeImpl
public open class JetTypeImpl
private constructor(
private val annotations: Annotations,
private val constructor: TypeConstructor,
@@ -47,9 +47,14 @@ private constructor(
nullable: Boolean,
arguments: List<TypeProjection>,
substitution: TypeSubstitution,
memberScope: JetScope): JetTypeImpl
= JetTypeImpl(annotations, constructor, nullable, arguments, substitution, memberScope)
memberScope: JetScope,
capabilities: TypeCapabilities
): JetTypeImpl {
if (capabilities !== TypeCapabilities.NONE) {
return WithCapabilities(annotations, constructor, nullable, arguments, substitution, memberScope, capabilities)
}
return JetTypeImpl(annotations, constructor, nullable, arguments, substitution, memberScope)
}
@platformStatic
public fun create(annotations: Annotations,
@@ -62,6 +67,18 @@ private constructor(
)
}
private class WithCapabilities(
annotations: Annotations,
constructor: TypeConstructor,
nullable: Boolean,
arguments: List<TypeProjection>,
substitution: TypeSubstitution?,
memberScope: JetScope,
private val typeCapabilities: TypeCapabilities
) : JetTypeImpl(annotations, constructor, nullable, arguments, substitution, memberScope) {
override fun getCapabilities(): TypeCapabilities = typeCapabilities
}
init {
if (memberScope is ErrorUtils.ErrorScope) {
throw IllegalStateException("JetTypeImpl should not be created for error type: $memberScope\n$constructor")
@@ -27,6 +27,9 @@ public interface TypeCapabilities {
fun <T : TypeCapability> getCapability(capabilityClass: Class<T>): T?
}
public inline fun <reified T : TypeCapability> JetType.getCapability(): T? = getCapability(javaClass<T>())
public interface Specificity : TypeCapability {
public enum class Relation {
@@ -81,3 +84,7 @@ public fun sameTypeConstructors(first: JetType, second: JetType): Boolean {
return first.getCapability(typeRangeCapability)?.sameTypeConstructor(second) ?: false
|| second.getCapability(typeRangeCapability)?.sameTypeConstructor(first) ?: false
}
interface CustomSubstitutionCapability : TypeCapability {
public val substitution: TypeSubstitution
}
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.types.LazyType
import org.jetbrains.kotlin.utils.toReadOnlyList
class DeserializedType(
c: DeserializationContext,
private val c: DeserializationContext,
private val typeProto: ProtoBuf.Type
) : AbstractLazyType(c.storageManager), LazyType {
private val typeDeserializer = c.typeDeserializer
@@ -51,6 +51,8 @@ class DeserializedType(
override fun getAnnotations(): Annotations = annotations
override fun getCapabilities() = c.components.typeCapabilitiesLoader.loadCapabilities(typeProto)
private fun <E: Any> List<E>.getOrNull(index: Int): E? {
return if (index in indices) this[index] else null
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.types.TypeCapabilities
public abstract class TypeCapabilitiesLoader {
public object NONE : TypeCapabilitiesLoader() {
override fun loadCapabilities(type: ProtoBuf.Type): TypeCapabilities = TypeCapabilities.NONE
}
public abstract fun loadCapabilities(type: ProtoBuf.Type): TypeCapabilities
}
@@ -31,7 +31,8 @@ public class DeserializationComponents(
public val packageFragmentProvider: PackageFragmentProvider,
public val localClassResolver: LocalClassResolver,
public val flexibleTypeCapabilitiesDeserializer: FlexibleTypeCapabilitiesDeserializer,
public val fictitiousClassDescriptorFactory: ClassDescriptorFactory
public val fictitiousClassDescriptorFactory: ClassDescriptorFactory,
public val typeCapabilitiesLoader: TypeCapabilitiesLoader = TypeCapabilitiesLoader.NONE
) {
public val classDeserializer: ClassDeserializer = ClassDeserializer(this)
@@ -177,6 +177,11 @@ open class ProtoCompareGenerated(private val oldNameResolver: NameResolver, priv
}
if (old.hasExtension(JvmProtoBuf.isRaw) != new.hasExtension(JvmProtoBuf.isRaw)) return false
if (old.hasExtension(JvmProtoBuf.isRaw)) {
if (old.getExtension(JvmProtoBuf.isRaw) != new.getExtension(JvmProtoBuf.isRaw)) return false
}
return true
}