Record COMPILE_TIME_INITIALIZER for all final variables
This commit is contained in:
+57
-29
@@ -182,8 +182,9 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
|
||||
if (argumentsEntrySet.isEmpty()) {
|
||||
val result = evaluateUnaryAndCheck(argumentForReceiver, resultingDescriptorName.asString(), callExpression)
|
||||
val isArgumentPure = trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, argumentForReceiver.expression) ?: false
|
||||
val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression)
|
||||
val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS
|
||||
return createCompileTimeConstant(result, fullExpression, expectedType, !isNumberConversionMethod && isArgumentPure)
|
||||
return createCompileTimeConstant(result, fullExpression, expectedType, !isNumberConversionMethod && isArgumentPure, canBeUsedInAnnotation)
|
||||
}
|
||||
else if (argumentsEntrySet.size() == 1) {
|
||||
val (parameter, argument) = argumentsEntrySet.first()
|
||||
@@ -203,7 +204,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
|
||||
else -> {
|
||||
val areArgumentsPure = trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, argumentForReceiver.expression) ?: false &&
|
||||
trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, argumentForParameter.expression) ?: false
|
||||
createCompileTimeConstant(result, fullExpression, expectedType, areArgumentsPure)
|
||||
val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression)
|
||||
createCompileTimeConstant(result, fullExpression, expectedType, areArgumentsPure, canBeUsedInAnnotation)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,6 +213,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
|
||||
return null
|
||||
}
|
||||
|
||||
private fun canBeUsedInAnnotation(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.canBeUsedInAnnotations() ?: false
|
||||
|
||||
private fun evaluateUnaryAndCheck(receiver: OperationArgument, name: String, callExpression: JetExpression): Any? {
|
||||
val functions = unaryOperations[UnaryOperationKey(receiver.ctcType, name)]
|
||||
if (functions == null) return null
|
||||
@@ -254,7 +258,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
|
||||
return actualResult
|
||||
}
|
||||
|
||||
private fun isDivisionByZero(name: String, parameter: Any?): Boolean {
|
||||
private fun isDivisionByZero(name: String, parameter: Any?): Boolean {
|
||||
if (name == OperatorConventions.BINARY_OPERATION_NAMES[JetTokens.DIV]!!.asString()) {
|
||||
if (isIntegerType(parameter)) {
|
||||
return (parameter as Number).toLong() == 0.toLong()
|
||||
@@ -282,10 +286,17 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
|
||||
val resolvedCall = trace.getBindingContext().get(BindingContext.RESOLVED_CALL, expression)
|
||||
if (resolvedCall != null) {
|
||||
val callableDescriptor = resolvedCall.getResultingDescriptor()
|
||||
if (callableDescriptor is PropertyDescriptor) {
|
||||
if (AnnotationUtils.isPropertyCompileTimeConstant(callableDescriptor)) {
|
||||
return trace.getBindingContext().get(COMPILE_TIME_INITIALIZER, callableDescriptor)
|
||||
}
|
||||
if (callableDescriptor is VariableDescriptor) {
|
||||
val compileTimeConstant = trace.getBindingContext().get(COMPILE_TIME_INITIALIZER, callableDescriptor)
|
||||
if (compileTimeConstant == null) return null
|
||||
|
||||
val value: Any? =
|
||||
if (compileTimeConstant is IntegerValueTypeConstant)
|
||||
compileTimeConstant.getValue(expectedType ?: TypeUtils.NO_EXPECTED_TYPE)
|
||||
else
|
||||
compileTimeConstant.getValue()
|
||||
return createCompileTimeConstant(value, expression, expectedType, false,
|
||||
AnnotationUtils.isPropertyCompileTimeConstant(callableDescriptor))
|
||||
}
|
||||
}
|
||||
return null
|
||||
@@ -306,7 +317,11 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
|
||||
|
||||
// MyEnum.A, Integer.MAX_VALUE
|
||||
if (selectorExpression != null) {
|
||||
return evaluate(selectorExpression, expectedType)
|
||||
val compileTimeConstant = evaluate(selectorExpression, expectedType)
|
||||
if (trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, selectorExpression) == true) {
|
||||
trace.record(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression, true)
|
||||
}
|
||||
return compileTimeConstant
|
||||
}
|
||||
|
||||
return null
|
||||
@@ -404,18 +419,36 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
|
||||
return OperationArgument(evaluationResult, compileTimeType, expression)
|
||||
}
|
||||
|
||||
fun createCompileTimeConstant(value: Any?, expression: JetExpression, expectedType: JetType?, isPure: Boolean = true): CompileTimeConstant<*>? {
|
||||
if (isPure) {
|
||||
val compileTimeConstant = createCompileTimeConstant(value, expectedType ?: TypeUtils.NO_EXPECTED_TYPE)
|
||||
trace.record(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression, true)
|
||||
return compileTimeConstant
|
||||
}
|
||||
fun createCompileTimeConstant(value: Any?, expression: JetExpression, expectedType: JetType?, isPure: Boolean = true, canBeUsedInAnnotation: Boolean = true): CompileTimeConstant<*>? {
|
||||
val compileTimeConstant =
|
||||
if (isPure) {
|
||||
trace.record(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression, true)
|
||||
createCompileTimeConstant(value, expectedType ?: TypeUtils.NO_EXPECTED_TYPE)
|
||||
}
|
||||
else createCompileTimeConstant(value)
|
||||
|
||||
compileTimeConstant?.setCanBeUsedInAnnotations(canBeUsedInAnnotation)
|
||||
|
||||
val compileTimeConstant = createCompileTimeConstant(value)
|
||||
return compileTimeConstant
|
||||
}
|
||||
}
|
||||
|
||||
public fun recordCompileTimeValueForInitializerIfNeeded(
|
||||
variableDescriptor: VariableDescriptor,
|
||||
initializer: JetExpression,
|
||||
variableType: JetType,
|
||||
trace: BindingTrace
|
||||
) {
|
||||
if (!variableDescriptor.isVar()) {
|
||||
if (trace.get(BindingContext.COMPILE_TIME_INITIALIZER, variableDescriptor) == null) {
|
||||
val constant = ConstantExpressionEvaluator.evaluate(initializer, trace, variableType)
|
||||
if (constant != null) {
|
||||
trace.record(BindingContext.COMPILE_TIME_INITIALIZER, variableDescriptor, constant)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun IntegerValueTypeConstant.createCompileTimeConstantWithType(expectedType: JetType): CompileTimeConstant<*>?
|
||||
= createCompileTimeConstant(getValue(expectedType))
|
||||
|
||||
@@ -524,21 +557,16 @@ private fun createStringConstant(value: CompileTimeConstant<*>?): StringValue? {
|
||||
}
|
||||
|
||||
private fun createCompileTimeConstant(value: Any?, expectedType: JetType? = null): CompileTimeConstant<*>? {
|
||||
return when(value) {
|
||||
is Byte, is Short, is Int, is Long -> {
|
||||
return if (expectedType == null) {
|
||||
when(value) {
|
||||
is Byte -> ByteValue(value)
|
||||
is Short -> ShortValue(value)
|
||||
is Int -> IntValue(value)
|
||||
is Long -> LongValue(value)
|
||||
else -> throw IllegalArgumentException("All cases should be catched: $value")
|
||||
}
|
||||
}
|
||||
else {
|
||||
getIntegerValue((value as Number).toLong(), expectedType)
|
||||
}
|
||||
if (expectedType == null) {
|
||||
when(value) {
|
||||
is Byte -> return ByteValue(value)
|
||||
is Short -> return ShortValue(value)
|
||||
is Int -> return IntValue(value)
|
||||
is Long -> return LongValue(value)
|
||||
}
|
||||
}
|
||||
return when(value) {
|
||||
is Byte, is Short, is Int, is Long -> getIntegerValue((value as Number).toLong(), expectedType)
|
||||
is Char -> CharValue(value)
|
||||
is Float -> FloatValue(value)
|
||||
is Double -> DoubleValue(value)
|
||||
|
||||
@@ -252,7 +252,7 @@ public class AnnotationResolver {
|
||||
JetType defaultType = ((IntegerValueTypeConstant) constant).getType(expectedType);
|
||||
ArgumentTypeResolver.updateNumberType(defaultType, argumentExpression, trace);
|
||||
}
|
||||
if (constant != null) {
|
||||
if (constant != null && constant.canBeUsedInAnnotations()) {
|
||||
constants.add(constant);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -20,7 +20,6 @@ import jet.runtime.Intrinsic;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
@@ -116,7 +115,7 @@ public class AnnotationUtils {
|
||||
return "kotlin.javaClass.function".equals(getIntrinsicAnnotationArgument(resolvedCall.getResultingDescriptor().getOriginal()));
|
||||
}
|
||||
|
||||
public static boolean isPropertyCompileTimeConstant(@NotNull PropertyDescriptor descriptor) {
|
||||
public static boolean isPropertyCompileTimeConstant(@NotNull VariableDescriptor descriptor) {
|
||||
if (descriptor.isVar()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public interface BindingContext {
|
||||
|
||||
WritableSlice<JetExpression, Boolean> IS_PURE_CONSTANT_EXPRESSION = Slices.createSimpleSlice();
|
||||
WritableSlice<JetExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice();
|
||||
WritableSlice<PropertyDescriptor, CompileTimeConstant<?>> COMPILE_TIME_INITIALIZER = Slices.createSimpleSlice();
|
||||
WritableSlice<VariableDescriptor, CompileTimeConstant<?>> COMPILE_TIME_INITIALIZER = Slices.createSimpleSlice();
|
||||
|
||||
WritableSlice<JetTypeReference, JetType> TYPE = Slices.createSimpleSlice();
|
||||
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>(DO_NOTHING);
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
|
||||
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.jet.lang.evaluate.EvaluatePackage;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.ContextDependency;
|
||||
@@ -33,7 +33,6 @@ import org.jetbrains.jet.lang.resolve.calls.context.ResolutionResultsCacheImpl;
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.SimpleResolutionContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
@@ -573,12 +572,8 @@ public class BodyResolver {
|
||||
scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
|
||||
JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
|
||||
expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, context.getOuterDataFlowInfo(), trace);
|
||||
if (AnnotationUtils.isPropertyCompileTimeConstant(propertyDescriptor)) {
|
||||
CompileTimeConstant<?> constant = ConstantExpressionEvaluator.object$.evaluate(initializer, trace, expectedTypeForInitializer);
|
||||
if (constant != null) {
|
||||
trace.record(BindingContext.COMPILE_TIME_INITIALIZER, propertyDescriptor, constant);
|
||||
}
|
||||
}
|
||||
|
||||
EvaluatePackage.recordCompileTimeValueForInitializerIfNeeded(propertyDescriptor, initializer, expectedTypeForInitializer, trace);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.*;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1;
|
||||
import org.jetbrains.jet.lang.evaluate.EvaluatePackage;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
@@ -952,6 +953,10 @@ public class DescriptorResolver {
|
||||
JetType type =
|
||||
resolveInitializerType(scope, initializer, dataFlowInfo, trace);
|
||||
|
||||
EvaluatePackage.recordCompileTimeValueForInitializerIfNeeded(
|
||||
variableDescriptor,
|
||||
initializer, type,
|
||||
trace);
|
||||
return transformAnonymousTypeIfNeeded(variableDescriptor, variable, type,
|
||||
trace);
|
||||
}
|
||||
|
||||
+4
-2
@@ -466,8 +466,10 @@ public class CallExpressionResolver {
|
||||
}
|
||||
|
||||
CompileTimeConstant<?> value = ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, context.expectedType);
|
||||
if (value != null) {
|
||||
return BasicExpressionTypingVisitor.createCompileTimeConstantTypeInfo(value, expression, context);
|
||||
if (Boolean.TRUE.equals(context.trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression))) {
|
||||
if (value != null) {
|
||||
return BasicExpressionTypingVisitor.createCompileTimeConstantTypeInfo(value, expression, context);
|
||||
}
|
||||
}
|
||||
|
||||
JetTypeInfo typeInfo = JetTypeInfo.create(selectorReturnType, selectorReturnTypeInfo.getDataFlowInfo());
|
||||
|
||||
+3
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.evaluate.EvaluatePackage;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
@@ -125,6 +126,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
JetType outType = propertyDescriptor.getType();
|
||||
JetTypeInfo typeInfo = facade.getTypeInfo(initializer, context.replaceExpectedType(outType));
|
||||
dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||
|
||||
EvaluatePackage.recordCompileTimeValueForInitializerIfNeeded(propertyDescriptor, initializer, outType, context.trace);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user