Refactoring of CompileTimeConstant, introduce flag to represent a constant being referenced by a variable

This commit is contained in:
Tal Man
2014-04-09 14:38:50 -04:00
parent 32a2e63ae5
commit aeb5bae556
38 changed files with 303 additions and 130 deletions
@@ -108,7 +108,7 @@ class LazyJavaAnnotationDescriptor(
private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): CompileTimeConstant<*>? {
return when (argument) {
is JavaLiteralAnnotationArgument -> createCompileTimeConstant(argument.getValue(), true, false, null)
is JavaLiteralAnnotationArgument -> createCompileTimeConstant(argument.getValue(), true, false, false, null)
is JavaReferenceAnnotationArgument -> resolveFromReference(argument.resolve())
is JavaArrayAnnotationArgument -> resolveFromArray(argument.getName() ?: DEFAULT_ANNOTATION_MEMBER_NAME, argument.getElements())
is JavaAnnotationAsAnnotationArgument -> resolveFromAnnotation(argument.getAnnotation())
@@ -137,7 +137,7 @@ class LazyJavaAnnotationDescriptor(
val values = elements.map {
argument -> resolveAnnotationArgument(argument) ?: NullValue.NULL
}
return ArrayValue(values, valueParameter.getType(), true)
return ArrayValue(values, valueParameter.getType(), true, values.any { it.usesVariableAsConstant() })
}
private fun resolveFromReference(element: JavaElement?): CompileTimeConstant<*>? {
@@ -154,7 +154,7 @@ class LazyJavaAnnotationDescriptor(
val classifier = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(element.getName())
if (classifier !is ClassDescriptor) return null
return EnumValue(classifier)
return EnumValue(classifier, false)
}
private fun resolveFromJavaClassObjectType(javaType: JavaType): CompileTimeConstant<*>? {
@@ -126,7 +126,7 @@ public class AnnotationDescriptorDeserializer extends BaseDescriptorDeserializer
@Override
public void visit(@Nullable Name name, @Nullable Object value) {
if (name != null) {
CompileTimeConstant<?> argument = ConstantsPackage.createCompileTimeConstant(value, true, false, null);
CompileTimeConstant<?> argument = ConstantsPackage.createCompileTimeConstant(value, true, false, false, null);
setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name));
}
}
@@ -149,7 +149,7 @@ public class AnnotationDescriptorDeserializer extends BaseDescriptorDeserializer
if (enumClass.getKind() == ClassKind.ENUM_CLASS) {
ClassifierDescriptor classifier = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(name);
if (classifier instanceof ClassDescriptor) {
return new EnumValue((ClassDescriptor) classifier);
return new EnumValue((ClassDescriptor) classifier, false);
}
}
return ErrorValue.create("Unresolved enum entry: " + enumClassName.getInternalName() + "." + name);
@@ -89,7 +89,7 @@ public class DescriptorDeserializersStorage {
MemberSignature signature = MemberSignature.fromFieldNameAndDesc(name, desc);
if (initializer != null) {
propertyConstants.put(signature, ConstantsPackage.createCompileTimeConstant(
initializer, /* canBeUsedInAnnotation */ true, /* isPureIntConstant */ true, /* expectedType */ null));
initializer, /* canBeUsedInAnnotation */ true, /* isPureIntConstant */ true, /* usesVariableAsConstant */ true, /* expectedType */ null));
}
return new MemberAnnotationVisitor(signature);
}
@@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class AnnotationValue extends CompileTimeConstant<AnnotationDescriptor> {
public AnnotationValue(@NotNull AnnotationDescriptor value) {
super(value, true);
super(value, true, false, false);
}
@NotNull
@@ -27,8 +27,11 @@ public class ArrayValue extends CompileTimeConstant<List<CompileTimeConstant<?>>
private final JetType type;
public ArrayValue(@NotNull List<CompileTimeConstant<?>> value, @NotNull JetType type, boolean canBeUsedInAnnotations) {
super(value, canBeUsedInAnnotations);
public ArrayValue(@NotNull List<CompileTimeConstant<?>> value,
@NotNull JetType type,
boolean canBeUsedInAnnotations,
boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, false, usesVariableAsConstant);
this.type = type;
}
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class BooleanValue extends CompileTimeConstant<Boolean> {
public BooleanValue(boolean value, boolean canBeUseInAnnotation) {
super(value, canBeUseInAnnotation);
public BooleanValue(boolean value, boolean canBeUseInAnnotation, boolean usesVariableAsConstant) {
super(value, canBeUseInAnnotation, false, usesVariableAsConstant);
}
@NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class ByteValue extends IntegerValueConstant<Byte> {
public ByteValue(byte value, boolean canBeUsedInAnnotations, boolean pure) {
super(value, canBeUsedInAnnotations, pure);
public ByteValue(byte value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVaraiableAsConstant) {
super(value, canBeUsedInAnnotations, pure, usesVaraiableAsConstant);
}
@NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class CharValue extends IntegerValueConstant<Character> {
public CharValue(char value, boolean canBeUsedInAnnotations, boolean pure) {
super(value, canBeUsedInAnnotations, pure);
public CharValue(char value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant);
}
@NotNull
@@ -24,15 +24,38 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public abstract class CompileTimeConstant<T> {
protected final T value;
private final boolean canBeUsedInAnnotations;
private final int flags;
protected CompileTimeConstant(T value, boolean canBeUsedInAnnotations) {
/*
* if is pure is false then constant type cannot be changed
* ex1. val a: Long = 1.toInt() (TYPE_MISMATCH error, 1.toInt() isn't pure)
* ex2. val b: Int = a (TYPE_MISMATCH error, a isn't pure)
*
*/
private static final int IS_PURE_MASK = 1;
private static final int CAN_BE_USED_IN_ANNOTATIONS_MASK = 1 << 1;
private static final int USES_VARIABLE_AS_CONSTANT_MASK = 1 << 2;
protected CompileTimeConstant(T value,
boolean canBeUsedInAnnotations,
boolean isPure,
boolean usesVariableAsConstant) {
this.value = value;
this.canBeUsedInAnnotations = canBeUsedInAnnotations;
flags = (isPure ? IS_PURE_MASK : 0) |
(canBeUsedInAnnotations ? CAN_BE_USED_IN_ANNOTATIONS_MASK : 0) |
(usesVariableAsConstant ? USES_VARIABLE_AS_CONSTANT_MASK : 0);
}
public boolean canBeUsedInAnnotations() {
return canBeUsedInAnnotations;
return (flags & CAN_BE_USED_IN_ANNOTATIONS_MASK) != 0;
}
public boolean isPure() {
return (flags & IS_PURE_MASK) != 0;
}
public boolean usesVariableAsConstant() {
return (flags & USES_VARIABLE_AS_CONSTANT_MASK) != 0;
}
@Nullable
@@ -24,23 +24,24 @@ public fun createCompileTimeConstant(
value: Any?,
canBeUsedInAnnotation: Boolean,
isPureIntConstant: Boolean,
usesVariableAsConstant: Boolean = false,
expectedType: JetType? = null
): CompileTimeConstant<*>? {
if (expectedType == null) {
when(value) {
is Byte -> return ByteValue(value, canBeUsedInAnnotation, isPureIntConstant)
is Short -> return ShortValue(value, canBeUsedInAnnotation, isPureIntConstant)
is Int -> return IntValue(value, canBeUsedInAnnotation, isPureIntConstant)
is Long -> return LongValue(value, canBeUsedInAnnotation, isPureIntConstant)
is Byte -> return ByteValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
is Short -> return ShortValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
is Int -> return IntValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
is Long -> return LongValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
}
}
return when(value) {
is Byte, is Short, is Int, is Long -> getIntegerValue((value as Number).toLong(), canBeUsedInAnnotation, isPureIntConstant, expectedType)
is Char -> CharValue(value, canBeUsedInAnnotation, isPureIntConstant)
is Float -> FloatValue(value, canBeUsedInAnnotation)
is Double -> DoubleValue(value, canBeUsedInAnnotation)
is Boolean -> BooleanValue(value, canBeUsedInAnnotation)
is String -> StringValue(value, canBeUsedInAnnotation)
is Byte, is Short, is Int, is Long -> getIntegerValue((value as Number).toLong(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant, expectedType)
is Char -> CharValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
is Float -> FloatValue(value, canBeUsedInAnnotation, usesVariableAsConstant)
is Double -> DoubleValue(value, canBeUsedInAnnotation, usesVariableAsConstant)
is Boolean -> BooleanValue(value, canBeUsedInAnnotation, usesVariableAsConstant)
is String -> StringValue(value, canBeUsedInAnnotation, usesVariableAsConstant)
null -> NullValue.NULL
else -> null
}
@@ -50,30 +51,31 @@ private fun getIntegerValue(
value: Long,
canBeUsedInAnnotation: Boolean,
isPureIntConstant: Boolean,
usesVariableAsConstant: Boolean,
expectedType: JetType
): CompileTimeConstant<*>? {
fun defaultIntegerValue(value: Long) = when (value) {
value.toInt().toLong() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant)
else -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant)
value.toInt().toLong() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
else -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
}
if (TypeUtils.noExpectedType(expectedType) || expectedType.isError()) {
return IntegerValueTypeConstant(value, canBeUsedInAnnotation)
return IntegerValueTypeConstant(value, canBeUsedInAnnotation, usesVariableAsConstant)
}
val builtIns = KotlinBuiltIns.getInstance()
return when (TypeUtils.makeNotNullable(expectedType)) {
builtIns.getLongType() -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant)
builtIns.getLongType() -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
builtIns.getShortType() -> when (value) {
value.toShort().toLong() -> ShortValue(value.toShort(), canBeUsedInAnnotation, isPureIntConstant)
value.toShort().toLong() -> ShortValue(value.toShort(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
else -> defaultIntegerValue(value)
}
builtIns.getByteType() -> when (value) {
value.toByte().toLong() -> ByteValue(value.toByte(), canBeUsedInAnnotation, isPureIntConstant)
value.toByte().toLong() -> ByteValue(value.toByte(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
else -> defaultIntegerValue(value)
}
builtIns.getCharType() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant)
builtIns.getCharType() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
else -> defaultIntegerValue(value)
}
}
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class DoubleValue extends CompileTimeConstant<Double> {
public DoubleValue(double value, boolean canBeUsedInAnnotations) {
super(value, canBeUsedInAnnotations);
public DoubleValue(double value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, false, usesVariableAsConstant);
}
@NotNull
@@ -24,8 +24,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class EnumValue extends CompileTimeConstant<ClassDescriptor> {
public EnumValue(@NotNull ClassDescriptor value) {
super(value, true);
public EnumValue(@NotNull ClassDescriptor value, boolean usesVariableAsConstant) {
super(value, true, false, usesVariableAsConstant);
}
@NotNull
@@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public abstract class ErrorValue extends CompileTimeConstant<Void> {
public ErrorValue() {
super(null, true);
super(null, true, false, false);
}
@Override
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class FloatValue extends CompileTimeConstant<Float> {
public FloatValue(float value, boolean canBeUsedInAnnotations) {
super(value, canBeUsedInAnnotations);
public FloatValue(float value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, false, usesVariableAsConstant);
}
@NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class IntValue extends IntegerValueConstant<Integer> {
public IntValue(int value, boolean canBeUsedInAnnotations, boolean pure) {
super(value, canBeUsedInAnnotations, pure);
public IntValue(int value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant);
}
@NotNull
@@ -18,19 +18,7 @@ package org.jetbrains.jet.lang.resolve.constants;
public abstract class IntegerValueConstant<T> extends CompileTimeConstant<T> {
/*
* if false then constant type cannot be changed
* ex1. val a: Long = 1.toInt() (TYPE_MISMATCH error, 1.toInt() isn't pure)
* ex2. val b: Int = a (TYPE_MISMATCH error, a isn't pure)
* */
private final boolean isPure;
protected IntegerValueConstant(T value, boolean canBeUsedInAnnotations, boolean pure) {
super(value, canBeUsedInAnnotations);
isPure = pure;
}
public boolean isPure() {
return isPure;
protected IntegerValueConstant(T value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVaraiableAsConstant) {
super(value, canBeUsedInAnnotations, pure, usesVaraiableAsConstant);
}
}
@@ -19,10 +19,9 @@ package org.jetbrains.jet.lang.resolve.constants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import java.util.Collections;
@@ -30,8 +29,8 @@ public class IntegerValueTypeConstant extends IntegerValueConstant<Number> {
private final IntegerValueTypeConstructor typeConstructor;
public IntegerValueTypeConstant(@NotNull Number value, boolean canBeUsedInAnnotations) {
super(value, canBeUsedInAnnotations, true);
public IntegerValueTypeConstant(@NotNull Number value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, true, usesVariableAsConstant);
this.typeConstructor = new IntegerValueTypeConstructor(value.longValue());
}
@@ -24,7 +24,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class JavaClassValue extends CompileTimeConstant<JetType> {
public JavaClassValue(@NotNull JetType value) {
super(value, true);
super(value, true, false, false);
}
@NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class LongValue extends IntegerValueConstant<Long> {
public LongValue(long value, boolean canBeUsedInAnnotations, boolean pure) {
super(value, canBeUsedInAnnotations, pure);
public LongValue(long value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant);
}
@NotNull
@@ -26,7 +26,7 @@ public class NullValue extends CompileTimeConstant<Void> {
public static final NullValue NULL = new NullValue();
private NullValue() {
super(null, false);
super(null, false, false, false);
}
@NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class ShortValue extends IntegerValueConstant<Short> {
public ShortValue(short value, boolean canBeUsedInAnnotations, boolean pure) {
super(value, canBeUsedInAnnotations, pure);
public ShortValue(short value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant);
}
@NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class StringValue extends CompileTimeConstant<String> {
public StringValue(String value, boolean canBeUsedInAnnotations) {
super(value, canBeUsedInAnnotations);
public StringValue(String value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, false, usesVariableAsConstant);
}
@NotNull