From aeb5bae556bb26cfe9c2f3101037cce0d3ebc146 Mon Sep 17 00:00:00 2001 From: Tal Man Date: Wed, 9 Apr 2014 14:38:50 -0400 Subject: [PATCH 1/2] Refactoring of CompileTimeConstant, introduce flag to represent a constant being referenced by a variable --- .../JavaPropertyInitializerEvaluatorImpl.java | 1 + .../evaluate/ConstantExpressionEvaluator.kt | 72 +++++++++++-------- .../jet/lang/resolve/AnnotationResolver.java | 12 +++- .../resolve/CompileTimeConstantUtils.java | 8 +-- .../OnlyWhileInFunctionBody.instructions | 22 +++--- .../OnlyWhileInFunctionBody.kt | 4 +- .../diagnostics/tests/annotations/onLoops.kt | 4 +- .../tests/annotations/onLoopsUnreachable.kt | 12 ++++ .../usesVariableAsConstant/NamedConstants.kt | 11 +++ .../usesVariableAsConstant/OtherTypes.kt | 16 +++++ .../usesVariableAsConstant/binaryTypes.kt | 29 ++++++++ .../usesVariableAsConstant/simpleTypes.kt | 23 ++++++ .../checkers/JetDiagnosticsTestGenerated.java | 5 ++ .../AbstractEvaluateExpressionTest.kt | 25 +++++-- .../EvaluateExpressionTestGenerated.java | 31 +++++++- .../LazyJavaAnnotationDescriptor.kt | 6 +- .../AnnotationDescriptorDeserializer.java | 4 +- .../DescriptorDeserializersStorage.java | 2 +- .../resolve/constants/AnnotationValue.java | 2 +- .../lang/resolve/constants/ArrayValue.java | 7 +- .../lang/resolve/constants/BooleanValue.java | 4 +- .../jet/lang/resolve/constants/ByteValue.java | 4 +- .../jet/lang/resolve/constants/CharValue.java | 4 +- .../constants/CompileTimeConstant.java | 31 ++++++-- .../lang/resolve/constants/ConstantUtils.kt | 36 +++++----- .../lang/resolve/constants/DoubleValue.java | 4 +- .../jet/lang/resolve/constants/EnumValue.java | 4 +- .../lang/resolve/constants/ErrorValue.java | 2 +- .../lang/resolve/constants/FloatValue.java | 4 +- .../jet/lang/resolve/constants/IntValue.java | 4 +- .../constants/IntegerValueConstant.java | 16 +---- .../constants/IntegerValueTypeConstant.java | 7 +- .../resolve/constants/JavaClassValue.java | 2 +- .../jet/lang/resolve/constants/LongValue.java | 4 +- .../jet/lang/resolve/constants/NullValue.java | 2 +- .../lang/resolve/constants/ShortValue.java | 4 +- .../lang/resolve/constants/StringValue.java | 4 +- .../jet/generators/tests/GenerateTests.kt | 1 + 38 files changed, 303 insertions(+), 130 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt create mode 100644 compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt create mode 100644 compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt create mode 100644 compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt create mode 100644 compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java index 13aac25950a70..929a1ecfe286c 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java @@ -38,6 +38,7 @@ public CompileTimeConstant getInitializerConstant(@NotNull JavaField field, @ evaluatedExpression, DescriptorUtils.isPropertyCompileTimeConstant(descriptor), false, + true, descriptor.getType()); } return null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt index 641ae0175a92a..ee99117602610 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt @@ -54,7 +54,6 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet trace.record(BindingContext.COMPILE_TIME_VALUE, expression, compileTimeConstant) return compileTimeConstant } - return null } @@ -70,9 +69,9 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet return createStringConstant(this@ConstantExpressionEvaluator.evaluate(expression, KotlinBuiltIns.getInstance().getStringType())) } - override fun visitLiteralStringTemplateEntry(entry: JetLiteralStringTemplateEntry, data: Nothing?) = StringValue(entry.getText(), true) + override fun visitLiteralStringTemplateEntry(entry: JetLiteralStringTemplateEntry, data: Nothing?) = StringValue(entry.getText(), true, false) - override fun visitEscapeStringTemplateEntry(entry: JetEscapeStringTemplateEntry, data: Nothing?) = StringValue(entry.getUnescapedValue(), true) + override fun visitEscapeStringTemplateEntry(entry: JetEscapeStringTemplateEntry, data: Nothing?) = StringValue(entry.getUnescapedValue(), true, false) } override fun visitConstantExpression(expression: JetConstantExpression, expectedType: JetType?): CompileTimeConstant<*>? { @@ -92,8 +91,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet if (result == null) return null fun isLongWithSuffix() = nodeElementType == JetNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text) - - return createCompileTimeConstant(result, expectedType, !isLongWithSuffix()) + return createCompileTimeConstant(result, expectedType, !isLongWithSuffix(), true, false) } override fun visitParenthesizedExpression(expression: JetParenthesizedExpression, expectedType: JetType?): CompileTimeConstant<*>? { @@ -118,6 +116,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val sb = StringBuilder() var interupted = false var canBeUsedInAnnotation = true + var usesVariableAsConstant = false for (entry in expression.getEntries()) { val constant = stringExpressionEvaluator.evaluate(entry) if (constant == null) { @@ -126,12 +125,14 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet } else { if (!constant.canBeUsedInAnnotations()) canBeUsedInAnnotation = false + if (constant.usesVariableAsConstant()) usesVariableAsConstant = true sb.append(constant.getValue()) } } return if (!interupted) createCompileTimeConstant(sb.toString(), expectedType, - isPure = true, canBeUsedInAnnotation = canBeUsedInAnnotation) + isPure = true, canBeUsedInAnnotation = canBeUsedInAnnotation, + usesVariableAsConstant = usesVariableAsConstant) else null } @@ -160,7 +161,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet JetTokens.OROR -> leftValue as Boolean || rightValue as Boolean else -> throw IllegalArgumentException("Unknown boolean operation token ${operationToken}") } - return createCompileTimeConstant(result, expectedType) + val usesVariableAsConstant = leftConstant.usesVariableAsConstant() || rightConstant.usesVariableAsConstant() + return createCompileTimeConstant(result, expectedType, true, true, usesVariableAsConstant) } else { return evaluateCall(expression.getOperationReference(), leftExpression, expectedType) @@ -182,12 +184,16 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet if (result == null) return null val isArgumentPure = isPureConstant(argumentForReceiver.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) + val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS - return createCompileTimeConstant(result, expectedType, !isNumberConversionMethod && isArgumentPure, canBeUsedInAnnotation) + return createCompileTimeConstant(result, + expectedType, + !isNumberConversionMethod && isArgumentPure, + canBeUsedInAnnotation, + usesVariableAsConstant) } else if (argumentsEntrySet.size() == 1) { val (parameter, argument) = argumentsEntrySet.first() - val argumentForParameter = createOperationArgumentForFirstParameter(argument, parameter) if (argumentForParameter == null) return null @@ -200,12 +206,13 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression) - val c = EvaluatorContext(canBeUsedInAnnotation, areArgumentsPure) + val usesVariableAsConstant = usesVariableAsConstant(argumentForReceiver.expression) || usesVariableAsConstant(argumentForParameter.expression) + val c = EvaluatorContext(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant) return when(resultingDescriptorName) { OperatorConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, c) OperatorConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, c) else -> { - createCompileTimeConstant(result, expectedType, areArgumentsPure, canBeUsedInAnnotation) + createCompileTimeConstant(result, expectedType, areArgumentsPure, canBeUsedInAnnotation, usesVariableAsConstant) } } } @@ -213,7 +220,10 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet return null } + private fun usesVariableAsConstant(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.usesVariableAsConstant() ?: false + private fun canBeUsedInAnnotation(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.canBeUsedInAnnotations() ?: false + private fun isPureConstant(expression: JetExpression): Boolean { val compileTimeConstant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression) if (compileTimeConstant is IntegerValueConstant) { @@ -287,7 +297,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet override fun visitSimpleNameExpression(expression: JetSimpleNameExpression, expectedType: JetType?): CompileTimeConstant<*>? { val enumDescriptor = trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, expression); if (enumDescriptor != null && DescriptorUtils.isEnumEntry(enumDescriptor)) { - return EnumValue(enumDescriptor as ClassDescriptor); + return EnumValue(enumDescriptor as ClassDescriptor, false); } val resolvedCall = trace.getBindingContext().get(BindingContext.RESOLVED_CALL, expression) @@ -303,7 +313,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet else compileTimeConstant.getValue() return createCompileTimeConstant(value, expectedType, isPure = false, - canBeUsedInAnnotation = DescriptorUtils.isPropertyCompileTimeConstant(callableDescriptor)) + canBeUsedInAnnotation = DescriptorUtils.isPropertyCompileTimeConstant(callableDescriptor), + usesVariableAsConstant = true) } } return null @@ -341,7 +352,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val varargType = resultingDescriptor.getValueParameters().first?.getVarargElementType()!! val arguments = call.getValueArguments().values().flatMap { resolveArguments(it.getArguments(), varargType) } - return ArrayValue(arguments, resultingDescriptor.getReturnType()!!, true) + return ArrayValue(arguments, resultingDescriptor.getReturnType()!!, true, arguments.any() { it.usesVariableAsConstant() }) } // Ann() @@ -402,7 +413,6 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val argumentExpression = arguments.first().getArgumentExpression() if (argumentExpression == null) return null - return createOperationArgument(argumentExpression, parameter.getType(), argumentCompileTimeType) } @@ -421,8 +431,12 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet return OperationArgument(evaluationResult, compileTimeType, expression) } - fun createCompileTimeConstant(value: Any?, expectedType: JetType?, isPure: Boolean = true, canBeUsedInAnnotation: Boolean = true): CompileTimeConstant<*>? { - val c = EvaluatorContext(canBeUsedInAnnotation, isPure) + fun createCompileTimeConstant(value: Any?, + expectedType: JetType?, + isPure: Boolean = true, + canBeUsedInAnnotation: Boolean = true, + usesVariableAsConstant: Boolean = false): CompileTimeConstant<*>? { + val c = EvaluatorContext(canBeUsedInAnnotation, isPure, usesVariableAsConstant) return createCompileTimeConstant(value, c, if (isPure) expectedType ?: TypeUtils.NO_EXPECTED_TYPE else null) } } @@ -490,11 +504,11 @@ private fun createCompileTimeConstantForEquals(result: Any?, operationReference: assert(operationReference is JetSimpleNameExpression, "This method should be called only for equals operations") val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType() return when (operationToken) { - JetTokens.EQEQ -> BooleanValue(result, c.canBeUsedInAnnotation) - JetTokens.EXCLEQ -> BooleanValue(!result, c.canBeUsedInAnnotation) + JetTokens.EQEQ -> BooleanValue(result, c.canBeUsedInAnnotation, c.usesVariableAsConstant) + JetTokens.EXCLEQ -> BooleanValue(!result, c.canBeUsedInAnnotation, c.usesVariableAsConstant) JetTokens.IDENTIFIER -> { assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.EQUALS, "This method should be called only for equals operations") - return BooleanValue(result, c.canBeUsedInAnnotation) + return BooleanValue(result, c.canBeUsedInAnnotation, c.usesVariableAsConstant) } else -> throw IllegalStateException("Unknown equals operation token: $operationToken ${operationReference.getText()}") } @@ -507,13 +521,13 @@ private fun createCompileTimeConstantForCompareTo(result: Any?, operationReferen assert(operationReference is JetSimpleNameExpression, "This method should be called only for compareTo operations") val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType() return when (operationToken) { - JetTokens.LT -> BooleanValue(result < 0, c.canBeUsedInAnnotation) - JetTokens.LTEQ -> BooleanValue(result <= 0, c.canBeUsedInAnnotation) - JetTokens.GT -> BooleanValue(result > 0, c.canBeUsedInAnnotation) - JetTokens.GTEQ -> BooleanValue(result >= 0, c.canBeUsedInAnnotation) + JetTokens.LT -> BooleanValue(result < 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant) + JetTokens.LTEQ -> BooleanValue(result <= 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant) + JetTokens.GT -> BooleanValue(result > 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant) + JetTokens.GTEQ -> BooleanValue(result >= 0, c.canBeUsedInAnnotation, c.usesVariableAsConstant) JetTokens.IDENTIFIER -> { assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.COMPARE_TO, "This method should be called only for compareTo operations") - return IntValue(result, c.canBeUsedInAnnotation, c.isPure) + return IntValue(result, c.canBeUsedInAnnotation, c.isPure, c.usesVariableAsConstant) } else -> throw IllegalStateException("Unknown compareTo operation token: $operationToken") } @@ -523,19 +537,19 @@ private fun createCompileTimeConstantForCompareTo(result: Any?, operationReferen private fun createStringConstant(value: CompileTimeConstant<*>?): StringValue? { return when (value) { - is IntegerValueTypeConstant -> StringValue(value.getValue(TypeUtils.NO_EXPECTED_TYPE).toString(), value.canBeUsedInAnnotations()) + is IntegerValueTypeConstant -> StringValue(value.getValue(TypeUtils.NO_EXPECTED_TYPE).toString(), value.canBeUsedInAnnotations(), value.usesVariableAsConstant()) is StringValue -> value is IntValue, is ByteValue, is ShortValue, is LongValue, is CharValue, is DoubleValue, is FloatValue, is BooleanValue, - is NullValue -> StringValue(value.getValue().toString(), value.canBeUsedInAnnotations()) + is NullValue -> StringValue(value.getValue().toString(), value.canBeUsedInAnnotations(), value.usesVariableAsConstant()) else -> null } } private fun createCompileTimeConstant(value: Any?, c: EvaluatorContext, expectedType: JetType? = null): CompileTimeConstant<*>? { - return createCompileTimeConstant(value, c.canBeUsedInAnnotation, c.isPure, expectedType) + return createCompileTimeConstant(value, c.canBeUsedInAnnotation, c.isPure, c.usesVariableAsConstant, expectedType) } fun isIntegerType(value: Any?) = value is Byte || value is Short || value is Int || value is Long @@ -567,7 +581,7 @@ private fun getCompileTimeType(c: JetType): CompileTimeType? { } } -private class EvaluatorContext(val canBeUsedInAnnotation: Boolean, val isPure: Boolean) +private class EvaluatorContext(val canBeUsedInAnnotation: Boolean, val isPure: Boolean, val usesVariableAsConstant: Boolean = false) private class CompileTimeType diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index c0195fc28d91c..a6e31b0b0ce75 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -18,6 +18,7 @@ import com.google.common.collect.Lists; import com.intellij.openapi.util.Pair; +import kotlin.Function1; import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -282,11 +283,20 @@ public static CompileTimeConstant getAnnotationArgumentValue( trace); if (argumentsAsVararg) { + + boolean usesVariableAsConstant = KotlinPackage.any(constants, new Function1, Boolean>() { + @Override + public Boolean invoke(CompileTimeConstant constant) { + return constant.usesVariableAsConstant(); + } + }); + JetType arrayType = KotlinBuiltIns.getInstance().getPrimitiveArrayJetTypeByPrimitiveJetType(varargElementType); if (arrayType == null) { arrayType = KotlinBuiltIns.getInstance().getArrayType(varargElementType); } - return new ArrayValue(constants, arrayType, true); + + return new ArrayValue(constants, arrayType, true, usesVariableAsConstant); } else { // we should actually get only one element, but just in case of getting many, we take the last one diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java index 5fc5f3e77701c..8cb6b4ff9e04f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/CompileTimeConstantUtils.java @@ -18,13 +18,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.Annotated; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator; -import org.jetbrains.jet.lang.psi.JetConstantExpression; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetParameter; import org.jetbrains.jet.lang.psi.JetTypeReference; @@ -129,12 +127,10 @@ public static boolean canBeReducedToBooleanConstant( @NotNull BindingTrace trace, @Nullable Boolean expectedValue ) { - if (!(expression instanceof JetConstantExpression) || expression.getNode().getElementType() != JetNodeTypes.BOOLEAN_CONSTANT) { - return false; - } + if (expression == null) return false; CompileTimeConstant compileTimeConstant = ConstantExpressionEvaluator.object$.evaluate(expression, trace, KotlinBuiltIns.getInstance().getBooleanType()); - if (!(compileTimeConstant instanceof BooleanValue)) return false; + if (!(compileTimeConstant instanceof BooleanValue) || compileTimeConstant.usesVariableAsConstant()) return false; Boolean value = ((BooleanValue) compileTimeConstant).getValue(); return expectedValue == null || expectedValue.equals(value); diff --git a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions index 62b6f1fde5f80..47e3b1c956f59 100644 --- a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions +++ b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions @@ -1,25 +1,25 @@ == main == fun main() { - while(1 > 0) { + while(0 > 1) { 2 } } --------------------- L0: 1 - 2 mark({ while(1 > 0) { 2 } }) - mark(while(1 > 0) { 2 }) + 2 mark({ while(0 > 1) { 2 } }) + mark(while(0 > 1) { 2 }) L2 [loop entry point]: L5 [condition entry point]: - mark(1 > 0) PREV:[mark(while(1 > 0) { 2 }), jmp(L2 [loop entry point])] - r(1) + mark(0 > 1) PREV:[mark(while(0 > 1) { 2 }), jmp(L2 [loop entry point])] r(0) + r(1) call(>, compareTo) jf(L3 [loop exit point]) NEXT:[read (Unit), mark({ 2 })] L4 [body entry point]: 3 mark({ 2 }) r(2) - 2 jmp(L2 [loop entry point]) NEXT:[mark(1 > 0)] + 2 jmp(L2 [loop entry point]) NEXT:[mark(0 > 1)] L3 [loop exit point]: read (Unit) PREV:[jf(L3 [loop exit point])] L1: @@ -32,21 +32,21 @@ sink: == dowhile == fun dowhile() { do {return} - while(1 > 0) + while(0 > 1) } --------------------- L0: 1 - 2 mark({ do {return} while(1 > 0) }) - 3 mark(do {return} while(1 > 0)) + 2 mark({ do {return} while(0 > 1) }) + 3 mark(do {return} while(0 > 1)) L2 [loop entry point]: L4 [body entry point]: mark({return}) ret L1 NEXT:[] L5 [condition entry point]: -- mark(1 > 0) PREV:[] -- r(1) PREV:[] +- mark(0 > 1) PREV:[] - r(0) PREV:[] +- r(1) PREV:[] - call(>, compareTo) PREV:[] - jt(L2 [loop entry point]) NEXT:[read (Unit), mark({return})] PREV:[] L3 [loop exit point]: diff --git a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt index 2cbdf06163472..0e4aa0aa8e6dd 100644 --- a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt +++ b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt @@ -1,10 +1,10 @@ fun main() { - while(1 > 0) { + while(0 > 1) { 2 } } fun dowhile() { do {return} - while(1 > 0) + while(0 > 1) } diff --git a/compiler/testData/diagnostics/tests/annotations/onLoops.kt b/compiler/testData/diagnostics/tests/annotations/onLoops.kt index 427af32532ad8..954c7050f1927 100644 --- a/compiler/testData/diagnostics/tests/annotations/onLoops.kt +++ b/compiler/testData/diagnostics/tests/annotations/onLoops.kt @@ -1,9 +1,9 @@ fun test() { [ann] - while (1 < 2) {} + while (2 < 1) {} [ann] - do {} while (1 < 2) + do {} while (2 < 1) [ann] for (i in 1..2) {} diff --git a/compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt b/compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt new file mode 100644 index 0000000000000..0ac9390d72a8f --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt @@ -0,0 +1,12 @@ +fun test() { + [ann] + while (2 > 1) {} + + [ann] + do {} while (2 > 1) + + [ann] + for (i in 1..2) {} +} + +annotation class ann \ No newline at end of file diff --git a/compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt b/compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt new file mode 100644 index 0000000000000..50bfaefa0f207 --- /dev/null +++ b/compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt @@ -0,0 +1,11 @@ +package test + +val x = 1 +val y = "a" + +// val prop1: true +val prop1 = x + +// val prop2: true +val prop2 = y + diff --git a/compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt b/compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt new file mode 100644 index 0000000000000..eed8758f3713b --- /dev/null +++ b/compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt @@ -0,0 +1,16 @@ +package test + +enum class MyEnum { A;B } + +fun foo(): Boolean = true + +val x = 1 + +// val prop1: null +val prop1 = MyEnum.A + +// val prop2: null +val prop2 = foo() + +// val prop3: true +val prop3 = "$x" \ No newline at end of file diff --git a/compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt b/compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt new file mode 100644 index 0000000000000..fb22226574b6b --- /dev/null +++ b/compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt @@ -0,0 +1,29 @@ +package test + +val x = 1 +val y = true + +// val prop1: false +val prop1 = 1 > 2 + +// val prop2: false +val prop2 = 2 + 3 + +// val prop3: true +val prop3 = 2 + x + +// val prop4: true +val prop4 = x < 2 + +// val prop5: true +val prop5 = y && true + +// val prop6: false +val prop6 = true && false || 2 > 1 + +// val prop7: true +val prop7 = x == 1 + +// val prop8: true +val prop8 = 1 / x + diff --git a/compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt b/compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt new file mode 100644 index 0000000000000..ed6fcb4b07a6f --- /dev/null +++ b/compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt @@ -0,0 +1,23 @@ +package test + +// val prop1: false +val prop1 = 1 + +// val prop2: false +val prop2 = "hello" + +// val prop3: false +val prop3 = true + +// val prop4: false +val prop4 = false + +// val prop5: false +val prop5 = -7453 + +// val prop6: false +val prop6 = 3.56 + +// val prop7: false +val prop7 = 5464564L + diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 056c34b859fb6..b356c8e0b9d6f 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -616,6 +616,11 @@ public void testOnLoops() throws Exception { doTest("compiler/testData/diagnostics/tests/annotations/onLoops.kt"); } + @TestMetadata("onLoopsUnreachable.kt") + public void testOnLoopsUnreachable() throws Exception { + doTest("compiler/testData/diagnostics/tests/annotations/onLoopsUnreachable.kt"); + } + @TestMetadata("onMultiDeclaration.kt") public void testOnMultiDeclaration() throws Exception { doTest("compiler/testData/diagnostics/tests/annotations/onMultiDeclaration.kt"); diff --git a/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt b/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt index 08147d345c1e2..f2c9aa5c31330 100644 --- a/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt +++ b/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt @@ -20,20 +20,18 @@ import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.resolve.annotation.AbstractAnnotationDescriptorResolveTest import java.io.File import com.intellij.openapi.util.io.FileUtil -import org.jetbrains.jet.lang.resolve.BindingContextUtils -import org.jetbrains.jet.lang.psi.JetProperty import org.jetbrains.jet.InTextDirectivesUtils -import kotlin.test.assertEquals import kotlin.test.assertNotNull import java.util.regex.Pattern -import org.intellij.lang.annotations.RegExp -import com.intellij.openapi.util.text.StringUtil import org.jetbrains.jet.JetTestUtils -import org.jetbrains.jet.util.slicedmap.WritableSlice -import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant import org.jetbrains.jet.lang.resolve.constants.StringValue import org.jetbrains.jet.lang.descriptors.VariableDescriptor import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant +import java.util.HashMap +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace +import org.jetbrains.jet.lang.types.TypeUtils abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorResolveTest() { @@ -63,6 +61,19 @@ abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorReso } } + // Test directives should look like [// val testedPropertyName: expectedValue] + fun doUsesVariableAsConstantTest(path: String) { + doTest(path) { + property, context -> + val compileTimeConstant = property.getCompileTimeInitializer() + if (compileTimeConstant == null) { + "null" + } else { + compileTimeConstant.usesVariableAsConstant().toString() + } + } + } + private fun doTest(path: String, getValueToTest: (VariableDescriptor, BindingContext) -> String) { val myFile = File(path) val fileText = FileUtil.loadFile(myFile, true) diff --git a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java index 89de1e1eda91c..2e75c5fa72ab7 100644 --- a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java @@ -30,7 +30,7 @@ /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@InnerTestClasses({EvaluateExpressionTestGenerated.Constant.class, EvaluateExpressionTestGenerated.IsPure.class}) +@InnerTestClasses({EvaluateExpressionTestGenerated.Constant.class, EvaluateExpressionTestGenerated.IsPure.class, EvaluateExpressionTestGenerated.UsesVariableAsConstant.class}) public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionTest { @TestMetadata("compiler/testData/evaluate/constant") public static class Constant extends AbstractEvaluateExpressionTest { @@ -168,10 +168,39 @@ public void testUnaryMinusIndependentExpType() throws Exception { } + @TestMetadata("compiler/testData/evaluate/usesVariableAsConstant") + public static class UsesVariableAsConstant extends AbstractEvaluateExpressionTest { + public void testAllFilesPresentInUsesVariableAsConstant() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/evaluate/usesVariableAsConstant"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("binaryTypes.kt") + public void testBinaryTypes() throws Exception { + doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/binaryTypes.kt"); + } + + @TestMetadata("NamedConstants.kt") + public void testNamedConstants() throws Exception { + doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/NamedConstants.kt"); + } + + @TestMetadata("OtherTypes.kt") + public void testOtherTypes() throws Exception { + doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/OtherTypes.kt"); + } + + @TestMetadata("simpleTypes.kt") + public void testSimpleTypes() throws Exception { + doUsesVariableAsConstantTest("compiler/testData/evaluate/usesVariableAsConstant/simpleTypes.kt"); + } + + } + public static Test suite() { TestSuite suite = new TestSuite("EvaluateExpressionTestGenerated"); suite.addTestSuite(Constant.class); suite.addTestSuite(IsPure.class); + suite.addTestSuite(UsesVariableAsConstant.class); return suite; } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt index 6b4a87b2a23fc..c3b11250b21d6 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt @@ -108,7 +108,7 @@ class LazyJavaAnnotationDescriptor( private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): CompileTimeConstant<*>? { return when (argument) { - is JavaLiteralAnnotationArgument -> createCompileTimeConstant(argument.getValue(), true, false, null) + is JavaLiteralAnnotationArgument -> createCompileTimeConstant(argument.getValue(), true, false, false, null) is JavaReferenceAnnotationArgument -> resolveFromReference(argument.resolve()) is JavaArrayAnnotationArgument -> resolveFromArray(argument.getName() ?: DEFAULT_ANNOTATION_MEMBER_NAME, argument.getElements()) is JavaAnnotationAsAnnotationArgument -> resolveFromAnnotation(argument.getAnnotation()) @@ -137,7 +137,7 @@ class LazyJavaAnnotationDescriptor( val values = elements.map { argument -> resolveAnnotationArgument(argument) ?: NullValue.NULL } - return ArrayValue(values, valueParameter.getType(), true) + return ArrayValue(values, valueParameter.getType(), true, values.any { it.usesVariableAsConstant() }) } private fun resolveFromReference(element: JavaElement?): CompileTimeConstant<*>? { @@ -154,7 +154,7 @@ class LazyJavaAnnotationDescriptor( val classifier = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(element.getName()) if (classifier !is ClassDescriptor) return null - return EnumValue(classifier) + return EnumValue(classifier, false) } private fun resolveFromJavaClassObjectType(javaType: JavaType): CompileTimeConstant<*>? { diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java index 1dbb21646d024..c1bcb19ff0567 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/AnnotationDescriptorDeserializer.java @@ -126,7 +126,7 @@ public static KotlinJvmBinaryClass.AnnotationArgumentVisitor resolveAnnotation( @Override public void visit(@Nullable Name name, @Nullable Object value) { if (name != null) { - CompileTimeConstant argument = ConstantsPackage.createCompileTimeConstant(value, true, false, null); + CompileTimeConstant argument = ConstantsPackage.createCompileTimeConstant(value, true, false, false, null); setArgumentValueByName(name, argument != null ? argument : ErrorValue.create("Unsupported annotation argument: " + name)); } } @@ -149,7 +149,7 @@ private CompileTimeConstant enumEntryValue(@NotNull JvmClassName enumClassNam if (enumClass.getKind() == ClassKind.ENUM_CLASS) { ClassifierDescriptor classifier = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(name); if (classifier instanceof ClassDescriptor) { - return new EnumValue((ClassDescriptor) classifier); + return new EnumValue((ClassDescriptor) classifier, false); } } return ErrorValue.create("Unresolved enum entry: " + enumClassName.getInternalName() + "." + name); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java index 9ef635890e438..a0e7c12688a00 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java @@ -89,7 +89,7 @@ public KotlinJvmBinaryClass.AnnotationVisitor visitField(@NotNull Name name, @No MemberSignature signature = MemberSignature.fromFieldNameAndDesc(name, desc); if (initializer != null) { propertyConstants.put(signature, ConstantsPackage.createCompileTimeConstant( - initializer, /* canBeUsedInAnnotation */ true, /* isPureIntConstant */ true, /* expectedType */ null)); + initializer, /* canBeUsedInAnnotation */ true, /* isPureIntConstant */ true, /* usesVariableAsConstant */ true, /* expectedType */ null)); } return new MemberAnnotationVisitor(signature); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java index 3eed4039b4f72..6de8be2b9db78 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java @@ -25,7 +25,7 @@ public class AnnotationValue extends CompileTimeConstant { public AnnotationValue(@NotNull AnnotationDescriptor value) { - super(value, true); + super(value, true, false, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java index d082d2a7410ba..a62af0666b842 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java @@ -27,8 +27,11 @@ public class ArrayValue extends CompileTimeConstant> private final JetType type; - public ArrayValue(@NotNull List> value, @NotNull JetType type, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public ArrayValue(@NotNull List> value, + @NotNull JetType type, + boolean canBeUsedInAnnotations, + boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, false, usesVariableAsConstant); this.type = type; } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java index 76494dbc3eabe..f83621dcf167c 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java @@ -23,8 +23,8 @@ public class BooleanValue extends CompileTimeConstant { - public BooleanValue(boolean value, boolean canBeUseInAnnotation) { - super(value, canBeUseInAnnotation); + public BooleanValue(boolean value, boolean canBeUseInAnnotation, boolean usesVariableAsConstant) { + super(value, canBeUseInAnnotation, false, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java index 74ea6b13c7382..7c030c6cd4d21 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java @@ -23,8 +23,8 @@ public class ByteValue extends IntegerValueConstant { - public ByteValue(byte value, boolean canBeUsedInAnnotations, boolean pure) { - super(value, canBeUsedInAnnotations, pure); + public ByteValue(byte value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVaraiableAsConstant) { + super(value, canBeUsedInAnnotations, pure, usesVaraiableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java index 197c2e1aac355..41b1d0db9d6bf 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java @@ -23,8 +23,8 @@ public class CharValue extends IntegerValueConstant { - public CharValue(char value, boolean canBeUsedInAnnotations, boolean pure) { - super(value, canBeUsedInAnnotations, pure); + public CharValue(char value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java index 07dce8a09bf63..205aa23a67e76 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java @@ -24,15 +24,38 @@ public abstract class CompileTimeConstant { protected final T value; - private final boolean canBeUsedInAnnotations; + private final int flags; - protected CompileTimeConstant(T value, boolean canBeUsedInAnnotations) { + /* + * if is pure is false then constant type cannot be changed + * ex1. val a: Long = 1.toInt() (TYPE_MISMATCH error, 1.toInt() isn't pure) + * ex2. val b: Int = a (TYPE_MISMATCH error, a isn't pure) + * + */ + private static final int IS_PURE_MASK = 1; + private static final int CAN_BE_USED_IN_ANNOTATIONS_MASK = 1 << 1; + private static final int USES_VARIABLE_AS_CONSTANT_MASK = 1 << 2; + + protected CompileTimeConstant(T value, + boolean canBeUsedInAnnotations, + boolean isPure, + boolean usesVariableAsConstant) { this.value = value; - this.canBeUsedInAnnotations = canBeUsedInAnnotations; + flags = (isPure ? IS_PURE_MASK : 0) | + (canBeUsedInAnnotations ? CAN_BE_USED_IN_ANNOTATIONS_MASK : 0) | + (usesVariableAsConstant ? USES_VARIABLE_AS_CONSTANT_MASK : 0); } public boolean canBeUsedInAnnotations() { - return canBeUsedInAnnotations; + return (flags & CAN_BE_USED_IN_ANNOTATIONS_MASK) != 0; + } + + public boolean isPure() { + return (flags & IS_PURE_MASK) != 0; + } + + public boolean usesVariableAsConstant() { + return (flags & USES_VARIABLE_AS_CONSTANT_MASK) != 0; } @Nullable diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt index 39e85825861e0..5fe1f759334b3 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt @@ -24,23 +24,24 @@ public fun createCompileTimeConstant( value: Any?, canBeUsedInAnnotation: Boolean, isPureIntConstant: Boolean, + usesVariableAsConstant: Boolean = false, expectedType: JetType? = null ): CompileTimeConstant<*>? { if (expectedType == null) { when(value) { - is Byte -> return ByteValue(value, canBeUsedInAnnotation, isPureIntConstant) - is Short -> return ShortValue(value, canBeUsedInAnnotation, isPureIntConstant) - is Int -> return IntValue(value, canBeUsedInAnnotation, isPureIntConstant) - is Long -> return LongValue(value, canBeUsedInAnnotation, isPureIntConstant) + is Byte -> return ByteValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) + is Short -> return ShortValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) + is Int -> return IntValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) + is Long -> return LongValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) } } return when(value) { - is Byte, is Short, is Int, is Long -> getIntegerValue((value as Number).toLong(), canBeUsedInAnnotation, isPureIntConstant, expectedType) - is Char -> CharValue(value, canBeUsedInAnnotation, isPureIntConstant) - is Float -> FloatValue(value, canBeUsedInAnnotation) - is Double -> DoubleValue(value, canBeUsedInAnnotation) - is Boolean -> BooleanValue(value, canBeUsedInAnnotation) - is String -> StringValue(value, canBeUsedInAnnotation) + is Byte, is Short, is Int, is Long -> getIntegerValue((value as Number).toLong(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant, expectedType) + is Char -> CharValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) + is Float -> FloatValue(value, canBeUsedInAnnotation, usesVariableAsConstant) + is Double -> DoubleValue(value, canBeUsedInAnnotation, usesVariableAsConstant) + is Boolean -> BooleanValue(value, canBeUsedInAnnotation, usesVariableAsConstant) + is String -> StringValue(value, canBeUsedInAnnotation, usesVariableAsConstant) null -> NullValue.NULL else -> null } @@ -50,30 +51,31 @@ private fun getIntegerValue( value: Long, canBeUsedInAnnotation: Boolean, isPureIntConstant: Boolean, + usesVariableAsConstant: Boolean, expectedType: JetType ): CompileTimeConstant<*>? { fun defaultIntegerValue(value: Long) = when (value) { - value.toInt().toLong() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant) - else -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant) + value.toInt().toLong() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) + else -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) } if (TypeUtils.noExpectedType(expectedType) || expectedType.isError()) { - return IntegerValueTypeConstant(value, canBeUsedInAnnotation) + return IntegerValueTypeConstant(value, canBeUsedInAnnotation, usesVariableAsConstant) } val builtIns = KotlinBuiltIns.getInstance() return when (TypeUtils.makeNotNullable(expectedType)) { - builtIns.getLongType() -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant) + builtIns.getLongType() -> LongValue(value, canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) builtIns.getShortType() -> when (value) { - value.toShort().toLong() -> ShortValue(value.toShort(), canBeUsedInAnnotation, isPureIntConstant) + value.toShort().toLong() -> ShortValue(value.toShort(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) else -> defaultIntegerValue(value) } builtIns.getByteType() -> when (value) { - value.toByte().toLong() -> ByteValue(value.toByte(), canBeUsedInAnnotation, isPureIntConstant) + value.toByte().toLong() -> ByteValue(value.toByte(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) else -> defaultIntegerValue(value) } - builtIns.getCharType() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant) + builtIns.getCharType() -> IntValue(value.toInt(), canBeUsedInAnnotation, isPureIntConstant, usesVariableAsConstant) else -> defaultIntegerValue(value) } } \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java index 6f06ee2e64250..d342fe312f86c 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java @@ -23,8 +23,8 @@ public class DoubleValue extends CompileTimeConstant { - public DoubleValue(double value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public DoubleValue(double value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, false, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java index 0b6f05a566ae9..b5c97152ab0df 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java @@ -24,8 +24,8 @@ public class EnumValue extends CompileTimeConstant { - public EnumValue(@NotNull ClassDescriptor value) { - super(value, true); + public EnumValue(@NotNull ClassDescriptor value, boolean usesVariableAsConstant) { + super(value, true, false, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java index 465dde4892c00..60c9471184c1c 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java @@ -25,7 +25,7 @@ public abstract class ErrorValue extends CompileTimeConstant { public ErrorValue() { - super(null, true); + super(null, true, false, false); } @Override diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java index 3e439e467a7dc..102912ae4bca7 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java @@ -23,8 +23,8 @@ public class FloatValue extends CompileTimeConstant { - public FloatValue(float value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public FloatValue(float value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, false, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java index 0f411c4bbda82..5d39377065dad 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java @@ -23,8 +23,8 @@ public class IntValue extends IntegerValueConstant { - public IntValue(int value, boolean canBeUsedInAnnotations, boolean pure) { - super(value, canBeUsedInAnnotations, pure); + public IntValue(int value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueConstant.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueConstant.java index fa21468393ca8..a2d34cf91af72 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueConstant.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueConstant.java @@ -18,19 +18,7 @@ public abstract class IntegerValueConstant extends CompileTimeConstant { - /* - * if false then constant type cannot be changed - * ex1. val a: Long = 1.toInt() (TYPE_MISMATCH error, 1.toInt() isn't pure) - * ex2. val b: Int = a (TYPE_MISMATCH error, a isn't pure) - * */ - private final boolean isPure; - - protected IntegerValueConstant(T value, boolean canBeUsedInAnnotations, boolean pure) { - super(value, canBeUsedInAnnotations); - isPure = pure; - } - - public boolean isPure() { - return isPure; + protected IntegerValueConstant(T value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVaraiableAsConstant) { + super(value, canBeUsedInAnnotations, pure, usesVaraiableAsConstant); } } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java index a1425930b2ad1..7bac4b2d574ba 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java @@ -19,10 +19,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor; -import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; -import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import java.util.Collections; @@ -30,8 +29,8 @@ public class IntegerValueTypeConstant extends IntegerValueConstant { private final IntegerValueTypeConstructor typeConstructor; - public IntegerValueTypeConstant(@NotNull Number value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations, true); + public IntegerValueTypeConstant(@NotNull Number value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, true, usesVariableAsConstant); this.typeConstructor = new IntegerValueTypeConstructor(value.longValue()); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java index 60b2e3f631b6a..d1b8bd25e21c6 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java @@ -24,7 +24,7 @@ public class JavaClassValue extends CompileTimeConstant { public JavaClassValue(@NotNull JetType value) { - super(value, true); + super(value, true, false, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java index 326c53fb05f34..32c23057164e4 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java @@ -23,8 +23,8 @@ public class LongValue extends IntegerValueConstant { - public LongValue(long value, boolean canBeUsedInAnnotations, boolean pure) { - super(value, canBeUsedInAnnotations, pure); + public LongValue(long value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java index e9cdaeb553f49..37085399151fb 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java @@ -26,7 +26,7 @@ public class NullValue extends CompileTimeConstant { public static final NullValue NULL = new NullValue(); private NullValue() { - super(null, false); + super(null, false, false, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java index 1df4b4e7b5167..36bfee596c3da 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java @@ -23,8 +23,8 @@ public class ShortValue extends IntegerValueConstant { - public ShortValue(short value, boolean canBeUsedInAnnotations, boolean pure) { - super(value, canBeUsedInAnnotations, pure); + public ShortValue(short value, boolean canBeUsedInAnnotations, boolean pure, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, pure, usesVariableAsConstant); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java index 1c1a762a456e8..316912f65f47d 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java @@ -23,8 +23,8 @@ public class StringValue extends CompileTimeConstant { - public StringValue(String value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public StringValue(String value, boolean canBeUsedInAnnotations, boolean usesVariableAsConstant) { + super(value, canBeUsedInAnnotations, false, usesVariableAsConstant); } @NotNull diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index 3014280c0a4d4..f94762b0cf722 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -242,6 +242,7 @@ fun main(args: Array) { testClass(javaClass()) { model("evaluate/constant", testMethod = "doConstantTest") model("evaluate/isPure", testMethod = "doIsPureTest") + model("evaluate/usesVariableAsConstant", testMethod = "doUsesVariableAsConstantTest") } } From 0feb0d35e6ee7af269fcc044e41970ad76e63958 Mon Sep 17 00:00:00 2001 From: Tal Man Date: Wed, 9 Apr 2014 14:45:42 -0400 Subject: [PATCH 2/2] Intention to simplify boolean expressions that have expressions in them that can be simplified to constants --- .../jet/generators/tests/GenerateTests.kt | 1 + .../after.kt.template | 3 + .../before.kt.template | 3 + .../description.html | 5 + idea/src/META-INF/plugin.xml | 5 + .../jetbrains/jet/plugin/JetBundle.properties | 2 + .../SimplifyBooleanWithConstantsIntention.kt | 137 ++++++++++++++++++ .../inapplicableNoConstants.kt | 4 + .../inapplicableNotBinary.kt | 4 + .../inapplicableUsesVals.kt | 6 + .../inapplicableUsesVals2.kt | 6 + .../inapplicableUsesVals3.kt | 6 + .../reduceableBinary.kt | 3 + .../reduceableBinary.kt.after | 3 + .../reduceableBinary2.kt | 3 + .../reduceableBinary2.kt.after | 3 + .../reduceableBinary3.kt | 3 + .../reduceableBinary3.kt.after | 3 + .../reduceableBinaryWithParenthese.kt | 4 + .../reduceableBinaryWithParenthese.kt.after | 4 + .../simplifyBooleanWithConstants/simple.kt | 3 + .../simple.kt.after | 3 + .../simpleWithMoreBinaries.kt | 3 + .../simpleWithMoreBinaries.kt.after | 3 + .../simpleWithMoreBinaries2.kt | 3 + .../simpleWithMoreBinaries2.kt.after | 3 + .../simpleWithMoreBinaries3.kt | 3 + .../simpleWithMoreBinaries3.kt.after | 3 + .../simpleWithMoreBinariesAndParentheses.kt | 3 + ...pleWithMoreBinariesAndParentheses.kt.after | 3 + .../simpleWithMoreBinariesAndParentheses2.kt | 5 + ...leWithMoreBinariesAndParentheses2.kt.after | 5 + .../simpleWithMoreBinariesAndParentheses3.kt | 3 + ...leWithMoreBinariesAndParentheses3.kt.after | 3 + .../simpleWithNonsensical2.kt | 3 + .../simpleWithNonsensical2.kt.after | 3 + .../simpleWithParentheses.kt | 3 + .../simpleWithParentheses.kt.after | 3 + .../simpleWithParentheses2.kt | 3 + .../simpleWithParentheses2.kt.after | 3 + .../AbstractCodeTransformationTest.java | 4 + .../CodeTransformationTestGenerated.java | 106 +++++++++++++- 42 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/after.kt.template create mode 100644 idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/before.kt.template create mode 100644 idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/description.html create mode 100644 idea/src/org/jetbrains/jet/plugin/intentions/SimplifyBooleanWithConstantsIntention.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNoConstants.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNotBinary.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals2.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals3.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary2.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary2.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary3.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary3.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinaryWithParenthese.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinaryWithParenthese.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simple.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simple.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries2.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries2.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries3.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries3.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses2.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses2.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses3.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses3.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithNonsensical2.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithNonsensical2.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses.kt.after create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses2.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses2.kt.after diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index f94762b0cf722..1f2a3d545aa40 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -389,6 +389,7 @@ fun main(args: Array) { model("intentions/splitIf", testMethod = "doTestSplitIf") model("intentions/replaceWithOperatorAssign", testMethod = "doTestReplaceWithOperatorAssign") model("intentions/replaceWithTraditionalAssignment", testMethod = "doTestReplaceWithTraditionalAssignment") + model("intentions/simplifyBooleanWithConstants", testMethod = "doTestSimplifyBooleanWithConstants") } testClass(javaClass()) { diff --git a/idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/after.kt.template b/idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/after.kt.template new file mode 100644 index 0000000000000..32311bcaef73a --- /dev/null +++ b/idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/after.kt.template @@ -0,0 +1,3 @@ +fun foo() { + val x = y +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/before.kt.template b/idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/before.kt.template new file mode 100644 index 0000000000000..c83e94d456148 --- /dev/null +++ b/idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/before.kt.template @@ -0,0 +1,3 @@ +fun foo() { + val x = 3 > 2 && y && true +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/description.html b/idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/description.html new file mode 100644 index 0000000000000..b1a70490a7c6f --- /dev/null +++ b/idea/resources/intentionDescriptions/SimplifyBooleanWithConstantsIntention/description.html @@ -0,0 +1,5 @@ + + +This intention simplifies a boolean expression that has parts which can be reduced to constants + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 3c317df1cbaaf..4bacf5d97d74f 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -627,6 +627,11 @@ org.jetbrains.jet.plugin.intentions.ConvertNegatedExpressionWithDemorgansLawIntention Kotlin + + + org.jetbrains.jet.plugin.intentions.SimplifyBooleanWithConstantsIntention + Kotlin + ( + "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) + } +} diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNoConstants.kt b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNoConstants.kt new file mode 100644 index 0000000000000..20dd86315843d --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNoConstants.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +fun foo(y: Boolean) { + y && y || y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNotBinary.kt b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNotBinary.kt new file mode 100644 index 0000000000000..6aa592b3e72f3 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableNotBinary.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +fun foo(y: Boolean) { + true +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals.kt b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals.kt new file mode 100644 index 0000000000000..834ca1b45e66e --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals.kt @@ -0,0 +1,6 @@ +// IS_APPLICABLE: false +fun foo(y: Boolean) { + val x = 4 + val z = 5 + x < z +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals2.kt b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals2.kt new file mode 100644 index 0000000000000..d70bd6adc2791 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals2.kt @@ -0,0 +1,6 @@ +// IS_APPLICABLE: false +fun foo(y: Boolean) { + val x = 4 + val z = 5 + x == z || x != z +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals3.kt b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals3.kt new file mode 100644 index 0000000000000..21f731ec2a5ac --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/inapplicableUsesVals3.kt @@ -0,0 +1,6 @@ +// IS_APPLICABLE: false +fun foo(y: Boolean) { + val x = true + val z = false + x && z +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt new file mode 100644 index 0000000000000..7a394a65216c3 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + 2 > 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt.after new file mode 100644 index 0000000000000..c15837d7d4afc --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + true +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary2.kt b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary2.kt new file mode 100644 index 0000000000000..ae09d0f23f281 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary2.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + 2 > 1 && y || y || (3 + 3 > 10) +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary2.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary2.kt.after new file mode 100644 index 0000000000000..501d29656709f --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary2.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + y || y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary3.kt b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary3.kt new file mode 100644 index 0000000000000..3830c1f899275 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary3.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + 3 != 3 && 2 > 1 || y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary3.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary3.kt.after new file mode 100644 index 0000000000000..545846c7ac942 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary3.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinaryWithParenthese.kt b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinaryWithParenthese.kt new file mode 100644 index 0000000000000..7c864ca3f246a --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinaryWithParenthese.kt @@ -0,0 +1,4 @@ +fun foo(y: Boolean) { + val x = 3 + x != x && (2 > 1 || y) +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinaryWithParenthese.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinaryWithParenthese.kt.after new file mode 100644 index 0000000000000..de547d50fbb63 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinaryWithParenthese.kt.after @@ -0,0 +1,4 @@ +fun foo(y: Boolean) { + val x = 3 + x != x +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simple.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simple.kt new file mode 100644 index 0000000000000..4dd678b46cf47 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simple.kt @@ -0,0 +1,3 @@ +fun foo() { + val x = true && false || true +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simple.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simple.kt.after new file mode 100644 index 0000000000000..d0087ee87c7af --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simple.kt.after @@ -0,0 +1,3 @@ +fun foo() { + val x = true +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries.kt new file mode 100644 index 0000000000000..55948f5e210a2 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + (y && false) || (y && y && true && (y && true)) && false && true +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries.kt.after new file mode 100644 index 0000000000000..68065ba55814b --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + false +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries2.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries2.kt new file mode 100644 index 0000000000000..543ae6d89f82a --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries2.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + false || false || y || y || false || y && y || y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries2.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries2.kt.after new file mode 100644 index 0000000000000..23af54238c6cb --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries2.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + y || y || y && y || y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries3.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries3.kt new file mode 100644 index 0000000000000..c685f38e1762b --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries3.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + y || false && true || false || false || false || y && true +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries3.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries3.kt.after new file mode 100644 index 0000000000000..501d29656709f --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinaries3.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + y || y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses.kt new file mode 100644 index 0000000000000..42eebf87be182 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + false || false || y || y || false && (y && y || true) +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses.kt.after new file mode 100644 index 0000000000000..501d29656709f --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + y || y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses2.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses2.kt new file mode 100644 index 0000000000000..ca40f2d7143f4 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses2.kt @@ -0,0 +1,5 @@ +fun foo(y: Boolean) { + bar() && y || (y && true && bar()) || false +} + +fun bar(): Boolean = false \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses2.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses2.kt.after new file mode 100644 index 0000000000000..1baa6dbc722e5 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses2.kt.after @@ -0,0 +1,5 @@ +fun foo(y: Boolean) { + bar() && y || (y && bar()) +} + +fun bar(): Boolean = false \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses3.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses3.kt new file mode 100644 index 0000000000000..b05a98ce8550f --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses3.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + ((y && true) || false) && (true && (y && (y && (y ||false)))) +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses3.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses3.kt.after new file mode 100644 index 0000000000000..5f6fcefd08be6 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithMoreBinariesAndParentheses3.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + y && (y && (y && y)) +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithNonsensical2.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithNonsensical2.kt new file mode 100644 index 0000000000000..d75b39f588cda --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithNonsensical2.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + true && () && y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithNonsensical2.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithNonsensical2.kt.after new file mode 100644 index 0000000000000..d34b9a8986ef6 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithNonsensical2.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + () && y +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses.kt new file mode 100644 index 0000000000000..eacee43d5bd38 --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + (false) && true +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses.kt.after new file mode 100644 index 0000000000000..68065ba55814b --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + false +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses2.kt b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses2.kt new file mode 100644 index 0000000000000..e231d4c79642d --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses2.kt @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + y || (y && true) +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses2.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses2.kt.after new file mode 100644 index 0000000000000..501d29656709f --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/simpleWithParentheses2.kt.after @@ -0,0 +1,3 @@ +fun foo(y: Boolean) { + y || y +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java index b6812a17f4972..42ad6aae97273 100644 --- a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java @@ -227,6 +227,10 @@ public void doTestReplaceWithTraditionalAssignment(@NotNull String path) throws 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 { configureByFile(path); diff --git a/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java index dbaee1285b428..096584d013d40 100644 --- a/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java @@ -30,7 +30,7 @@ /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @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 { @TestMetadata("idea/testData/intentions/branched/elvisToIfThen") public static class ElvisToIfThen extends AbstractCodeTransformationTest { @@ -3173,6 +3173,109 @@ public void testSimple() throws Exception { } + @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() { TestSuite suite = new TestSuite("CodeTransformationTestGenerated"); suite.addTestSuite(ElvisToIfThen.class); @@ -3222,6 +3325,7 @@ public static Test suite() { suite.addTestSuite(SplitIf.class); suite.addTestSuite(ReplaceWithOperatorAssign.class); suite.addTestSuite(ReplaceWithTraditionalAssignment.class); + suite.addTestSuite(SimplifyBooleanWithConstants.class); return suite; } }