Merge pull request #392 from wutalman/simplify_booleans

KT-4569: Intention to simplify boolean expressions with constants #KT-4569 Fixed
This commit is contained in:
Natalia Ukhorskaya
2014-04-10 11:00:16 +04:00
79 changed files with 684 additions and 131 deletions
@@ -38,6 +38,7 @@ public class JavaPropertyInitializerEvaluatorImpl implements JavaPropertyInitial
evaluatedExpression, evaluatedExpression,
DescriptorUtils.isPropertyCompileTimeConstant(descriptor), DescriptorUtils.isPropertyCompileTimeConstant(descriptor),
false, false,
true,
descriptor.getType()); descriptor.getType());
} }
return null; return null;
@@ -54,7 +54,6 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, compileTimeConstant) trace.record(BindingContext.COMPILE_TIME_VALUE, expression, compileTimeConstant)
return compileTimeConstant return compileTimeConstant
} }
return null return null
} }
@@ -70,9 +69,9 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
return createStringConstant(this@ConstantExpressionEvaluator.evaluate(expression, KotlinBuiltIns.getInstance().getStringType())) return createStringConstant(this@ConstantExpressionEvaluator.evaluate(expression, KotlinBuiltIns.getInstance().getStringType()))
} }
override fun visitLiteralStringTemplateEntry(entry: JetLiteralStringTemplateEntry, data: Nothing?) = StringValue(entry.getText(), true) override fun visitLiteralStringTemplateEntry(entry: JetLiteralStringTemplateEntry, data: Nothing?) = StringValue(entry.getText(), true, false)
override fun visitEscapeStringTemplateEntry(entry: JetEscapeStringTemplateEntry, data: Nothing?) = StringValue(entry.getUnescapedValue(), true) override fun visitEscapeStringTemplateEntry(entry: JetEscapeStringTemplateEntry, data: Nothing?) = StringValue(entry.getUnescapedValue(), true, false)
} }
override fun visitConstantExpression(expression: JetConstantExpression, expectedType: JetType?): CompileTimeConstant<*>? { override fun visitConstantExpression(expression: JetConstantExpression, expectedType: JetType?): CompileTimeConstant<*>? {
@@ -92,8 +91,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
if (result == null) return null if (result == null) return null
fun isLongWithSuffix() = nodeElementType == JetNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text) fun isLongWithSuffix() = nodeElementType == JetNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text)
return createCompileTimeConstant(result, expectedType, !isLongWithSuffix(), true, false)
return createCompileTimeConstant(result, expectedType, !isLongWithSuffix())
} }
override fun visitParenthesizedExpression(expression: JetParenthesizedExpression, expectedType: JetType?): CompileTimeConstant<*>? { override fun visitParenthesizedExpression(expression: JetParenthesizedExpression, expectedType: JetType?): CompileTimeConstant<*>? {
@@ -118,6 +116,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
val sb = StringBuilder() val sb = StringBuilder()
var interupted = false var interupted = false
var canBeUsedInAnnotation = true var canBeUsedInAnnotation = true
var usesVariableAsConstant = false
for (entry in expression.getEntries()) { for (entry in expression.getEntries()) {
val constant = stringExpressionEvaluator.evaluate(entry) val constant = stringExpressionEvaluator.evaluate(entry)
if (constant == null) { if (constant == null) {
@@ -126,12 +125,14 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
} }
else { else {
if (!constant.canBeUsedInAnnotations()) canBeUsedInAnnotation = false if (!constant.canBeUsedInAnnotations()) canBeUsedInAnnotation = false
if (constant.usesVariableAsConstant()) usesVariableAsConstant = true
sb.append(constant.getValue()) sb.append(constant.getValue())
} }
} }
return if (!interupted) return if (!interupted)
createCompileTimeConstant(sb.toString(), expectedType, createCompileTimeConstant(sb.toString(), expectedType,
isPure = true, canBeUsedInAnnotation = canBeUsedInAnnotation) isPure = true, canBeUsedInAnnotation = canBeUsedInAnnotation,
usesVariableAsConstant = usesVariableAsConstant)
else null else null
} }
@@ -160,7 +161,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
JetTokens.OROR -> leftValue as Boolean || rightValue as Boolean JetTokens.OROR -> leftValue as Boolean || rightValue as Boolean
else -> throw IllegalArgumentException("Unknown boolean operation token ${operationToken}") else -> throw IllegalArgumentException("Unknown boolean operation token ${operationToken}")
} }
return createCompileTimeConstant(result, expectedType) val usesVariableAsConstant = leftConstant.usesVariableAsConstant() || rightConstant.usesVariableAsConstant()
return createCompileTimeConstant(result, expectedType, true, true, usesVariableAsConstant)
} }
else { else {
return evaluateCall(expression.getOperationReference(), leftExpression, expectedType) return evaluateCall(expression.getOperationReference(), leftExpression, expectedType)
@@ -182,12 +184,16 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
if (result == null) return null if (result == null) return null
val isArgumentPure = isPureConstant(argumentForReceiver.expression) val isArgumentPure = isPureConstant(argumentForReceiver.expression)
val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression)
val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression)
val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS
return createCompileTimeConstant(result, expectedType, !isNumberConversionMethod && isArgumentPure, canBeUsedInAnnotation) return createCompileTimeConstant(result,
expectedType,
!isNumberConversionMethod && isArgumentPure,
canBeUsedInAnnotation,
usesVariableAsConstant)
} }
else if (argumentsEntrySet.size() == 1) { else if (argumentsEntrySet.size() == 1) {
val (parameter, argument) = argumentsEntrySet.first() val (parameter, argument) = argumentsEntrySet.first()
val argumentForParameter = createOperationArgumentForFirstParameter(argument, parameter) val argumentForParameter = createOperationArgumentForFirstParameter(argument, parameter)
if (argumentForParameter == null) return null if (argumentForParameter == null) return null
@@ -200,12 +206,13 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression) val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression)
val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression)
val c = EvaluatorContext(canBeUsedInAnnotation, areArgumentsPure) val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) || usesVariableAsConstant(argumentForParameter.expression)
val c = EvaluatorContext(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant)
return when(resultingDescriptorName) { return when(resultingDescriptorName) {
OperatorConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, c) OperatorConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, c)
OperatorConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, c) OperatorConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, c)
else -> { else -> {
createCompileTimeConstant(result, expectedType, areArgumentsPure, canBeUsedInAnnotation) createCompileTimeConstant(result, expectedType, areArgumentsPure, canBeUsedInAnnotation, usesVariableAsConstant)
} }
} }
} }
@@ -213,7 +220,10 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
return null return null
} }
private fun usesVariableAsConstant(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.usesVariableAsConstant() ?: false
private fun canBeUsedInAnnotation(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.canBeUsedInAnnotations() ?: false private fun canBeUsedInAnnotation(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.canBeUsedInAnnotations() ?: false
private fun isPureConstant(expression: JetExpression): Boolean { private fun isPureConstant(expression: JetExpression): Boolean {
val compileTimeConstant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression) val compileTimeConstant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)
if (compileTimeConstant is IntegerValueConstant) { if (compileTimeConstant is IntegerValueConstant) {
@@ -287,7 +297,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
override fun visitSimpleNameExpression(expression: JetSimpleNameExpression, expectedType: JetType?): CompileTimeConstant<*>? { override fun visitSimpleNameExpression(expression: JetSimpleNameExpression, expectedType: JetType?): CompileTimeConstant<*>? {
val enumDescriptor = trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, expression); val enumDescriptor = trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, expression);
if (enumDescriptor != null && DescriptorUtils.isEnumEntry(enumDescriptor)) { if (enumDescriptor != null && DescriptorUtils.isEnumEntry(enumDescriptor)) {
return EnumValue(enumDescriptor as ClassDescriptor); return EnumValue(enumDescriptor as ClassDescriptor, false);
} }
val resolvedCall = trace.getBindingContext().get(BindingContext.RESOLVED_CALL, expression) val resolvedCall = trace.getBindingContext().get(BindingContext.RESOLVED_CALL, expression)
@@ -303,7 +313,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
else else
compileTimeConstant.getValue() compileTimeConstant.getValue()
return createCompileTimeConstant(value, expectedType, isPure = false, return createCompileTimeConstant(value, expectedType, isPure = false,
canBeUsedInAnnotation = DescriptorUtils.isPropertyCompileTimeConstant(callableDescriptor)) canBeUsedInAnnotation = DescriptorUtils.isPropertyCompileTimeConstant(callableDescriptor),
usesVariableAsConstant = true)
} }
} }
return null return null
@@ -341,7 +352,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
val varargType = resultingDescriptor.getValueParameters().first?.getVarargElementType()!! val varargType = resultingDescriptor.getValueParameters().first?.getVarargElementType()!!
val arguments = call.getValueArguments().values().flatMap { resolveArguments(it.getArguments(), varargType) } val arguments = call.getValueArguments().values().flatMap { resolveArguments(it.getArguments(), varargType) }
return ArrayValue(arguments, resultingDescriptor.getReturnType()!!, true) return ArrayValue(arguments, resultingDescriptor.getReturnType()!!, true, arguments.any() { it.usesVariableAsConstant() })
} }
// Ann() // Ann()
@@ -402,7 +413,6 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
val argumentExpression = arguments.first().getArgumentExpression() val argumentExpression = arguments.first().getArgumentExpression()
if (argumentExpression == null) return null if (argumentExpression == null) return null
return createOperationArgument(argumentExpression, parameter.getType(), argumentCompileTimeType) return createOperationArgument(argumentExpression, parameter.getType(), argumentCompileTimeType)
} }
@@ -421,8 +431,12 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
return OperationArgument(evaluationResult, compileTimeType, expression) return OperationArgument(evaluationResult, compileTimeType, expression)
} }
fun createCompileTimeConstant(value: Any?, expectedType: JetType?, isPure: Boolean = true, canBeUsedInAnnotation: Boolean = true): CompileTimeConstant<*>? { fun createCompileTimeConstant(value: Any?,
val c = EvaluatorContext(canBeUsedInAnnotation, isPure) expectedType: JetType?,
isPure: Boolean = true,
canBeUsedInAnnotation: Boolean = true,
usesVariableAsConstant: Boolean = false): CompileTimeConstant<*>? {
val c = EvaluatorContext(canBeUsedInAnnotation, isPure, usesVariableAsConstant)
return createCompileTimeConstant(value, c, if (isPure) expectedType ?: TypeUtils.NO_EXPECTED_TYPE else null) return createCompileTimeConstant(value, c, if (isPure) expectedType ?: TypeUtils.NO_EXPECTED_TYPE else null)
} }
} }
@@ -490,11 +504,11 @@ private fun createCompileTimeConstantForEquals(result: Any?, operationReference:
assert(operationReference is JetSimpleNameExpression, "This method should be called only for equals operations") assert(operationReference is JetSimpleNameExpression, "This method should be called only for equals operations")
val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType() val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType()
return when (operationToken) { return when (operationToken) {
JetTokens.EQEQ -> BooleanValue(result, c.canBeUsedInAnnotation) JetTokens.EQEQ -> BooleanValue(result, c.canBeUsedInAnnotation, c.usesVariableAsConstant)
JetTokens.EXCLEQ -> BooleanValue(!result, c.canBeUsedInAnnotation) JetTokens.EXCLEQ -> BooleanValue(!result, c.canBeUsedInAnnotation, c.usesVariableAsConstant)
JetTokens.IDENTIFIER -> { JetTokens.IDENTIFIER -> {
assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.EQUALS, "This method should be called only for equals operations") assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.EQUALS, "This method should be called only for equals operations")
return BooleanValue(result, c.canBeUsedInAnnotation) return BooleanValue(result, c.canBeUsedInAnnotation, c.usesVariableAsConstant)
} }
else -> throw IllegalStateException("Unknown equals operation token: $operationToken ${operationReference.getText()}") else -> throw IllegalStateException("Unknown equals operation token: $operationToken ${operationReference.getText()}")
} }
@@ -507,13 +521,13 @@ private fun createCompileTimeConstantForCompareTo(result: Any?, operationReferen
assert(operationReference is JetSimpleNameExpression, "This method should be called only for compareTo operations") assert(operationReference is JetSimpleNameExpression, "This method should be called only for compareTo operations")
val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType() val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType()
return when (operationToken) { return when (operationToken) {
JetTokens.LT -> BooleanValue(result < 0, c.canBeUsedInAnnotation) JetTokens.LT -> BooleanValue(result < 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant)
JetTokens.LTEQ -> BooleanValue(result <= 0, c.canBeUsedInAnnotation) JetTokens.LTEQ -> BooleanValue(result <= 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant)
JetTokens.GT -> BooleanValue(result > 0, c.canBeUsedInAnnotation) JetTokens.GT -> BooleanValue(result > 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant)
JetTokens.GTEQ -> BooleanValue(result >= 0, c.canBeUsedInAnnotation) JetTokens.GTEQ -> BooleanValue(result >= 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant)
JetTokens.IDENTIFIER -> { JetTokens.IDENTIFIER -> {
assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.COMPARE_TO, "This method should be called only for compareTo operations") assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.COMPARE_TO, "This method should be called only for compareTo operations")
return IntValue(result, c.canBeUsedInAnnotation, c.isPure) return IntValue(result, c.canBeUsedInAnnotation, c.isPure, c.usesVariableAsConstant)
} }
else -> throw IllegalStateException("Unknown compareTo operation token: $operationToken") else -> throw IllegalStateException("Unknown compareTo operation token: $operationToken")
} }
@@ -523,19 +537,19 @@ private fun createCompileTimeConstantForCompareTo(result: Any?, operationReferen
private fun createStringConstant(value: CompileTimeConstant<*>?): StringValue? { private fun createStringConstant(value: CompileTimeConstant<*>?): StringValue? {
return when (value) { return when (value) {
is IntegerValueTypeConstant -> StringValue(value.getValue(TypeUtils.NO_EXPECTED_TYPE).toString(), value.canBeUsedInAnnotations()) is IntegerValueTypeConstant -> StringValue(value.getValue(TypeUtils.NO_EXPECTED_TYPE).toString(), value.canBeUsedInAnnotations(), value.usesVariableAsConstant())
is StringValue -> value is StringValue -> value
is IntValue, is ByteValue, is ShortValue, is LongValue, is IntValue, is ByteValue, is ShortValue, is LongValue,
is CharValue, is CharValue,
is DoubleValue, is FloatValue, is DoubleValue, is FloatValue,
is BooleanValue, is BooleanValue,
is NullValue -> StringValue(value.getValue().toString(), value.canBeUsedInAnnotations()) is NullValue -> StringValue(value.getValue().toString(), value.canBeUsedInAnnotations(), value.usesVariableAsConstant())
else -> null else -> null
} }
} }
private fun createCompileTimeConstant(value: Any?, c: EvaluatorContext, expectedType: JetType? = null): CompileTimeConstant<*>? { private fun createCompileTimeConstant(value: Any?, c: EvaluatorContext, expectedType: JetType? = null): CompileTimeConstant<*>? {
return createCompileTimeConstant(value, c.canBeUsedInAnnotation, c.isPure, expectedType) return createCompileTimeConstant(value, c.canBeUsedInAnnotation, c.isPure, c.usesVariableAsConstant, expectedType)
} }
fun isIntegerType(value: Any?) = value is Byte || value is Short || value is Int || value is Long fun isIntegerType(value: Any?) = value is Byte || value is Short || value is Int || value is Long
@@ -567,7 +581,7 @@ private fun getCompileTimeType(c: JetType): CompileTimeType<out Any>? {
} }
} }
private class EvaluatorContext(val canBeUsedInAnnotation: Boolean, val isPure: Boolean) private class EvaluatorContext(val canBeUsedInAnnotation: Boolean, val isPure: Boolean, val usesVariableAsConstant: Boolean = false)
private class CompileTimeType<T> private class CompileTimeType<T>
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import kotlin.Function1;
import kotlin.KotlinPackage; import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -282,11 +283,20 @@ public class AnnotationResolver {
trace); trace);
if (argumentsAsVararg) { if (argumentsAsVararg) {
boolean usesVariableAsConstant = KotlinPackage.any(constants, new Function1<CompileTimeConstant<?>, Boolean>() {
@Override
public Boolean invoke(CompileTimeConstant<?> constant) {
return constant.usesVariableAsConstant();
}
});
JetType arrayType = KotlinBuiltIns.getInstance().getPrimitiveArrayJetTypeByPrimitiveJetType(varargElementType); JetType arrayType = KotlinBuiltIns.getInstance().getPrimitiveArrayJetTypeByPrimitiveJetType(varargElementType);
if (arrayType == null) { if (arrayType == null) {
arrayType = KotlinBuiltIns.getInstance().getArrayType(varargElementType); arrayType = KotlinBuiltIns.getInstance().getArrayType(varargElementType);
} }
return new ArrayValue(constants, arrayType, true);
return new ArrayValue(constants, arrayType, true, usesVariableAsConstant);
} }
else { else {
// we should actually get only one element, but just in case of getting many, we take the last one // we should actually get only one element, but just in case of getting many, we take the last one
@@ -18,13 +18,11 @@ package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.Annotated; import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator; import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.jet.lang.psi.JetConstantExpression;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetParameter; import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.jet.lang.psi.JetTypeReference; import org.jetbrains.jet.lang.psi.JetTypeReference;
@@ -129,12 +127,10 @@ public class CompileTimeConstantUtils {
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@Nullable Boolean expectedValue @Nullable Boolean expectedValue
) { ) {
if (!(expression instanceof JetConstantExpression) || expression.getNode().getElementType() != JetNodeTypes.BOOLEAN_CONSTANT) { if (expression == null) return false;
return false;
}
CompileTimeConstant<?> compileTimeConstant = CompileTimeConstant<?> compileTimeConstant =
ConstantExpressionEvaluator.object$.evaluate(expression, trace, KotlinBuiltIns.getInstance().getBooleanType()); ConstantExpressionEvaluator.object$.evaluate(expression, trace, KotlinBuiltIns.getInstance().getBooleanType());
if (!(compileTimeConstant instanceof BooleanValue)) return false; if (!(compileTimeConstant instanceof BooleanValue) || compileTimeConstant.usesVariableAsConstant()) return false;
Boolean value = ((BooleanValue) compileTimeConstant).getValue(); Boolean value = ((BooleanValue) compileTimeConstant).getValue();
return expectedValue == null || expectedValue.equals(value); return expectedValue == null || expectedValue.equals(value);
@@ -1,25 +1,25 @@
== main == == main ==
fun main() { fun main() {
while(1 > 0) { while(0 > 1) {
2 2
} }
} }
--------------------- ---------------------
L0: L0:
1 <START> 1 <START>
2 mark({ while(1 > 0) { 2 } }) 2 mark({ while(0 > 1) { 2 } })
mark(while(1 > 0) { 2 }) mark(while(0 > 1) { 2 })
L2 [loop entry point]: L2 [loop entry point]:
L5 [condition entry point]: L5 [condition entry point]:
mark(1 > 0) PREV:[mark(while(1 > 0) { 2 }), jmp(L2 [loop entry point])] mark(0 > 1) PREV:[mark(while(0 > 1) { 2 }), jmp(L2 [loop entry point])]
r(1)
r(0) r(0)
r(1)
call(>, compareTo) call(>, compareTo)
jf(L3 [loop exit point]) NEXT:[read (Unit), mark({ 2 })] jf(L3 [loop exit point]) NEXT:[read (Unit), mark({ 2 })]
L4 [body entry point]: L4 [body entry point]:
3 mark({ 2 }) 3 mark({ 2 })
r(2) r(2)
2 jmp(L2 [loop entry point]) NEXT:[mark(1 > 0)] 2 jmp(L2 [loop entry point]) NEXT:[mark(0 > 1)]
L3 [loop exit point]: L3 [loop exit point]:
read (Unit) PREV:[jf(L3 [loop exit point])] read (Unit) PREV:[jf(L3 [loop exit point])]
L1: L1:
@@ -32,21 +32,21 @@ sink:
== dowhile == == dowhile ==
fun dowhile() { fun dowhile() {
do {return} do {return}
while(1 > 0) while(0 > 1)
} }
--------------------- ---------------------
L0: L0:
1 <START> 1 <START>
2 mark({ do {return} while(1 > 0) }) 2 mark({ do {return} while(0 > 1) })
3 mark(do {return} while(1 > 0)) 3 mark(do {return} while(0 > 1))
L2 [loop entry point]: L2 [loop entry point]:
L4 [body entry point]: L4 [body entry point]:
mark({return}) mark({return})
ret L1 NEXT:[<END>] ret L1 NEXT:[<END>]
L5 [condition entry point]: L5 [condition entry point]:
- mark(1 > 0) PREV:[] - mark(0 > 1) PREV:[]
- r(1) PREV:[]
- r(0) PREV:[] - r(0) PREV:[]
- r(1) PREV:[]
- call(>, compareTo) PREV:[] - call(>, compareTo) PREV:[]
- jt(L2 [loop entry point]) NEXT:[read (Unit), mark({return})] PREV:[] - jt(L2 [loop entry point]) NEXT:[read (Unit), mark({return})] PREV:[]
L3 [loop exit point]: L3 [loop exit point]:
@@ -1,10 +1,10 @@
fun main() { fun main() {
while(1 > 0) { while(0 > 1) {
2 2
} }
} }
fun dowhile() { fun dowhile() {
do {return} do {return}
while(1 > 0) while(0 > 1)
} }
@@ -1,9 +1,9 @@
fun test() { fun test() {
[ann] [ann]
while (1 < 2) {} while (2 < 1) {}
[ann] [ann]
do {} while (1 < 2) do {} while (2 < 1)
[ann] [ann]
for (i in 1..2) {} for (i in 1..2) {}
@@ -0,0 +1,12 @@
fun test() {
[ann]
while (2 > 1) {}
[ann]
<!UNREACHABLE_CODE!>do {} while (2 > 1)<!>
[ann]
<!UNREACHABLE_CODE!>for (i in 1..2) {}<!>
}
annotation class ann
@@ -0,0 +1,11 @@
package test
val x = 1
val y = "a"
// val prop1: true
val prop1 = x
// val prop2: true
val prop2 = y
@@ -0,0 +1,16 @@
package test
enum class MyEnum { A;B }
fun foo(): Boolean = true
val x = 1
// val prop1: null
val prop1 = MyEnum.A
// val prop2: null
val prop2 = foo()
// val prop3: true
val prop3 = "$x"
@@ -0,0 +1,29 @@
package test
val x = 1
val y = true
// val prop1: false
val prop1 = 1 > 2
// val prop2: false
val prop2 = 2 + 3
// val prop3: true
val prop3 = 2 + x
// val prop4: true
val prop4 = x < 2
// val prop5: true
val prop5 = y && true
// val prop6: false
val prop6 = true && false || 2 > 1
// val prop7: true
val prop7 = x == 1
// val prop8: true
val prop8 = 1 / x
@@ -0,0 +1,23 @@
package test
// val prop1: false
val prop1 = 1
// val prop2: false
val prop2 = "hello"
// val prop3: false
val prop3 = true
// val prop4: false
val prop4 = false
// val prop5: false
val prop5 = -7453
// val prop6: false
val prop6 = 3.56
// val prop7: false
val prop7 = 5464564L
@@ -616,6 +616,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/annotations/onLoops.kt"); doTest("compiler/testData/diagnostics/tests/annotations/onLoops.kt");
} }
@TestMetadata("onLoopsUnreachable.kt")
public void testOnLoopsUnreachable() throws Exception {
doTest("compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt");
}
@TestMetadata("onMultiDeclaration.kt") @TestMetadata("onMultiDeclaration.kt")
public void testOnMultiDeclaration() throws Exception { public void testOnMultiDeclaration() throws Exception {
doTest("compiler/testData/diagnostics/tests/annotations/onMultiDeclaration.kt"); doTest("compiler/testData/diagnostics/tests/annotations/onMultiDeclaration.kt");
@@ -20,20 +20,18 @@ import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.resolve.annotation.AbstractAnnotationDescriptorResolveTest import org.jetbrains.jet.resolve.annotation.AbstractAnnotationDescriptorResolveTest
import java.io.File import java.io.File
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.jet.lang.resolve.BindingContextUtils
import org.jetbrains.jet.lang.psi.JetProperty
import org.jetbrains.jet.InTextDirectivesUtils import org.jetbrains.jet.InTextDirectivesUtils
import kotlin.test.assertEquals
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
import java.util.regex.Pattern 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.JetTestUtils
import org.jetbrains.jet.util.slicedmap.WritableSlice
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant
import org.jetbrains.jet.lang.resolve.constants.StringValue import org.jetbrains.jet.lang.resolve.constants.StringValue
import org.jetbrains.jet.lang.descriptors.VariableDescriptor import org.jetbrains.jet.lang.descriptors.VariableDescriptor
import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant
import java.util.HashMap
import org.jetbrains.jet.lang.psi.JetPsiFactory
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace
import org.jetbrains.jet.lang.types.TypeUtils
abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorResolveTest() { abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorResolveTest() {
@@ -63,6 +61,19 @@ abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorReso
} }
} }
// Test directives should look like [// val testedPropertyName: expectedValue]
fun doUsesVariableAsConstantTest(path: String) {
doTest(path) {
property, context ->
val compileTimeConstant = property.getCompileTimeInitializer()
if (compileTimeConstant == null) {
"null"
} else {
compileTimeConstant.usesVariableAsConstant().toString()
}
}
}
private fun doTest(path: String, getValueToTest: (VariableDescriptor, BindingContext) -> String) { private fun doTest(path: String, getValueToTest: (VariableDescriptor, BindingContext) -> String) {
val myFile = File(path) val myFile = File(path)
val fileText = FileUtil.loadFile(myFile, true) val fileText = FileUtil.loadFile(myFile, true)
@@ -30,7 +30,7 @@ import org.jetbrains.jet.evaluate.AbstractEvaluateExpressionTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all") @SuppressWarnings("all")
@InnerTestClasses({EvaluateExpressionTestGenerated.Constant.class, EvaluateExpressionTestGenerated.IsPure.class}) @InnerTestClasses({EvaluateExpressionTestGenerated.Constant.class, EvaluateExpressionTestGenerated.IsPure.class, EvaluateExpressionTestGenerated.UsesVariableAsConstant.class})
public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionTest { public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionTest {
@TestMetadata("compiler/testData/evaluate/constant") @TestMetadata("compiler/testData/evaluate/constant")
public static class Constant extends AbstractEvaluateExpressionTest { public static class Constant extends AbstractEvaluateExpressionTest {
@@ -168,10 +168,39 @@ public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionT
} }
@TestMetadata("compiler/testData/evaluate/usesVariableAsConstant")
public static class UsesVariableAsConstant extends AbstractEvaluateExpressionTest {
public void testAllFilesPresentInUsesVariableAsConstant() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/evaluate/usesVariableAsConstant"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("binaryTypes.kt")
public void testBinaryTypes() throws Exception {
doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt");
}
@TestMetadata("NamedConstants.kt")
public void testNamedConstants() throws Exception {
doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt");
}
@TestMetadata("OtherTypes.kt")
public void testOtherTypes() throws Exception {
doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt");
}
@TestMetadata("simpleTypes.kt")
public void testSimpleTypes() throws Exception {
doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt");
}
}
public static Test suite() { public static Test suite() {
TestSuite suite = new TestSuite("EvaluateExpressionTestGenerated"); TestSuite suite = new TestSuite("EvaluateExpressionTestGenerated");
suite.addTestSuite(Constant.class); suite.addTestSuite(Constant.class);
suite.addTestSuite(IsPure.class); suite.addTestSuite(IsPure.class);
suite.addTestSuite(UsesVariableAsConstant.class);
return suite; return suite;
} }
} }
@@ -108,7 +108,7 @@ class LazyJavaAnnotationDescriptor(
private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): CompileTimeConstant<*>? { private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): CompileTimeConstant<*>? {
return when (argument) { return when (argument) {
is JavaLiteralAnnotationArgument -> createCompileTimeConstant(argument.getValue(), true, false, null) is JavaLiteralAnnotationArgument -> createCompileTimeConstant(argument.getValue(), true, false, false, null)
is JavaReferenceAnnotationArgument -> resolveFromReference(argument.resolve()) is JavaReferenceAnnotationArgument -> resolveFromReference(argument.resolve())
is JavaArrayAnnotationArgument -> resolveFromArray(argument.getName() ?: DEFAULT_ANNOTATION_MEMBER_NAME, argument.getElements()) is JavaArrayAnnotationArgument -> resolveFromArray(argument.getName() ?: DEFAULT_ANNOTATION_MEMBER_NAME, argument.getElements())
is JavaAnnotationAsAnnotationArgument -> resolveFromAnnotation(argument.getAnnotation()) is JavaAnnotationAsAnnotationArgument -> resolveFromAnnotation(argument.getAnnotation())
@@ -137,7 +137,7 @@ class LazyJavaAnnotationDescriptor(
val values = elements.map { val values = elements.map {
argument -> resolveAnnotationArgument(argument) ?: NullValue.NULL argument -> resolveAnnotationArgument(argument) ?: NullValue.NULL
} }
return ArrayValue(values, valueParameter.getType(), true) return ArrayValue(values, valueParameter.getType(), true, values.any { it.usesVariableAsConstant() })
} }
private fun resolveFromReference(element: JavaElement?): CompileTimeConstant<*>? { private fun resolveFromReference(element: JavaElement?): CompileTimeConstant<*>? {
@@ -154,7 +154,7 @@ class LazyJavaAnnotationDescriptor(
val classifier = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(element.getName()) val classifier = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(element.getName())
if (classifier !is ClassDescriptor) return null if (classifier !is ClassDescriptor) return null
return EnumValue(classifier) return EnumValue(classifier, false)
} }
private fun resolveFromJavaClassObjectType(javaType: JavaType): CompileTimeConstant<*>? { private fun resolveFromJavaClassObjectType(javaType: JavaType): CompileTimeConstant<*>? {
@@ -126,7 +126,7 @@ public class AnnotationDescriptorDeserializer extends BaseDescriptorDeserializer
@Override @Override
public void visit(@Nullable Name name, @Nullable Object value) { public void visit(@Nullable Name name, @Nullable Object value) {
if (name != null) { if (name != null) {
CompileTimeConstant<?> argument = ConstantsPackage.createCompileTimeConstant(value, true, false, null); CompileTimeConstant<?> argument = ConstantsPackage.createCompileTimeConstant(value, true, false, false, null);
setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name)); setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name));
} }
} }
@@ -149,7 +149,7 @@ public class AnnotationDescriptorDeserializer extends BaseDescriptorDeserializer
if (enumClass.getKind() == ClassKind.ENUM_CLASS) { if (enumClass.getKind() == ClassKind.ENUM_CLASS) {
ClassifierDescriptor classifier = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(name); ClassifierDescriptor classifier = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(name);
if (classifier instanceof ClassDescriptor) { if (classifier instanceof ClassDescriptor) {
return new EnumValue((ClassDescriptor) classifier); return new EnumValue((ClassDescriptor) classifier, false);
} }
} }
return ErrorValue.create("Unresolved enum entry: " + enumClassName.getInternalName() + "." + name); return ErrorValue.create("Unresolved enum entry: " + enumClassName.getInternalName() + "." + name);
@@ -89,7 +89,7 @@ public class DescriptorDeserializersStorage {
MemberSignature signature = MemberSignature.fromFieldNameAndDesc(name, desc); MemberSignature signature = MemberSignature.fromFieldNameAndDesc(name, desc);
if (initializer != null) { if (initializer != null) {
propertyConstants.put(signature, ConstantsPackage.createCompileTimeConstant( propertyConstants.put(signature, ConstantsPackage.createCompileTimeConstant(
initializer, /* canBeUsedInAnnotation */ true, /* isPureIntConstant */ true, /* expectedType */ null)); initializer, /* canBeUsedInAnnotation */ true, /* isPureIntConstant */ true, /* usesVariableAsConstant */ true, /* expectedType */ null));
} }
return new MemberAnnotationVisitor(signature); return new MemberAnnotationVisitor(signature);
} }
@@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class AnnotationValue extends CompileTimeConstant<AnnotationDescriptor> { public class AnnotationValue extends CompileTimeConstant<AnnotationDescriptor> {
public AnnotationValue(@NotNull AnnotationDescriptor value) { public AnnotationValue(@NotNull AnnotationDescriptor value) {
super(value, true); super(value, true, false, false);
} }
@NotNull @NotNull
@@ -27,8 +27,11 @@ public class ArrayValue extends CompileTimeConstant<List<CompileTimeConstant<?>>
private final JetType type; private final JetType type;
public ArrayValue(@NotNull List<CompileTimeConstant<?>> value, @NotNull JetType type, boolean canBeUsedInAnnotations) { public ArrayValue(@NotNull List<CompileTimeConstant<?>> value,
super(value, canBeUsedInAnnotations); @NotNull JetType type,
boolean canBeUsedInAnnotations,
boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, false, usesVariableAsConstant);
this.type = type; this.type = type;
} }
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class BooleanValue extends CompileTimeConstant<Boolean> { public class BooleanValue extends CompileTimeConstant<Boolean> {
public BooleanValue(boolean value, boolean canBeUseInAnnotation) { public BooleanValue(boolean value, boolean canBeUseInAnnotation, boolean usesVariableAsConstant) {
super(value, canBeUseInAnnotation); super(value, canBeUseInAnnotation, false, usesVariableAsConstant);
} }
@NotNull @NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class ByteValue extends IntegerValueConstant<Byte> { public class ByteValue extends IntegerValueConstant<Byte> {
public ByteValue(byte value, boolean canBeUsedInAnnotations, boolean pure) { public ByteValue(byte value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVaraiableAsConstant) {
super(value, canBeUsedInAnnotations, pure); super(value, canBeUsedInAnnotations, pure, usesVaraiableAsConstant);
} }
@NotNull @NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class CharValue extends IntegerValueConstant<Character> { public class CharValue extends IntegerValueConstant<Character> {
public CharValue(char value, boolean canBeUsedInAnnotations, boolean pure) { public CharValue(char value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, pure); super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant);
} }
@NotNull @NotNull
@@ -24,15 +24,38 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public abstract class CompileTimeConstant<T> { public abstract class CompileTimeConstant<T> {
protected final T value; protected final T value;
private final boolean canBeUsedInAnnotations; private final int flags;
protected CompileTimeConstant(T value, boolean canBeUsedInAnnotations) { /*
* if is pure is false then constant type cannot be changed
* ex1. val a: Long = 1.toInt() (TYPE_MISMATCH error, 1.toInt() isn't pure)
* ex2. val b: Int = a (TYPE_MISMATCH error, a isn't pure)
*
*/
private static final int IS_PURE_MASK = 1;
private static final int CAN_BE_USED_IN_ANNOTATIONS_MASK = 1 << 1;
private static final int USES_VARIABLE_AS_CONSTANT_MASK = 1 << 2;
protected CompileTimeConstant(T value,
boolean canBeUsedInAnnotations,
boolean isPure,
boolean usesVariableAsConstant) {
this.value = value; this.value = value;
this.canBeUsedInAnnotations = canBeUsedInAnnotations; flags = (isPure ? IS_PURE_MASK : 0) |
(canBeUsedInAnnotations ? CAN_BE_USED_IN_ANNOTATIONS_MASK : 0) |
(usesVariableAsConstant ? USES_VARIABLE_AS_CONSTANT_MASK : 0);
} }
public boolean canBeUsedInAnnotations() { public boolean canBeUsedInAnnotations() {
return canBeUsedInAnnotations; return (flags & CAN_BE_USED_IN_ANNOTATIONS_MASK) != 0;
}
public boolean isPure() {
return (flags & IS_PURE_MASK) != 0;
}
public boolean usesVariableAsConstant() {
return (flags & USES_VARIABLE_AS_CONSTANT_MASK) != 0;
} }
@Nullable @Nullable
@@ -24,23 +24,24 @@ public fun createCompileTimeConstant(
value: Any?, value: Any?,
canBeUsedInAnnotation: Boolean, canBeUsedInAnnotation: Boolean,
isPureIntConstant: Boolean, isPureIntConstant: Boolean,
usesVariableAsConstant: Boolean = false,
expectedType: JetType? = null expectedType: JetType? = null
): CompileTimeConstant<*>? { ): CompileTimeConstant<*>? {
if (expectedType == null) { if (expectedType == null) {
when(value) { when(value) {
is Byte -> return ByteValue(value, canBeUsedInAnnotation, isPureIntConstant) is Byte -> return ByteValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
is Short -> return ShortValue(value, canBeUsedInAnnotation, isPureIntConstant) is Short -> return ShortValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
is Int -> return IntValue(value, canBeUsedInAnnotation, isPureIntConstant) is Int -> return IntValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
is Long -> return LongValue(value, canBeUsedInAnnotation, isPureIntConstant) is Long -> return LongValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
} }
} }
return when(value) { return when(value) {
is Byte, is Short, is Int, is Long -> getIntegerValue((value as Number).toLong(), canBeUsedInAnnotation, isPureIntConstant, expectedType) is Byte, is Short, is Int, is Long -> getIntegerValue((value as Number).toLong(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant, expectedType)
is Char -> CharValue(value, canBeUsedInAnnotation, isPureIntConstant) is Char -> CharValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
is Float -> FloatValue(value, canBeUsedInAnnotation) is Float -> FloatValue(value, canBeUsedInAnnotation, usesVariableAsConstant)
is Double -> DoubleValue(value, canBeUsedInAnnotation) is Double -> DoubleValue(value, canBeUsedInAnnotation, usesVariableAsConstant)
is Boolean -> BooleanValue(value, canBeUsedInAnnotation) is Boolean -> BooleanValue(value, canBeUsedInAnnotation, usesVariableAsConstant)
is String -> StringValue(value, canBeUsedInAnnotation) is String -> StringValue(value, canBeUsedInAnnotation, usesVariableAsConstant)
null -> NullValue.NULL null -> NullValue.NULL
else -> null else -> null
} }
@@ -50,30 +51,31 @@ private fun getIntegerValue(
value: Long, value: Long,
canBeUsedInAnnotation: Boolean, canBeUsedInAnnotation: Boolean,
isPureIntConstant: Boolean, isPureIntConstant: Boolean,
usesVariableAsConstant: Boolean,
expectedType: JetType expectedType: JetType
): CompileTimeConstant<*>? { ): CompileTimeConstant<*>? {
fun defaultIntegerValue(value: Long) = when (value) { fun defaultIntegerValue(value: Long) = when (value) {
value.toInt().toLong() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant) value.toInt().toLong() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
else -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant) else -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
} }
if (TypeUtils.noExpectedType(expectedType) || expectedType.isError()) { if (TypeUtils.noExpectedType(expectedType) || expectedType.isError()) {
return IntegerValueTypeConstant(value, canBeUsedInAnnotation) return IntegerValueTypeConstant(value, canBeUsedInAnnotation, usesVariableAsConstant)
} }
val builtIns = KotlinBuiltIns.getInstance() val builtIns = KotlinBuiltIns.getInstance()
return when (TypeUtils.makeNotNullable(expectedType)) { return when (TypeUtils.makeNotNullable(expectedType)) {
builtIns.getLongType() -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant) builtIns.getLongType() -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
builtIns.getShortType() -> when (value) { builtIns.getShortType() -> when (value) {
value.toShort().toLong() -> ShortValue(value.toShort(), canBeUsedInAnnotation, isPureIntConstant) value.toShort().toLong() -> ShortValue(value.toShort(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
else -> defaultIntegerValue(value) else -> defaultIntegerValue(value)
} }
builtIns.getByteType() -> when (value) { builtIns.getByteType() -> when (value) {
value.toByte().toLong() -> ByteValue(value.toByte(), canBeUsedInAnnotation, isPureIntConstant) value.toByte().toLong() -> ByteValue(value.toByte(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
else -> defaultIntegerValue(value) else -> defaultIntegerValue(value)
} }
builtIns.getCharType() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant) builtIns.getCharType() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant)
else -> defaultIntegerValue(value) else -> defaultIntegerValue(value)
} }
} }
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class DoubleValue extends CompileTimeConstant<Double> { public class DoubleValue extends CompileTimeConstant<Double> {
public DoubleValue(double value, boolean canBeUsedInAnnotations) { public DoubleValue(double value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations); super(value, canBeUsedInAnnotations, false, usesVariableAsConstant);
} }
@NotNull @NotNull
@@ -24,8 +24,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class EnumValue extends CompileTimeConstant<ClassDescriptor> { public class EnumValue extends CompileTimeConstant<ClassDescriptor> {
public EnumValue(@NotNull ClassDescriptor value) { public EnumValue(@NotNull ClassDescriptor value, boolean usesVariableAsConstant) {
super(value, true); super(value, true, false, usesVariableAsConstant);
} }
@NotNull @NotNull
@@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public abstract class ErrorValue extends CompileTimeConstant<Void> { public abstract class ErrorValue extends CompileTimeConstant<Void> {
public ErrorValue() { public ErrorValue() {
super(null, true); super(null, true, false, false);
} }
@Override @Override
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class FloatValue extends CompileTimeConstant<Float> { public class FloatValue extends CompileTimeConstant<Float> {
public FloatValue(float value, boolean canBeUsedInAnnotations) { public FloatValue(float value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations); super(value, canBeUsedInAnnotations, false, usesVariableAsConstant);
} }
@NotNull @NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class IntValue extends IntegerValueConstant<Integer> { public class IntValue extends IntegerValueConstant<Integer> {
public IntValue(int value, boolean canBeUsedInAnnotations, boolean pure) { public IntValue(int value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, pure); super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant);
} }
@NotNull @NotNull
@@ -18,19 +18,7 @@ package org.jetbrains.jet.lang.resolve.constants;
public abstract class IntegerValueConstant<T> extends CompileTimeConstant<T> { public abstract class IntegerValueConstant<T> extends CompileTimeConstant<T> {
/* protected IntegerValueConstant(T value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVaraiableAsConstant) {
* if false then constant type cannot be changed super(value, canBeUsedInAnnotations, pure, usesVaraiableAsConstant);
* ex1. val a: Long = 1.toInt() (TYPE_MISMATCH error, 1.toInt() isn't pure)
* ex2. val b: Int = a (TYPE_MISMATCH error, a isn't pure)
* */
private final boolean isPure;
protected IntegerValueConstant(T value, boolean canBeUsedInAnnotations, boolean pure) {
super(value, canBeUsedInAnnotations);
isPure = pure;
}
public boolean isPure() {
return isPure;
} }
} }
@@ -19,10 +19,9 @@ package org.jetbrains.jet.lang.resolve.constants;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import java.util.Collections; import java.util.Collections;
@@ -30,8 +29,8 @@ public class IntegerValueTypeConstant extends IntegerValueConstant<Number> {
private final IntegerValueTypeConstructor typeConstructor; private final IntegerValueTypeConstructor typeConstructor;
public IntegerValueTypeConstant(@NotNull Number value, boolean canBeUsedInAnnotations) { public IntegerValueTypeConstant(@NotNull Number value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, true); super(value, canBeUsedInAnnotations, true, usesVariableAsConstant);
this.typeConstructor = new IntegerValueTypeConstructor(value.longValue()); this.typeConstructor = new IntegerValueTypeConstructor(value.longValue());
} }
@@ -24,7 +24,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class JavaClassValue extends CompileTimeConstant<JetType> { public class JavaClassValue extends CompileTimeConstant<JetType> {
public JavaClassValue(@NotNull JetType value) { public JavaClassValue(@NotNull JetType value) {
super(value, true); super(value, true, false, false);
} }
@NotNull @NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class LongValue extends IntegerValueConstant<Long> { public class LongValue extends IntegerValueConstant<Long> {
public LongValue(long value, boolean canBeUsedInAnnotations, boolean pure) { public LongValue(long value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, pure); super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant);
} }
@NotNull @NotNull
@@ -26,7 +26,7 @@ public class NullValue extends CompileTimeConstant<Void> {
public static final NullValue NULL = new NullValue(); public static final NullValue NULL = new NullValue();
private NullValue() { private NullValue() {
super(null, false); super(null, false, false, false);
} }
@NotNull @NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class ShortValue extends IntegerValueConstant<Short> { public class ShortValue extends IntegerValueConstant<Short> {
public ShortValue(short value, boolean canBeUsedInAnnotations, boolean pure) { public ShortValue(short value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations, pure); super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant);
} }
@NotNull @NotNull
@@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType;
public class StringValue extends CompileTimeConstant<String> { public class StringValue extends CompileTimeConstant<String> {
public StringValue(String value, boolean canBeUsedInAnnotations) { public StringValue(String value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) {
super(value, canBeUsedInAnnotations); super(value, canBeUsedInAnnotations, false, usesVariableAsConstant);
} }
@NotNull @NotNull
@@ -242,6 +242,7 @@ fun main(args: Array<String>) {
testClass(javaClass<AbstractEvaluateExpressionTest>()) { testClass(javaClass<AbstractEvaluateExpressionTest>()) {
model("evaluate/constant", testMethod = "doConstantTest") model("evaluate/constant", testMethod = "doConstantTest")
model("evaluate/isPure", testMethod = "doIsPureTest") model("evaluate/isPure", testMethod = "doIsPureTest")
model("evaluate/usesVariableAsConstant", testMethod = "doUsesVariableAsConstantTest")
} }
} }
@@ -388,6 +389,7 @@ fun main(args: Array<String>) {
model("intentions/splitIf", testMethod = "doTestSplitIf") model("intentions/splitIf", testMethod = "doTestSplitIf")
model("intentions/replaceWithOperatorAssign", testMethod = "doTestReplaceWithOperatorAssign") model("intentions/replaceWithOperatorAssign", testMethod = "doTestReplaceWithOperatorAssign")
model("intentions/replaceWithTraditionalAssignment", testMethod = "doTestReplaceWithTraditionalAssignment") model("intentions/replaceWithTraditionalAssignment", testMethod = "doTestReplaceWithTraditionalAssignment")
model("intentions/simplifyBooleanWithConstants", testMethod = "doTestSimplifyBooleanWithConstants")
} }
testClass(javaClass<AbstractJetInspectionTest>()) { testClass(javaClass<AbstractJetInspectionTest>()) {
@@ -0,0 +1,3 @@
fun foo() {
val x = <spot>y</spot>
}
@@ -0,0 +1,3 @@
fun foo() {
val x = <spot>3 > 2 && y && true</spot>
}
@@ -0,0 +1,5 @@
<html>
<body>
This intention simplifies a boolean expression that has parts which can be reduced to constants
</body>
</html>
+5
View File
@@ -627,6 +627,11 @@
<className>org.jetbrains.jet.plugin.intentions.ConvertNegatedExpressionWithDemorgansLawIntention</className> <className>org.jetbrains.jet.plugin.intentions.ConvertNegatedExpressionWithDemorgansLawIntention</className>
<category>Kotlin</category> <category>Kotlin</category>
</intentionAction> </intentionAction>
<intentionAction>
<className>org.jetbrains.jet.plugin.intentions.SimplifyBooleanWithConstantsIntention</className>
<category>Kotlin</category>
</intentionAction>
<localInspection implementationClass="org.jetbrains.jet.plugin.inspections.ExplicitGetInspection" <localInspection implementationClass="org.jetbrains.jet.plugin.inspections.ExplicitGetInspection"
displayName="Explicit 'get'" displayName="Explicit 'get'"
@@ -291,6 +291,8 @@ replace.with.operator.assign.intention=Replace with an Operator-Assign Expressio
replace.with.operator.assign.intention.family=Replace with an Operator-Assign Expression replace.with.operator.assign.intention.family=Replace with an Operator-Assign Expression
replace.with.traditional.assignment.intention=Replace with Traditional Assignment replace.with.traditional.assignment.intention=Replace with Traditional Assignment
replace.with.traditional.assignment.intention.family=Replace with Traditional Assignment replace.with.traditional.assignment.intention.family=Replace with Traditional Assignment
simplify.boolean.with.constants=Simplify boolean expression
simplify.boolean.with.constants.family=Simplify boolean expression
property.is.implemented.too.many=Has implementations property.is.implemented.too.many=Has implementations
property.is.overridden.too.many=Is overridden in subclasses property.is.overridden.too.many=Is overridden in subclasses
@@ -0,0 +1,137 @@
/*
* Copyright 2010-2014 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.plugin.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.jet.lang.psi.JetBinaryExpression
import org.jetbrains.jet.lang.psi.JetPsiUtil
import org.jetbrains.jet.lang.psi.JetExpression
import org.jetbrains.jet.lang.psi.JetPsiFactory
import org.jetbrains.jet.lang.psi.JetParenthesizedExpression
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.lang.resolve.CompileTimeConstantUtils
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import com.intellij.psi.tree.IElementType
public class SimplifyBooleanWithConstantsIntention : JetSelfTargetingIntention<JetBinaryExpression>(
"simplify.boolean.with.constants", javaClass()) {
private var topParent : JetBinaryExpression? = null
override fun isApplicableTo(element: JetBinaryExpression): Boolean {
topParent = JetPsiUtil.getTopmostParentOfTypes(element, element.javaClass) as JetBinaryExpression? ?: element
return areThereExpressionsToBeSimplified(topParent)
}
private fun areThereExpressionsToBeSimplified(element: JetExpression?) : Boolean {
if (element == null) return false
when (element) {
is JetParenthesizedExpression -> return areThereExpressionsToBeSimplified(element.getExpression())
is JetBinaryExpression -> {
val op = element.getOperationToken()
if ((op == JetTokens.ANDAND || op == JetTokens.OROR) &&
(areThereExpressionsToBeSimplified(element.getLeft()) ||
areThereExpressionsToBeSimplified(element.getRight()))) return true
}
}
return element.canBeReducedToBooleanConstant(null)
}
override fun applyTo(element: JetBinaryExpression, editor: Editor) {
// we know from isApplicableTo that topParent is not null
val simplified = simplifyBoolean(topParent!!)
if (simplified is JetParenthesizedExpression) {
val expr = simplified.getExpression()
if (expr != null) {
// this extra check is for the case where there are empty parentheses ()
topParent!!.replace(expr)
return
}
}
topParent!!.replace(simplified)
}
private fun simplifyBoolean(element: JetExpression) : JetExpression {
if (element.canBeReducedToTrue())
return JetPsiFactory.createExpression(element.getProject(), "true")
if (element.canBeReducedToFalse())
return JetPsiFactory.createExpression(element.getProject(), "false")
when (element) {
is JetParenthesizedExpression -> {
val expr = element.getExpression()
if (expr == null) return element
val simplified = simplifyBoolean(expr)
if (expr == simplified) return element
if (simplified is JetBinaryExpression) {
val simpText = simplified.getText()
if (simpText == null) return element
// wrap in new parentheses to keep the user's original format
return JetPsiFactory.createExpression(element.getProject(), "($simpText)")
}
// if we now have a simpleName, constant, or parenthesized we don't need parentheses
return simplified
}
is JetBinaryExpression -> {
val left = element.getLeft()
val right = element.getRight()
val op = element.getOperationToken()
if (left == null || right == null || op == null || (op != JetTokens.ANDAND && op != JetTokens.OROR))
return element
val simpleLeft = simplifyBoolean(left)
val simpleRight = simplifyBoolean(right)
if (simpleLeft.canBeReducedToTrue() || simpleLeft.canBeReducedToFalse())
return simplifyBooleanBinaryExpressionWithConstantOperand(simpleLeft, simpleRight, op)
if (simpleRight.canBeReducedToTrue() || simpleRight.canBeReducedToFalse())
return simplifyBooleanBinaryExpressionWithConstantOperand(simpleRight, simpleLeft, op)
val opText = element.getOperationReference().getText()
if (opText == null) return element
return JetPsiFactory.createBinaryExpression(element.getProject(), simpleLeft, opText, simpleRight)
}
else -> return element
}
}
private fun simplifyBooleanBinaryExpressionWithConstantOperand(
booleanConstantOperand: JetExpression,
otherOperand: JetExpression,
operation: IElementType
): JetExpression {
assert(booleanConstantOperand.canBeReducedToBooleanConstant(null), "should only be called when we know it can be reduced")
if (booleanConstantOperand.canBeReducedToTrue() && operation == JetTokens.OROR)
return JetPsiFactory.createExpression(otherOperand.getProject(), "true")
if (booleanConstantOperand.canBeReducedToFalse() && operation == JetTokens.ANDAND)
return JetPsiFactory.createExpression(otherOperand.getProject(), "false")
return simplifyBoolean(otherOperand)
}
private fun JetExpression.canBeReducedToBooleanConstant(constant: Boolean?): Boolean {
val bindingContext = AnalyzerFacadeWithCache.getContextForElement(this)
val trace = DelegatingBindingTrace(bindingContext, "trace for constant check")
return CompileTimeConstantUtils.canBeReducedToBooleanConstant(this, trace, constant)
}
private fun JetExpression.canBeReducedToTrue(): Boolean {
return this.canBeReducedToBooleanConstant(true)
}
private fun JetExpression.canBeReducedToFalse(): Boolean {
return this.canBeReducedToBooleanConstant(false)
}
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun foo(y: Boolean) {
y && <caret>y || y
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun foo(y: Boolean) {
<caret>true
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun foo(y: Boolean) {
val x = 4
val z = 5
<caret>x < z
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun foo(y: Boolean) {
val x = 4
val z = 5
<caret>x == z || x != z
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun foo(y: Boolean) {
val x = true
val z = false
<caret>x && z
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
<caret>2 > 1
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
true
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
<caret>2 > 1 && y || y || (3 + 3 > 10)
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
y || y
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
<caret>3 != 3 && 2 > 1 || y
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
y
}
@@ -0,0 +1,4 @@
fun foo(y: Boolean) {
val x = 3
<caret>x != x && (2 > 1 || y)
}
@@ -0,0 +1,4 @@
fun foo(y: Boolean) {
val x = 3
x != x
}
@@ -0,0 +1,3 @@
fun foo() {
val x = <caret>true && false || true
}
@@ -0,0 +1,3 @@
fun foo() {
val x = true
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
(y && false) || (y && y && true && (y && true))<caret> && false && true
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
false
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
false || false || y || y ||<caret> false || y && y || y
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
y || y || y && y || y
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
y || false && true || <caret>false || false || false || y && true
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
y || y
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
false || false || y || y || <caret>false && (y && y || true)
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
y || y
}
@@ -0,0 +1,5 @@
fun foo(y: Boolean) {
bar() && y || <caret>(y && true && bar()) || false
}
fun bar(): Boolean = false
@@ -0,0 +1,5 @@
fun foo(y: Boolean) {
bar() && y || (y && bar())
}
fun bar(): Boolean = false
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
((y && true) || false) <caret>&& (true && (y && (y && (y ||false))))
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
y && (y && (y && y))
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
<caret>true && () && y
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
() && y
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
(false)<caret> && true
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
false
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
y || <caret>(y && true)
}
@@ -0,0 +1,3 @@
fun foo(y: Boolean) {
y || y
}
@@ -227,6 +227,10 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes
doTestIntention(path, new ReplaceWithTraditionalAssignmentIntention()); doTestIntention(path, new ReplaceWithTraditionalAssignmentIntention());
} }
public void doTestSimplifyBooleanWithConstants(@NotNull String path) throws Exception {
doTestIntention(path, new SimplifyBooleanWithConstantsIntention());
}
private void doTestIntention(@NotNull String path, @NotNull IntentionAction intentionAction) throws Exception { private void doTestIntention(@NotNull String path, @NotNull IntentionAction intentionAction) throws Exception {
configureByFile(path); configureByFile(path);
@@ -30,7 +30,7 @@ import org.jetbrains.jet.plugin.intentions.AbstractCodeTransformationTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all") @SuppressWarnings("all")
@InnerTestClasses({CodeTransformationTestGenerated.ElvisToIfThen.class, CodeTransformationTestGenerated.IfThenToElvis.class, CodeTransformationTestGenerated.SafeAccessToIfThen.class, CodeTransformationTestGenerated.IfThenToSafeAccess.class, CodeTransformationTestGenerated.IfToAssignment.class, CodeTransformationTestGenerated.IfToReturn.class, CodeTransformationTestGenerated.IfToReturnAsymmetrically.class, CodeTransformationTestGenerated.WhenToAssignment.class, CodeTransformationTestGenerated.WhenToReturn.class, CodeTransformationTestGenerated.AssignmentToIf.class, CodeTransformationTestGenerated.AssignmentToWhen.class, CodeTransformationTestGenerated.PropertyToIf.class, CodeTransformationTestGenerated.PropertyToWhen.class, CodeTransformationTestGenerated.ReturnToIf.class, CodeTransformationTestGenerated.ReturnToWhen.class, CodeTransformationTestGenerated.IfToWhen.class, CodeTransformationTestGenerated.WhenToIf.class, CodeTransformationTestGenerated.Flatten.class, CodeTransformationTestGenerated.Merge.class, CodeTransformationTestGenerated.IntroduceSubject.class, CodeTransformationTestGenerated.EliminateSubject.class, CodeTransformationTestGenerated.Split.class, CodeTransformationTestGenerated.Join.class, CodeTransformationTestGenerated.ConvertMemberToExtension.class, CodeTransformationTestGenerated.ReconstructedType.class, CodeTransformationTestGenerated.RemoveUnnecessaryParentheses.class, CodeTransformationTestGenerated.ReplaceWithDotQualifiedMethodCall.class, CodeTransformationTestGenerated.ReplaceWithInfixFunctionCall.class, CodeTransformationTestGenerated.RemoveCurlyBracesFromTemplate.class, CodeTransformationTestGenerated.MoveLambdaInsideParentheses.class, CodeTransformationTestGenerated.MoveLambdaOutsideParentheses.class, CodeTransformationTestGenerated.ReplaceExplicitFunctionLiteralParamWithIt.class, CodeTransformationTestGenerated.ReplaceItWithExplicitFunctionLiteralParam.class, CodeTransformationTestGenerated.RemoveBraces.class, CodeTransformationTestGenerated.AddBraces.class, CodeTransformationTestGenerated.ReplaceGetIntention.class, CodeTransformationTestGenerated.ReplaceContainsIntention.class, CodeTransformationTestGenerated.ReplaceBinaryInfixIntention.class, CodeTransformationTestGenerated.ReplaceUnaryPrefixIntention.class, CodeTransformationTestGenerated.ReplaceInvokeIntention.class, CodeTransformationTestGenerated.SimplifyNegatedBinaryExpressionIntention.class, CodeTransformationTestGenerated.ConvertNegatedBooleanSequence.class, CodeTransformationTestGenerated.ConvertNegatedExpressionWithDemorgansLaw.class, CodeTransformationTestGenerated.SwapBinaryExpression.class, CodeTransformationTestGenerated.SplitIf.class, CodeTransformationTestGenerated.ReplaceWithOperatorAssign.class, CodeTransformationTestGenerated.ReplaceWithTraditionalAssignment.class}) @InnerTestClasses({CodeTransformationTestGenerated.ElvisToIfThen.class, CodeTransformationTestGenerated.IfThenToElvis.class, CodeTransformationTestGenerated.SafeAccessToIfThen.class, CodeTransformationTestGenerated.IfThenToSafeAccess.class, CodeTransformationTestGenerated.IfToAssignment.class, CodeTransformationTestGenerated.IfToReturn.class, CodeTransformationTestGenerated.IfToReturnAsymmetrically.class, CodeTransformationTestGenerated.WhenToAssignment.class, CodeTransformationTestGenerated.WhenToReturn.class, CodeTransformationTestGenerated.AssignmentToIf.class, CodeTransformationTestGenerated.AssignmentToWhen.class, CodeTransformationTestGenerated.PropertyToIf.class, CodeTransformationTestGenerated.PropertyToWhen.class, CodeTransformationTestGenerated.ReturnToIf.class, CodeTransformationTestGenerated.ReturnToWhen.class, CodeTransformationTestGenerated.IfToWhen.class, CodeTransformationTestGenerated.WhenToIf.class, CodeTransformationTestGenerated.Flatten.class, CodeTransformationTestGenerated.Merge.class, CodeTransformationTestGenerated.IntroduceSubject.class, CodeTransformationTestGenerated.EliminateSubject.class, CodeTransformationTestGenerated.Split.class, CodeTransformationTestGenerated.Join.class, CodeTransformationTestGenerated.ConvertMemberToExtension.class, CodeTransformationTestGenerated.ReconstructedType.class, CodeTransformationTestGenerated.RemoveUnnecessaryParentheses.class, CodeTransformationTestGenerated.ReplaceWithDotQualifiedMethodCall.class, CodeTransformationTestGenerated.ReplaceWithInfixFunctionCall.class, CodeTransformationTestGenerated.RemoveCurlyBracesFromTemplate.class, CodeTransformationTestGenerated.MoveLambdaInsideParentheses.class, CodeTransformationTestGenerated.MoveLambdaOutsideParentheses.class, CodeTransformationTestGenerated.ReplaceExplicitFunctionLiteralParamWithIt.class, CodeTransformationTestGenerated.ReplaceItWithExplicitFunctionLiteralParam.class, CodeTransformationTestGenerated.RemoveBraces.class, CodeTransformationTestGenerated.AddBraces.class, CodeTransformationTestGenerated.ReplaceGetIntention.class, CodeTransformationTestGenerated.ReplaceContainsIntention.class, CodeTransformationTestGenerated.ReplaceBinaryInfixIntention.class, CodeTransformationTestGenerated.ReplaceUnaryPrefixIntention.class, CodeTransformationTestGenerated.ReplaceInvokeIntention.class, CodeTransformationTestGenerated.SimplifyNegatedBinaryExpressionIntention.class, CodeTransformationTestGenerated.ConvertNegatedBooleanSequence.class, CodeTransformationTestGenerated.ConvertNegatedExpressionWithDemorgansLaw.class, CodeTransformationTestGenerated.SwapBinaryExpression.class, CodeTransformationTestGenerated.SplitIf.class, CodeTransformationTestGenerated.ReplaceWithOperatorAssign.class, CodeTransformationTestGenerated.ReplaceWithTraditionalAssignment.class, CodeTransformationTestGenerated.SimplifyBooleanWithConstants.class})
public class CodeTransformationTestGenerated extends AbstractCodeTransformationTest { public class CodeTransformationTestGenerated extends AbstractCodeTransformationTest {
@TestMetadata("idea/testData/intentions/branched/elvisToIfThen") @TestMetadata("idea/testData/intentions/branched/elvisToIfThen")
public static class ElvisToIfThen extends AbstractCodeTransformationTest { public static class ElvisToIfThen extends AbstractCodeTransformationTest {
@@ -3224,6 +3224,109 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
} }
@TestMetadata("idea/testData/intentions/simplifyBooleanWithConstants")
public static class SimplifyBooleanWithConstants extends AbstractCodeTransformationTest {
public void testAllFilesPresentInSimplifyBooleanWithConstants() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/intentions/simplifyBooleanWithConstants"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("inapplicableNoConstants.kt")
public void testInapplicableNoConstants() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNoConstants.kt");
}
@TestMetadata("inapplicableNotBinary.kt")
public void testInapplicableNotBinary() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNotBinary.kt");
}
@TestMetadata("inapplicableUsesVals.kt")
public void testInapplicableUsesVals() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals.kt");
}
@TestMetadata("inapplicableUsesVals2.kt")
public void testInapplicableUsesVals2() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals2.kt");
}
@TestMetadata("inapplicableUsesVals3.kt")
public void testInapplicableUsesVals3() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals3.kt");
}
@TestMetadata("reduceableBinary.kt")
public void testReduceableBinary() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt");
}
@TestMetadata("reduceableBinary2.kt")
public void testReduceableBinary2() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary2.kt");
}
@TestMetadata("reduceableBinary3.kt")
public void testReduceableBinary3() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary3.kt");
}
@TestMetadata("reduceableBinaryWithParenthese.kt")
public void testReduceableBinaryWithParenthese() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinaryWithParenthese.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simple.kt");
}
@TestMetadata("simpleWithMoreBinaries.kt")
public void testSimpleWithMoreBinaries() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries.kt");
}
@TestMetadata("simpleWithMoreBinaries2.kt")
public void testSimpleWithMoreBinaries2() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries2.kt");
}
@TestMetadata("simpleWithMoreBinaries3.kt")
public void testSimpleWithMoreBinaries3() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries3.kt");
}
@TestMetadata("simpleWithMoreBinariesAndParentheses.kt")
public void testSimpleWithMoreBinariesAndParentheses() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses.kt");
}
@TestMetadata("simpleWithMoreBinariesAndParentheses2.kt")
public void testSimpleWithMoreBinariesAndParentheses2() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses2.kt");
}
@TestMetadata("simpleWithMoreBinariesAndParentheses3.kt")
public void testSimpleWithMoreBinariesAndParentheses3() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses3.kt");
}
@TestMetadata("simpleWithNonsensical2.kt")
public void testSimpleWithNonsensical2() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simpleWithNonsensical2.kt");
}
@TestMetadata("simpleWithParentheses.kt")
public void testSimpleWithParentheses() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses.kt");
}
@TestMetadata("simpleWithParentheses2.kt")
public void testSimpleWithParentheses2() throws Exception {
doTestSimplifyBooleanWithConstants("idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses2.kt");
}
}
public static Test suite() { public static Test suite() {
TestSuite suite = new TestSuite("CodeTransformationTestGenerated"); TestSuite suite = new TestSuite("CodeTransformationTestGenerated");
suite.addTestSuite(ElvisToIfThen.class); suite.addTestSuite(ElvisToIfThen.class);
@@ -3273,6 +3376,7 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
suite.addTestSuite(SplitIf.class); suite.addTestSuite(SplitIf.class);
suite.addTestSuite(ReplaceWithOperatorAssign.class); suite.addTestSuite(ReplaceWithOperatorAssign.class);
suite.addTestSuite(ReplaceWithTraditionalAssignment.class); suite.addTestSuite(ReplaceWithTraditionalAssignment.class);
suite.addTestSuite(SimplifyBooleanWithConstants.class);
return suite; return suite;
} }
} }