Implement raw types (de)serialization via special TypeCapabilities
This commit is contained in:
@@ -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
|
||||
|
||||
+9
@@ -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;
|
||||
}
|
||||
+7
@@ -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
|
||||
+30
@@ -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 {
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+16
-1
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -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)
|
||||
}
|
||||
|
||||
+1
-1
@@ -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)
|
||||
}
|
||||
|
||||
+28
@@ -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
|
||||
}
|
||||
+16
@@ -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
|
||||
}
|
||||
|
||||
+3
-1
@@ -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
|
||||
}
|
||||
|
||||
+28
@@ -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
|
||||
}
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user