Simplify message expression from lambda argument when converting assert to if.
This commit is contained in:
+23
-9
@@ -23,8 +23,12 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
|||||||
import org.jetbrains.kotlin.idea.core.replaced
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
|
|
||||||
public class ConvertAssertToIfWithThrowIntention : SelfTargetingIntention<KtCallExpression>(javaClass(), "Replace 'assert' with 'if' statement"), LowPriorityAction {
|
public class ConvertAssertToIfWithThrowIntention : SelfTargetingIntention<KtCallExpression>(javaClass(), "Replace 'assert' with 'if' statement"), LowPriorityAction {
|
||||||
override fun isApplicableTo(element: KtCallExpression, caretOffset: Int): Boolean {
|
override fun isApplicableTo(element: KtCallExpression, caretOffset: Int): Boolean {
|
||||||
@@ -44,17 +48,21 @@ public class ConvertAssertToIfWithThrowIntention : SelfTargetingIntention<KtCall
|
|||||||
override fun applyTo(element: KtCallExpression, editor: Editor) {
|
override fun applyTo(element: KtCallExpression, editor: Editor) {
|
||||||
val args = element.getValueArguments()
|
val args = element.getValueArguments()
|
||||||
val conditionText = args[0]?.getArgumentExpression()?.getText() ?: return
|
val conditionText = args[0]?.getArgumentExpression()?.getText() ?: return
|
||||||
val functionLiteral = element.getFunctionLiteralArguments().singleOrNull()
|
val functionLiteralArgument = element.functionLiteralArguments.singleOrNull()
|
||||||
val messageIsFunction = messageIsFunction(element)
|
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
|
||||||
|
|
||||||
val psiFactory = KtPsiFactory(element)
|
val psiFactory = KtPsiFactory(element)
|
||||||
|
|
||||||
val messageExpr = when {
|
val messageFunctionExpr = when {
|
||||||
args.size() == 2 -> args[1]?.getArgumentExpression() ?: return
|
args.size == 2 -> args[1]?.getArgumentExpression() ?: return
|
||||||
functionLiteral != null -> functionLiteral!!
|
functionLiteralArgument != null -> functionLiteralArgument.getFunctionLiteral()
|
||||||
else -> psiFactory.createExpression("\"Assertion failed\"")
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val extractedMessageSingleExpr = (messageFunctionExpr as? KtFunctionLiteralExpression)?.let { extractMessageSingleExpression(it, bindingContext) }
|
||||||
|
|
||||||
|
val messageIsFunction = extractedMessageSingleExpr == null && messageIsFunction(element, bindingContext)
|
||||||
|
val messageExpr = extractedMessageSingleExpr ?: messageFunctionExpr ?: psiFactory.createExpression("\"Assertion failed\"")
|
||||||
|
|
||||||
val ifExpression = replaceWithIfThenThrowExpression(element)
|
val ifExpression = replaceWithIfThenThrowExpression(element)
|
||||||
|
|
||||||
// shorten java.lang.AssertionError
|
// shorten java.lang.AssertionError
|
||||||
@@ -85,8 +93,14 @@ public class ConvertAssertToIfWithThrowIntention : SelfTargetingIntention<KtCall
|
|||||||
simplifyConditionIfPossible(ifExpression)
|
simplifyConditionIfPossible(ifExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun messageIsFunction(callExpr: KtCallExpression): Boolean {
|
private fun extractMessageSingleExpression(functionLiteral: KtFunctionLiteralExpression, bindingContext: BindingContext): KtExpression? {
|
||||||
val resolvedCall = callExpr.getResolvedCall(callExpr.analyze()) ?: return false
|
return functionLiteral.bodyExpression?.statements?.singleOrNull()?.let { singleStatement ->
|
||||||
|
singleStatement.check { it.isUsedAsExpression(bindingContext) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun messageIsFunction(callExpr: KtCallExpression, bindingContext: BindingContext): Boolean {
|
||||||
|
val resolvedCall = callExpr.getResolvedCall(bindingContext) ?: return false
|
||||||
val valParameters = resolvedCall.getResultingDescriptor().getValueParameters()
|
val valParameters = resolvedCall.getResultingDescriptor().getValueParameters()
|
||||||
return valParameters.size() > 1 && !KotlinBuiltIns.isAny(valParameters[1].type)
|
return valParameters.size() > 1 && !KotlinBuiltIns.isAny(valParameters[1].type)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package a
|
package a
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<caret>assert(true, "text")
|
<caret>assert(true, { "text" })
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssertionError
|
class AssertionError
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<caret>assert(true && false, "text")
|
<caret>assert(true && false, { "text" })
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<caret>assert(1 > 0, "text")
|
<caret>assert(1 > 0) { "text" }
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<caret>assert(0 != 1, "text")
|
<caret>assert(0 != 1) { "text" }
|
||||||
}
|
}
|
||||||
+1
-1
@@ -2,5 +2,5 @@
|
|||||||
fun foo() {
|
fun foo() {
|
||||||
val x = true
|
val x = true
|
||||||
val y = false
|
val y = false
|
||||||
<caret>assert(x || y, "text")
|
<caret>assert(x || y) { "text" }
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
asse<caret>rt(false, "mess" as kotlin.String)
|
asse<caret>rt(false) { "mess" as kotlin.String }
|
||||||
}
|
}
|
||||||
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
kotlin.<caret>assert(true, "text")
|
kotlin.<caret>assert(true) {"text"}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<caret>assert(bar(), "text")
|
<caret>assert(bar()) { "text" }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bar(): Boolean = true
|
fun bar(): Boolean = true
|
||||||
+3
-1
@@ -1,4 +1,6 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<caret>assert(true, { "text" })
|
<caret>assert(true, {
|
||||||
|
if (true) "text" else return
|
||||||
|
})
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
if (!true) {
|
if (!true) {
|
||||||
throw AssertionError({ "text" }())
|
throw AssertionError(if (true) "text" else return)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-1
@@ -1,4 +1,6 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<caret>assert(true) { "text" }
|
<caret>assert(true) {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+3
-1
@@ -1,6 +1,8 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
if (!true) {
|
if (!true) {
|
||||||
throw AssertionError({ "text" }())
|
throw AssertionError({
|
||||||
|
return
|
||||||
|
}())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo() {
|
||||||
|
<caret>assert(true, {
|
||||||
|
val value = 1
|
||||||
|
"text and $value"
|
||||||
|
})
|
||||||
|
}
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo() {
|
||||||
|
if (!true) {
|
||||||
|
throw AssertionError({
|
||||||
|
val value = 1
|
||||||
|
"text and $value"
|
||||||
|
}())
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo() {
|
||||||
|
<caret>assert(true) {
|
||||||
|
if (false) return
|
||||||
|
"text"
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo() {
|
||||||
|
if (!true) {
|
||||||
|
throw AssertionError({
|
||||||
|
if (false) return
|
||||||
|
"text"
|
||||||
|
}())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<caret>assert((true && false), "text")
|
<caret>assert((true && false)) { "text" }
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<caret>assert(true, "text")
|
<caret>assert(true) { "text" }
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
fun foo() {
|
fun foo() {
|
||||||
val f = "text"
|
val f = "text"
|
||||||
<caret>assert(true, f)
|
<caret>assert(true) { f }
|
||||||
}
|
}
|
||||||
@@ -3088,6 +3088,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaMultiStatementMessageInsideParentheses.kt")
|
||||||
|
public void testLambdaMultiStatementMessageInsideParentheses() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertAssertToIf/lambdaMultiStatementMessageInsideParentheses.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaMultiStatementMessageOutsideParentheses.kt")
|
||||||
|
public void testLambdaMultiStatementMessageOutsideParentheses() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertAssertToIf/lambdaMultiStatementMessageOutsideParentheses.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambdaVariable.kt")
|
@TestMetadata("lambdaVariable.kt")
|
||||||
public void testLambdaVariable() throws Exception {
|
public void testLambdaVariable() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertAssertToIf/lambdaVariable.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertAssertToIf/lambdaVariable.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user