diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java index 13aac25950a..929a1ecfe28 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java @@ -38,6 +38,7 @@ public class JavaPropertyInitializerEvaluatorImpl implements JavaPropertyInitial evaluatedExpression, DescriptorUtils.isPropertyCompileTimeConstant(descriptor), false, + true, descriptor.getType()); } return null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt index 641ae0175a9..ee991176026 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt @@ -54,7 +54,6 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet trace.record(BindingContext.COMPILE_TIME_VALUE, expression, compileTimeConstant) return compileTimeConstant } - return null } @@ -70,9 +69,9 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet return createStringConstant(this@ConstantExpressionEvaluator.evaluate(expression, KotlinBuiltIns.getInstance().getStringType())) } - override fun visitLiteralStringTemplateEntry(entry: JetLiteralStringTemplateEntry, data: Nothing?) = StringValue(entry.getText(), true) + override fun visitLiteralStringTemplateEntry(entry: JetLiteralStringTemplateEntry, data: Nothing?) = StringValue(entry.getText(), true, false) - override fun visitEscapeStringTemplateEntry(entry: JetEscapeStringTemplateEntry, data: Nothing?) = StringValue(entry.getUnescapedValue(), true) + override fun visitEscapeStringTemplateEntry(entry: JetEscapeStringTemplateEntry, data: Nothing?) = StringValue(entry.getUnescapedValue(), true, false) } override fun visitConstantExpression(expression: JetConstantExpression, expectedType: JetType?): CompileTimeConstant<*>? { @@ -92,8 +91,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet if (result == null) return null fun isLongWithSuffix() = nodeElementType == JetNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text) - - return createCompileTimeConstant(result, expectedType, !isLongWithSuffix()) + return createCompileTimeConstant(result, expectedType, !isLongWithSuffix(), true, false) } override fun visitParenthesizedExpression(expression: JetParenthesizedExpression, expectedType: JetType?): CompileTimeConstant<*>? { @@ -118,6 +116,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val sb = StringBuilder() var interupted = false var canBeUsedInAnnotation = true + var usesVariableAsConstant = false for (entry in expression.getEntries()) { val constant = stringExpressionEvaluator.evaluate(entry) if (constant == null) { @@ -126,12 +125,14 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet } else { if (!constant.canBeUsedInAnnotations()) canBeUsedInAnnotation = false + if (constant.usesVariableAsConstant()) usesVariableAsConstant = true sb.append(constant.getValue()) } } return if (!interupted) createCompileTimeConstant(sb.toString(), expectedType, - isPure = true, canBeUsedInAnnotation = canBeUsedInAnnotation) + isPure = true, canBeUsedInAnnotation = canBeUsedInAnnotation, + usesVariableAsConstant = usesVariableAsConstant) else null } @@ -160,7 +161,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet JetTokens.OROR -> leftValue as Boolean || rightValue as Boolean else -> throw IllegalArgumentException("Unknown boolean operation token ${operationToken}") } - return createCompileTimeConstant(result, expectedType) + val usesVariableAsConstant = leftConstant.usesVariableAsConstant() || rightConstant.usesVariableAsConstant() + return createCompileTimeConstant(result, expectedType, true, true, usesVariableAsConstant) } else { return evaluateCall(expression.getOperationReference(), leftExpression, expectedType) @@ -182,12 +184,16 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet if (result == null) return null val isArgumentPure = isPureConstant(argumentForReceiver.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) + val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS - return createCompileTimeConstant(result, expectedType, !isNumberConversionMethod && isArgumentPure, canBeUsedInAnnotation) + return createCompileTimeConstant(result, + expectedType, + !isNumberConversionMethod && isArgumentPure, + canBeUsedInAnnotation, + usesVariableAsConstant) } else if (argumentsEntrySet.size() == 1) { val (parameter, argument) = argumentsEntrySet.first() - val argumentForParameter = createOperationArgumentForFirstParameter(argument, parameter) if (argumentForParameter == null) return null @@ -200,12 +206,13 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression) - val c = EvaluatorContext(canBeUsedInAnnotation, areArgumentsPure) + val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) || usesVariableAsConstant(argumentForParameter.expression) + val c = EvaluatorContext(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant) return when(resultingDescriptorName) { OperatorConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, c) OperatorConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, c) else -> { - createCompileTimeConstant(result, expectedType, areArgumentsPure, canBeUsedInAnnotation) + createCompileTimeConstant(result, expectedType, areArgumentsPure, canBeUsedInAnnotation, usesVariableAsConstant) } } } @@ -213,7 +220,10 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet return null } + private fun usesVariableAsConstant(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.usesVariableAsConstant() ?: false + private fun canBeUsedInAnnotation(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.canBeUsedInAnnotations() ?: false + private fun isPureConstant(expression: JetExpression): Boolean { val compileTimeConstant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression) if (compileTimeConstant is IntegerValueConstant) { @@ -287,7 +297,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet override fun visitSimpleNameExpression(expression: JetSimpleNameExpression, expectedType: JetType?): CompileTimeConstant<*>? { val enumDescriptor = trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, expression); if (enumDescriptor != null && DescriptorUtils.isEnumEntry(enumDescriptor)) { - return EnumValue(enumDescriptor as ClassDescriptor); + return EnumValue(enumDescriptor as ClassDescriptor, false); } val resolvedCall = trace.getBindingContext().get(BindingContext.RESOLVED_CALL, expression) @@ -303,7 +313,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet else compileTimeConstant.getValue() return createCompileTimeConstant(value, expectedType, isPure = false, - canBeUsedInAnnotation = DescriptorUtils.isPropertyCompileTimeConstant(callableDescriptor)) + canBeUsedInAnnotation = DescriptorUtils.isPropertyCompileTimeConstant(callableDescriptor), + usesVariableAsConstant = true) } } return null @@ -341,7 +352,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val varargType = resultingDescriptor.getValueParameters().first?.getVarargElementType()!! val arguments = call.getValueArguments().values().flatMap { resolveArguments(it.getArguments(), varargType) } - return ArrayValue(arguments, resultingDescriptor.getReturnType()!!, true) + return ArrayValue(arguments, resultingDescriptor.getReturnType()!!, true, arguments.any() { it.usesVariableAsConstant() }) } // Ann() @@ -402,7 +413,6 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val argumentExpression = arguments.first().getArgumentExpression() if (argumentExpression == null) return null - return createOperationArgument(argumentExpression, parameter.getType(), argumentCompileTimeType) } @@ -421,8 +431,12 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet return OperationArgument(evaluationResult, compileTimeType, expression) } - fun createCompileTimeConstant(value: Any?, expectedType: JetType?, isPure: Boolean = true, canBeUsedInAnnotation: Boolean = true): CompileTimeConstant<*>? { - val c = EvaluatorContext(canBeUsedInAnnotation, isPure) + fun createCompileTimeConstant(value: Any?, + expectedType: JetType?, + isPure: Boolean = true, + canBeUsedInAnnotation: Boolean = true, + usesVariableAsConstant: Boolean = false): CompileTimeConstant<*>? { + val c = EvaluatorContext(canBeUsedInAnnotation, isPure, usesVariableAsConstant) return createCompileTimeConstant(value, c, if (isPure) expectedType ?: TypeUtils.NO_EXPECTED_TYPE else null) } } @@ -490,11 +504,11 @@ private fun createCompileTimeConstantForEquals(result: Any?, operationReference: assert(operationReference is JetSimpleNameExpression, "This method should be called only for equals operations") val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType() return when (operationToken) { - JetTokens.EQEQ -> BooleanValue(result, c.canBeUsedInAnnotation) - JetTokens.EXCLEQ -> BooleanValue(!result, c.canBeUsedInAnnotation) + JetTokens.EQEQ -> BooleanValue(result, c.canBeUsedInAnnotation, c.usesVariableAsConstant) + JetTokens.EXCLEQ -> BooleanValue(!result, c.canBeUsedInAnnotation, c.usesVariableAsConstant) JetTokens.IDENTIFIER -> { assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.EQUALS, "This method should be called only for equals operations") - return BooleanValue(result, c.canBeUsedInAnnotation) + return BooleanValue(result, c.canBeUsedInAnnotation, c.usesVariableAsConstant) } else -> throw IllegalStateException("Unknown equals operation token: $operationToken ${operationReference.getText()}") } @@ -507,13 +521,13 @@ private fun createCompileTimeConstantForCompareTo(result: Any?, operationReferen assert(operationReference is JetSimpleNameExpression, "This method should be called only for compareTo operations") val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType() return when (operationToken) { - JetTokens.LT -> BooleanValue(result < 0, c.canBeUsedInAnnotation) - JetTokens.LTEQ -> BooleanValue(result <= 0, c.canBeUsedInAnnotation) - JetTokens.GT -> BooleanValue(result > 0, c.canBeUsedInAnnotation) - JetTokens.GTEQ -> BooleanValue(result >= 0, c.canBeUsedInAnnotation) + JetTokens.LT -> BooleanValue(result < 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant) + JetTokens.LTEQ -> BooleanValue(result <= 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant) + JetTokens.GT -> BooleanValue(result > 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant) + JetTokens.GTEQ -> BooleanValue(result >= 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant) JetTokens.IDENTIFIER -> { assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.COMPARE_TO, "This method should be called only for compareTo operations") - return IntValue(result, c.canBeUsedInAnnotation, c.isPure) + return IntValue(result, c.canBeUsedInAnnotation, c.isPure, c.usesVariableAsConstant) } else -> throw IllegalStateException("Unknown compareTo operation token: $operationToken") } @@ -523,19 +537,19 @@ private fun createCompileTimeConstantForCompareTo(result: Any?, operationReferen private fun createStringConstant(value: CompileTimeConstant<*>?): StringValue? { return when (value) { - is IntegerValueTypeConstant -> StringValue(value.getValue(TypeUtils.NO_EXPECTED_TYPE).toString(), value.canBeUsedInAnnotations()) + is IntegerValueTypeConstant -> StringValue(value.getValue(TypeUtils.NO_EXPECTED_TYPE).toString(), value.canBeUsedInAnnotations(), value.usesVariableAsConstant()) is StringValue -> value is IntValue, is ByteValue, is ShortValue, is LongValue, is CharValue, is DoubleValue, is FloatValue, is BooleanValue, - is NullValue -> StringValue(value.getValue().toString(), value.canBeUsedInAnnotations()) + is NullValue -> StringValue(value.getValue().toString(), value.canBeUsedInAnnotations(), value.usesVariableAsConstant()) else -> null } } private fun createCompileTimeConstant(value: Any?, c: EvaluatorContext, expectedType: JetType? = null): CompileTimeConstant<*>? { - return createCompileTimeConstant(value, c.canBeUsedInAnnotation, c.isPure, expectedType) + return createCompileTimeConstant(value, c.canBeUsedInAnnotation, c.isPure, c.usesVariableAsConstant, expectedType) } fun isIntegerType(value: Any?) = value is Byte || value is Short || value is Int || value is Long @@ -567,7 +581,7 @@ private fun getCompileTimeType(c: JetType): CompileTimeType? { } } -private class EvaluatorContext(val canBeUsedInAnnotation: Boolean, val isPure: Boolean) +private class EvaluatorContext(val canBeUsedInAnnotation: Boolean, val isPure: Boolean, val usesVariableAsConstant: Boolean = false) private class CompileTimeType diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index c0195fc28d9..a6e31b0b0ce 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; import com.intellij.openapi.util.Pair; +import kotlin.Function1; import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -282,11 +283,20 @@ public class AnnotationResolver { trace); if (argumentsAsVararg) { + + boolean usesVariableAsConstant = KotlinPackage.any(constants, new Function1, Boolean>() { + @Override + public Boolean invoke(CompileTimeConstant constant) { + return constant.usesVariableAsConstant(); + } + }); + JetType arrayType = KotlinBuiltIns.getInstance().getPrimitiveArrayJetTypeByPrimitiveJetType(varargElementType); if (arrayType == null) { arrayType = KotlinBuiltIns.getInstance().getArrayType(varargElementType); } - return new ArrayValue(constants, arrayType, true); + + return new ArrayValue(constants, arrayType, true, usesVariableAsConstant); } else { // we should actually get only one element, but just in case of getting many, we take the last one diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java index 5fc5f3e7770..8cb6b4ff9e0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java @@ -18,13 +18,11 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.Annotated; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator; -import org.jetbrains.jet.lang.psi.JetConstantExpression; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetParameter; import org.jetbrains.jet.lang.psi.JetTypeReference; @@ -129,12 +127,10 @@ public class CompileTimeConstantUtils { @NotNull BindingTrace trace, @Nullable Boolean expectedValue ) { - if (!(expression instanceof JetConstantExpression) || expression.getNode().getElementType() != JetNodeTypes.BOOLEAN_CONSTANT) { - return false; - } + if (expression == null) return false; CompileTimeConstant compileTimeConstant = ConstantExpressionEvaluator.object$.evaluate(expression, trace, KotlinBuiltIns.getInstance().getBooleanType()); - if (!(compileTimeConstant instanceof BooleanValue)) return false; + if (!(compileTimeConstant instanceof BooleanValue) || compileTimeConstant.usesVariableAsConstant()) return false; Boolean value = ((BooleanValue) compileTimeConstant).getValue(); return expectedValue == null || expectedValue.equals(value); diff --git a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions index 62b6f1fde5f..47e3b1c956f 100644 --- a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions +++ b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions @@ -1,25 +1,25 @@ == main == fun main() { - while(1 > 0) { + while(0 > 1) { 2 } } --------------------- L0: 1 - 2 mark({ while(1 > 0) { 2 } }) - mark(while(1 > 0) { 2 }) + 2 mark({ while(0 > 1) { 2 } }) + mark(while(0 > 1) { 2 }) L2 [loop entry point]: L5 [condition entry point]: - mark(1 > 0) PREV:[mark(while(1 > 0) { 2 }), jmp(L2 [loop entry point])] - r(1) + mark(0 > 1) PREV:[mark(while(0 > 1) { 2 }), jmp(L2 [loop entry point])] r(0) + r(1) call(>, compareTo) jf(L3 [loop exit point]) NEXT:[read (Unit), mark({ 2 })] L4 [body entry point]: 3 mark({ 2 }) r(2) - 2 jmp(L2 [loop entry point]) NEXT:[mark(1 > 0)] + 2 jmp(L2 [loop entry point]) NEXT:[mark(0 > 1)] L3 [loop exit point]: read (Unit) PREV:[jf(L3 [loop exit point])] L1: @@ -32,21 +32,21 @@ sink: == dowhile == fun dowhile() { do {return} - while(1 > 0) + while(0 > 1) } --------------------- L0: 1 - 2 mark({ do {return} while(1 > 0) }) - 3 mark(do {return} while(1 > 0)) + 2 mark({ do {return} while(0 > 1) }) + 3 mark(do {return} while(0 > 1)) L2 [loop entry point]: L4 [body entry point]: mark({return}) ret L1 NEXT:[] L5 [condition entry point]: -- mark(1 > 0) PREV:[] -- r(1) PREV:[] +- mark(0 > 1) PREV:[] - r(0) PREV:[] +- r(1) PREV:[] - call(>, compareTo) PREV:[] - jt(L2 [loop entry point]) NEXT:[read (Unit), mark({return})] PREV:[] L3 [loop exit point]: diff --git a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt index 2cbdf061634..0e4aa0aa8e6 100644 --- a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt +++ b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt @@ -1,10 +1,10 @@ fun main() { - while(1 > 0) { + while(0 > 1) { 2 } } fun dowhile() { do {return} - while(1 > 0) + while(0 > 1) } diff --git a/compiler/testData/diagnostics/tests/annotations/onLoops.kt b/compiler/testData/diagnostics/tests/annotations/onLoops.kt index 427af32532a..954c7050f19 100644 --- a/compiler/testData/diagnostics/tests/annotations/onLoops.kt +++ b/compiler/testData/diagnostics/tests/annotations/onLoops.kt @@ -1,9 +1,9 @@ fun test() { [ann] - while (1 < 2) {} + while (2 < 1) {} [ann] - do {} while (1 < 2) + do {} while (2 < 1) [ann] for (i in 1..2) {} diff --git a/compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt b/compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt new file mode 100644 index 00000000000..0ac9390d72a --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt @@ -0,0 +1,12 @@ +fun test() { + [ann] + while (2 > 1) {} + + [ann] + do {} while (2 > 1) + + [ann] + for (i in 1..2) {} +} + +annotation class ann \ No newline at end of file diff --git a/compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt b/compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt new file mode 100644 index 00000000000..50bfaefa0f2 --- /dev/null +++ b/compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt @@ -0,0 +1,11 @@ +package test + +val x = 1 +val y = "a" + +// val prop1: true +val prop1 = x + +// val prop2: true +val prop2 = y + diff --git a/compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt b/compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt new file mode 100644 index 00000000000..eed8758f371 --- /dev/null +++ b/compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt @@ -0,0 +1,16 @@ +package test + +enum class MyEnum { A;B } + +fun foo(): Boolean = true + +val x = 1 + +// val prop1: null +val prop1 = MyEnum.A + +// val prop2: null +val prop2 = foo() + +// val prop3: true +val prop3 = "$x" \ No newline at end of file diff --git a/compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt b/compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt new file mode 100644 index 00000000000..fb22226574b --- /dev/null +++ b/compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt @@ -0,0 +1,29 @@ +package test + +val x = 1 +val y = true + +// val prop1: false +val prop1 = 1 > 2 + +// val prop2: false +val prop2 = 2 + 3 + +// val prop3: true +val prop3 = 2 + x + +// val prop4: true +val prop4 = x < 2 + +// val prop5: true +val prop5 = y && true + +// val prop6: false +val prop6 = true && false || 2 > 1 + +// val prop7: true +val prop7 = x == 1 + +// val prop8: true +val prop8 = 1 / x + diff --git a/compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt b/compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt new file mode 100644 index 00000000000..ed6fcb4b07a --- /dev/null +++ b/compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt @@ -0,0 +1,23 @@ +package test + +// val prop1: false +val prop1 = 1 + +// val prop2: false +val prop2 = "hello" + +// val prop3: false +val prop3 = true + +// val prop4: false +val prop4 = false + +// val prop5: false +val prop5 = -7453 + +// val prop6: false +val prop6 = 3.56 + +// val prop7: false +val prop7 = 5464564L + diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 056c34b859f..b356c8e0b9d 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -616,6 +616,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/annotations/onLoops.kt"); } + @TestMetadata("onLoopsUnreachable.kt") + public void testOnLoopsUnreachable() throws Exception { + doTest("compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt"); + } + @TestMetadata("onMultiDeclaration.kt") public void testOnMultiDeclaration() throws Exception { doTest("compiler/testData/diagnostics/tests/annotations/onMultiDeclaration.kt"); diff --git a/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt b/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt index 08147d345c1..f2c9aa5c313 100644 --- a/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt +++ b/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt @@ -20,20 +20,18 @@ import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.resolve.annotation.AbstractAnnotationDescriptorResolveTest import java.io.File import com.intellij.openapi.util.io.FileUtil -import org.jetbrains.jet.lang.resolve.BindingContextUtils -import org.jetbrains.jet.lang.psi.JetProperty import org.jetbrains.jet.InTextDirectivesUtils -import kotlin.test.assertEquals import kotlin.test.assertNotNull import java.util.regex.Pattern -import org.intellij.lang.annotations.RegExp -import com.intellij.openapi.util.text.StringUtil 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 import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant +import java.util.HashMap +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace +import org.jetbrains.jet.lang.types.TypeUtils abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorResolveTest() { @@ -63,6 +61,19 @@ abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorReso } } + // Test directives should look like [// val testedPropertyName: expectedValue] + fun doUsesVariableAsConstantTest(path: String) { + doTest(path) { + property, context -> + val compileTimeConstant = property.getCompileTimeInitializer() + if (compileTimeConstant == null) { + "null" + } else { + compileTimeConstant.usesVariableAsConstant().toString() + } + } + } + private fun doTest(path: String, getValueToTest: (VariableDescriptor, BindingContext) -> String) { val myFile = File(path) val fileText = FileUtil.loadFile(myFile, true) diff --git a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java index 89de1e1eda9..2e75c5fa72a 100644 --- a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java @@ -30,7 +30,7 @@ import org.jetbrains.jet.evaluate.AbstractEvaluateExpressionTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@InnerTestClasses({EvaluateExpressionTestGenerated.Constant.class, EvaluateExpressionTestGenerated.IsPure.class}) +@InnerTestClasses({EvaluateExpressionTestGenerated.Constant.class, EvaluateExpressionTestGenerated.IsPure.class, EvaluateExpressionTestGenerated.UsesVariableAsConstant.class}) public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionTest { @TestMetadata("compiler/testData/evaluate/constant") public static class Constant extends AbstractEvaluateExpressionTest { @@ -168,10 +168,39 @@ public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionT } + @TestMetadata("compiler/testData/evaluate/usesVariableAsConstant") + public static class UsesVariableAsConstant extends AbstractEvaluateExpressionTest { + public void testAllFilesPresentInUsesVariableAsConstant() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/evaluate/usesVariableAsConstant"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("binaryTypes.kt") + public void testBinaryTypes() throws Exception { + doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt"); + } + + @TestMetadata("NamedConstants.kt") + public void testNamedConstants() throws Exception { + doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt"); + } + + @TestMetadata("OtherTypes.kt") + public void testOtherTypes() throws Exception { + doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt"); + } + + @TestMetadata("simpleTypes.kt") + public void testSimpleTypes() throws Exception { + doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt"); + } + + } + public static Test suite() { TestSuite suite = new TestSuite("EvaluateExpressionTestGenerated"); suite.addTestSuite(Constant.class); suite.addTestSuite(IsPure.class); + suite.addTestSuite(UsesVariableAsConstant.class); return suite; } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt index 6b4a87b2a23..c3b11250b21 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt @@ -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<*>? { diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java index 1dbb21646d0..c1bcb19ff05 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java @@ -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); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java index 9ef635890e4..a0e7c12688a 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java @@ -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); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java index 3eed4039b4f..6de8be2b9db 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java @@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class AnnotationValue extends CompileTimeConstant { public AnnotationValue(@NotNull AnnotationDescriptor value) { - super(value, true); + super(value, true, false, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java index d082d2a7410..a62af0666b8 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java @@ -27,8 +27,11 @@ public class ArrayValue extends CompileTimeConstant> private final JetType type; - public ArrayValue(@NotNull List> value, @NotNull JetType type, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public ArrayValue(@NotNull List> value, + @NotNull JetType type, + boolean canBeUsedInAnnotations, + boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, false, usesVariableAsConstant); this.type = type; } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java index 76494dbc3ea..f83621dcf16 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType; public class BooleanValue extends CompileTimeConstant { - public BooleanValue(boolean value, boolean canBeUseInAnnotation) { - super(value, canBeUseInAnnotation); + public BooleanValue(boolean value, boolean canBeUseInAnnotation, boolean usesVariableAsConstant) { + super(value, canBeUseInAnnotation, false, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java index 74ea6b13c73..7c030c6cd4d 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class ByteValue extends IntegerValueConstant { - 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 diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java index 197c2e1aac3..41b1d0db9d6 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType; public class CharValue extends IntegerValueConstant { - 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 diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java index 07dce8a09bf..205aa23a67e 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java @@ -24,15 +24,38 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public abstract class CompileTimeConstant { 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 diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt index 39e85825861..5fe1f759334 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt @@ -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) } } \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java index 6f06ee2e642..d342fe312f8 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType; public class DoubleValue extends CompileTimeConstant { - public DoubleValue(double value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public DoubleValue(double value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, false, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java index 0b6f05a566a..b5c97152ab0 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java @@ -24,8 +24,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class EnumValue extends CompileTimeConstant { - public EnumValue(@NotNull ClassDescriptor value) { - super(value, true); + public EnumValue(@NotNull ClassDescriptor value, boolean usesVariableAsConstant) { + super(value, true, false, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java index 465dde4892c..60c9471184c 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java @@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public abstract class ErrorValue extends CompileTimeConstant { public ErrorValue() { - super(null, true); + super(null, true, false, false); } @Override diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java index 3e439e467a7..102912ae4bc 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType; public class FloatValue extends CompileTimeConstant { - public FloatValue(float value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public FloatValue(float value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, false, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java index 0f411c4bbda..5d39377065d 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class IntValue extends IntegerValueConstant { - 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 diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueConstant.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueConstant.java index fa21468393c..a2d34cf91af 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueConstant.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueConstant.java @@ -18,19 +18,7 @@ package org.jetbrains.jet.lang.resolve.constants; public abstract class IntegerValueConstant extends CompileTimeConstant { - /* - * 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); } } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java index a1425930b2a..7bac4b2d574 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java @@ -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 { 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()); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java index 60b2e3f631b..d1b8bd25e21 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java @@ -24,7 +24,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class JavaClassValue extends CompileTimeConstant { public JavaClassValue(@NotNull JetType value) { - super(value, true); + super(value, true, false, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java index 326c53fb05f..32c23057164 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class LongValue extends IntegerValueConstant { - 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 diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java index e9cdaeb553f..37085399151 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java @@ -26,7 +26,7 @@ public class NullValue extends CompileTimeConstant { public static final NullValue NULL = new NullValue(); private NullValue() { - super(null, false); + super(null, false, false, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java index 1df4b4e7b51..36bfee596c3 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class ShortValue extends IntegerValueConstant { - 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 diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java index 1c1a762a456..316912f65f4 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType; public class StringValue extends CompileTimeConstant { - public StringValue(String value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public StringValue(String value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, false, usesVariableAsConstant); } @NotNull diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index 3014280c0a4..f94762b0cf7 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -242,6 +242,7 @@ fun main(args: Array) { testClass(javaClass()) { model("evaluate/constant", testMethod = "doConstantTest") model("evaluate/isPure", testMethod = "doIsPureTest") + model("evaluate/usesVariableAsConstant", testMethod = "doUsesVariableAsConstantTest") } }