Support toInt, toChar and etc as CompileTimeConstants
This commit is contained in:
@@ -83,6 +83,10 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
||||
|
||||
@Override
|
||||
public CompileTimeConstant<?> visitQualifiedExpression(@NotNull JetQualifiedExpression expression, Void data) {
|
||||
CompileTimeConstant<?> compileTimeConstant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
||||
if (compileTimeConstant != null) {
|
||||
return compileTimeConstant;
|
||||
}
|
||||
JetExpression selectorExpression = expression.getSelectorExpression();
|
||||
if (selectorExpression != null) {
|
||||
return selectorExpression.accept(this, null);
|
||||
|
||||
+5
-5
@@ -34,7 +34,7 @@ import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
|
||||
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.constants.ConstantUtils;
|
||||
import org.jetbrains.jet.lang.resolve.constants.ConstantsPackage;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -417,15 +417,15 @@ public class CallExpressionResolver {
|
||||
|
||||
context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo());
|
||||
|
||||
if (selectorExpression instanceof JetSimpleNameExpression) {
|
||||
ConstantUtils.propagateConstantValues(expression, context.trace, (JetSimpleNameExpression) selectorExpression);
|
||||
}
|
||||
|
||||
JetTypeInfo selectorReturnTypeInfo = getSelectorReturnTypeInfo(
|
||||
new ExpressionReceiver(receiverExpression, receiverType),
|
||||
expression.getOperationTokenNode(), selectorExpression, context);
|
||||
JetType selectorReturnType = selectorReturnTypeInfo.getType();
|
||||
|
||||
if (receiverExpression instanceof JetConstantExpression && selectorExpression instanceof JetCallExpression) {
|
||||
ConstantsPackage.propagateConstantValues(expression, context.trace, (JetCallExpression) selectorExpression);
|
||||
}
|
||||
|
||||
//TODO move further
|
||||
if (!(receiverType instanceof NamespaceType) && expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
|
||||
if (selectorReturnType != null && !selectorReturnType.isNullable() && !KotlinBuiltIns.getInstance().isUnit(selectorReturnType)) {
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* 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.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
|
||||
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
||||
|
||||
public class ConstantUtils {
|
||||
|
||||
public static void propagateConstantValues(JetQualifiedExpression expression, BindingTrace trace, JetSimpleNameExpression selectorExpression) {
|
||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||
CompileTimeConstant<?> receiverValue = trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, receiverExpression);
|
||||
CompileTimeConstant<?> wholeExpressionValue = trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, expression);
|
||||
DeclarationDescriptor declarationDescriptor = trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, selectorExpression);
|
||||
if (wholeExpressionValue == null && receiverValue != null && !(receiverValue instanceof ErrorValue) && receiverValue.getValue() instanceof Number
|
||||
&& KotlinBuiltIns.getInstance().getNumber() == declarationDescriptor) {
|
||||
Number value = (Number) receiverValue.getValue();
|
||||
Name referencedName = selectorExpression.getReferencedNameAsName();
|
||||
if (OperatorConventions.NUMBER_CONVERSIONS.contains(referencedName)) {
|
||||
if (DOUBLE.equals(referencedName)) {
|
||||
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new DoubleValue(value.doubleValue()));
|
||||
}
|
||||
else if (FLOAT.equals(referencedName)) {
|
||||
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new FloatValue(value.floatValue()));
|
||||
}
|
||||
else if (LONG.equals(referencedName)) {
|
||||
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new LongValue(value.longValue()));
|
||||
}
|
||||
else if (SHORT.equals(referencedName)) {
|
||||
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new ShortValue(value.shortValue()));
|
||||
}
|
||||
else if (BYTE.equals(referencedName)) {
|
||||
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new ByteValue(value.byteValue()));
|
||||
}
|
||||
else if (INT.equals(referencedName)) {
|
||||
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new IntValue(value.intValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.jet.lang.psi.JetQualifiedExpression
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
|
||||
|
||||
public fun propagateConstantValues(expression : JetQualifiedExpression, trace : BindingTrace, selectorExpression : JetCallExpression) {
|
||||
val wholeExpressionValue = trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, expression)
|
||||
if (wholeExpressionValue != null) {
|
||||
return
|
||||
}
|
||||
|
||||
val receiverExpression = expression.getReceiverExpression()
|
||||
val receiverValue = trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, receiverExpression)
|
||||
if (receiverValue == null || receiverValue is ErrorValue) {
|
||||
return
|
||||
}
|
||||
|
||||
val calleeExpression = selectorExpression.getCalleeExpression()
|
||||
if (calleeExpression !is JetSimpleNameExpression) {
|
||||
return
|
||||
}
|
||||
|
||||
val declarationDescriptor = trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, calleeExpression)
|
||||
if (declarationDescriptor !is FunctionDescriptor) {
|
||||
return
|
||||
}
|
||||
|
||||
val returnType = declarationDescriptor.getReturnType()
|
||||
if (returnType == null || !KotlinBuiltIns.getInstance().isPrimitiveType(returnType)) {
|
||||
return
|
||||
}
|
||||
|
||||
val referencedName = calleeExpression.getReferencedNameAsName()
|
||||
val value = receiverValue.getValue()
|
||||
val compileTimeValue = when (value) {
|
||||
is Number -> {
|
||||
when(referencedName) {
|
||||
OperatorConventions.DOUBLE -> DoubleValue(value.toDouble())
|
||||
OperatorConventions.FLOAT -> FloatValue(value.toFloat())
|
||||
OperatorConventions.LONG -> LongValue(value.toLong())
|
||||
OperatorConventions.SHORT -> ShortValue(value.toShort())
|
||||
OperatorConventions.BYTE -> ByteValue(value.toByte())
|
||||
OperatorConventions.INT -> IntValue(value.toInt())
|
||||
OperatorConventions.CHAR -> CharValue(value.toInt().toChar())
|
||||
}
|
||||
}
|
||||
is Char -> {
|
||||
when(referencedName) {
|
||||
OperatorConventions.DOUBLE -> DoubleValue(value.toChar().toDouble())
|
||||
OperatorConventions.FLOAT -> FloatValue(value.toChar().toFloat())
|
||||
OperatorConventions.LONG -> LongValue(value.toChar().toLong())
|
||||
OperatorConventions.SHORT -> ShortValue(value.toChar().toShort())
|
||||
OperatorConventions.BYTE -> ByteValue(value.toChar().toByte())
|
||||
OperatorConventions.INT -> IntValue(value.toChar().toInt())
|
||||
OperatorConventions.CHAR -> CharValue(value.toChar())
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (compileTimeValue != null) {
|
||||
trace.record(BindingContext.COMPILE_TIME_VALUE, expression,compileTimeValue)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Byte,
|
||||
val b2: Byte,
|
||||
val b3: Byte,
|
||||
val b4: Byte
|
||||
)
|
||||
|
||||
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]
|
||||
@@ -0,0 +1,16 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Char,
|
||||
val b2: Char,
|
||||
val b3: Int,
|
||||
val b4: Long,
|
||||
val b5: Byte,
|
||||
val b6: Short,
|
||||
val b7: Double,
|
||||
val b8: Float
|
||||
)
|
||||
|
||||
Ann('c', 99.toChar(), 'c'.toInt(), 'c'.toLong(), 'c'.toByte(), 'c'.toShort(), 'c'.toDouble(), 'c'.toFloat()) class MyClass
|
||||
|
||||
// EXPECTED: Ann[b1 = #99(c): jet.Char, b2 = #99(c): jet.Char, b3 = 99.toInt(): jet.Int, b4 = 99.toLong(): jet.Long, b5 = 99.toByte(): jet.Byte, b6 = 99.toShort(): jet.Short, b7 = 99.0.toDouble(): jet.Double, b8 = 99.0.toFloat(): jet.Float]
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Double,
|
||||
val b2: Double,
|
||||
val b3: Double,
|
||||
val b4: Double
|
||||
)
|
||||
|
||||
Ann(1.0, 1.toDouble(), 1.7976931348623157E309.toDouble(), 1.7976931348623157E309) class MyClass
|
||||
|
||||
// EXPECTED: Ann[b1 = 1.0.toDouble(): jet.Double, b2 = 1.0.toDouble(): jet.Double, b3 = Infinity.toDouble(): jet.Double, b4 = Infinity.toDouble(): jet.Double]
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Float,
|
||||
val b2: Float,
|
||||
val b3: Float,
|
||||
val b4: Float
|
||||
)
|
||||
|
||||
Ann(1.0, 1.toFloat(), 1.0.toFloat()) class MyClass
|
||||
|
||||
// EXPECTED: Ann[b1 = 1.0.toFloat(): jet.Float, b2 = 1.0.toFloat(): jet.Float, b3 = 1.0.toFloat(): jet.Float]
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Int,
|
||||
val b2: Int,
|
||||
val b3: Int,
|
||||
val b4: Int
|
||||
)
|
||||
|
||||
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]
|
||||
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Long,
|
||||
val b2: Long
|
||||
)
|
||||
|
||||
Ann(1, 1.toLong()) class MyClass
|
||||
|
||||
// EXPECTED: Ann[b1 = 1.toLong(): jet.Long, b2 = 1.toLong(): jet.Long]
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Short,
|
||||
val b2: Short,
|
||||
val b3: Short,
|
||||
val b4: Short
|
||||
)
|
||||
|
||||
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]
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.resolve.annotation
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.jet.InTextDirectivesUtils
|
||||
import java.io.File
|
||||
|
||||
public abstract class AbstractAnnotationParameterTest : AbstractAnnotationDescriptorResolveTest() {
|
||||
fun doTest(path: String) {
|
||||
val fileText = FileUtil.loadFile(File(path))
|
||||
val namespaceDescriptor = getNamespaceDescriptor(fileText)
|
||||
val classDescriptor = AbstractAnnotationDescriptorResolveTest.getClassDescriptor(namespaceDescriptor, "MyClass")
|
||||
|
||||
val expected = InTextDirectivesUtils.findListWithPrefixes(fileText, "// EXPECTED: ").makeString(", ")
|
||||
AbstractAnnotationDescriptorResolveTest.checkDescriptor(expected, classDescriptor)
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.resolve.annotation;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.test.InnerTestClasses;
|
||||
import org.jetbrains.jet.test.TestMetadata;
|
||||
|
||||
import org.jetbrains.jet.resolve.annotation.AbstractAnnotationParameterTest;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/resolveAnnotations/parameters")
|
||||
public class AnnotationParameterTestGenerated extends AbstractAnnotationParameterTest {
|
||||
public void testAllFilesPresentInParameters() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/resolveAnnotations/parameters"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("byte.kt")
|
||||
public void testByte() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/byte.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("char.kt")
|
||||
public void testChar() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/char.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("double.kt")
|
||||
public void testDouble() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/double.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("float.kt")
|
||||
public void testFloat() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/float.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("int.kt")
|
||||
public void testInt() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/int.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("long.kt")
|
||||
public void testLong() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/long.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("short.kt")
|
||||
public void testShort() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/short.kt");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -64,6 +64,7 @@ import org.jetbrains.jet.psi.AbstractJetPsiMatcherTest;
|
||||
import org.jetbrains.jet.resolve.AbstractResolveBaseTest;
|
||||
import org.jetbrains.jet.resolve.AbstractResolveTest;
|
||||
import org.jetbrains.jet.resolve.AbstractResolveWithLibTest;
|
||||
import org.jetbrains.jet.resolve.annotation.AbstractAnnotationParameterTest;
|
||||
import org.jetbrains.jet.safeDelete.AbstractJetSafeDeleteTest;
|
||||
|
||||
import java.io.File;
|
||||
@@ -557,6 +558,13 @@ public class GenerateTests {
|
||||
AbstractRenameTest.class,
|
||||
new SingleClassTestModel(new File("idea/testData/refactoring/rename"), Pattern.compile("^(.+)\\.test$"), "doTest")
|
||||
);
|
||||
|
||||
generateTest(
|
||||
"compiler/tests",
|
||||
"AnnotationParameterTestGenerated",
|
||||
AbstractAnnotationParameterTest.class,
|
||||
testModel("compiler/testData/resolveAnnotations/parameters")
|
||||
);
|
||||
}
|
||||
|
||||
private static SimpleTestClassModel testModel(@NotNull String rootPath) {
|
||||
|
||||
Reference in New Issue
Block a user