Don't serialize non-serializable types
If there's a private property in a class which has a type of some local class/object, write its type as jet.Any (otherwise there's no obvious way to construct a FQ name of such type)
This commit is contained in:
@@ -61,10 +61,8 @@ import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.utils.ExceptionUtils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
@@ -213,21 +211,23 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
|
||||
|
||||
writeKotlinInfoIfNeeded();
|
||||
if (isTopLevelOrInnerClass(descriptor)) {
|
||||
writeKotlinInfo();
|
||||
}
|
||||
|
||||
writeClassSignatureIfNeeded(signature);
|
||||
}
|
||||
|
||||
private void writeKotlinInfoIfNeeded() {
|
||||
if (!(descriptor.getContainingDeclaration() instanceof ClassOrNamespaceDescriptor)) return;
|
||||
|
||||
private void writeKotlinInfo() {
|
||||
final AnnotationVisitor av = v.getVisitor().visitAnnotation("Ljet/KotlinInfo;", true);
|
||||
DescriptorSerializer serializer = new DescriptorSerializer(DescriptorNamer.DEFAULT);
|
||||
|
||||
ClassSerializationUtil.serializeClass(descriptor, constantSerializer(serializer), new ClassSerializationUtil.Sink() {
|
||||
@Override
|
||||
public void writeClass(@NotNull ClassDescriptor classDescriptor, @NotNull ProtoBuf.Class classProto) {
|
||||
av.visit("data", classProto.toByteArray());
|
||||
if (classDescriptor == descriptor) {
|
||||
av.visit("data", classProto.toByteArray());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+33
-1
@@ -22,10 +22,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTopLevelOrInnerClass;
|
||||
|
||||
public class DescriptorSerializer {
|
||||
|
||||
private static final DescriptorRenderer RENDERER = DescriptorRenderer.STARTS_FROM_NAME;
|
||||
@@ -193,11 +196,40 @@ public class DescriptorSerializer {
|
||||
builder.addValueParameters(local.valueParameter(valueParameterDescriptor));
|
||||
}
|
||||
|
||||
builder.setReturnType(local.type(descriptor.getReturnType()));
|
||||
builder.setReturnType(local.type(getSerializableReturnType(descriptor.getReturnType())));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JetType getSerializableReturnType(@NotNull JetType type) {
|
||||
return isSerializableType(type) ? type : KotlinBuiltIns.getInstance().getAnyType();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true iff this type can be serialized. Types which correspond to type parameters, top-level classes, inner classes, and
|
||||
* generic classes with serializable arguments are serializable. For other types (local classes, inner of local, etc.) it may be
|
||||
* problematical to construct a FQ name for serialization
|
||||
*/
|
||||
private static boolean isSerializableType(@NotNull JetType type) {
|
||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor instanceof TypeParameterDescriptor) {
|
||||
return true;
|
||||
}
|
||||
else if (descriptor instanceof ClassDescriptor) {
|
||||
for (TypeProjection projection : type.getArguments()) {
|
||||
if (!isSerializableType(projection.getType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return isTopLevelOrInnerClass((ClassDescriptor) descriptor);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unknown type constructor: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getAccessorFlags(@NotNull PropertyAccessorDescriptor accessor) {
|
||||
return Flags.getAccessorFlags(
|
||||
hasAnnotations(accessor),
|
||||
|
||||
@@ -598,4 +598,13 @@ public class DescriptorUtils {
|
||||
assert descriptor != null;
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true iff {@code descriptor}'s first non-class container is a namespace
|
||||
*/
|
||||
public static boolean isTopLevelOrInnerClass(@NotNull ClassDescriptor descriptor) {
|
||||
DeclarationDescriptor containing = descriptor.getContainingDeclaration();
|
||||
return isTopLevelDeclaration(descriptor) ||
|
||||
containing instanceof ClassDescriptor && isTopLevelOrInnerClass((ClassDescriptor) containing);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user