Serialize compile time constant for property initializer

This commit is contained in:
Natalia Ukhorskaya
2014-02-06 14:53:13 +04:00
parent bb7312b47f
commit 9b5050dddd
23 changed files with 80 additions and 38 deletions
@@ -158,7 +158,7 @@ public class VirtualFileKotlinClass implements KotlinJvmBinaryClass {
new ClassReader(file.contentsToByteArray()).accept(new ClassVisitor(ASM4) { new ClassReader(file.contentsToByteArray()).accept(new ClassVisitor(ASM4) {
@Override @Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
final AnnotationVisitor v = memberVisitor.visitField(Name.guess(name), desc); final AnnotationVisitor v = memberVisitor.visitField(Name.guess(name), desc, value);
if (v == null) return null; if (v == null) return null;
return new FieldVisitor(ASM4) { return new FieldVisitor(ASM4) {
@@ -170,6 +170,7 @@ message Callable {
MemberKind MemberKind
hasGetter hasGetter
hasSetter hasSetter
hasConstant
*/ */
optional int32 flags = 1; optional int32 flags = 1;
optional string extra_visibility = 2; // for things like java-specific visibilities optional string extra_visibility = 2; // for things like java-specific visibilities
@@ -18,15 +18,13 @@ package org.jetbrains.jet.descriptors.serialization;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer; import org.jetbrains.jet.descriptors.serialization.descriptors.*;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedSimpleFunctionDescriptor;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedTypeParameterDescriptor;
import org.jetbrains.jet.descriptors.serialization.descriptors.Deserializers;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.impl.*; import org.jetbrains.jet.lang.descriptors.impl.*;
import org.jetbrains.jet.lang.resolve.DescriptorFactory; import org.jetbrains.jet.lang.resolve.DescriptorFactory;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.storage.StorageManager; import org.jetbrains.jet.storage.StorageManager;
@@ -195,6 +193,11 @@ public class DescriptorDeserializer {
} }
} }
property.setCompileTimeInitializer(
getPropertyConstant(containingDeclaration, proto, flags, AnnotatedCallableKind.PROPERTY,
deserializers.getConstantDeserializer(), nameResolver)
);
property.initialize(getter, setter); property.initialize(getter, setter);
return property; return property;
@@ -269,6 +272,23 @@ public class DescriptorDeserializer {
: Annotations.EMPTY; : Annotations.EMPTY;
} }
@Nullable
public static CompileTimeConstant<?> getPropertyConstant(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull Callable proto,
int flags,
@NotNull AnnotatedCallableKind kind,
@NotNull ConstantDeserializer constantDeserializer,
@NotNull NameResolver nameResolver
) {
assert containingDeclaration instanceof ClassOrPackageFragmentDescriptor
: "Only members in classes or package fragments should be serialized: " + containingDeclaration;
return Flags.HAS_CONSTANT.get(flags)
? constantDeserializer
.loadPropertyConstant((ClassOrPackageFragmentDescriptor) containingDeclaration, proto, nameResolver, kind)
: null;
}
public static CallableMemberDescriptor.Kind memberKind(Callable.MemberKind memberKind) { public static CallableMemberDescriptor.Kind memberKind(Callable.MemberKind memberKind) {
switch (memberKind) { switch (memberKind) {
case DECLARATION: case DECLARATION:
@@ -161,6 +161,7 @@ public class DescriptorSerializer {
boolean hasGetter = false; boolean hasGetter = false;
boolean hasSetter = false; boolean hasSetter = false;
boolean hasConstant = false;
if (descriptor instanceof PropertyDescriptor) { if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
@@ -194,6 +195,8 @@ public class DescriptorSerializer {
} }
} }
} }
hasConstant = propertyDescriptor.getCompileTimeInitializer() != null;
} }
builder.setFlags(Flags.getCallableFlags( builder.setFlags(Flags.getCallableFlags(
@@ -203,7 +206,8 @@ public class DescriptorSerializer {
descriptor.getKind(), descriptor.getKind(),
callableKind(descriptor), callableKind(descriptor),
hasGetter, hasGetter,
hasSetter hasSetter,
hasConstant
)); ));
//TODO builder.setExtraVisibility() //TODO builder.setExtraVisibility()
@@ -30,6 +30,7 @@ public class Flags {
ProtoBuf.Callable.MemberKind.values()); ProtoBuf.Callable.MemberKind.values());
public static final FlagField<Boolean> HAS_GETTER = FlagField.booleanAfter(MEMBER_KIND); public static final FlagField<Boolean> HAS_GETTER = FlagField.booleanAfter(MEMBER_KIND);
public static final FlagField<Boolean> HAS_SETTER = FlagField.booleanAfter(HAS_GETTER); public static final FlagField<Boolean> HAS_SETTER = FlagField.booleanAfter(HAS_GETTER);
public static final FlagField<Boolean> HAS_CONSTANT = FlagField.booleanAfter(HAS_SETTER);
// Parameters // Parameters
@@ -93,7 +94,8 @@ public class Flags {
@NotNull CallableMemberDescriptor.Kind memberKind, @NotNull CallableMemberDescriptor.Kind memberKind,
@NotNull ProtoBuf.Callable.CallableKind callableKind, @NotNull ProtoBuf.Callable.CallableKind callableKind,
boolean hasGetter, boolean hasGetter,
boolean hasSetter boolean hasSetter,
boolean hasConstant
) { ) {
return HAS_ANNOTATIONS.toFlags(hasAnnotations) return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| MODALITY.toFlags(modality(modality)) | MODALITY.toFlags(modality(modality))
@@ -102,6 +104,7 @@ public class Flags {
| CALLABLE_KIND.toFlags(callableKind) | CALLABLE_KIND.toFlags(callableKind)
| HAS_GETTER.toFlags(hasGetter) | HAS_GETTER.toFlags(hasGetter)
| HAS_SETTER.toFlags(hasSetter) | HAS_SETTER.toFlags(hasSetter)
| HAS_CONSTANT.toFlags(hasConstant)
; ;
} }
@@ -8,7 +8,7 @@ internal final class A {
internal class object <class-object-for-B> { internal class object <class-object-for-B> {
/*primary*/ private constructor <class-object-for-B>() /*primary*/ private constructor <class-object-for-B>()
internal final val TEST: kotlin.Int internal final val TEST: kotlin.Int = 1.toInt()
internal final fun <get-TEST>(): kotlin.Int internal final fun <get-TEST>(): kotlin.Int
} }
} }
@@ -1,6 +1,6 @@
package test package test
test.Anno(t = ElementType.FIELD: java.lang.annotation.ElementType) internal val bar: kotlin.Int test.Anno(t = ElementType.FIELD: java.lang.annotation.ElementType) internal val bar: kotlin.Int = 42.toInt()
internal fun <get-bar>(): kotlin.Int internal fun <get-bar>(): kotlin.Int
test.Anno(t = ElementType.METHOD: java.lang.annotation.ElementType) internal fun foo(): kotlin.Unit test.Anno(t = ElementType.METHOD: java.lang.annotation.ElementType) internal fun foo(): kotlin.Unit
@@ -2,12 +2,12 @@ package test
internal final class ConstructorTypeParamClassObjectConflict</*0*/ test> { internal final class ConstructorTypeParamClassObjectConflict</*0*/ test> {
/*primary*/ public constructor ConstructorTypeParamClassObjectConflict</*0*/ test>() /*primary*/ public constructor ConstructorTypeParamClassObjectConflict</*0*/ test>()
internal final val some: kotlin.Int internal final val some: kotlin.Int = 12.toInt()
internal final fun <get-some>(): kotlin.Int internal final fun <get-some>(): kotlin.Int
internal class object <class-object-for-ConstructorTypeParamClassObjectConflict> { internal class object <class-object-for-ConstructorTypeParamClassObjectConflict> {
/*primary*/ private constructor <class-object-for-ConstructorTypeParamClassObjectConflict>() /*primary*/ private constructor <class-object-for-ConstructorTypeParamClassObjectConflict>()
internal final val test: kotlin.Int internal final val test: kotlin.Int = 12.toInt()
internal final fun <get-test>(): kotlin.Int internal final fun <get-test>(): kotlin.Int
} }
} }
@@ -27,14 +27,14 @@ internal final class ConstructorTypeParamClassObjectTypeConflict</*0*/ test> {
internal final class TestClassObjectAndClassConflict { internal final class TestClassObjectAndClassConflict {
/*primary*/ public constructor TestClassObjectAndClassConflict() /*primary*/ public constructor TestClassObjectAndClassConflict()
internal final val bla: kotlin.String internal final val bla: kotlin.String = "More"
internal final fun <get-bla>(): kotlin.String internal final fun <get-bla>(): kotlin.String
internal final val some: kotlin.String internal final val some: kotlin.String = "More"
internal final fun <get-some>(): kotlin.String internal final fun <get-some>(): kotlin.String
internal class object <class-object-for-TestClassObjectAndClassConflict> { internal class object <class-object-for-TestClassObjectAndClassConflict> {
/*primary*/ private constructor <class-object-for-TestClassObjectAndClassConflict>() /*primary*/ private constructor <class-object-for-TestClassObjectAndClassConflict>()
internal final val bla: kotlin.Int internal final val bla: kotlin.Int = 12.toInt()
internal final fun <get-bla>(): kotlin.Int internal final fun <get-bla>(): kotlin.Int
} }
} }
@@ -46,7 +46,7 @@ internal final class TestConstructorParamClassObjectConflict {
internal class object <class-object-for-TestConstructorParamClassObjectConflict> { internal class object <class-object-for-TestConstructorParamClassObjectConflict> {
/*primary*/ private constructor <class-object-for-TestConstructorParamClassObjectConflict>() /*primary*/ private constructor <class-object-for-TestConstructorParamClassObjectConflict>()
internal final val test: kotlin.Int internal final val test: kotlin.Int = 12.toInt()
internal final fun <get-test>(): kotlin.Int internal final fun <get-test>(): kotlin.Int
} }
} }
@@ -60,7 +60,7 @@ internal final class TestConstructorValClassObjectConflict {
internal class object <class-object-for-TestConstructorValClassObjectConflict> { internal class object <class-object-for-TestConstructorValClassObjectConflict> {
/*primary*/ private constructor <class-object-for-TestConstructorValClassObjectConflict>() /*primary*/ private constructor <class-object-for-TestConstructorValClassObjectConflict>()
internal final val test: kotlin.Int internal final val test: kotlin.Int = 12.toInt()
internal final fun <get-test>(): kotlin.Int internal final fun <get-test>(): kotlin.Int
} }
} }
@@ -1,6 +1,6 @@
package test package test
internal val x: kotlin.Int internal val x: kotlin.Int = 5.toInt()
internal fun <get-x>(): kotlin.Int internal fun <get-x>(): kotlin.Int
public object Obj { public object Obj {
@@ -5,7 +5,7 @@ internal final class ClassObjectDeclaresProperty {
internal class object <class-object-for-ClassObjectDeclaresProperty> { internal class object <class-object-for-ClassObjectDeclaresProperty> {
/*primary*/ private constructor <class-object-for-ClassObjectDeclaresProperty>() /*primary*/ private constructor <class-object-for-ClassObjectDeclaresProperty>()
internal final val i: kotlin.Int internal final val i: kotlin.Int = 1.toInt()
internal final fun <get-i>(): kotlin.Int internal final fun <get-i>(): kotlin.Int
} }
} }
@@ -2,12 +2,12 @@ package test
internal final class A { internal final class A {
/*primary*/ public constructor A() /*primary*/ public constructor A()
internal final val other: kotlin.Int internal final val other: kotlin.Int = 1.toInt()
internal final fun <get-other>(): kotlin.Int internal final fun <get-other>(): kotlin.Int
internal class object <class-object-for-A> { internal class object <class-object-for-A> {
/*primary*/ private constructor <class-object-for-A>() /*primary*/ private constructor <class-object-for-A>()
internal final val some: kotlin.Int internal final val some: kotlin.Int = 1.toInt()
internal final fun <get-some>(): kotlin.Int internal final fun <get-some>(): kotlin.Int
} }
} }
@@ -2,6 +2,6 @@ package test
internal final class ClassVal { internal final class ClassVal {
/*primary*/ public constructor ClassVal() /*primary*/ public constructor ClassVal()
internal final val aa: kotlin.Int internal final val aa: kotlin.Int = 1.toInt()
internal final fun <get-aa>(): kotlin.Int internal final fun <get-aa>(): kotlin.Int
} }
@@ -1,4 +1,4 @@
package test package test
internal val nsVal: kotlin.Int internal val nsVal: kotlin.Int = 1.toInt()
internal fun <get-nsVal>(): kotlin.Int internal fun <get-nsVal>(): kotlin.Int
@@ -2,12 +2,12 @@ package test
internal open class BaseClass { internal open class BaseClass {
/*primary*/ public constructor BaseClass() /*primary*/ public constructor BaseClass()
internal open val shape: kotlin.String internal open val shape: kotlin.String = "square"
internal open fun <get-shape>(): kotlin.String internal open fun <get-shape>(): kotlin.String
} }
internal open class Subclass : test.BaseClass { internal open class Subclass : test.BaseClass {
/*primary*/ public constructor Subclass() /*primary*/ public constructor Subclass()
internal open override /*1*/ val shape: kotlin.String internal open override /*1*/ val shape: kotlin.String = "circle"
internal open override /*1*/ fun <get-shape>(): kotlin.String internal open override /*1*/ fun <get-shape>(): kotlin.String
} }
@@ -2,7 +2,7 @@ package test
internal open class Subclass : test.Trait { internal open class Subclass : test.Trait {
/*primary*/ public constructor Subclass() /*primary*/ public constructor Subclass()
internal open override /*1*/ val shape: kotlin.String internal open override /*1*/ val shape: kotlin.String = "circle"
internal open override /*1*/ fun <get-shape>(): kotlin.String internal open override /*1*/ fun <get-shape>(): kotlin.String
} }
@@ -2,7 +2,7 @@ package test
internal open class BaseClass { internal open class BaseClass {
/*primary*/ public constructor BaseClass() /*primary*/ public constructor BaseClass()
internal final val exactly: kotlin.Int internal final val exactly: kotlin.Int = 17.toInt()
internal final fun <get-exactly>(): kotlin.Int internal final fun <get-exactly>(): kotlin.Int
} }
@@ -2,9 +2,9 @@ package test
internal final class ClassVal { internal final class ClassVal {
/*primary*/ public constructor ClassVal() /*primary*/ public constructor ClassVal()
internal final val property1: kotlin.Int internal final val property1: kotlin.Int = 1.toInt()
internal final fun <get-property1>(): kotlin.Int internal final fun <get-property1>(): kotlin.Int
internal final val property2: kotlin.Int internal final val property2: kotlin.Int = 1.toInt()
internal final fun <get-property2>(): kotlin.Int internal final fun <get-property2>(): kotlin.Int
private final val property3: java.lang.Object private final val property3: java.lang.Object
private final fun <get-property3>(): java.lang.Object private final fun <get-property3>(): java.lang.Object
@@ -2,9 +2,9 @@ package test
internal final class ClassVal { internal final class ClassVal {
/*primary*/ public constructor ClassVal() /*primary*/ public constructor ClassVal()
internal final val property1: kotlin.Int internal final val property1: kotlin.Int = 1.toInt()
internal final fun <get-property1>(): kotlin.Int internal final fun <get-property1>(): kotlin.Int
internal final val property2: kotlin.Int internal final val property2: kotlin.Int = 1.toInt()
internal final fun <get-property2>(): kotlin.Int internal final fun <get-property2>(): kotlin.Int
private final val property3: java.lang.Object private final val property3: java.lang.Object
private final fun <get-property3>(): java.lang.Object private final fun <get-property3>(): java.lang.Object
@@ -1,5 +1,5 @@
package test package test
internal val x: kotlin.Int internal val x: kotlin.Int = 0.toInt()
internal fun <get-x>(): kotlin.Int internal fun <get-x>(): kotlin.Int
internal fun f(): kotlin.Int internal fun f(): kotlin.Int
@@ -1,4 +1,4 @@
package test package test
private val topLevelVal: kotlin.Int private val topLevelVal: kotlin.Int = 0.toInt()
private fun <get-topLevelVal>(): kotlin.Int private fun <get-topLevelVal>(): kotlin.Int
@@ -56,6 +56,16 @@ public class RecursiveDescriptorComparator {
public static final Configuration RECURSIVE = new Configuration(false, false, true, public static final Configuration RECURSIVE = new Configuration(false, false, true,
Predicates.<FqName>alwaysTrue(), Predicates.<FqName>alwaysTrue(),
FORBID_ERROR_TYPES, DEFAULT_RENDERER); FORBID_ERROR_TYPES, DEFAULT_RENDERER);
public static final Configuration WITHOUT_COMPILE_TIME_CONSTANTS = new Configuration(false, false, true,
Predicates.<FqName>alwaysTrue(),
FORBID_ERROR_TYPES,
new DescriptorRendererBuilder()
.setWithDefinedIn(false)
.setExcludedAnnotationClasses(Arrays.asList(new FqName(ExpectedLoadErrorsUtil.ANNOTATION_CLASS_NAME)))
.setOverrideRenderingPolicy(DescriptorRenderer.OverrideRenderingPolicy.RENDER_OPEN_OVERRIDE)
.setVerbose(true)
.setIncludePropertyConstant(false)
.build());
public static final Configuration RECURSIVE_ALL = new Configuration(true, true, true, public static final Configuration RECURSIVE_ALL = new Configuration(true, true, true,
Predicates.<FqName>alwaysTrue(), Predicates.<FqName>alwaysTrue(),
@@ -20,11 +20,10 @@ import kotlin.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.*;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter; import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
import org.jetbrains.jet.lang.resolve.java.resolver.ResolverPackage;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver; import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver;
import org.jetbrains.jet.storage.MemoizedFunctionToNotNull; import org.jetbrains.jet.storage.MemoizedFunctionToNotNull;
@@ -87,8 +86,13 @@ public class DescriptorDeserializersStorage {
@Nullable @Nullable
@Override @Override
public KotlinJvmBinaryClass.AnnotationVisitor visitField(@NotNull Name name, @NotNull String desc) { public KotlinJvmBinaryClass.AnnotationVisitor visitField(@NotNull Name name, @NotNull String desc, @Nullable Object initializer) {
return new MemberAnnotationVisitor(MemberSignature.fromFieldNameAndDesc(name, desc)); MemberSignature signature = MemberSignature.fromFieldNameAndDesc(name, desc);
if (initializer != null) {
propertyConstants.put(signature, ConstantUtils.createCompileTimeConstant(
initializer, /* canBeUsedInAnnotation */ true, /* isPureIntConstant */ true, /* expectedType */ null));
}
return new MemberAnnotationVisitor(signature);
} }
class AnnotationVisitorForMethod extends MemberAnnotationVisitor implements KotlinJvmBinaryClass.MethodAnnotationVisitor { class AnnotationVisitorForMethod extends MemberAnnotationVisitor implements KotlinJvmBinaryClass.MethodAnnotationVisitor {
@@ -40,7 +40,7 @@ public interface KotlinJvmBinaryClass {
MethodAnnotationVisitor visitMethod(@NotNull Name name, @NotNull String desc); MethodAnnotationVisitor visitMethod(@NotNull Name name, @NotNull String desc);
@Nullable @Nullable
AnnotationVisitor visitField(@NotNull Name name, @NotNull String desc); AnnotationVisitor visitField(@NotNull Name name, @NotNull String desc, @Nullable Object initializer);
} }
interface AnnotationVisitor { interface AnnotationVisitor {