Intention to transform an if an AssertionError throw into an assert

This commit is contained in:
Tal Man
2014-04-20 11:47:50 -04:00
committed by Zalim Bashorov
parent d06b9abd4f
commit f61db2decc
30 changed files with 348 additions and 5 deletions
@@ -408,6 +408,7 @@ fun main(args: Array<String>) {
model("intentions/insertExplicitTypeArguments", testMethod = "doTestInsertExplicitTypeArguments")
model("intentions/removeExplicitTypeArguments", testMethod = "doTestRemoveExplicitTypeArguments")
model("intentions/convertAssertToIf", testMethod = "doTestConvertAssertToIfWithThrowIntention")
model("intentions/convertIfToAssert", testMethod = "doTestConvertIfWithThrowToAssertIntention")
}
testClass(javaClass<AbstractJetInspectionTest>()) {
@@ -0,0 +1,3 @@
fun foo() {
<spot>assert(!true, "text")</spot>
}
@@ -0,0 +1,5 @@
fun foo() {
<spot>if (true) {
throw AssertionError("text")
}</spot>
}
@@ -0,0 +1,5 @@
<html>
<body>
This intention converts an if statement that throws an AssertionError exception into an assertion
</body>
</html>
+5
View File
@@ -682,6 +682,11 @@
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.jet.plugin.intentions.ConvertIfWithThrowToAssertIntention</className>
<category>Kotlin</category>
</intentionAction>
<localInspection implementationClass="org.jetbrains.jet.plugin.inspections.ExplicitGetInspection"
displayName="Explicit 'get'"
groupName="Kotlin"
@@ -304,8 +304,10 @@ insert.explicit.type.arguments=Add explicit type arguments
insert.explicit.type.arguments.family=Add explicit type arguments
remove.explicit.type.arguments=Remove explicit type arguments
remove.explicit.type.arguments.family=Remove explicit type arguments
convert.assert.to.if.with.throw=Convert assert to if with throw
convert.assert.to.if.with.throw.family=Convert assert to if with throw
convert.assert.to.if.with.throw=Replace 'assert' with 'if' statement
convert.assert.to.if.with.throw.family=Replace 'assert' with 'if' statement
convert.if.with.throw.to.assert=Replace 'if' with 'assert' statement
convert.if.with.throw.to.assert.family=Replace 'if' with 'assert' statement
property.is.implemented.too.many=Has implementations
property.is.overridden.too.many=Is overridden in subclasses
@@ -0,0 +1,106 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.psi.JetPsiFactory
import org.jetbrains.jet.lang.psi.JetPrefixExpression
import org.jetbrains.jet.plugin.codeInsight.ShortenReferences
import org.jetbrains.jet.lang.psi.JetCallableReferenceExpression
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import kotlin.properties.Delegates
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.lang.psi.JetIfExpression
import org.jetbrains.jet.plugin.intentions.branchedTransformations.extractExpressionIfSingle
import org.jetbrains.jet.lang.psi.JetThrowExpression
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression
import com.intellij.psi.PsiElement
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.jet.renderer.DescriptorRenderer
import org.jetbrains.jet.lang.psi.JetExpression
import org.jetbrains.jet.lang.psi.JetUserType
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isNullExpression
public class ConvertIfWithThrowToAssertIntention :
JetSelfTargetingIntention<JetIfExpression>("convert.if.with.throw.to.assert", javaClass()) {
override fun isApplicableTo(element: JetIfExpression): Boolean {
if (element.getElse() != null) return false
val thenExpr = element.getThen()?.extractExpressionIfSingle()
if (thenExpr !is JetThrowExpression) return false
val thrownExpr = getSelector(thenExpr.getThrownExpression())
if (thrownExpr !is JetCallExpression) return false
if (thrownExpr.getCalleeExpression()?.getText() != "AssertionError") return false
val paramAmount = thrownExpr.getValueArguments().size
if (paramAmount > 1) return false
val context = AnalyzerFacadeWithCache.getContextForElement(thrownExpr)
val resolvedCall = context[BindingContext.RESOLVED_CALL, thrownExpr.getCalleeExpression()]
if (resolvedCall == null) return false
return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).toString() == "java.lang.AssertionError.<init>"
}
override fun applyTo(element: JetIfExpression, editor: Editor) {
val condition = element.getCondition()
if (condition == null) return
val thenExpr = element.getThen()?.extractExpressionIfSingle() as JetThrowExpression
val thrownExpr = getSelector(thenExpr.getThrownExpression()) as JetCallExpression
val args = thrownExpr.getValueArguments()
val paramText =
if (args.isNotEmpty()) {
val param = args.first!!.getArgumentExpression()!!
if (param.isNullExpression()) "" else ", ${param.getText()}"
} else {
""
}
val negatedCondition = JetPsiFactory.createExpression(element.getProject(), "!true") as JetPrefixExpression
negatedCondition.getBaseExpression()!!.replace(condition)
condition.replace(negatedCondition)
val newCondition = element.getCondition() as JetPrefixExpression
val simplifier = SimplifyNegatedBinaryExpressionIntention()
if (simplifier.isApplicableTo(newCondition)) {
simplifier.applyTo(newCondition, editor)
}
val assertText = "kotlin.assert(${element.getCondition()?.getText()} $paramText)"
val assertExpr = JetPsiFactory.createExpression(element.getProject(), assertText)
val newExpr = element.replace(assertExpr) as JetExpression
ShortenReferences.process(newExpr)
}
private fun getSelector(element: JetExpression?): JetExpression? {
if (element is JetDotQualifiedExpression) {
return element.getSelectorExpression()
}
return element
}
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo() {
if <caret>(true) {
throw AssertionError("text")
}
}
fun assert(x: Boolean, y: Any) {}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
kotlin.assert(!true, "text")
}
fun assert(x: Boolean, y: Any) {}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
package foo.kotlin
fun foo() {
if <caret>(true) {
throw AssertionError("text")
}
}
fun assert(x: Boolean, y: Any) {}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
package foo.kotlin
fun foo() {
kotlin.assert(!true, "text")
}
fun assert(x: Boolean, y: Any) {}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun foo() {
val x = true
if <caret>(x && false) {
throw AssertionError("text")
}
}
@@ -0,0 +1,5 @@
// WITH_RUNTIME
fun foo() {
val x = true
assert(!(x && false), "text")
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
if <caret>(true) {
throw java.lang.AssertionError("text")
}
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun foo() {
assert(!true, "text")
}
@@ -0,0 +1,9 @@
// IS_APPLICABLE: false
// WITH_RUNTIME
fun foo() {
if <caret>(1 == 0) {
throw AssertionError("text")
}
}
class AssertionError(x: String): Exception(x) {}
@@ -0,0 +1,7 @@
// IS_APPLICABLE: false
// WITH_RUNTIME
fun foo() {
if <caret>(1 == 0) {
throw AssertionError("text", Exception())
}
}
@@ -0,0 +1,9 @@
// IS_APPLICABLE: false
// WITH_RUNTIME
fun foo() {
if <caret>(1 == 0) {
throw AssertionError("text")
} else {
val x = 1
}
}
@@ -0,0 +1,8 @@
// IS_APPLICABLE: false
// WITH_RUNTIME
fun foo() {
if <caret>(1 == 0) {
val y = 1
throw AssertionError("text")
}
}
@@ -0,0 +1,8 @@
// IS_APPLICABLE: false
// WITH_RUNTIME
fun foo() {
if <caret>(1 == 0) {
throw AssertionError("text")
val y = 1
}
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
if <caret>(true) {
throw AssertionError()
}
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun foo() {
assert(!true)
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
if <caret>(true) {
throw AssertionError(null)
}
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun foo() {
assert(!true)
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
if <caret>(true) {
throw AssertionError("text")
}
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun foo() {
assert(!true, "text")
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
if <caret>(1 == 0) {
throw AssertionError("text")
}
}
@@ -0,0 +1,4 @@
// WITH_RUNTIME
fun foo() {
assert(1 != 0, "text")
}
@@ -237,6 +237,10 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes
doTestIntention(path, new ConvertAssertToIfWithThrowIntention());
}
public void doTestConvertIfWithThrowToAssertIntention(@NotNull String path) throws Exception {
doTestIntention(path, new ConvertIfWithThrowToAssertIntention());
}
public void doTestSplitIf(@NotNull String path) throws Exception {
doTestIntention(path, new SplitIfIntention());
}
@@ -16,18 +16,21 @@
package org.jetbrains.jet.plugin.intentions;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
import java.io.File;
import java.util.regex.Pattern;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.test.InnerTestClasses;
import org.jetbrains.jet.test.TestMetadata;
import java.io.File;
import java.util.regex.Pattern;
import org.jetbrains.jet.plugin.intentions.AbstractCodeTransformationTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@InnerTestClasses({CodeTransformationTestGenerated.DoubleBangToIfThen.class, CodeTransformationTestGenerated.IfThenToDoubleBang.class, 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, CodeTransformationTestGenerated.InsertExplicitTypeArguments.class, CodeTransformationTestGenerated.RemoveExplicitTypeArguments.class, CodeTransformationTestGenerated.ConvertAssertToIf.class})
@InnerTestClasses({CodeTransformationTestGenerated.DoubleBangToIfThen.class, CodeTransformationTestGenerated.IfThenToDoubleBang.class, 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, CodeTransformationTestGenerated.InsertExplicitTypeArguments.class, CodeTransformationTestGenerated.RemoveExplicitTypeArguments.class, CodeTransformationTestGenerated.ConvertAssertToIf.class, CodeTransformationTestGenerated.ConvertIfToAssert.class})
public class CodeTransformationTestGenerated extends AbstractCodeTransformationTest {
@TestMetadata("idea/testData/intentions/branched/doubleBangToIfThen")
public static class DoubleBangToIfThen extends AbstractCodeTransformationTest {
@@ -3881,6 +3884,79 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
}
@TestMetadata("idea/testData/intentions/convertIfToAssert")
public static class ConvertIfToAssert extends AbstractCodeTransformationTest {
public void testAllFilesPresentInConvertIfToAssert() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/intentions/convertIfToAssert"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("assertOverloaded.kt")
public void testAssertOverloaded() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/assertOverloaded.kt");
}
@TestMetadata("assertOverloaded2.kt")
public void testAssertOverloaded2() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/assertOverloaded2.kt");
}
@TestMetadata("booleanCondition.kt")
public void testBooleanCondition() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/booleanCondition.kt");
}
@TestMetadata("dotQualifiedThrow.kt")
public void testDotQualifiedThrow() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/dotQualifiedThrow.kt");
}
@TestMetadata("inapplicableAssertionErrorOverloaded.kt")
public void testInapplicableAssertionErrorOverloaded() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/inapplicableAssertionErrorOverloaded.kt");
}
@TestMetadata("inapplicableCauseSent.kt")
public void testInapplicableCauseSent() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/inapplicableCauseSent.kt");
}
@TestMetadata("inapplicableHasElse.kt")
public void testInapplicableHasElse() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/inapplicableHasElse.kt");
}
@TestMetadata("inapplicableMoreThanSingleExpression.kt")
public void testInapplicableMoreThanSingleExpression() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/inapplicableMoreThanSingleExpression.kt");
}
@TestMetadata("inapplicableMoreThanSingleExpression2.kt")
public void testInapplicableMoreThanSingleExpression2() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/inapplicableMoreThanSingleExpression2.kt");
}
@TestMetadata("noMessageSent.kt")
public void testNoMessageSent() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/noMessageSent.kt");
}
@TestMetadata("nullSent.kt")
public void testNullSent() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/nullSent.kt");
}
@TestMetadata("simpleConvert.kt")
public void testSimpleConvert() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/simpleConvert.kt");
}
@TestMetadata("simplifiedCondition.kt")
public void testSimplifiedCondition() throws Exception {
doTestConvertIfWithThrowToAssertIntention("idea/testData/intentions/convertIfToAssert/simplifiedCondition.kt");
}
}
public static Test suite() {
TestSuite suite = new TestSuite("CodeTransformationTestGenerated");
suite.addTestSuite(DoubleBangToIfThen.class);
@@ -3936,6 +4012,7 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
suite.addTestSuite(InsertExplicitTypeArguments.class);
suite.addTestSuite(RemoveExplicitTypeArguments.class);
suite.addTestSuite(ConvertAssertToIf.class);
suite.addTestSuite(ConvertIfToAssert.class);
return suite;
}
}