Record COMPILE_TIME_INITIALIZER for all final variables

This commit is contained in:
Natalia Ukhorskaya
2014-01-17 13:10:55 +04:00
parent 2ddda59465
commit 97da2def08
23 changed files with 611 additions and 52 deletions
@@ -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);
}
@@ -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());
@@ -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);
}
{
@@ -1,3 +1,5 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
val intMaxValue: Int = 0x7fffffff
val intMinValue: Int = 1 shl 31
@@ -18,4 +20,48 @@ val i15: Int = <!INTEGER_OVERFLOW!>intMinValue / -1<!>
val l20: Int = <!INTEGER_OVERFLOW!>30 * 24 * 60 * 60 * 1000<!>
val l21: Int = intMinValue - intMinValue
val l22: Int = <!INTEGER_OVERFLOW!>intMinValue + <!INTEGER_OVERFLOW!>-intMinValue<!><!>
val l23: Int = intMaxValue + <!INTEGER_OVERFLOW!>-intMinValue<!>
val l23: Int = intMaxValue + <!INTEGER_OVERFLOW!>-intMinValue<!>
fun foo() {
val a3: Int = <!INTEGER_OVERFLOW!><!INTEGER_OVERFLOW!>intMaxValue + 1<!> - 10<!>
val a4: Int = <!INTEGER_OVERFLOW!>intMaxValue + 1<!> + 10
val i2: Int = <!INTEGER_OVERFLOW!>intMaxValue - 1 + 2<!>
val i3: Int = <!INTEGER_OVERFLOW!>intMaxValue - intMinValue<!>
val i4: Int = <!INTEGER_OVERFLOW!>-intMinValue<!>
val i5: Int = <!INTEGER_OVERFLOW!>intMinValue - 1<!>
val i6: Int = <!INTEGER_OVERFLOW!>intMinValue - intMaxValue<!>
val i7: Int = intMinValue + intMaxValue
val i8: Int = -intMaxValue
val i10: Int = <!INTEGER_OVERFLOW!>intMinValue * -1<!>
val i11: Int = <!INTEGER_OVERFLOW!>intMinValue * 2<!>
val i12: Int = <!INTEGER_OVERFLOW!>intMaxValue * -2<!>
val i13: Int = intMaxValue * -1
val i15: Int = <!INTEGER_OVERFLOW!>intMinValue / -1<!>
val l20: Int = <!INTEGER_OVERFLOW!>30 * 24 * 60 * 60 * 1000<!>
val l21: Int = intMinValue - intMinValue
val l22: Int = <!INTEGER_OVERFLOW!>intMinValue + <!INTEGER_OVERFLOW!>-intMinValue<!><!>
val l23: Int = intMaxValue + <!INTEGER_OVERFLOW!>-intMinValue<!>
}
class A {
fun foo() {
val a3: Int = <!INTEGER_OVERFLOW!><!INTEGER_OVERFLOW!>intMaxValue + 1<!> - 10<!>
val a4: Int = <!INTEGER_OVERFLOW!>intMaxValue + 1<!> + 10
val i2: Int = <!INTEGER_OVERFLOW!>intMaxValue - 1 + 2<!>
val i3: Int = <!INTEGER_OVERFLOW!>intMaxValue - intMinValue<!>
val i4: Int = <!INTEGER_OVERFLOW!>-intMinValue<!>
val i5: Int = <!INTEGER_OVERFLOW!>intMinValue - 1<!>
val i6: Int = <!INTEGER_OVERFLOW!>intMinValue - intMaxValue<!>
val i7: Int = intMinValue + intMaxValue
val i8: Int = -intMaxValue
val i10: Int = <!INTEGER_OVERFLOW!>intMinValue * -1<!>
val i11: Int = <!INTEGER_OVERFLOW!>intMinValue * 2<!>
val i12: Int = <!INTEGER_OVERFLOW!>intMaxValue * -2<!>
val i13: Int = intMaxValue * -1
val i15: Int = <!INTEGER_OVERFLOW!>intMinValue / -1<!>
val l20: Int = <!INTEGER_OVERFLOW!>30 * 24 * 60 * 60 * 1000<!>
val l21: Int = intMinValue - intMinValue
val l22: Int = <!INTEGER_OVERFLOW!>intMinValue + <!INTEGER_OVERFLOW!>-intMinValue<!><!>
val l23: Int = intMaxValue + <!INTEGER_OVERFLOW!>-intMinValue<!>
}
}
@@ -1,3 +1,5 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
val longMaxValue: Long = 0x7fffffffffffffff
val longMinValue: Long = -longMaxValue - 1
val intMaxValue: Int = 0x7fffffff
@@ -20,4 +22,44 @@ val l13: Long = <!INTEGER_OVERFLOW!>longMinValue * -1<!>
val l14: Long = <!INTEGER_OVERFLOW!>longMinValue * 2<!>
val l15: Long = <!INTEGER_OVERFLOW!>longMaxValue * -2<!>
val l16: Long = intMinValue.toLong() * -1
val l19: Long = <!INTEGER_OVERFLOW!>longMinValue / -1<!>
val l19: Long = <!INTEGER_OVERFLOW!>longMinValue / -1<!>
fun foo() {
val l1: Long = <!INTEGER_OVERFLOW!>longMaxValue + 1<!>
val l2: Long = <!INTEGER_OVERFLOW!>longMaxValue - 1 + 2<!>
val l3: Long = <!INTEGER_OVERFLOW!>longMaxValue - longMinValue<!>
val l4: Long = <!INTEGER_OVERFLOW!>-longMinValue<!>
val l5: Long = <!INTEGER_OVERFLOW!>longMinValue - 1<!>
val l6: Long = <!INTEGER_OVERFLOW!>longMinValue - longMaxValue<!>
val l7: Long = longMinValue + longMaxValue
val l8: Long = -longMaxValue
val l10: Long = -intMinValue.toLong()
val l11: Long = -1 + intMinValue.toLong()
val l12: Long = <!INTEGER_OVERFLOW!>longMinValue * intMinValue<!>
val l13: Long = <!INTEGER_OVERFLOW!>longMinValue * -1<!>
val l14: Long = <!INTEGER_OVERFLOW!>longMinValue * 2<!>
val l15: Long = <!INTEGER_OVERFLOW!>longMaxValue * -2<!>
val l16: Long = intMinValue.toLong() * -1
val l19: Long = <!INTEGER_OVERFLOW!>longMinValue / -1<!>
}
class A {
fun foo() {
val l1: Long = <!INTEGER_OVERFLOW!>longMaxValue + 1<!>
val l2: Long = <!INTEGER_OVERFLOW!>longMaxValue - 1 + 2<!>
val l3: Long = <!INTEGER_OVERFLOW!>longMaxValue - longMinValue<!>
val l4: Long = <!INTEGER_OVERFLOW!>-longMinValue<!>
val l5: Long = <!INTEGER_OVERFLOW!>longMinValue - 1<!>
val l6: Long = <!INTEGER_OVERFLOW!>longMinValue - longMaxValue<!>
val l7: Long = longMinValue + longMaxValue
val l8: Long = -longMaxValue
val l10: Long = -intMinValue.toLong()
val l11: Long = -1 + intMinValue.toLong()
val l12: Long = <!INTEGER_OVERFLOW!>longMinValue * intMinValue<!>
val l13: Long = <!INTEGER_OVERFLOW!>longMinValue * -1<!>
val l14: Long = <!INTEGER_OVERFLOW!>longMinValue * 2<!>
val l15: Long = <!INTEGER_OVERFLOW!>longMaxValue * -2<!>
val l16: Long = intMinValue.toLong() * -1
val l19: Long = <!INTEGER_OVERFLOW!>longMinValue / -1<!>
}
}
@@ -0,0 +1,8 @@
// FILE: a.kt
package example.ns
val y: Any? = 2
// FILE: b.kt
package example
val x: Int = if (ns.y is Int) <!DEBUG_INFO_AUTOCAST!>ns.y<!> else 2
@@ -0,0 +1,49 @@
package test
// val prop1: 1.toInt()
val prop1 = A.a
// val prop2: 2.toInt()
val prop2 = A.a + 1
class A {
// val prop3: 1.toInt()
val prop3 = A.a
// val prop4: 2.toInt()
val prop4 = A.a + 1
class object {
val a = 1
}
}
fun foo() {
// val prop5: 1.toInt()
val prop5 = A.a
// val prop6: 2.toInt()
val prop6 = A.a + 1
val b = {
// val prop11: 1.toInt()
val prop11 = A.a
// val prop12: 2.toInt()
val prop12 = A.a + 1
}
val c = object: Foo {
override fun f() {
// val prop9: 1.toInt()
val prop9 = A.a
// val prop10: 2.toInt()
val prop10 = A.a + 1
}
}
}
trait Foo {
fun f()
}
@@ -0,0 +1,55 @@
package test
// val prop1: 1.toInt()
val prop1 = A().a
// val prop2: 2.toInt()
val prop2 = A().a + 1
class A() {
val a = 1
// val prop3: 1.toInt()
val prop3 = a
// val prop4: 2.toInt()
val prop4 = a + 1
fun foo() {
// val prop5: 1.toInt()
val prop5 = A().a
// val prop6: 2.toInt()
val prop6 = A().a + 1
val b = {
// val prop11: 1.toInt()
val prop11 = A().a
// val prop12: 2.toInt()
val prop12 = A().a + 1
}
val c = object: Foo {
override fun f() {
// val prop9: 1.toInt()
val prop9 = A().a
// val prop10: 2.toInt()
val prop10 = A().a + 1
}
}
}
}
fun foo() {
// val prop7: 1.toInt()
val prop7 = A().a
// val prop8: 2.toInt()
val prop8 = A().a + 1
}
trait Foo {
fun f()
}
@@ -0,0 +1,53 @@
package test
class A() {
fun foo() {
val a = 1
// val prop5: 1.toInt()
val prop5 = a
// val prop6: 2.toInt()
val prop6 = a + 1
fun local() {
// val prop1: 1.toInt()
val prop1 = a
// val prop2: 2.toInt()
val prop2 = a + 1
}
val b = {
// val prop3: 1.toInt()
val prop3 = a
// val prop4: 2.toInt()
val prop4 = a + 1
}
val c = object: Foo {
override fun f() {
// val prop9: 1.toInt()
val prop9 = a
// val prop10: 2.toInt()
val prop10 = a + 1
}
}
}
}
fun foo() {
val a = 1
// val prop7: 1.toInt()
val prop7 = a
// val prop8: 2.toInt()
val prop8 = a + 1
}
trait Foo {
fun f()
}
@@ -0,0 +1,53 @@
package test
class A() {
fun foo() {
var a = 1
// val prop5: null
val prop5 = a
// val prop6: null
val prop6 = a + 1
fun local() {
// val prop1: null
val prop1 = a
// val prop2: null
val prop2 = a + 1
}
val b = {
// val prop3: null
val prop3 = a
// val prop4: null
val prop4 = a + 1
}
val c = object: Foo {
override fun f() {
// val prop9: null
val prop9 = a
// val prop10: null
val prop10 = a + 1
}
}
}
}
fun foo() {
var a = 1
// val prop7: null
val prop7 = a
// val prop8: null
val prop8 = a + 1
}
trait Foo {
fun f()
}
@@ -0,0 +1,56 @@
package test
// val prop1: null
val prop1 = A().a
// val prop2: null
val prop2 = A().a + 1
class A() {
var a = 1
// val prop3: null
val prop3 = a
// val prop4: null
val prop4 = a + 1
fun foo() {
// val prop5: null
val prop5 = A().a
// val prop6: null
val prop6 = A().a + 1
val b = {
// val prop11: null
val prop11 = A().a
// val prop12: null
val prop12 = A().a + 1
}
val c = object: Foo {
override fun f() {
// val prop9: null
val prop9 = A().a
// val prop10: null
val prop10 = A().a + 1
}
}
}
}
fun foo() {
// val prop7: null
val prop7 = A().a
// val prop8: null
val prop8 = A().a + 1
}
trait Foo {
fun f()
}
@@ -0,0 +1,47 @@
package test
val a = 1
// val prop1: 1.toInt()
val prop1 = a
// val prop2: 2.toInt()
val prop2 = a + 1
class A {
// val prop3: 1.toInt()
val prop3 = a
// val prop4: 2.toInt()
val prop4 = a + 1
val b = {
// val prop11: 1.toInt()
val prop11 = a
// val prop12: 2.toInt()
val prop12 = a + 1
}
val c = object: Foo {
override fun f() {
// val prop9: 1.toInt()
val prop9 = a
// val prop10: 2.toInt()
val prop10 = a + 1
}
}
}
fun foo() {
// val prop5: 1.toInt()
val prop5 = a
// val prop6: 2.toInt()
val prop6 = a + 1
}
trait Foo {
fun f()
}
@@ -0,0 +1,47 @@
package test
var a = 1
// val prop1: null
val prop1 = a
// val prop2: null
val prop2 = a + 1
class A {
// val prop3: null
val prop3 = a
// val prop4: null
val prop4 = a + 1
val b = {
// val prop11: null
val prop11 = a
// val prop12: null
val prop12 = a + 1
}
val c = object: Foo {
override fun f() {
// val prop9: null
val prop9 = a
// val prop10: null
val prop10 = a + 1
}
}
}
fun foo() {
// val prop5: null
val prop5 = a
// val prop6: null
val prop6 = a + 1
}
trait Foo {
fun f()
}
@@ -2889,6 +2889,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/evaluate/parentesized.kt");
}
@TestMetadata("qualifiedExpressions.kt")
public void testQualifiedExpressions() throws Exception {
doTest("compiler/testData/diagnostics/tests/evaluate/qualifiedExpressions.kt");
}
@TestMetadata("unaryMinusDepOnExpType.kt")
public void testUnaryMinusDepOnExpType() throws Exception {
doTest("compiler/testData/diagnostics/tests/evaluate/unaryMinusDepOnExpType.kt");
@@ -32,6 +32,7 @@ import org.jetbrains.jet.JetTestUtils
import org.jetbrains.jet.util.slicedmap.WritableSlice
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant
import org.jetbrains.jet.lang.resolve.constants.StringValue
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
abstract class AbstractEvaluateExpressionTest: AbstractAnnotationDescriptorResolveTest() {
@@ -72,7 +73,9 @@ abstract class AbstractEvaluateExpressionTest: AbstractAnnotationDescriptorResol
val expected = InTextDirectivesUtils.findStringWithPrefixes(fileText, expectedPropertyPrefix)
assertNotNull(expected, "Failed to find expected directive: $expectedPropertyPrefix")
val property = AbstractAnnotationDescriptorResolveTest.getPropertyDescriptor(packageView, propertyName)
val property = AbstractAnnotationDescriptorResolveTest.getPropertyDescriptor(packageView, propertyName, false)
?: AbstractAnnotationDescriptorResolveTest.getLocalVarDescriptor(context!!, propertyName)
val jetProperty = BindingContextUtils.descriptorToDeclaration(context!!, property) as JetProperty
val testedObject = getValueToTest(jetProperty, context!!)
@@ -38,6 +38,11 @@ public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionT
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/evaluate/constant"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("classObjectProperty.kt")
public void testClassObjectProperty() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/classObjectProperty.kt");
}
@TestMetadata("compareTo.kt")
public void testCompareTo() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/compareTo.kt");
@@ -58,6 +63,11 @@ public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionT
doConstantTest("compiler/testData/evaluate/constant/exceptionWhenEvaluate.kt");
}
@TestMetadata("finalProperty.kt")
public void testFinalProperty() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/finalProperty.kt");
}
@TestMetadata("float.kt")
public void testFloat() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/float.kt");
@@ -78,11 +88,36 @@ public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionT
doConstantTest("compiler/testData/evaluate/constant/integers.kt");
}
@TestMetadata("localVal.kt")
public void testLocalVal() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/localVal.kt");
}
@TestMetadata("localVar.kt")
public void testLocalVar() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/localVar.kt");
}
@TestMetadata("nonFinalProperty.kt")
public void testNonFinalProperty() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/nonFinalProperty.kt");
}
@TestMetadata("strings.kt")
public void testStrings() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/strings.kt");
}
@TestMetadata("topLevelVal.kt")
public void testTopLevelVal() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/topLevelVal.kt");
}
@TestMetadata("topLevelVar.kt")
public void testTopLevelVar() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/topLevelVar.kt");
}
@TestMetadata("unaryMinusIndepWoExpType.kt")
public void testUnaryMinusIndepWoExpType() throws Exception {
doConstantTest("compiler/testData/evaluate/constant/unaryMinusIndepWoExpType.kt");
@@ -20,6 +20,7 @@ package org.jetbrains.jet.resolve.annotation;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
@@ -87,7 +88,7 @@ public abstract class AbstractAnnotationDescriptorResolveTest extends JetLiteFix
FunctionDescriptor topFoo = getFunctionDescriptor(test, "topFoo");
checkAnnotationsOnFunction(expectedAnnotation, topFoo);
PropertyDescriptor topProp = getPropertyDescriptor(test, "topProp");
PropertyDescriptor topProp = getPropertyDescriptor(test, "topProp", true);
checkAnnotationsOnProperty(expectedAnnotation, topProp);
checkDescriptor(expectedAnnotation, getClassDescriptor(test, "MyObject"));
@@ -100,7 +101,7 @@ public abstract class AbstractAnnotationDescriptorResolveTest extends JetLiteFix
checkDescriptor(expectedAnnotation, getLocalClassDescriptor("LocalClass"));
checkDescriptor(expectedAnnotation, getLocalObjectDescriptor("LocalObject"));
checkDescriptor(expectedAnnotation, getLocalFunDescriptor("localFun"));
checkDescriptor(expectedAnnotation, getLocalVarDescriptor("localVar"));
checkDescriptor(expectedAnnotation, getLocalVarDescriptor(context, "localVar"));
}
private static void checkAnnotationsOnProperty(String expectedAnnotation, PropertyDescriptor prop) {
@@ -134,12 +135,30 @@ public abstract class AbstractAnnotationDescriptorResolveTest extends JetLiteFix
return functions.iterator().next();
}
@NotNull
protected static PropertyDescriptor getPropertyDescriptor(@NotNull PackageViewDescriptor packageView, @NotNull String name) {
@Nullable
protected static PropertyDescriptor getPropertyDescriptor(@NotNull PackageViewDescriptor packageView, @NotNull String name, boolean failOnMissing) {
Name propertyName = Name.identifier(name);
JetScope memberScope = packageView.getMemberScope();
Collection<VariableDescriptor> properties = memberScope.getProperties(propertyName);
assert properties.size() == 1 : "Failed to find property " + propertyName + " in class " + packageView.getName();
if (properties.isEmpty()) {
for (DeclarationDescriptor descriptor : memberScope.getAllDescriptors()) {
if (descriptor instanceof ClassDescriptor) {
Collection<VariableDescriptor> classProperties =
((ClassDescriptor) descriptor).getMemberScope(Collections.<TypeProjection>emptyList())
.getProperties(propertyName);
if (!classProperties.isEmpty()) {
properties = classProperties;
break;
}
}
}
}
if (failOnMissing) {
assert properties.size() == 1 : "Failed to find property " + propertyName + " in class " + packageView.getName();
}
else if (properties.size() != 1) {
return null;
}
return (PropertyDescriptor) properties.iterator().next();
}
@@ -216,7 +235,7 @@ public abstract class AbstractAnnotationDescriptorResolveTest extends JetLiteFix
}
@NotNull
private VariableDescriptor getLocalVarDescriptor(@NotNull String name) {
protected static VariableDescriptor getLocalVarDescriptor(@NotNull BindingContext context, @NotNull String name) {
for (VariableDescriptor descriptor : context.getSliceContents(BindingContext.VARIABLE).values()) {
if (descriptor.getName().asString().equals(name)) {
return descriptor;
@@ -24,11 +24,20 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public abstract class CompileTimeConstant<T> {
protected final T value;
private boolean canBeUsedInAnnotations = true;
protected CompileTimeConstant(T value) {
this.value = value;
}
public boolean canBeUsedInAnnotations() {
return canBeUsedInAnnotations;
}
public void setCanBeUsedInAnnotations(boolean canBeUsedInAnnotations) {
this.canBeUsedInAnnotations = canBeUsedInAnnotations;
}
@Nullable
public T getValue() {
return value;