Support for unary expressions
This commit is contained in:
@@ -212,6 +212,15 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompileTimeConstant<?> visitUnaryExpression(@NotNull JetUnaryExpression expression, Void data) {
|
||||
JetExpression leftExpression = expression.getBaseExpression();
|
||||
if (leftExpression == null) {
|
||||
return null;
|
||||
}
|
||||
return getCallConstant(expression.getOperationReference(), leftExpression);
|
||||
}
|
||||
|
||||
public static CompileTimeConstant<?> createCompileTimeConstant(@NotNull Object value, @NotNull JetType expectedType) {
|
||||
if (value instanceof Integer) {
|
||||
return getIntegerValue(((Integer) value).longValue(), expectedType);
|
||||
|
||||
@@ -21,6 +21,22 @@ fun evaluateBinaryExpression(firstCompileTimeConstant: CompileTimeConstant<*>, s
|
||||
return null
|
||||
}
|
||||
|
||||
fun evaluateUnaryExpression(compileTimeConstant: CompileTimeConstant<*>, functionName: Name): Any? {
|
||||
val compileTimeType = getCompileTimeType(compileTimeConstant)
|
||||
if (compileTimeType == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val value = compileTimeConstant.getValue()
|
||||
|
||||
val function = unaryOperations[UnaryOperation(compileTimeType, functionName)]
|
||||
if (function != null) {
|
||||
return function(value)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun getCompileTimeType(c: CompileTimeConstant<*>): CompileTimeType<out Any>? = when (c.getValue()) {
|
||||
is Int -> INT
|
||||
is Byte -> BYTE
|
||||
@@ -47,8 +63,29 @@ private val BOOLEAN = CompileTimeType<Boolean>()
|
||||
private val STRING = CompileTimeType<String>()
|
||||
|
||||
private fun <A, B> bOp(a: CompileTimeType<A>, b: CompileTimeType<B>, functionNameAsString: String, f: (A, B) -> Any) = BinaryOperation(a, b, Name.identifier(functionNameAsString)) to f as Function2<Any?, Any?, Any>
|
||||
private fun <A> uOp(a: CompileTimeType<A>, functionNameAsString: String, f: (A) -> Any) = UnaryOperation(a, Name.identifier(functionNameAsString)) to f as Function1<Any?, Any>
|
||||
|
||||
private data class BinaryOperation<A, B>(val f: CompileTimeType<out A>, val s: CompileTimeType<out B>, val functionName: Name)
|
||||
private data class UnaryOperation<A>(val f: CompileTimeType<out A>, val functionName: Name)
|
||||
|
||||
private val unaryOperations = hashMapOf<UnaryOperation<*>, (Any?) -> Any>(
|
||||
uOp(DOUBLE, "minus", { a -> a.minus() }),
|
||||
uOp(FLOAT, "minus", { a -> a.minus() }),
|
||||
uOp(LONG, "minus", { a -> a.minus() }),
|
||||
uOp(INT, "minus", { a -> a.minus() }),
|
||||
uOp(SHORT, "minus", { a -> a.minus() }),
|
||||
uOp(BYTE, "minus", { a -> a.minus() }),
|
||||
uOp(CHAR, "minus", { a -> a.minus() }),
|
||||
uOp(DOUBLE, "plus", { a -> a.plus() }),
|
||||
uOp(FLOAT, "plus", { a -> a.plus() }),
|
||||
uOp(LONG, "plus", { a -> a.plus() }),
|
||||
uOp(INT, "plus", { a -> a.plus() }),
|
||||
uOp(SHORT, "plus", { a -> a.plus() }),
|
||||
uOp(BYTE, "plus", { a -> a.plus() }),
|
||||
uOp(CHAR, "plus", { a -> a.plus() }),
|
||||
|
||||
uOp(BOOLEAN, "not", { a -> a.not() })
|
||||
)
|
||||
|
||||
private val binaryOperations = hashMapOf<BinaryOperation<*, *>, (Any?, Any?) -> Any>(
|
||||
// String
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import org.jetbrains.jet.lang.evaluate.evaluateBinaryExpression
|
||||
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.evaluate.evaluateUnaryExpression
|
||||
|
||||
public fun resolveCallToCompileTimeValue(
|
||||
callName: Name,
|
||||
@@ -30,7 +31,7 @@ public fun resolveCallToCompileTimeValue(
|
||||
): CompileTimeConstant<*>? {
|
||||
if (arguments.isEmpty()) {
|
||||
val value = receiverValue.getValue()
|
||||
return when (value) {
|
||||
val toTypeConstant = when (value) {
|
||||
is Number -> {
|
||||
when(callName) {
|
||||
OperatorConventions.DOUBLE -> DoubleValue(value.toDouble())
|
||||
@@ -57,6 +58,14 @@ public fun resolveCallToCompileTimeValue(
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
if (toTypeConstant != null) {
|
||||
return toTypeConstant
|
||||
}
|
||||
val result = evaluateUnaryExpression(receiverValue, callName)
|
||||
if (result == null) {
|
||||
return null
|
||||
}
|
||||
return ConstantExpressionEvaluator.createCompileTimeConstant(result, expectedType)
|
||||
}
|
||||
else if (arguments.size() == 1) {
|
||||
val result = evaluateBinaryExpression(receiverValue, arguments.iterator().next(), callName)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Boolean,
|
||||
val b2: Boolean,
|
||||
val b3: Boolean
|
||||
)
|
||||
|
||||
Ann(!true, !false) class MyClass
|
||||
|
||||
// EXPECTED: Ann[b1 = false: jet.Boolean, b2 = true: jet.Boolean]
|
||||
@@ -0,0 +1,15 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Byte,
|
||||
val b2: Short,
|
||||
val b3: Int,
|
||||
val b4: Long,
|
||||
val b5: Double,
|
||||
val b6: Float,
|
||||
val b7: Char
|
||||
)
|
||||
|
||||
Ann(-1, -1, -1, -1, -1.0, -1.0, -'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.toDouble(): jet.Double, b7 = -99.toInt(): jet.Int]
|
||||
@@ -0,0 +1,15 @@
|
||||
package test
|
||||
|
||||
annotation class Ann(
|
||||
val b1: Byte,
|
||||
val b2: Short,
|
||||
val b3: Int,
|
||||
val b4: Long,
|
||||
val b5: Double,
|
||||
val b6: Float,
|
||||
val b7: Char
|
||||
)
|
||||
|
||||
Ann(+1, +1, +1, +1, +1.0, +1.0, +'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.toDouble(): jet.Double, b7 = 99.toInt(): jet.Int]
|
||||
+15
@@ -198,6 +198,11 @@ public class AnnotationParameterTestGenerated extends AbstractAnnotationParamete
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/expressions/multilineString.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("not.kt")
|
||||
public void testNot() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/expressions/not.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("orOr.kt")
|
||||
public void testOrOr() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/expressions/orOr.kt");
|
||||
@@ -233,6 +238,16 @@ public class AnnotationParameterTestGenerated extends AbstractAnnotationParamete
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/expressions/strings.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unaryMinus.kt")
|
||||
public void testUnaryMinus() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/expressions/unaryMinus.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unaryPlus.kt")
|
||||
public void testUnaryPlus() throws Exception {
|
||||
doTest("compiler/testData/resolveAnnotations/parameters/expressions/unaryPlus.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
|
||||
Reference in New Issue
Block a user