From 2a023c16a983dd0ea01df1ee05245e9ed58646e3 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Mon, 2 Dec 2013 15:01:32 +0400 Subject: [PATCH] Use type from compile time value for prefix expression --- .../evaluate/ConstantExpressionEvaluator.kt | 142 ++++++++++++++---- .../jet/lang/resolve/AnnotationResolver.java | 9 ++ .../jet/lang/resolve/BindingContext.java | 1 + .../resolve/calls/ArgumentTypeResolver.java | 16 +- .../constants/IntegerValueTypeConstant.java | 39 +++++ .../IntegerValueTypeConstructor.java | 7 +- .../BasicExpressionTypingVisitor.java | 67 +++++---- .../lang/types/expressions/DataFlowUtils.java | 7 +- .../tests/evaluate/unaryMinusDepOnExpType.kt | 34 +++++ .../evaluate/unaryMinusIndepWoExpType.kt | 41 +++++ .../evaluate/unaryMinusIndependentExpType.kt | 29 ++++ .../testData/evaluate/constant/compareTo.kt | 19 +++ .../evaluate/{ => constant}/divideByZero.kt | 0 compiler/testData/evaluate/constant/equals.kt | 4 + .../{ => constant}/floatsAndDoubles.kt | 0 .../testData/evaluate/constant/integers.kt | 10 ++ .../evaluate/{ => constant}/strings.kt | 6 + .../constant/unaryMinusIndepWoExpType.kt | 16 ++ .../constant/unaryMinusIndependentExpType.kt | 63 ++++++++ compiler/testData/evaluate/integers.kt | 19 --- compiler/testData/evaluate/isPure/enum.kt | 9 ++ .../testData/evaluate/isPure/innerToType.kt | 13 ++ compiler/testData/evaluate/isPure/strings.kt | 16 ++ compiler/testData/evaluate/isPure/toType.kt | 22 +++ .../isPure/unaryMinusIndepWoExpType.kt | 16 ++ .../isPure/unaryMinusIndependentExpType.kt | 63 ++++++++ .../AnnotationOnObject.txt | 2 +- .../WrongAnnotationArgsOnObject.txt | 2 +- .../annotations/classes/WithArgument.txt | 2 +- .../classes/WithMultipleArguments.txt | 2 +- .../resolveAnnotations/parameters/byte.kt | 2 +- .../parameters/expressions/labeled.kt | 6 +- .../parameters/expressions/maxValueByte.kt | 2 +- .../parameters/expressions/maxValueInt.kt | 2 +- .../parameters/expressions/unaryMinus.kt | 2 +- .../parameters/expressions/unaryPlus.kt | 2 +- .../resolveAnnotations/parameters/int.kt | 2 +- .../resolveAnnotations/parameters/long.kt | 2 +- .../resolveAnnotations/parameters/short.kt | 2 +- .../checkers/JetDiagnosticsTestGenerated.java | 15 ++ .../AbstractEvaluateExpressionTest.kt | 44 +++++- .../EvaluateExpressionTestGenerated.java | 108 ++++++++++--- ...stractAnnotationDescriptorResolveTest.java | 10 ++ .../AbstractAnnotationParameterTest.kt | 5 +- .../AnnotationDescriptorResolveTest.java | 8 +- .../AnnotationArgumentVisitor.java | 2 + .../constants/NumberValueTypeConstant.java | 48 ++++++ .../constants/NumberValueTypeConstructor.java | 4 +- .../jet/generators/tests/GenerateTests.java | 3 +- 49 files changed, 805 insertions(+), 140 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java create mode 100644 compiler/testData/diagnostics/tests/evaluate/unaryMinusDepOnExpType.kt create mode 100644 compiler/testData/diagnostics/tests/evaluate/unaryMinusIndepWoExpType.kt create mode 100644 compiler/testData/diagnostics/tests/evaluate/unaryMinusIndependentExpType.kt create mode 100644 compiler/testData/evaluate/constant/compareTo.kt rename compiler/testData/evaluate/{ => constant}/divideByZero.kt (100%) create mode 100644 compiler/testData/evaluate/constant/equals.kt rename compiler/testData/evaluate/{ => constant}/floatsAndDoubles.kt (100%) create mode 100644 compiler/testData/evaluate/constant/integers.kt rename compiler/testData/evaluate/{ => constant}/strings.kt (79%) create mode 100644 compiler/testData/evaluate/constant/unaryMinusIndepWoExpType.kt create mode 100644 compiler/testData/evaluate/constant/unaryMinusIndependentExpType.kt delete mode 100644 compiler/testData/evaluate/integers.kt create mode 100644 compiler/testData/evaluate/isPure/enum.kt create mode 100644 compiler/testData/evaluate/isPure/innerToType.kt create mode 100644 compiler/testData/evaluate/isPure/strings.kt create mode 100644 compiler/testData/evaluate/isPure/toType.kt create mode 100644 compiler/testData/evaluate/isPure/unaryMinusIndepWoExpType.kt create mode 100644 compiler/testData/evaluate/isPure/unaryMinusIndependentExpType.kt create mode 100644 core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NumberValueTypeConstant.java 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 cbe564b1079..484774be7b0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt @@ -93,7 +93,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet } if (result == null && expression.getNode().getElementType() == JetNodeTypes.NULL) return NullValue.NULL - return createCompileTimeConstant(result, expectedType) + return createCompileTimeConstant(result, expression, expectedType) } override fun visitParenthesizedExpression(expression: JetParenthesizedExpression, expectedType: JetType?): CompileTimeConstant<*>? { @@ -127,7 +127,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet sb.append(constant.getValue()) } } - return if (!interupted) createCompileTimeConstant(sb.toString(), expectedType) else null + return if (!interupted) createCompileTimeConstant(sb.toString(), expression, expectedType) else null } override fun visitBinaryExpression(expression: JetBinaryExpression, expectedType: JetType?): CompileTimeConstant<*>? { @@ -155,23 +155,18 @@ 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) + return createCompileTimeConstant(result, expression, expectedType) } else { - val result = evaluateCall(expression.getOperationReference(), leftExpression) - return when(operationToken) { - in OperatorConventions.COMPARISON_OPERATIONS -> createCompileTimeConstantForCompareTo(result, operationToken!!) - in OperatorConventions.EQUALS_OPERATIONS -> createCompileTimeConstantForEquals(result, operationToken!!) - else -> createCompileTimeConstant(result, expectedType) - } + return evaluateCall(expression, expression.getOperationReference(), leftExpression, expectedType) } } - private fun evaluateCall(callExpression: JetExpression, receiverExpression: JetExpression): Any? { + private fun evaluateCall(fullExpression: JetExpression, callExpression: JetExpression, receiverExpression: JetExpression, expectedType: JetType?): CompileTimeConstant<*>? { val resolvedCall = trace.getBindingContext().get(BindingContext.RESOLVED_CALL, callExpression) if (resolvedCall == null) return null - val resultingDescriptorName = resolvedCall.getResultingDescriptor()?.getName()?.asString() + val resultingDescriptorName = resolvedCall.getResultingDescriptor()?.getName() if (resultingDescriptorName == null) return null val argumentForReceiver = createOperationArgumentForReceiver(resolvedCall, receiverExpression) @@ -179,7 +174,10 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val argumentsEntrySet = resolvedCall.getValueArguments().entrySet() if (argumentsEntrySet.isEmpty()) { - return evaluateUnaryAndCheck(argumentForReceiver, resultingDescriptorName, callExpression) + val result = evaluateUnaryAndCheck(argumentForReceiver, resultingDescriptorName.asString(), callExpression) + val isArgumentPure = trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, argumentForReceiver.expression) + val isNumberConventionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS + return createCompileTimeConstant(result, fullExpression, expectedType, !isNumberConventionMethod && isArgumentPure ?: false) } else if (argumentsEntrySet.size() == 1) { val (parameter, argument) = argumentsEntrySet.first() @@ -187,7 +185,16 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val argumentForParameter = createOperationArgumentForFirstParameter(argument, parameter) if (argumentForParameter == null) return null - return evaluateBinaryAndCheck(argumentForReceiver, argumentForParameter, resultingDescriptorName, callExpression) + val result = evaluateBinaryAndCheck(argumentForReceiver, argumentForParameter, resultingDescriptorName.asString(), callExpression) + return when(resultingDescriptorName) { + OperatorConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression) + OperatorConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression) + 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) + } + } } return null @@ -251,8 +258,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet override fun visitUnaryExpression(expression: JetUnaryExpression, expectedType: JetType?): CompileTimeConstant<*>? { val leftExpression = expression.getBaseExpression() if (leftExpression == null) return null - val result = evaluateCall(expression.getOperationReference(), leftExpression) - return createCompileTimeConstant(result, expectedType) + + return evaluateCall(expression, expression.getOperationReference(), leftExpression, expectedType) } override fun visitSimpleNameExpression(expression: JetSimpleNameExpression, expectedType: JetType?): CompileTimeConstant<*>? { @@ -283,13 +290,16 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet } val receiverExpression = expression.getReceiverExpression() - val result = evaluateCall(calleeExpression, receiverExpression) - return createCompileTimeConstant(result, expectedType) + return evaluateCall(expression, calleeExpression, receiverExpression, expectedType) } // Mynum.A if (selectorExpression != null) { - return evaluate(selectorExpression, expectedType) + val compileTimeConstant = evaluate(selectorExpression, expectedType) + if (compileTimeConstant != null) { + trace.record(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression, true); + } + return compileTimeConstant } return null @@ -348,7 +358,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet } - private class OperationArgument(val value: Any?, val ctcType: CompileTimeType<*>) + private class OperationArgument(val value: Any, val ctcType: CompileTimeType<*>, val expression: JetExpression) private fun createOperationArgumentForReceiver(resolvedCall: ResolvedCall<*>, expression: JetExpression): OperationArgument? { val receiverExpressionType = getReceiverExpressionType(resolvedCall) @@ -360,21 +370,65 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val receiverValue = evaluate(expression, receiverExpressionType)?.getValue() if (receiverValue == null) return null - return OperationArgument(receiverValue, receiverCompileTimeType) + if (receiverValue is NumberValueTypeConstructor<*>) { + val newValue = receiverValue.getValueForNumberType(receiverExpressionType) + if (newValue != null) { + return OperationArgument(newValue, receiverCompileTimeType, expression) + } + } + + return OperationArgument(receiverValue, receiverCompileTimeType, expression) } private fun createOperationArgumentForFirstParameter(argument: ResolvedValueArgument, parameter: ValueParameterDescriptor): OperationArgument? { val argumentCompileTimeType = getCompileTimeType(parameter.getType()) if (argumentCompileTimeType == null) return null - val argumentCompileTimeValue = resolveArguments(argument.getArguments(), parameter.getType()) - if (argumentCompileTimeValue.size != 1) return null + val arguments = argument.getArguments() + if (arguments.size != 1) return null - val argumentValue = argumentCompileTimeValue.first().getValue() + val argumentExpression = arguments.first().getArgumentExpression() + if (argumentExpression == null) return null + + val constant = evaluate(argumentExpression, parameter.getType()) + if (constant == null) return null + + val argumentValue = constant.getValue() if (argumentValue == null) return null - return OperationArgument(argumentValue, argumentCompileTimeType) + if (argumentValue is NumberValueTypeConstructor<*>) { + val newValue = argumentValue.getValueForNumberType(parameter.getType()) + if (newValue != null) { + return OperationArgument(newValue, argumentCompileTimeType, argumentExpression) + } + } + + return OperationArgument(argumentValue, argumentCompileTimeType, argumentExpression) } + + fun createCompileTimeConstant(value: Any?, expression: JetExpression, expectedType: JetType?, isPure: Boolean = true): CompileTimeConstant<*>? { + if (isPure) { + val compileTimeConstant = createConvertibleCompileTimeConstant(value, expectedType) + trace.record(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression, true) + return compileTimeConstant + } + + val compileTimeConstant = createUnconvertibleCompileTimeConstant(value) + return compileTimeConstant + } +} + +public fun NumberValueTypeConstructor.getValueForNumberType(expectedType: JetType): Any? { + val valueWithNewType = this.getCompileTimeConstantForNumberType(expectedType) + if (valueWithNewType != null) { + return valueWithNewType.getValue() + } + return null +} + +public fun NumberValueTypeConstructor.getCompileTimeConstantForNumberType(expectedType: JetType): CompileTimeConstant<*>? { + val defaultType = TypeUtils.getPrimitiveNumberType(this, expectedType) + return createConvertibleCompileTimeConstant(this.getValue(), defaultType) } public fun parseLong(text: String): Long? { @@ -411,33 +465,61 @@ private fun parseBoolean(text: String): Boolean { } -private fun createCompileTimeConstantForEquals(result: Any?, operationToken: IElementType): CompileTimeConstant<*>? { +private fun createCompileTimeConstantForEquals(result: Any?, operationReference: JetExpression): CompileTimeConstant<*>? { if (result is Boolean) { + 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.valueOf(result) JetTokens.EXCLEQ -> BooleanValue.valueOf(!result) - else -> throw IllegalStateException("Unknown equals operation token: $operationToken") + JetTokens.IDENTIFIER -> { + assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.EQUALS, "This method should be called only for equals operations") + return BooleanValue.valueOf(result) + } + else -> throw IllegalStateException("Unknown equals operation token: $operationToken ${operationReference.getText()}") } } return null } -private fun createCompileTimeConstantForCompareTo(result: Any?, operationToken: IElementType): CompileTimeConstant<*>? { +private fun createCompileTimeConstantForCompareTo(result: Any?, operationReference: JetExpression): CompileTimeConstant<*>? { if (result is Int) { + 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.valueOf(result < 0) JetTokens.LTEQ -> BooleanValue.valueOf(result <= 0) JetTokens.GT -> BooleanValue.valueOf(result > 0) JetTokens.GTEQ -> BooleanValue.valueOf(result >= 0) + JetTokens.IDENTIFIER -> { + assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.COMPARE_TO, "This method should be called only for compareTo operations") + return IntValue(result) + } else -> throw IllegalStateException("Unknown compareTo operation token: $operationToken") } } return null } +private fun createUnconvertibleCompileTimeConstant(value: Any?): CompileTimeConstant<*>? { + return when(value) { + null -> null + is Byte -> ByteValue(value) + is Short -> ShortValue(value) + is Int -> IntValue(value) + is Long -> LongValue(value) + is Char -> CharValue(value) + is Float -> FloatValue(value) + is Double -> DoubleValue(value) + is Boolean -> BooleanValue.valueOf(value) + else -> null + } +} + private fun createStringConstant(value: CompileTimeConstant<*>?): StringValue? { return when (value) { null -> null + is IntegerValueTypeConstant -> createStringConstant(value.getValue().getCompileTimeConstantForNumberType(TypeUtils.NO_EXPECTED_TYPE)) is StringValue -> value is IntValue, is ByteValue, is ShortValue, is LongValue, is CharValue, @@ -447,10 +529,10 @@ private fun createStringConstant(value: CompileTimeConstant<*>?): StringValue? { } } -public fun createCompileTimeConstant(value: Any?, expectedType: JetType?): CompileTimeConstant<*>? { +private fun createConvertibleCompileTimeConstant(value: Any?, expectedType: JetType?): CompileTimeConstant<*>? { return when(value) { null -> null - is Byte, is Short, is Int, is Long -> getIntegerValue((value as Number).toLong(), expectedType ?: TypeUtils.NO_EXPECTED_TYPE) + is Byte, is Short, is Int, is Long-> getIntegerValue((value as Number).toLong(), expectedType ?: TypeUtils.NO_EXPECTED_TYPE) is Char -> CharValue(value) is Float -> FloatValue(value) is Double -> DoubleValue(value) @@ -469,7 +551,7 @@ private fun getIntegerValue(value: Long, expectedType: JetType): CompileTimeCons } if (CompileTimeConstantResolver.noExpectedTypeOrError(expectedType)) { - return defaultIntegerValue(value) + return IntegerValueTypeConstant(value) } val builtIns = KotlinBuiltIns.getInstance() 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 2ce7e691cd6..1cf17b5ae5d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptorImpl; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; @@ -34,6 +35,8 @@ 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.ArrayValue; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.constants.NumberValueTypeConstant; +import org.jetbrains.jet.lang.resolve.constants.NumberValueTypeConstructor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.ErrorUtils; @@ -49,6 +52,7 @@ import java.util.Map; import static org.jetbrains.jet.lang.resolve.BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT; import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; +import static org.jetbrains.jet.lang.types.TypeUtils.getPrimitiveNumberType; public class AnnotationResolver { @@ -243,6 +247,11 @@ public class AnnotationResolver { JetExpression argumentExpression = argument.getArgumentExpression(); if (argumentExpression != null) { CompileTimeConstant constant = resolveExpressionToCompileTimeValue(argumentExpression, expectedType, trace); + if (constant instanceof NumberValueTypeConstant) { + NumberValueTypeConstructor typeConstructor = ((NumberValueTypeConstant) constant).getValue(); + JetType defaultType = getPrimitiveNumberType(typeConstructor, expectedType); + ArgumentTypeResolver.updateNumberType(defaultType, argumentExpression, trace); + } if (constant != null) { constants.add(constant); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index e0d3b9dd767..9c2ea2b73e6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -73,6 +73,7 @@ public interface BindingContext { WritableSlice ANNOTATION = Slices.sliceBuilder().setOpposite(ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT).build(); + WritableSlice IS_PURE_CONSTANT_EXPRESSION = Slices.createSimpleSlice(); WritableSlice> COMPILE_TIME_VALUE = Slices.createSimpleSlice(); WritableSlice> COMPILE_TIME_INITIALIZER = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java index aa84bffe3ee..1b978989539 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java @@ -264,7 +264,7 @@ public class ArgumentTypeResolver { } @Nullable - public JetType updateResultArgumentTypeIfNotDenotable( + public static JetType updateResultArgumentTypeIfNotDenotable( @NotNull ResolutionContext context, @NotNull JetExpression expression ) { @@ -273,35 +273,35 @@ public class ArgumentTypeResolver { if (type.getConstructor() instanceof NumberValueTypeConstructor) { NumberValueTypeConstructor constructor = (NumberValueTypeConstructor) type.getConstructor(); JetType primitiveType = TypeUtils.getPrimitiveNumberType(constructor, context.expectedType); - updateNumberType(primitiveType, expression, context); + updateNumberType(primitiveType, expression, context.trace); return primitiveType; } } return type; } - private void updateNumberType( + public static void updateNumberType( @NotNull JetType numberType, @Nullable JetExpression expression, - @NotNull ResolutionContext context + @NotNull BindingTrace trace ) { if (expression == null) return; - BindingContextUtils.updateRecordedType(numberType, expression, context.trace, false); + BindingContextUtils.updateRecordedType(numberType, expression, trace, false); if (!(expression instanceof JetConstantExpression)) { JetExpression deparenthesized = JetPsiUtil.deparenthesize(expression, false); if (deparenthesized != expression) { - updateNumberType(numberType, deparenthesized, context); + updateNumberType(numberType, deparenthesized, trace); } if (deparenthesized instanceof JetBlockExpression) { JetElement lastStatement = JetPsiUtil.getLastStatementInABlock((JetBlockExpression) deparenthesized); if (lastStatement instanceof JetExpression) { - updateNumberType(numberType, (JetExpression) lastStatement, context); + updateNumberType(numberType, (JetExpression) lastStatement, trace); } } return; } - ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, numberType); + ConstantExpressionEvaluator.object$.evaluate(expression, trace, numberType); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java new file mode 100644 index 00000000000..5be9cdde8d1 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.constants; + +import org.jetbrains.annotations.NotNull; + +public class IntegerValueTypeConstant extends NumberValueTypeConstant { + + private final IntegerValueTypeConstructor value; + + public IntegerValueTypeConstant(long value) { + this.value = new IntegerValueTypeConstructor(value); + } + + @NotNull + @Override + public IntegerValueTypeConstructor getValue() { + return value; + } + + @Override + public String toString() { + return value.toString(); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstructor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstructor.java index e987688c0a7..da80241d942 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstructor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstructor.java @@ -23,7 +23,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.util.Collection; -public class IntegerValueTypeConstructor extends NumberValueTypeConstructor { +public class IntegerValueTypeConstructor extends NumberValueTypeConstructor { private final long value; private final Collection supertypes = Lists.newArrayList(); @@ -44,6 +44,11 @@ public class IntegerValueTypeConstructor extends NumberValueTypeConstructor { } } + @Override + public Long getValue() { + return value; + } + @NotNull @Override public Collection getSupertypes() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 3662dfaf9fb..f21b7c2af44 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -22,16 +22,15 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.PlatformToKotlinClassMap; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.jet.lang.diagnostics.Errors; 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.*; +import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver; import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue; @@ -50,7 +49,7 @@ import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; -import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstructor; +import org.jetbrains.jet.lang.resolve.constants.NumberValueTypeConstant; import org.jetbrains.jet.lang.resolve.constants.NumberValueTypeConstructor; import org.jetbrains.jet.lang.resolve.name.LabelName; import org.jetbrains.jet.lang.resolve.name.Name; @@ -73,12 +72,10 @@ import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_ import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope; -import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.DEPENDENT; import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT; import static org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver.ErrorCharValueWithDiagnostic; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; -import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; -import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType; +import static org.jetbrains.jet.lang.types.TypeUtils.*; import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction; import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.resolveSpecialConstructionAsCall; import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*; @@ -122,39 +119,21 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return facade.getTypeInfo(innerExpression, context.replaceScope(context.scope), isStatement); } - private static JetTypeInfo createNumberValueTypeInfo( - @NotNull NumberValueTypeConstructor numberValueTypeConstructor, - @NotNull Number value, - @NotNull DataFlowInfo dataFlowInfo - ) { - return JetTypeInfo.create(new JetTypeImpl( - Collections.emptyList(), numberValueTypeConstructor, - false, Collections.emptyList(), - ErrorUtils.createErrorScope("Scope for number value type (" + value + ")", true)), dataFlowInfo); - } - @Override public JetTypeInfo visitConstantExpression(@NotNull JetConstantExpression expression, ExpressionTypingContext context) { - IElementType elementType = expression.getNode().getElementType(); - String text = expression.getNode().getText(); - KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); + CompileTimeConstant value = ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, context.expectedType); - if (noExpectedType(context.expectedType) && context.contextDependency == DEPENDENT) { - if (elementType == JetNodeTypes.INTEGER_CONSTANT) { - Long longValue = EvaluatePackage.parseLong(text); - if (longValue != null) { - return createNumberValueTypeInfo(new IntegerValueTypeConstructor(longValue), longValue, context.dataFlowInfo); - } + if (!(value instanceof NumberValueTypeConstant)) { + CompileTimeConstantResolver compileTimeConstantResolver = context.getCompileTimeConstantResolver(); + boolean hasError = compileTimeConstantResolver.checkConstantExpressionType(value, expression, context.expectedType); + if (hasError) { + IElementType elementType = expression.getNode().getElementType(); + return JetTypeInfo.create(getDefaultType(elementType), context.dataFlowInfo); } } - CompileTimeConstantResolver compileTimeConstantResolver = context.getCompileTimeConstantResolver(); - CompileTimeConstant value = ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, context.expectedType); - boolean hasError = compileTimeConstantResolver.checkConstantExpressionType(value, expression, context.expectedType); - if (hasError) { - return JetTypeInfo.create(getDefaultType(elementType), context.dataFlowInfo); - } + assert value != null : "CompileTimeConstant should be evaluated for constant expression or an error should be recorded " + expression.getText(); - return DataFlowUtils.checkType(value.getType(builtIns), expression, context, context.dataFlowInfo); + return createCompileTimeConstantTypeInfo(value, expression, context); } @Override @@ -715,9 +694,31 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { else { result = returnType; } + + CompileTimeConstant value = ConstantExpressionEvaluator.object$.evaluate(expression, contextWithExpectedType.trace, + contextWithExpectedType.expectedType); + if (value != null) { + return createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType); + } + return DataFlowUtils.checkType(result, expression, contextWithExpectedType, dataFlowInfo); } + @NotNull + private static JetTypeInfo createCompileTimeConstantTypeInfo( + @NotNull CompileTimeConstant value, + @NotNull JetExpression expression, + @NotNull ExpressionTypingContext context + ) { + JetType expressionType = value.getType(KotlinBuiltIns.getInstance()); + if (value instanceof NumberValueTypeConstant && context.contextDependency == INDEPENDENT) { + expressionType = getPrimitiveNumberType(((NumberValueTypeConstant) value).getValue(), context.expectedType); + ArgumentTypeResolver.updateNumberType(expressionType, expression, context.trace); + } + + return DataFlowUtils.checkType(expressionType, expression, context, context.dataFlowInfo); + } + private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) { JetExpression baseExpression = expression.getBaseExpression(); assert baseExpression != null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java index f6cdc57d748..a4304ba4c4e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java @@ -21,6 +21,7 @@ import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; 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.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; @@ -30,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory; import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; +import org.jetbrains.jet.lang.resolve.constants.NumberValueTypeConstant; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetTypeInfo; import org.jetbrains.jet.lang.types.TypeUtils; @@ -161,13 +163,16 @@ public class DataFlowUtils { JetExpression expression = JetPsiUtil.safeDeparenthesize(expressionToCheck, false); recordExpectedType(trace, expression, expectedType); - if (expressionType == null || noExpectedType(expectedType) || + if (expressionType == null || noExpectedType(expectedType) || !expectedType.getConstructor().isDenotable() || JetTypeChecker.INSTANCE.isSubtypeOf(expressionType, expectedType)) { return expressionType; } if (expression instanceof JetConstantExpression) { CompileTimeConstant value = ConstantExpressionEvaluator.object$.evaluate(expression, trace, expectedType); + if (value instanceof NumberValueTypeConstant) { + value = EvaluatePackage.getCompileTimeConstantForNumberType(((NumberValueTypeConstant) value).getValue(), expectedType); + } new CompileTimeConstantResolver(trace, true).checkConstantExpressionType(value, (JetConstantExpression) expression, expectedType); return expressionType; } diff --git a/compiler/testData/diagnostics/tests/evaluate/unaryMinusDepOnExpType.kt b/compiler/testData/diagnostics/tests/evaluate/unaryMinusDepOnExpType.kt new file mode 100644 index 00000000000..2d120862fd0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/evaluate/unaryMinusDepOnExpType.kt @@ -0,0 +1,34 @@ +fun fooInt(p: Int) = p +fun fooLong(p: Long) = p +fun fooByte(p: Byte) = p +fun fooShort(p: Short) = p + +fun test() { + fooInt(-1) + fooInt(-1111111111111111111) + fooInt(-1.toInt()) + fooInt(-1.toByte()) + fooInt(-1.toLong()) + fooInt(-1.toShort()) + + fooByte(-1) + fooByte(-1111111111111111111) + fooByte(-1.toInt()) + fooByte(-1.toByte()) + fooByte(-1.toLong()) + fooByte(-1.toShort()) + + fooLong(-1) + fooLong(-1111111111111111111) + fooLong(-1.toInt()) + fooLong(-1.toByte()) + fooLong(-1.toLong()) + fooLong(-1.toShort()) + + fooShort(-1) + fooShort(-1111111111111111111) + fooShort(-1.toInt()) + fooShort(-1.toByte()) + fooShort(-1.toLong()) + fooShort(-1.toShort()) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndepWoExpType.kt b/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndepWoExpType.kt new file mode 100644 index 00000000000..d9dc367c7a3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndepWoExpType.kt @@ -0,0 +1,41 @@ +val p1 = -1 +val p2 = -1.toLong() +val p3 = -1.toByte() +val p4 = -1.toInt() +val p5 = -1.toShort() +val p6 = -1111111111111111111 + +fun fooInt(p: Int) = p +fun fooLong(p: Long) = p +fun fooByte(p: Byte) = p +fun fooShort(p: Short) = p + +fun test() { + fooInt(p1) + fooInt(p2) + fooInt(p3) + fooInt(p4) + fooInt(p5) + fooInt(p6) + + fooLong(p1) + fooLong(p2) + fooLong(p3) + fooLong(p4) + fooLong(p5) + fooLong(p6) + + fooShort(p1) + fooShort(p2) + fooShort(p3) + fooShort(p4) + fooShort(p5) + fooShort(p6) + + fooByte(p1) + fooByte(p2) + fooByte(p3) + fooByte(p4) + fooByte(p5) + fooByte(p6) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndependentExpType.kt b/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndependentExpType.kt new file mode 100644 index 00000000000..6e454d6090f --- /dev/null +++ b/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndependentExpType.kt @@ -0,0 +1,29 @@ +val p1: Int = -1 +val p2: Long = -1 +val p3: Byte = -1 +val p4: Short = -1 + +val lp1: Int = -1111111111111111111 +val lp2: Long = -1111111111111111111 +val lp3: Byte = -1111111111111111111 +val lp4: Short = -1111111111111111111 + +val l1: Long = -1.toLong() +val l2: Byte = -1.toLong() +val l3: Int = -1.toLong() +val l4: Short = -1.toLong() + +val b1: Byte = -1.toByte() +val b2: Int = -1.toByte() +val b3: Long = -1.toByte() +val b4: Short = -1.toByte() + +val i1: Byte = -1.toInt() +val i2: Int = -1.toInt() +val i3: Long = -1.toInt() +val i4: Short = -1.toInt() + +val s1: Byte = -1.toShort() +val s2: Int = -1.toShort() +val s3: Long = -1.toShort() +val s4: Short = -1.toShort() \ No newline at end of file diff --git a/compiler/testData/evaluate/constant/compareTo.kt b/compiler/testData/evaluate/constant/compareTo.kt new file mode 100644 index 00000000000..d0ecde47797 --- /dev/null +++ b/compiler/testData/evaluate/constant/compareTo.kt @@ -0,0 +1,19 @@ +package test + +// val prop1: false +val prop1 = 1 > 2 + +// val prop2: true +val prop2 = 1 < 2 + +// val prop3: true +val prop3 = 1 <= 2 + +// val prop4: false +val prop4 = 1 >= 2 + +// val prop5: -1.toInt() +val prop5 = 1.compareTo(2) + +// val prop6: false +val prop6 = 1.compareTo(2) > 0 diff --git a/compiler/testData/evaluate/divideByZero.kt b/compiler/testData/evaluate/constant/divideByZero.kt similarity index 100% rename from compiler/testData/evaluate/divideByZero.kt rename to compiler/testData/evaluate/constant/divideByZero.kt diff --git a/compiler/testData/evaluate/constant/equals.kt b/compiler/testData/evaluate/constant/equals.kt new file mode 100644 index 00000000000..285f7df03f0 --- /dev/null +++ b/compiler/testData/evaluate/constant/equals.kt @@ -0,0 +1,4 @@ +package test + +// val prop4: true +val prop4 = !1.equals(2) diff --git a/compiler/testData/evaluate/floatsAndDoubles.kt b/compiler/testData/evaluate/constant/floatsAndDoubles.kt similarity index 100% rename from compiler/testData/evaluate/floatsAndDoubles.kt rename to compiler/testData/evaluate/constant/floatsAndDoubles.kt diff --git a/compiler/testData/evaluate/constant/integers.kt b/compiler/testData/evaluate/constant/integers.kt new file mode 100644 index 00000000000..43012dcaa5b --- /dev/null +++ b/compiler/testData/evaluate/constant/integers.kt @@ -0,0 +1,10 @@ +package test + +// val prop1: 513105426295.toLong() +val prop1: Int = 0x7777777777 + +// val prop2: 513105426295.toLong() +val prop2: Long = 0x7777777777 + +// val prop3: IntegerValueType(513105426295) +val prop3 = 0x7777777777 diff --git a/compiler/testData/evaluate/strings.kt b/compiler/testData/evaluate/constant/strings.kt similarity index 79% rename from compiler/testData/evaluate/strings.kt rename to compiler/testData/evaluate/constant/strings.kt index 5196a0f653b..6a72ac406fc 100644 --- a/compiler/testData/evaluate/strings.kt +++ b/compiler/testData/evaluate/constant/strings.kt @@ -24,3 +24,9 @@ val prop6 = "${1.0}" // val prop7: null val prop7 = "${javaClass()}" + +// val prop8: "a1.0" +val prop8 = "a${1.toDouble()}" + +// val prop9: "ab" +val prop9 = "a" + "b" diff --git a/compiler/testData/evaluate/constant/unaryMinusIndepWoExpType.kt b/compiler/testData/evaluate/constant/unaryMinusIndepWoExpType.kt new file mode 100644 index 00000000000..9ba92fdde8a --- /dev/null +++ b/compiler/testData/evaluate/constant/unaryMinusIndepWoExpType.kt @@ -0,0 +1,16 @@ +package test + +// val p1: IntegerValueType(-1) +val p1 = -1 + +// val p2: -1.toLong() +val p2 = -1.toLong() + +// val p3: -1.toByte() +val p3 = -1.toByte() + +// val p4: -1.toInt() +val p4 = -1.toInt() + +// val p5: -1.toShort() +val p5 = -1.toShort() diff --git a/compiler/testData/evaluate/constant/unaryMinusIndependentExpType.kt b/compiler/testData/evaluate/constant/unaryMinusIndependentExpType.kt new file mode 100644 index 00000000000..288873a6cb6 --- /dev/null +++ b/compiler/testData/evaluate/constant/unaryMinusIndependentExpType.kt @@ -0,0 +1,63 @@ +package test + +// val p1: -1.toInt() +val p1: Int = -1 + +// val p2: -1.toLong() +val p2: Long = -1 + +// val p3: -1.toByte() +val p3: Byte = -1 + +// val p4: -1.toShort() +val p4: Short = -1 + +// val l1: -1.toLong() +val l1: Long = -1.toLong() + +// val l2: -1.toLong() +val l2: Byte = -1.toLong() + +// val l3: -1.toLong() +val l3: Int = -1.toLong() + +// val l4: -1.toLong() +val l4: Short = -1.toLong() + + +// val b1: -1.toByte() +val b1: Byte = -1.toByte() + +// val b2: -1.toByte() +val b2: Int = -1.toByte() + +// val b3: -1.toByte() +val b3: Long = -1.toByte() + +// val b4: -1.toByte() +val b4: Short = -1.toByte() + + +// val i1: -1.toInt() +val i1: Byte = -1.toInt() + +// val i2: -1.toInt() +val i2: Int = -1.toInt() + +// val i3: -1.toInt() +val i3: Long = -1.toInt() + +// val i4: -1.toInt() +val i4: Short = -1.toInt() + +// val s1: -1.toShort() +val s1: Byte = -1.toShort() + +// val s2: -1.toShort() +val s2: Int = -1.toShort() + +// val s3: -1.toShort() +val s3: Long = -1.toShort() + +// val s4: -1.toShort() +val s4: Short = -1.toShort() \ No newline at end of file diff --git a/compiler/testData/evaluate/integers.kt b/compiler/testData/evaluate/integers.kt deleted file mode 100644 index b780e6b25a2..00000000000 --- a/compiler/testData/evaluate/integers.kt +++ /dev/null @@ -1,19 +0,0 @@ -package test - -// val prop1: 513105426295.toLong() -val prop1: Int = 0x7777777777 - -// val prop2: 513105426295.toLong() -val prop2: Long = 0x7777777777 - -// val prop3: 513105426295.toLong() -val prop3 = 0x7777777777 - -// val prop4: -2147483648.toInt() -val prop4: Int = Integer.MAX_VALUE + 1 - -// val prop5: -2147483648.toLong() -val prop5: Long = Integer.MAX_VALUE + 1 - -// val prop6: -2147483648.toInt() -val prop6 = Integer.MAX_VALUE + 1 diff --git a/compiler/testData/evaluate/isPure/enum.kt b/compiler/testData/evaluate/isPure/enum.kt new file mode 100644 index 00000000000..e2a521590ab --- /dev/null +++ b/compiler/testData/evaluate/isPure/enum.kt @@ -0,0 +1,9 @@ +package test + +enum class MyEnum { A } + +// val prop1: true +val prop1 = MyEnum.A + +// val prop2: null +val prop2 = javaClass() diff --git a/compiler/testData/evaluate/isPure/innerToType.kt b/compiler/testData/evaluate/isPure/innerToType.kt new file mode 100644 index 00000000000..0416a92cae2 --- /dev/null +++ b/compiler/testData/evaluate/isPure/innerToType.kt @@ -0,0 +1,13 @@ +package test + +// val prop1: null +val prop1 = 1.toLong() + 1 + +// val prop2: null +val prop2 = -1.toInt() + +// val prop3: null +val prop3 = 1 + 1.toByte() + +// val prop4: null +val prop4 = 1 + 1.toShort() + 1 \ No newline at end of file diff --git a/compiler/testData/evaluate/isPure/strings.kt b/compiler/testData/evaluate/isPure/strings.kt new file mode 100644 index 00000000000..16d3937173c --- /dev/null +++ b/compiler/testData/evaluate/isPure/strings.kt @@ -0,0 +1,16 @@ +package test + +// val prop1: true +val prop1 = "" + +// val prop2: true +val prop2 = "a" + +// val prop3: true +val prop3 = "\"a\"" + +// val prop5: true +val prop5 = "a${1 + 1}" + +// val prop6: true +val prop6 = "a" + "b" diff --git a/compiler/testData/evaluate/isPure/toType.kt b/compiler/testData/evaluate/isPure/toType.kt new file mode 100644 index 00000000000..646696ddd4d --- /dev/null +++ b/compiler/testData/evaluate/isPure/toType.kt @@ -0,0 +1,22 @@ +package test + +// val prop1: null +val prop1 = 1.toLong() + +// val prop2: null +val prop2 = 1.toInt() + +// val prop3: null +val prop3 = 1.toByte() + +// val prop4: null +val prop4 = 1.toShort() + +// val prop5: null +val prop5 = 1.toChar() + +// val prop6: null +val prop6 = 1.toDouble() + +// val prop7: null +val prop7 = 1.toFloat() \ No newline at end of file diff --git a/compiler/testData/evaluate/isPure/unaryMinusIndepWoExpType.kt b/compiler/testData/evaluate/isPure/unaryMinusIndepWoExpType.kt new file mode 100644 index 00000000000..3b868c2c76f --- /dev/null +++ b/compiler/testData/evaluate/isPure/unaryMinusIndepWoExpType.kt @@ -0,0 +1,16 @@ +package test + +// val p1: true +val p1 = -1 + +// val p2: null +val p2 = -1.toLong() + +// val p3: null +val p3 = -1.toByte() + +// val p4: null +val p4 = -1.toInt() + +// val p5: null +val p5 = -1.toShort() diff --git a/compiler/testData/evaluate/isPure/unaryMinusIndependentExpType.kt b/compiler/testData/evaluate/isPure/unaryMinusIndependentExpType.kt new file mode 100644 index 00000000000..821c67f9fcf --- /dev/null +++ b/compiler/testData/evaluate/isPure/unaryMinusIndependentExpType.kt @@ -0,0 +1,63 @@ +package test + +// val p1: true +val p1: Int = -1 + +// val p2: true +val p2: Long = -1 + +// val p3: true +val p3: Byte = -1 + +// val p4: true +val p4: Short = -1 + +// val l1: null +val l1: Long = -1.toLong() + +// val l2: null +val l2: Byte = -1.toLong() + +// val l3: null +val l3: Int = -1.toLong() + +// val l4: null +val l4: Short = -1.toLong() + + +// val b1: null +val b1: Byte = -1.toByte() + +// val b2: null +val b2: Int = -1.toByte() + +// val b3: null +val b3: Long = -1.toByte() + +// val b4: null +val b4: Short = -1.toByte() + + +// val i1: null +val i1: Byte = -1.toInt() + +// val i2: null +val i2: Int = -1.toInt() + +// val i3: null +val i3: Long = -1.toInt() + +// val i4: null +val i4: Short = -1.toInt() + +// val s1: null +val s1: Byte = -1.toShort() + +// val s2: null +val s2: Int = -1.toShort() + +// val s3: null +val s3: Long = -1.toShort() + +// val s4: null +val s4: Short = -1.toShort() \ No newline at end of file diff --git a/compiler/testData/lazyResolve/namespaceComparator/AnnotationOnObject.txt b/compiler/testData/lazyResolve/namespaceComparator/AnnotationOnObject.txt index 0b2f4fd3f59..6ce6c7410d3 100644 --- a/compiler/testData/lazyResolve/namespaceComparator/AnnotationOnObject.txt +++ b/compiler/testData/lazyResolve/namespaceComparator/AnnotationOnObject.txt @@ -7,7 +7,7 @@ internal final annotation class A : jet.Annotation { internal final val c: jet.String } -test.A(a = 12.toInt(): jet.Int, c = "Hello": jet.String) internal object SomeObject { +test.A(a = IntegerValueType(12): IntegerValueType(12), c = "Hello": jet.String) internal object SomeObject { /*primary*/ private constructor SomeObject() public class object : test.SomeObject { diff --git a/compiler/testData/lazyResolve/namespaceComparator/WrongAnnotationArgsOnObject.txt b/compiler/testData/lazyResolve/namespaceComparator/WrongAnnotationArgsOnObject.txt index 511ebf05e49..08239675334 100644 --- a/compiler/testData/lazyResolve/namespaceComparator/WrongAnnotationArgsOnObject.txt +++ b/compiler/testData/lazyResolve/namespaceComparator/WrongAnnotationArgsOnObject.txt @@ -6,7 +6,7 @@ internal final annotation class BadAnnotation : jet.Annotation { /*primary*/ public constructor BadAnnotation(/*0*/ s: jet.String) } -test.BadAnnotation(s = 1.toInt(): jet.Int) internal object SomeObject { +test.BadAnnotation(s = IntegerValueType(1): IntegerValueType(1)) internal object SomeObject { /*primary*/ private constructor SomeObject() public class object : test.SomeObject { diff --git a/compiler/testData/loadKotlin/annotations/classes/WithArgument.txt b/compiler/testData/loadKotlin/annotations/classes/WithArgument.txt index 38adc78e6fe..0b87d1589b0 100644 --- a/compiler/testData/loadKotlin/annotations/classes/WithArgument.txt +++ b/compiler/testData/loadKotlin/annotations/classes/WithArgument.txt @@ -18,7 +18,7 @@ internal final annotation class CharAnno : jet.Annotation { internal final fun (): jet.Char } -test.IntAnno(value = 42.toInt(): jet.Int) test.ShortAnno(value = 42.toShort(): jet.Short) test.ByteAnno(value = 42.toByte(): jet.Byte) test.LongAnno(value = 42.toLong(): jet.Long) test.CharAnno(value = #65(A): jet.Char) test.BooleanAnno(value = false: jet.Boolean) test.FloatAnno(value = 3.14.toFloat(): jet.Float) test.DoubleAnno(value = 3.14.toDouble(): jet.Double) internal final class Class { +test.IntAnno(value = IntegerValueType(42): IntegerValueType(42)) test.ShortAnno(value = IntegerValueType(42): IntegerValueType(42)) test.ByteAnno(value = IntegerValueType(42): IntegerValueType(42)) test.LongAnno(value = IntegerValueType(42): IntegerValueType(42)) test.CharAnno(value = #65(A): jet.Char) test.BooleanAnno(value = false: jet.Boolean) test.FloatAnno(value = 3.14.toFloat(): jet.Float) test.DoubleAnno(value = 3.14.toDouble(): jet.Double) internal final class Class { /*primary*/ public constructor Class() } diff --git a/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.txt b/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.txt index 54d9e437220..dae51f4a466 100644 --- a/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.txt +++ b/compiler/testData/loadKotlin/annotations/classes/WithMultipleArguments.txt @@ -10,6 +10,6 @@ internal final annotation class Anno : jet.Annotation { internal final fun (): jet.String } -test.Anno(double = 3.14.toDouble(): jet.Double, int = 42.toInt(): jet.Int, string = "OK": jet.String) internal final class Class { +test.Anno(double = 3.14.toDouble(): jet.Double, int = IntegerValueType(42): IntegerValueType(42), string = "OK": jet.String) internal final class Class { /*primary*/ public constructor Class() } diff --git a/compiler/testData/resolveAnnotations/parameters/byte.kt b/compiler/testData/resolveAnnotations/parameters/byte.kt index 76a150332d8..0c74df912d9 100644 --- a/compiler/testData/resolveAnnotations/parameters/byte.kt +++ b/compiler/testData/resolveAnnotations/parameters/byte.kt @@ -9,4 +9,4 @@ annotation class Ann( Ann(1, 1.toByte(), 128.toByte(), 128) class MyClass -// EXPECTED: Ann[b1 = 1.toByte(): jet.Byte, b2 = 1.toByte(): jet.Byte, b3 = -128.toByte(): jet.Byte, b4 = 128.toInt(): jet.Int] \ No newline at end of file +// EXPECTED: Ann[b1 = IntegerValueType(1): IntegerValueType(1), b2 = 1.toByte(): jet.Byte, b3 = -128.toByte(): jet.Byte, b4 = IntegerValueType(128): IntegerValueType(128)] \ No newline at end of file diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/labeled.kt b/compiler/testData/resolveAnnotations/parameters/expressions/labeled.kt index 896f7461d08..4909e58ac7a 100644 --- a/compiler/testData/resolveAnnotations/parameters/expressions/labeled.kt +++ b/compiler/testData/resolveAnnotations/parameters/expressions/labeled.kt @@ -1,7 +1,7 @@ package test -annotation class Ann(i: Int) +annotation class Ann(i: Double) -Ann(@A 1) class MyClass +Ann(@A 1.0) class MyClass -// EXPECTED: Ann[i = 1.toInt(): jet.Int] +// EXPECTED: Ann[i = 1.0.toDouble(): jet.Double] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/maxValueByte.kt b/compiler/testData/resolveAnnotations/parameters/expressions/maxValueByte.kt index 081ca26e109..d055f54b24f 100644 --- a/compiler/testData/resolveAnnotations/parameters/expressions/maxValueByte.kt +++ b/compiler/testData/resolveAnnotations/parameters/expressions/maxValueByte.kt @@ -16,4 +16,4 @@ Ann( p5 = 1.toByte() + 1.toByte() ) class MyClass -// EXPECTED: Ann[p1 = 128.toInt(): jet.Int, p2 = 2.toByte(): jet.Byte, p3 = 128.toInt(): jet.Int, p4 = 2.toInt(): jet.Int, p5 = 2.toByte(): jet.Byte] +// EXPECTED: Ann[p1 = 128.toInt(): jet.Int, p2 = 2.toByte(): jet.Byte, p3 = 128.toInt(): jet.Int, p4 = 2.toInt(): jet.Int, p5 = 2.toInt(): jet.Int] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/maxValueInt.kt b/compiler/testData/resolveAnnotations/parameters/expressions/maxValueInt.kt index 6c3178be7a4..d717ae85d93 100644 --- a/compiler/testData/resolveAnnotations/parameters/expressions/maxValueInt.kt +++ b/compiler/testData/resolveAnnotations/parameters/expressions/maxValueInt.kt @@ -16,4 +16,4 @@ Ann( p5 = 1.toInt() + 1.toInt() ) class MyClass -// EXPECTED: Ann[p1 = -2147483648.toInt(): jet.Int, p2 = 2.toInt(): jet.Int, p3 = -2147483648.toLong(): jet.Long, p4 = 2.toLong(): jet.Long, p5 = 2.toInt(): jet.Int] +// EXPECTED: Ann[p1 = -2147483648.toInt(): jet.Int, p2 = 2.toInt(): jet.Int, p3 = -2147483648.toLong(): jet.Long, p4 = 2.toInt(): jet.Int, p5 = 2.toInt(): jet.Int] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/unaryMinus.kt b/compiler/testData/resolveAnnotations/parameters/expressions/unaryMinus.kt index 049fa865844..f11b21c32c6 100644 --- a/compiler/testData/resolveAnnotations/parameters/expressions/unaryMinus.kt +++ b/compiler/testData/resolveAnnotations/parameters/expressions/unaryMinus.kt @@ -12,4 +12,4 @@ annotation class Ann( Ann(-1, -1, -1, -1, -1.0, -1.0.toFloat(), -'c') class MyClass -// EXPECTED: Ann[b1 = -1.toByte(): jet.Byte, b2 = -1.toShort(): jet.Short, b3 = -1.toInt(): jet.Int, b4 = -1.toLong(): jet.Long, b5 = -1.0.toDouble(): jet.Double, b6 = -1.0.toFloat(): jet.Float, b7 = -99.toInt(): jet.Int] +// EXPECTED: Ann[b1 = IntegerValueType(-1): IntegerValueType(-1), b2 = IntegerValueType(-1): IntegerValueType(-1), b3 = IntegerValueType(-1): IntegerValueType(-1), b4 = IntegerValueType(-1): IntegerValueType(-1), b5 = -1.0.toDouble(): jet.Double, b6 = -1.0.toFloat(): jet.Float, b7 = IntegerValueType(-99): IntegerValueType(-99)] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/unaryPlus.kt b/compiler/testData/resolveAnnotations/parameters/expressions/unaryPlus.kt index 42bed1bd4e7..f6ab53d25f8 100644 --- a/compiler/testData/resolveAnnotations/parameters/expressions/unaryPlus.kt +++ b/compiler/testData/resolveAnnotations/parameters/expressions/unaryPlus.kt @@ -12,4 +12,4 @@ annotation class Ann( Ann(+1, +1, +1, +1, +1.0, +1.0.toFloat(), +'c') class MyClass -// EXPECTED: Ann[b1 = 1.toByte(): jet.Byte, b2 = 1.toShort(): jet.Short, b3 = 1.toInt(): jet.Int, b4 = 1.toLong(): jet.Long, b5 = 1.0.toDouble(): jet.Double, b6 = 1.0.toFloat(): jet.Float, b7 = 99.toInt(): jet.Int] +// EXPECTED: Ann[b1 = IntegerValueType(1): IntegerValueType(1), b2 = IntegerValueType(1): IntegerValueType(1), b3 = IntegerValueType(1): IntegerValueType(1), b4 = IntegerValueType(1): IntegerValueType(1), b5 = 1.0.toDouble(): jet.Double, b6 = 1.0.toFloat(): jet.Float, b7 = IntegerValueType(99): IntegerValueType(99)] diff --git a/compiler/testData/resolveAnnotations/parameters/int.kt b/compiler/testData/resolveAnnotations/parameters/int.kt index df6ec577022..f8487c84413 100644 --- a/compiler/testData/resolveAnnotations/parameters/int.kt +++ b/compiler/testData/resolveAnnotations/parameters/int.kt @@ -9,4 +9,4 @@ annotation class Ann( Ann(1, 1.toInt(), 2147483648.toInt(), 2147483648) class MyClass -// EXPECTED: Ann[b1 = 1.toInt(): jet.Int, b2 = 1.toInt(): jet.Int, b3 = -2147483648.toInt(): jet.Int, b4 = 2147483648.toLong(): jet.Long] \ No newline at end of file +// EXPECTED: Ann[b1 = IntegerValueType(1): IntegerValueType(1), b2 = 1.toInt(): jet.Int, b3 = -2147483648.toInt(): jet.Int, b4 = IntegerValueType(2147483648): IntegerValueType(2147483648)] \ No newline at end of file diff --git a/compiler/testData/resolveAnnotations/parameters/long.kt b/compiler/testData/resolveAnnotations/parameters/long.kt index 28c23aa4101..b83b9504ef8 100644 --- a/compiler/testData/resolveAnnotations/parameters/long.kt +++ b/compiler/testData/resolveAnnotations/parameters/long.kt @@ -7,4 +7,4 @@ annotation class Ann( Ann(1, 1.toLong()) class MyClass -// EXPECTED: Ann[b1 = 1.toLong(): jet.Long, b2 = 1.toLong(): jet.Long] \ No newline at end of file +// EXPECTED: Ann[b1 = IntegerValueType(1): IntegerValueType(1), b2 = 1.toLong(): jet.Long] \ No newline at end of file diff --git a/compiler/testData/resolveAnnotations/parameters/short.kt b/compiler/testData/resolveAnnotations/parameters/short.kt index 422bf8a4e0e..50437360117 100644 --- a/compiler/testData/resolveAnnotations/parameters/short.kt +++ b/compiler/testData/resolveAnnotations/parameters/short.kt @@ -9,4 +9,4 @@ annotation class Ann( Ann(1, 1.toShort(), 32768.toShort(), 32768) class MyClass -// EXPECTED: Ann[b1 = 1.toShort(): jet.Short, b2 = 1.toShort(): jet.Short, b3 = -32768.toShort(): jet.Short, b4 = 32768.toInt(): jet.Int] \ No newline at end of file +// EXPECTED: Ann[b1 = IntegerValueType(1): IntegerValueType(1), b2 = 1.toShort(): jet.Short, b3 = -32768.toShort(): jet.Short, b4 = IntegerValueType(32768): IntegerValueType(32768)] \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index a430119e283..2d4f98c3c5a 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -2749,6 +2749,21 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/evaluate/otherOverflow.kt"); } + @TestMetadata("unaryMinusDepOnExpType.kt") + public void testUnaryMinusDepOnExpType() throws Exception { + doTest("compiler/testData/diagnostics/tests/evaluate/unaryMinusDepOnExpType.kt"); + } + + @TestMetadata("unaryMinusIndepWoExpType.kt") + public void testUnaryMinusIndepWoExpType() throws Exception { + doTest("compiler/testData/diagnostics/tests/evaluate/unaryMinusIndepWoExpType.kt"); + } + + @TestMetadata("unaryMinusIndependentExpType.kt") + public void testUnaryMinusIndependentExpType() throws Exception { + doTest("compiler/testData/diagnostics/tests/evaluate/unaryMinusIndependentExpType.kt"); + } + } @TestMetadata("compiler/testData/diagnostics/tests/extensions") diff --git a/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt b/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt index 511899b20bc..7000a416e20 100644 --- a/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt +++ b/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt @@ -28,25 +28,57 @@ 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 abstract class AbstractEvaluateExpressionTest: AbstractAnnotationDescriptorResolveTest() { // Test directives should look like [// val testedPropertyName: expectedValue] - fun doTest(path: String) { - val fileText = FileUtil.loadFile(File(path)) + fun doConstantTest(path: String) { + doTest(path) { + property, context -> + val compileTimeConstant = context.get(BindingContext.COMPILE_TIME_VALUE, property.getInitializer()) + compileTimeConstant.toString() + } + } + + // Test directives should look like [// val testedPropertyName: expectedValue] + fun doIsPureTest(path: String) { + doTest(path) { + property, context -> + val isPureKey = context.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, property.getInitializer()) + isPureKey.toString() + } + } + + private fun doTest(path: String, getValueToTest: (JetProperty, BindingContext) -> String) { + val myFile = File(path) + val fileText = FileUtil.loadFile(myFile) val namespaceDescriptor = getNamespaceDescriptor(fileText) val propertiesForTest = getObjectsToTest(fileText) + val expectedActual = hashMapOf() + for (propertyName in propertiesForTest) { + val expectedProperyPrefix = "// val ${propertyName}: " + val expected = InTextDirectivesUtils.findStringWithPrefixes(fileText, expectedProperyPrefix) + assertNotNull(expected, "Failed to find expected directive: $expectedProperyPrefix") + val property = AbstractAnnotationDescriptorResolveTest.getPropertyDescriptor(namespaceDescriptor, propertyName) val jetProperty = BindingContextUtils.descriptorToDeclaration(context!!, property) as JetProperty - val compileTimeConstant = context!!.get(BindingContext.COMPILE_TIME_VALUE, jetProperty.getInitializer()) - val expected = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// val ${propertyName}: ") - assertNotNull(expected, "Failed to find expected directive: // val ${propertyName}: ") - assertEquals(expected, StringUtil.unquoteString(compileTimeConstant.toString()), "Failed for $propertyName") + val testedObject = getValueToTest(jetProperty, context!!) + expectedActual[expectedProperyPrefix + expected!!] = expectedProperyPrefix + StringUtil.unquoteString(testedObject) } + + var actualFileText = fileText + for ((expected, actual) in expectedActual) { + actualFileText = actualFileText.replace(expected, actual) + } + + JetTestUtils.assertEqualsToFile(myFile, actualFileText) } fun getObjectsToTest(fileText: String): List { diff --git a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java index f03ad66cd54..e3878fd7775 100644 --- a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java @@ -30,30 +30,98 @@ import org.jetbrains.jet.evaluate.AbstractEvaluateExpressionTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@TestMetadata("compiler/testData/evaluate") +@InnerTestClasses({EvaluateExpressionTestGenerated.Constant.class, EvaluateExpressionTestGenerated.IsPure.class}) public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionTest { - public void testAllFilesPresentInEvaluate() throws Exception { - JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/evaluate"), Pattern.compile("^(.+)\\.kt$"), true); + @TestMetadata("compiler/testData/evaluate/constant") + public static class Constant extends AbstractEvaluateExpressionTest { + public void testAllFilesPresentInConstant() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/evaluate/constant"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("compareTo.kt") + public void testCompareTo() throws Exception { + doConstantTest("compiler/testData/evaluate/constant/compareTo.kt"); + } + + @TestMetadata("divideByZero.kt") + public void testDivideByZero() throws Exception { + doConstantTest("compiler/testData/evaluate/constant/divideByZero.kt"); + } + + @TestMetadata("equals.kt") + public void testEquals() throws Exception { + doConstantTest("compiler/testData/evaluate/constant/equals.kt"); + } + + @TestMetadata("floatsAndDoubles.kt") + public void testFloatsAndDoubles() throws Exception { + doConstantTest("compiler/testData/evaluate/constant/floatsAndDoubles.kt"); + } + + @TestMetadata("integers.kt") + public void testIntegers() throws Exception { + doConstantTest("compiler/testData/evaluate/constant/integers.kt"); + } + + @TestMetadata("strings.kt") + public void testStrings() throws Exception { + doConstantTest("compiler/testData/evaluate/constant/strings.kt"); + } + + @TestMetadata("unaryMinusIndepWoExpType.kt") + public void testUnaryMinusIndepWoExpType() throws Exception { + doConstantTest("compiler/testData/evaluate/constant/unaryMinusIndepWoExpType.kt"); + } + + @TestMetadata("unaryMinusIndependentExpType.kt") + public void testUnaryMinusIndependentExpType() throws Exception { + doConstantTest("compiler/testData/evaluate/constant/unaryMinusIndependentExpType.kt"); + } + } - @TestMetadata("divideByZero.kt") - public void testDivideByZero() throws Exception { - doTest("compiler/testData/evaluate/divideByZero.kt"); + @TestMetadata("compiler/testData/evaluate/isPure") + public static class IsPure extends AbstractEvaluateExpressionTest { + public void testAllFilesPresentInIsPure() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/evaluate/isPure"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("enum.kt") + public void testEnum() throws Exception { + doIsPureTest("compiler/testData/evaluate/isPure/enum.kt"); + } + + @TestMetadata("innerToType.kt") + public void testInnerToType() throws Exception { + doIsPureTest("compiler/testData/evaluate/isPure/innerToType.kt"); + } + + @TestMetadata("strings.kt") + public void testStrings() throws Exception { + doIsPureTest("compiler/testData/evaluate/isPure/strings.kt"); + } + + @TestMetadata("toType.kt") + public void testToType() throws Exception { + doIsPureTest("compiler/testData/evaluate/isPure/toType.kt"); + } + + @TestMetadata("unaryMinusIndepWoExpType.kt") + public void testUnaryMinusIndepWoExpType() throws Exception { + doIsPureTest("compiler/testData/evaluate/isPure/unaryMinusIndepWoExpType.kt"); + } + + @TestMetadata("unaryMinusIndependentExpType.kt") + public void testUnaryMinusIndependentExpType() throws Exception { + doIsPureTest("compiler/testData/evaluate/isPure/unaryMinusIndependentExpType.kt"); + } + } - @TestMetadata("floatsAndDoubles.kt") - public void testFloatsAndDoubles() throws Exception { - doTest("compiler/testData/evaluate/floatsAndDoubles.kt"); + public static Test suite() { + TestSuite suite = new TestSuite("EvaluateExpressionTestGenerated"); + suite.addTestSuite(Constant.class); + suite.addTestSuite(IsPure.class); + return suite; } - - @TestMetadata("integers.kt") - public void testIntegers() throws Exception { - doTest("compiler/testData/evaluate/integers.kt"); - } - - @TestMetadata("strings.kt") - public void testStrings() throws Exception { - doTest("compiler/testData/evaluate/strings.kt"); - } - } diff --git a/compiler/tests/org/jetbrains/jet/resolve/annotation/AbstractAnnotationDescriptorResolveTest.java b/compiler/tests/org/jetbrains/jet/resolve/annotation/AbstractAnnotationDescriptorResolveTest.java index 35653a2673a..6b529161c65 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/annotation/AbstractAnnotationDescriptorResolveTest.java +++ b/compiler/tests/org/jetbrains/jet/resolve/annotation/AbstractAnnotationDescriptorResolveTest.java @@ -281,4 +281,14 @@ public abstract class AbstractAnnotationDescriptorResolveTest extends JetLiteFix }, " "); assertEquals("Failed to resolve annotation descriptor for " + member.toString(), expectedAnnotation, actual); } + + @NotNull + protected static String getAnnotations(DeclarationDescriptor member) { + return StringUtil.join(member.getAnnotations(), new Function() { + @Override + public String fun(AnnotationDescriptor annotationDescriptor) { + return annotationDescriptor.getType().toString() + DescriptorUtils.getSortedValueArguments(annotationDescriptor, DescriptorRenderer.TEXT); + } + }, " "); + } } diff --git a/compiler/tests/org/jetbrains/jet/resolve/annotation/AbstractAnnotationParameterTest.kt b/compiler/tests/org/jetbrains/jet/resolve/annotation/AbstractAnnotationParameterTest.kt index 5f8dd5ae905..25a532c6abc 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/annotation/AbstractAnnotationParameterTest.kt +++ b/compiler/tests/org/jetbrains/jet/resolve/annotation/AbstractAnnotationParameterTest.kt @@ -19,6 +19,7 @@ package org.jetbrains.jet.resolve.annotation import com.intellij.openapi.util.io.FileUtil import org.jetbrains.jet.InTextDirectivesUtils import java.io.File +import org.jetbrains.jet.JetTestUtils public abstract class AbstractAnnotationParameterTest : AbstractAnnotationDescriptorResolveTest() { fun doTest(path: String) { @@ -27,6 +28,8 @@ public abstract class AbstractAnnotationParameterTest : AbstractAnnotationDescri val classDescriptor = AbstractAnnotationDescriptorResolveTest.getClassDescriptor(namespaceDescriptor, "MyClass") val expected = InTextDirectivesUtils.findListWithPrefixes(fileText, "// EXPECTED: ").makeString(", ") - AbstractAnnotationDescriptorResolveTest.checkDescriptor(expected, classDescriptor) + val actual = AbstractAnnotationDescriptorResolveTest.getAnnotations(classDescriptor) + + JetTestUtils.assertEqualsToFile(File(path), fileText.replace(expected, actual)) } } diff --git a/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationDescriptorResolveTest.java b/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationDescriptorResolveTest.java index 0166ee459c8..a3c00fbad27 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationDescriptorResolveTest.java +++ b/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationDescriptorResolveTest.java @@ -21,7 +21,7 @@ import java.io.IOException; public class AnnotationDescriptorResolveTest extends AbstractAnnotationDescriptorResolveTest { public void testIntAnnotation() throws IOException { String content = getContent("AnnInt(1)"); - String expectedAnnotation = "AnnInt[a = 1.toInt(): jet.Int]"; + String expectedAnnotation = "AnnInt[a = IntegerValueType(1): IntegerValueType(1)]"; doTest(content, expectedAnnotation); } @@ -51,13 +51,13 @@ public class AnnotationDescriptorResolveTest extends AbstractAnnotationDescripto public void testIntArrayAnnotation() throws IOException { String content = getContent("AnnIntArray(intArray(1, 2))"); - String expectedAnnotation = "AnnIntArray[a = [1.toInt(), 2.toInt()]: jet.IntArray]"; + String expectedAnnotation = "AnnIntArray[a = [IntegerValueType(1), IntegerValueType(2)]: jet.IntArray]"; doTest(content, expectedAnnotation); } public void testIntArrayVarargAnnotation() throws IOException { String content = getContent("AnnIntVararg(1, 2)"); - String expectedAnnotation = "AnnIntVararg[a = [1.toInt(), 2.toInt()]: jet.IntArray]"; + String expectedAnnotation = "AnnIntVararg[a = [IntegerValueType(1), IntegerValueType(2)]: jet.IntArray]"; doTest(content, expectedAnnotation); } @@ -81,7 +81,7 @@ public class AnnotationDescriptorResolveTest extends AbstractAnnotationDescripto public void testAnnotationAnnotation() throws Exception { String content = getContent("AnnAnn(AnnInt(1))"); - String expectedAnnotation = "AnnAnn[a = AnnInt[a = 1.toInt()]: test.AnnInt]"; + String expectedAnnotation = "AnnAnn[a = AnnInt[a = IntegerValueType(1)]: test.AnnInt]"; doTest(content, expectedAnnotation); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationArgumentVisitor.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationArgumentVisitor.java index ef2fe79ae12..f585caa755e 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationArgumentVisitor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationArgumentVisitor.java @@ -50,4 +50,6 @@ public interface AnnotationArgumentVisitor { R visitAnnotationValue(AnnotationValue value, D data); R visitJavaClassValue(JavaClassValue value, D data); + + R visitNumberTypeValue(NumberValueTypeConstant value, D data); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NumberValueTypeConstant.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NumberValueTypeConstant.java new file mode 100644 index 00000000000..89529da357d --- /dev/null +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NumberValueTypeConstant.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.constants; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.types.ErrorUtils; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.JetTypeImpl; +import org.jetbrains.jet.lang.types.TypeProjection; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; + +import java.util.Collections; + +public abstract class NumberValueTypeConstant implements CompileTimeConstant> { + + @NotNull + @Override + public JetType getType(@NotNull KotlinBuiltIns kotlinBuiltIns) { + return new JetTypeImpl( + Collections.emptyList(), getValue(), + false, Collections.emptyList(), + ErrorUtils.createErrorScope("Scope for number value type (" + getValue().toString() + ")", true)); + } + + @Override + public R accept(AnnotationArgumentVisitor visitor, D data) { + return visitor.visitNumberTypeValue(this, data); + } + + @Override + public abstract NumberValueTypeConstructor getValue(); +} diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NumberValueTypeConstructor.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NumberValueTypeConstructor.java index 623cd57ce67..3d6c6430484 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NumberValueTypeConstructor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NumberValueTypeConstructor.java @@ -26,7 +26,7 @@ import org.jetbrains.jet.lang.types.TypeConstructor; import java.util.Collections; import java.util.List; -public abstract class NumberValueTypeConstructor implements TypeConstructor { +public abstract class NumberValueTypeConstructor implements TypeConstructor { @NotNull @Override public List getParameters() { @@ -54,4 +54,6 @@ public abstract class NumberValueTypeConstructor implements TypeConstructor { public List getAnnotations() { return Collections.emptyList(); } + + public abstract T getValue(); } diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.java b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.java index b0a6a02ac4f..024011b23fe 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.java +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.java @@ -571,7 +571,8 @@ public class GenerateTests { "compiler/tests", "EvaluateExpressionTestGenerated", AbstractEvaluateExpressionTest.class, - testModel("compiler/testData/evaluate") + testModel("compiler/testData/evaluate/constant", "doConstantTest"), + testModel("compiler/testData/evaluate/isPure", "doIsPureTest") ); }